From 06da74f753b76f1e7b4a64c89de6dd1fac61f40b Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Thu, 20 Apr 2023 13:04:43 +0300 Subject: [PATCH 1/9] Started rewriting old usage of embedded vertx to verticles deployment style --- .../pubstack/PubstackAnalyticsReporter.java | 4 +- .../pubstack/PubstackEventHandler.java | 4 +- .../server/bidder/BidderErrorNotifier.java | 4 +- .../server/bidder/HttpBidderRequester.java | 4 +- .../org/prebid/server/cache/CacheService.java | 4 +- .../currency/CurrencyConversionService.java | 4 +- .../prebid/server/deals/AlertHttpService.java | 4 +- .../server/deals/DeliveryStatsService.java | 4 +- .../prebid/server/deals/PlannerService.java | 4 +- .../prebid/server/deals/RegisterService.java | 4 +- .../org/prebid/server/deals/UserService.java | 4 +- .../SimulationAwareDeliveryStatsService.java | 2 +- .../SimulationAwareHttpBidderRequester.java | 2 +- .../SimulationAwarePlannerService.java | 2 +- .../SimulationAwareRegisterService.java | 2 +- .../SimulationAwareUserService.java | 2 +- .../server/floors/PriceFloorFetcher.java | 4 +- .../server/handler/BidderParamHandler.java | 13 +- .../server/handler/CookieSyncHandler.java | 13 +- .../handler/CustomizedAdminEndpoint.java | 79 ------- .../prebid/server/handler/GetuidsHandler.java | 13 +- .../handler/NotificationEventHandler.java | 13 +- .../prebid/server/handler/OptoutHandler.java | 14 +- .../prebid/server/handler/SetuidHandler.java | 12 +- .../prebid/server/handler/StatusHandler.java | 12 +- .../prebid/server/handler/VtrackHandler.java | 12 +- .../AccountCacheInvalidationHandler.java | 2 +- .../handler/admin/AdminResourceWrapper.java | 45 ++++ .../{ => admin}/CollectedMetricsHandler.java | 2 +- .../{ => admin}/CurrencyRatesHandler.java | 2 +- .../{ => admin}/DealsStatusHandler.java | 2 +- .../{ => admin}/ForceDealsUpdateHandler.java | 2 +- .../HttpInteractionLogHandler.java | 2 +- .../{ => admin}/LineItemStatusHandler.java | 2 +- .../{ => admin}/LoggerControlKnobHandler.java | 2 +- .../SettingsCacheNotificationHandler.java | 2 +- .../handler/{ => admin}/TracerLogHandler.java | 2 +- .../handler/{ => admin}/VersionHandler.java | 2 +- .../handler/info/BidderDetailsHandler.java | 13 +- .../server/handler/info/BiddersHandler.java | 13 +- .../server/handler/openrtb2/AmpHandler.java | 11 +- .../handler/openrtb2/AuctionHandler.java | 12 +- .../server/handler/openrtb2/VideoHandler.java | 11 +- .../optout/GoogleRecaptchaVerifier.java | 4 +- .../gdpr/vendorlist/VendorListService.java | 4 +- .../gdpr/vendorlist/VendorListServiceV2.java | 2 +- .../settings/HttpApplicationSettings.java | 4 +- .../service/HttpPeriodicRefreshService.java | 4 +- .../config/AdminServerConfiguration.java | 61 ----- .../spring/config/AnalyticsConfiguration.java | 2 +- .../spring/config/AopConfiguration.java | 2 +- .../spring/config/DealsConfiguration.java | 2 +- .../config/InitializationConfiguration.java | 2 +- .../config/PriceFloorsConfiguration.java | 2 +- .../config/PrivacyServiceConfiguration.java | 2 +- .../spring/config/ServiceConfiguration.java | 6 +- .../spring/config/SettingsConfiguration.java | 2 +- .../server/spring/config/VerticleStarter.java | 24 ++ .../spring/config/VertxConfiguration.java | 8 + .../metrics/PrometheusConfiguration.java | 83 +++---- .../model/ExternalConversionProperties.java | 2 +- .../server/HttpServerConfiguration.java | 63 ------ .../server/UnixSocketServerConfiguration.java | 63 ------ .../admin}/AdminEndpointsConfiguration.java | 212 +++++++++--------- .../server/admin/AdminResourcesBinder.java | 40 ++++ .../server/admin/AdminServerAuthProvider.java | 40 ++++ .../admin/AdminServerConfiguration.java | 47 ++++ .../ApplicationServerConfiguration.java} | 124 +++++----- .../prebid/server/vertx/ContextRunner.java | 51 ++--- .../{http => httpclient}/BasicHttpClient.java | 4 +- .../CircuitBreakerSecuredHttpClient.java | 4 +- .../{http => httpclient}/HttpClient.java | 4 +- .../model/HttpClientResponse.java | 2 +- .../server/vertx/jdbc/BasicJdbcClient.java | 1 + .../vertx/verticles/VerticleDefinition.java | 26 +++ .../vertx/verticles/VerticleDeployer.java | 65 ++++++ .../vertx/verticles/server/HttpEndpoint.java | 12 + .../verticles/server/ServerVerticle.java | 74 ++++++ .../verticles/server/admin/AdminResource.java | 13 ++ .../application/ApplicationResource.java | 12 + src/main/resources/application.yaml | 8 +- .../PubstackAnalyticsReporterTest.java | 4 +- .../pubstack/PubstackEventHandlerTest.java | 4 +- .../CurrencyConversionServiceTest.java | 4 +- .../bidder/BidderErrorNotifierTest.java | 4 +- .../bidder/HttpBidderRequesterTest.java | 4 +- .../prebid/server/cache/CacheServiceTest.java | 4 +- .../server/deals/AlertHttpServiceTest.java | 2 +- .../deals/DeliveryStatsServiceTest.java | 4 +- .../server/deals/PlannerServiceTest.java | 4 +- .../server/deals/RegisterServiceTest.java | 4 +- .../prebid/server/deals/UserServiceTest.java | 4 +- ...imulationAwareHttpBidderRequesterTest.java | 2 +- .../SimulationAwarePlannerServiceTest.java | 4 +- .../server/floors/PriceFloorFetcherTest.java | 4 +- .../AccountCacheInvalidationHandlerTest.java | 1 + ...est.java => AdminResourceWrapperTest.java} | 9 +- .../handler/CollectedMetricsHandlerTest.java | 1 + .../handler/CurrencyRatesHandlerTest.java | 1 + .../handler/DealsStatusHandlerTest.java | 1 + .../handler/ForceDealsUpdateHandlerTest.java | 1 + .../HttpInteractionLogHandlerTest.java | 1 + .../handler/LineItemStatusHandlerTest.java | 1 + .../handler/LoggerControlKnobHandlerTest.java | 1 + .../SettingsCacheNotificationHandlerTest.java | 1 + .../server/handler/TracerLogHandlerTest.java | 1 + .../server/handler/VersionHandlerTest.java | 1 + .../optout/GoogleRecaptchaVerifierTest.java | 4 +- .../vendorlist/VendorListServiceV2Test.java | 4 +- .../settings/HttpApplicationSettingsTest.java | 4 +- .../HttpPeriodicRefreshServiceTest.java | 4 +- .../BasicHttpClientTest.java | 2 +- .../CircuitBreakerSecuredHttpClientTest.java | 4 +- 113 files changed, 897 insertions(+), 644 deletions(-) delete mode 100644 src/main/java/org/prebid/server/handler/CustomizedAdminEndpoint.java rename src/main/java/org/prebid/server/handler/{ => admin}/AccountCacheInvalidationHandler.java (97%) create mode 100644 src/main/java/org/prebid/server/handler/admin/AdminResourceWrapper.java rename src/main/java/org/prebid/server/handler/{ => admin}/CollectedMetricsHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/CurrencyRatesHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/DealsStatusHandler.java (97%) rename src/main/java/org/prebid/server/handler/{ => admin}/ForceDealsUpdateHandler.java (99%) rename src/main/java/org/prebid/server/handler/{ => admin}/HttpInteractionLogHandler.java (99%) rename src/main/java/org/prebid/server/handler/{ => admin}/LineItemStatusHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/LoggerControlKnobHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/SettingsCacheNotificationHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/TracerLogHandler.java (98%) rename src/main/java/org/prebid/server/handler/{ => admin}/VersionHandler.java (98%) delete mode 100644 src/main/java/org/prebid/server/spring/config/AdminServerConfiguration.java create mode 100644 src/main/java/org/prebid/server/spring/config/VerticleStarter.java delete mode 100644 src/main/java/org/prebid/server/spring/config/server/HttpServerConfiguration.java delete mode 100644 src/main/java/org/prebid/server/spring/config/server/UnixSocketServerConfiguration.java rename src/main/java/org/prebid/server/spring/config/{ => server/admin}/AdminEndpointsConfiguration.java (66%) create mode 100644 src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java create mode 100644 src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java create mode 100644 src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java rename src/main/java/org/prebid/server/spring/config/{WebConfiguration.java => server/application/ApplicationServerConfiguration.java} (79%) rename src/main/java/org/prebid/server/vertx/{http => httpclient}/BasicHttpClient.java (97%) rename src/main/java/org/prebid/server/vertx/{http => httpclient}/CircuitBreakerSecuredHttpClient.java (98%) rename src/main/java/org/prebid/server/vertx/{http => httpclient}/HttpClient.java (94%) rename src/main/java/org/prebid/server/vertx/{http => httpclient}/model/HttpClientResponse.java (87%) create mode 100644 src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java create mode 100644 src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java create mode 100644 src/main/java/org/prebid/server/vertx/verticles/server/HttpEndpoint.java create mode 100644 src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java create mode 100644 src/main/java/org/prebid/server/vertx/verticles/server/admin/AdminResource.java create mode 100644 src/main/java/org/prebid/server/vertx/verticles/server/application/ApplicationResource.java rename src/test/java/org/prebid/server/handler/{CustomizedAdminEndpointTest.java => AdminResourceWrapperTest.java} (91%) rename src/test/java/org/prebid/server/vertx/{http => httpclient}/BasicHttpClientTest.java (99%) rename src/test/java/org/prebid/server/vertx/{http => httpclient}/CircuitBreakerSecuredHttpClientTest.java (98%) diff --git a/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporter.java b/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporter.java index 47e5a506a5d..87e52034472 100644 --- a/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporter.java +++ b/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporter.java @@ -22,8 +22,8 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.Arrays; import java.util.Collections; diff --git a/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandler.java b/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandler.java index 235677ad61e..0dd4eb229e9 100644 --- a/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandler.java +++ b/src/main/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandler.java @@ -13,8 +13,8 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/main/java/org/prebid/server/bidder/BidderErrorNotifier.java b/src/main/java/org/prebid/server/bidder/BidderErrorNotifier.java index 38fa9ec8ede..4fde2bbbcd5 100644 --- a/src/main/java/org/prebid/server/bidder/BidderErrorNotifier.java +++ b/src/main/java/org/prebid/server/bidder/BidderErrorNotifier.java @@ -7,8 +7,8 @@ import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.log.ConditionalLogger; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.Objects; diff --git a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java index 42976d52256..2514c6c86df 100644 --- a/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java +++ b/src/main/java/org/prebid/server/bidder/HttpBidderRequester.java @@ -32,8 +32,8 @@ import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/main/java/org/prebid/server/cache/CacheService.java b/src/main/java/org/prebid/server/cache/CacheService.java index dd3a0a19eec..9f7fa76ad8e 100644 --- a/src/main/java/org/prebid/server/cache/CacheService.java +++ b/src/main/java/org/prebid/server/cache/CacheService.java @@ -43,8 +43,8 @@ import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; import org.prebid.server.vast.VastModifier; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.net.MalformedURLException; import java.net.URL; diff --git a/src/main/java/org/prebid/server/currency/CurrencyConversionService.java b/src/main/java/org/prebid/server/currency/CurrencyConversionService.java index cc63eb5e927..2df259891b1 100644 --- a/src/main/java/org/prebid/server/currency/CurrencyConversionService.java +++ b/src/main/java/org/prebid/server/currency/CurrencyConversionService.java @@ -17,8 +17,8 @@ import org.prebid.server.spring.config.model.ExternalConversionProperties; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.IOException; import java.math.BigDecimal; diff --git a/src/main/java/org/prebid/server/deals/AlertHttpService.java b/src/main/java/org/prebid/server/deals/AlertHttpService.java index 3b89b0f2bd8..8db78dd6687 100644 --- a/src/main/java/org/prebid/server/deals/AlertHttpService.java +++ b/src/main/java/org/prebid/server/deals/AlertHttpService.java @@ -13,8 +13,8 @@ import org.prebid.server.json.EncodeException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.time.ZonedDateTime; diff --git a/src/main/java/org/prebid/server/deals/DeliveryStatsService.java b/src/main/java/org/prebid/server/deals/DeliveryStatsService.java index 13ff0607500..e3cb03e30a7 100644 --- a/src/main/java/org/prebid/server/deals/DeliveryStatsService.java +++ b/src/main/java/org/prebid/server/deals/DeliveryStatsService.java @@ -20,8 +20,8 @@ import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/src/main/java/org/prebid/server/deals/PlannerService.java b/src/main/java/org/prebid/server/deals/PlannerService.java index e719ad314f2..3502ce35b99 100644 --- a/src/main/java/org/prebid/server/deals/PlannerService.java +++ b/src/main/java/org/prebid/server/deals/PlannerService.java @@ -17,8 +17,8 @@ import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.util.Base64; diff --git a/src/main/java/org/prebid/server/deals/RegisterService.java b/src/main/java/org/prebid/server/deals/RegisterService.java index 19438bee658..6e62941041e 100644 --- a/src/main/java/org/prebid/server/deals/RegisterService.java +++ b/src/main/java/org/prebid/server/deals/RegisterService.java @@ -22,8 +22,8 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.math.BigDecimal; import java.time.ZonedDateTime; diff --git a/src/main/java/org/prebid/server/deals/UserService.java b/src/main/java/org/prebid/server/deals/UserService.java index 41e0b300b67..ed9550339bf 100644 --- a/src/main/java/org/prebid/server/deals/UserService.java +++ b/src/main/java/org/prebid/server/deals/UserService.java @@ -26,8 +26,8 @@ import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.time.ZonedDateTime; diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java index 7debdb649ed..a0b5ce4fbc6 100644 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java +++ b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java @@ -10,7 +10,7 @@ import org.prebid.server.deals.proto.report.DeliveryProgressReport; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.time.Clock; import java.time.ZonedDateTime; diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java index 8c201ac081f..35f6235be11 100644 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java +++ b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java @@ -31,7 +31,7 @@ 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.response.BidType; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.math.BigDecimal; import java.util.Collection; diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java index 2009f94e63f..624919d5e84 100644 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java +++ b/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java @@ -13,7 +13,7 @@ import org.prebid.server.deals.proto.LineItemMetaData; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.time.Clock; import java.time.ZonedDateTime; diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java index d185285937e..5737db04172 100644 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java +++ b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java @@ -11,7 +11,7 @@ import org.prebid.server.deals.model.PlannerProperties; import org.prebid.server.health.HealthMonitor; import org.prebid.server.json.JacksonMapper; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java index 78d9f8ae409..22bc5883cee 100644 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java +++ b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java @@ -11,7 +11,7 @@ import org.prebid.server.execution.Timeout; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.time.Clock; diff --git a/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java b/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java index d0cdbafb707..b74716cb265 100644 --- a/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java +++ b/src/main/java/org/prebid/server/floors/PriceFloorFetcher.java @@ -31,8 +31,8 @@ import org.prebid.server.settings.model.AccountPriceFloorsFetchConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.Map; import java.util.Objects; diff --git a/src/main/java/org/prebid/server/handler/BidderParamHandler.java b/src/main/java/org/prebid/server/handler/BidderParamHandler.java index 26366130cd1..8dd65b61f40 100644 --- a/src/main/java/org/prebid/server/handler/BidderParamHandler.java +++ b/src/main/java/org/prebid/server/handler/BidderParamHandler.java @@ -1,14 +1,18 @@ package org.prebid.server.handler; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.RoutingContext; import org.prebid.server.model.Endpoint; import org.prebid.server.util.HttpUtil; import org.prebid.server.validation.BidderParamValidator; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; +import java.util.Collections; +import java.util.List; import java.util.Objects; -public class BidderParamHandler implements Handler { +public class BidderParamHandler implements ApplicationResource { private final BidderParamValidator bidderParamValidator; @@ -16,6 +20,11 @@ public BidderParamHandler(BidderParamValidator bidderParamValidator) { this.bidderParamValidator = Objects.requireNonNull(bidderParamValidator); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/bidders/params")); + } + @Override public void handle(RoutingContext routingContext) { HttpUtil.executeSafely(routingContext, Endpoint.bidder_params, diff --git a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java index 72ad77d8789..02c826412fa 100644 --- a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java +++ b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java @@ -3,8 +3,8 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Future; -import io.vertx.core.Handler; import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpMethod; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; @@ -36,11 +36,15 @@ import org.prebid.server.settings.ApplicationSettings; import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Objects; -public class CookieSyncHandler implements Handler { +public class CookieSyncHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(CookieSyncHandler.class); private static final ConditionalLogger BAD_REQUEST_LOGGER = new ConditionalLogger(logger); @@ -82,6 +86,11 @@ public CookieSyncHandler(long defaultTimeout, this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/cookie_sync")); + } + @Override public void handle(RoutingContext routingContext) { metrics.updateCookieSyncRequestMetric(); diff --git a/src/main/java/org/prebid/server/handler/CustomizedAdminEndpoint.java b/src/main/java/org/prebid/server/handler/CustomizedAdminEndpoint.java deleted file mode 100644 index 4ac49624277..00000000000 --- a/src/main/java/org/prebid/server/handler/CustomizedAdminEndpoint.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.prebid.server.handler; - -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.ext.auth.AuthProvider; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.RoutingContext; -import io.vertx.ext.web.handler.BasicAuthHandler; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; -import java.util.Objects; - -public class CustomizedAdminEndpoint { - - private final String path; - private final Handler handler; - private final boolean isOnApplicationPort; - private final boolean isProtected; - private Map credentials; - - public CustomizedAdminEndpoint(String path, Handler handler, boolean isOnApplicationPort, - boolean isProtected) { - this.path = Objects.requireNonNull(path); - this.handler = Objects.requireNonNull(handler); - this.isOnApplicationPort = isOnApplicationPort; - this.isProtected = isProtected; - } - - public CustomizedAdminEndpoint withCredentials(Map credentials) { - this.credentials = credentials; - return this; - } - - public boolean isOnApplicationPort() { - return isOnApplicationPort; - } - - public void router(Router router) { - if (isProtected) { - routeToHandlerWithCredentials(router); - } else { - routeToHandler(router); - } - } - - private void routeToHandlerWithCredentials(Router router) { - if (credentials == null) { - throw new IllegalArgumentException("Credentials for admin endpoint is empty."); - } - - final AuthProvider authProvider = createAuthProvider(credentials); - router.route(path).handler(BasicAuthHandler.create(authProvider)).handler(handler); - } - - private void routeToHandler(Router router) { - router.route(path).handler(handler); - } - - private AuthProvider createAuthProvider(Map credentials) { - return (authInfo, resultHandler) -> { - if (MapUtils.isEmpty(credentials)) { - resultHandler.handle(Future.failedFuture("Credentials not set in configuration.")); - return; - } - - final String requestUsername = authInfo.getString("username"); - final String requestPassword = StringUtils.chomp(authInfo.getString("password")); - - final String storedPassword = credentials.get(requestUsername); - if (StringUtils.isNotBlank(requestPassword) && Objects.equals(storedPassword, requestPassword)) { - resultHandler.handle(Future.succeededFuture()); - } else { - resultHandler.handle(Future.failedFuture("No such user, or password incorrect.")); - } - }; - } -} diff --git a/src/main/java/org/prebid/server/handler/GetuidsHandler.java b/src/main/java/org/prebid/server/handler/GetuidsHandler.java index deb3822e4a9..d9a91a3e098 100644 --- a/src/main/java/org/prebid/server/handler/GetuidsHandler.java +++ b/src/main/java/org/prebid/server/handler/GetuidsHandler.java @@ -1,7 +1,7 @@ package org.prebid.server.handler; import com.fasterxml.jackson.annotation.JsonInclude; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.RoutingContext; import lombok.AllArgsConstructor; import lombok.Value; @@ -10,12 +10,16 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.model.Endpoint; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; +import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; -public class GetuidsHandler implements Handler { +public class GetuidsHandler implements ApplicationResource { private final UidsCookieService uidsCookieService; private final JacksonMapper mapper; @@ -25,6 +29,11 @@ public GetuidsHandler(UidsCookieService uidsCookieService, JacksonMapper mapper) this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/getuids")); + } + @Override public void handle(RoutingContext routingContext) { final Map uids = uidsFrom(routingContext); diff --git a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java index 6dabdc89cbf..097008052fb 100644 --- a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java +++ b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java @@ -3,9 +3,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; import io.vertx.core.Future; -import io.vertx.core.Handler; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -30,15 +30,19 @@ import org.prebid.server.settings.model.AccountEventsConfig; import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ResourceUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Objects; /** * Accepts notifications from browsers and mobile application for further processing by {@link AnalyticsReporter} * and responding with tracking pixel when requested. */ -public class NotificationEventHandler implements Handler { +public class NotificationEventHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(NotificationEventHandler.class); @@ -87,6 +91,11 @@ private static TrackingPixel createTrackingPixel() { return TrackingPixel.of(PNG_CONTENT_TYPE, bytes); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/event")); + } + @Override public void handle(RoutingContext routingContext) { try { diff --git a/src/main/java/org/prebid/server/handler/OptoutHandler.java b/src/main/java/org/prebid/server/handler/OptoutHandler.java index c4360fb003a..7a967100e87 100644 --- a/src/main/java/org/prebid/server/handler/OptoutHandler.java +++ b/src/main/java/org/prebid/server/handler/OptoutHandler.java @@ -2,8 +2,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpMethod; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; @@ -14,12 +14,15 @@ import org.prebid.server.optout.GoogleRecaptchaVerifier; import org.prebid.server.optout.model.RecaptchaResponse; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.net.MalformedURLException; import java.net.URL; +import java.util.List; import java.util.Objects; -public class OptoutHandler implements Handler { +public class OptoutHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(OptoutHandler.class); @@ -41,6 +44,13 @@ public OptoutHandler(GoogleRecaptchaVerifier googleRecaptchaVerifier, UidsCookie this.optinUrl = Objects.requireNonNull(optinUrl); } + @Override + public List endpoints() { + return List.of( + HttpEndpoint.of(HttpMethod.GET, "/optout"), + HttpEndpoint.of(HttpMethod.POST, "/optout")); + } + @Override public void handle(RoutingContext routingContext) { final String recaptcha = getRequestParam(routingContext, RECAPTCHA_PARAM); diff --git a/src/main/java/org/prebid/server/handler/SetuidHandler.java b/src/main/java/org/prebid/server/handler/SetuidHandler.java index 0530b6a6af5..562af639302 100644 --- a/src/main/java/org/prebid/server/handler/SetuidHandler.java +++ b/src/main/java/org/prebid/server/handler/SetuidHandler.java @@ -3,9 +3,9 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; import io.vertx.core.Future; -import io.vertx.core.Handler; import io.vertx.core.http.Cookie; import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; @@ -40,8 +40,11 @@ import org.prebid.server.settings.ApplicationSettings; import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -49,7 +52,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class SetuidHandler implements Handler { +public class SetuidHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(SetuidHandler.class); @@ -97,6 +100,11 @@ public SetuidHandler(long defaultTimeout, .collect(Collectors.toMap(Usersyncer::getCookieFamilyName, SetuidHandler::preferredUserSyncType)); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/setuid")); + } + private static UsersyncMethodType preferredUserSyncType(Usersyncer usersyncer) { return Stream.of(usersyncer.getIframe(), usersyncer.getRedirect()) .filter(Objects::nonNull) diff --git a/src/main/java/org/prebid/server/handler/StatusHandler.java b/src/main/java/org/prebid/server/handler/StatusHandler.java index f356971d598..6e8131a6a61 100644 --- a/src/main/java/org/prebid/server/handler/StatusHandler.java +++ b/src/main/java/org/prebid/server/handler/StatusHandler.java @@ -2,7 +2,7 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.RoutingContext; import org.apache.commons.collections4.CollectionUtils; import org.prebid.server.health.HealthChecker; @@ -10,13 +10,16 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.model.Endpoint; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.TreeMap; import java.util.stream.Collectors; -public class StatusHandler implements Handler { +public class StatusHandler implements ApplicationResource { private final List healthCheckers; private final JacksonMapper mapper; @@ -26,6 +29,11 @@ public StatusHandler(List healthCheckers, JacksonMapper mapper) { this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/status")); + } + @Override public void handle(RoutingContext routingContext) { if (CollectionUtils.isEmpty(healthCheckers)) { diff --git a/src/main/java/org/prebid/server/handler/VtrackHandler.java b/src/main/java/org/prebid/server/handler/VtrackHandler.java index d433867b01e..987d55be810 100644 --- a/src/main/java/org/prebid/server/handler/VtrackHandler.java +++ b/src/main/java/org/prebid/server/handler/VtrackHandler.java @@ -5,8 +5,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; import io.vertx.core.Future; -import io.vertx.core.Handler; import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpMethod; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; @@ -30,13 +30,16 @@ import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountEventsConfig; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -public class VtrackHandler implements Handler { +public class VtrackHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(VtrackHandler.class); @@ -72,6 +75,11 @@ public VtrackHandler(long defaultTimeout, this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/vtrack")); + } + @Override public void handle(RoutingContext routingContext) { final String accountId; diff --git a/src/main/java/org/prebid/server/handler/AccountCacheInvalidationHandler.java b/src/main/java/org/prebid/server/handler/admin/AccountCacheInvalidationHandler.java similarity index 97% rename from src/main/java/org/prebid/server/handler/AccountCacheInvalidationHandler.java rename to src/main/java/org/prebid/server/handler/admin/AccountCacheInvalidationHandler.java index 8ad70ec3bd0..afe07e9aa67 100644 --- a/src/main/java/org/prebid/server/handler/AccountCacheInvalidationHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/AccountCacheInvalidationHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/admin/AdminResourceWrapper.java b/src/main/java/org/prebid/server/handler/admin/AdminResourceWrapper.java new file mode 100644 index 00000000000..e75920659d6 --- /dev/null +++ b/src/main/java/org/prebid/server/handler/admin/AdminResourceWrapper.java @@ -0,0 +1,45 @@ +package org.prebid.server.handler.admin; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; +import org.prebid.server.vertx.verticles.server.admin.AdminResource; + +import java.util.Objects; + +public class AdminResourceWrapper implements AdminResource { + + private final String path; + private final Handler handler; + private final boolean isOnApplicationPort; + private final boolean isSecured; + + public AdminResourceWrapper(String path, + boolean isOnApplicationPort, + boolean isProtected, + Handler handler) { + + this.path = Objects.requireNonNull(path); + this.isOnApplicationPort = isOnApplicationPort; + this.isSecured = isProtected; + this.handler = Objects.requireNonNull(handler); + } + + @Override + public String path() { + return path; + } + + public boolean isOnApplicationPort() { + return isOnApplicationPort; + } + + @Override + public boolean isSecured() { + return isSecured; + } + + @Override + public void handle(RoutingContext routingContext) { + handler.handle(routingContext); + } +} diff --git a/src/main/java/org/prebid/server/handler/CollectedMetricsHandler.java b/src/main/java/org/prebid/server/handler/admin/CollectedMetricsHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/CollectedMetricsHandler.java rename to src/main/java/org/prebid/server/handler/admin/CollectedMetricsHandler.java index 0a789d87d92..c9db54e21fa 100644 --- a/src/main/java/org/prebid/server/handler/CollectedMetricsHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/CollectedMetricsHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import com.codahale.metrics.Counter; import com.codahale.metrics.Gauge; diff --git a/src/main/java/org/prebid/server/handler/CurrencyRatesHandler.java b/src/main/java/org/prebid/server/handler/admin/CurrencyRatesHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/CurrencyRatesHandler.java rename to src/main/java/org/prebid/server/handler/admin/CurrencyRatesHandler.java index fa7d54cafd4..f9b52a807e4 100644 --- a/src/main/java/org/prebid/server/handler/CurrencyRatesHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/CurrencyRatesHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import com.fasterxml.jackson.annotation.JsonProperty; import io.netty.handler.codec.http.HttpHeaderValues; diff --git a/src/main/java/org/prebid/server/handler/DealsStatusHandler.java b/src/main/java/org/prebid/server/handler/admin/DealsStatusHandler.java similarity index 97% rename from src/main/java/org/prebid/server/handler/DealsStatusHandler.java rename to src/main/java/org/prebid/server/handler/admin/DealsStatusHandler.java index 15a9dc066dd..528cccdab25 100644 --- a/src/main/java/org/prebid/server/handler/DealsStatusHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/DealsStatusHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpHeaderValues; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java b/src/main/java/org/prebid/server/handler/admin/ForceDealsUpdateHandler.java similarity index 99% rename from src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java rename to src/main/java/org/prebid/server/handler/admin/ForceDealsUpdateHandler.java index 942b4953147..75cfad13932 100644 --- a/src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/ForceDealsUpdateHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java b/src/main/java/org/prebid/server/handler/admin/HttpInteractionLogHandler.java similarity index 99% rename from src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java rename to src/main/java/org/prebid/server/handler/admin/HttpInteractionLogHandler.java index a6c17f0c4cd..b3573a5c4c5 100644 --- a/src/main/java/org/prebid/server/handler/HttpInteractionLogHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/HttpInteractionLogHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/LineItemStatusHandler.java b/src/main/java/org/prebid/server/handler/admin/LineItemStatusHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/LineItemStatusHandler.java rename to src/main/java/org/prebid/server/handler/admin/LineItemStatusHandler.java index e43a543025a..238ca3e9a5b 100644 --- a/src/main/java/org/prebid/server/handler/LineItemStatusHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/LineItemStatusHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/LoggerControlKnobHandler.java b/src/main/java/org/prebid/server/handler/admin/LoggerControlKnobHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/LoggerControlKnobHandler.java rename to src/main/java/org/prebid/server/handler/admin/LoggerControlKnobHandler.java index 61b6e305718..7875c7a52dd 100644 --- a/src/main/java/org/prebid/server/handler/LoggerControlKnobHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/LoggerControlKnobHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/SettingsCacheNotificationHandler.java b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/SettingsCacheNotificationHandler.java rename to src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java index 08aec26922b..42eb8368bd3 100644 --- a/src/main/java/org/prebid/server/handler/SettingsCacheNotificationHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/SettingsCacheNotificationHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/TracerLogHandler.java b/src/main/java/org/prebid/server/handler/admin/TracerLogHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/TracerLogHandler.java rename to src/main/java/org/prebid/server/handler/admin/TracerLogHandler.java index ae0412860ae..2e092ee9756 100644 --- a/src/main/java/org/prebid/server/handler/TracerLogHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/TracerLogHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.Handler; diff --git a/src/main/java/org/prebid/server/handler/VersionHandler.java b/src/main/java/org/prebid/server/handler/admin/VersionHandler.java similarity index 98% rename from src/main/java/org/prebid/server/handler/VersionHandler.java rename to src/main/java/org/prebid/server/handler/admin/VersionHandler.java index eeeecae349a..adf8088e423 100644 --- a/src/main/java/org/prebid/server/handler/VersionHandler.java +++ b/src/main/java/org/prebid/server/handler/admin/VersionHandler.java @@ -1,4 +1,4 @@ -package org.prebid.server.handler; +package org.prebid.server.handler.admin; import com.fasterxml.jackson.core.JsonProcessingException; import io.netty.handler.codec.http.HttpResponseStatus; diff --git a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java index 31af7280ced..564417e4c86 100644 --- a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.RoutingContext; import lombok.Value; import org.prebid.server.bidder.BidderCatalog; @@ -12,8 +12,11 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.model.Endpoint; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.TreeMap; @@ -21,7 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class BidderDetailsHandler implements Handler { +public class BidderDetailsHandler implements ApplicationResource { private static final String BIDDER_NAME_PARAM = "bidderName"; private static final String ALL_PARAM_VALUE = "all"; @@ -62,6 +65,12 @@ private ObjectNode allInfos(Map nameToInfo) { return mapper.mapper().valueToTree(new TreeMap<>(nameToInfo)); } + @Override + public List endpoints() { + return Collections.singletonList( + HttpEndpoint.of(HttpMethod.GET, "/info/bidders/:%s".formatted(BIDDER_NAME_PARAM))); + } + @Override public void handle(RoutingContext routingContext) { final String bidderName = routingContext.request().getParam(BIDDER_NAME_PARAM); diff --git a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java index 258580ed5e1..4436baaabee 100644 --- a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java @@ -2,20 +2,24 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.ext.web.RoutingContext; import org.apache.commons.lang3.StringUtils; import org.prebid.server.bidder.BidderCatalog; import org.prebid.server.json.JacksonMapper; import org.prebid.server.model.Endpoint; import org.prebid.server.util.HttpUtil; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; +import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; -public class BiddersHandler implements Handler { +public class BiddersHandler implements ApplicationResource { private static final String ENABLED_ONLY_PARAM = "enabledonly"; private final BidderCatalog bidderCatalog; @@ -27,6 +31,11 @@ public BiddersHandler(BidderCatalog bidderCatalog, JacksonMapper mapper) { this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/info/bidders")); + } + @Override public void handle(RoutingContext routingContext) { try { diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java index c874edbaa4c..a7f4841e455 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java @@ -12,8 +12,8 @@ import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; import io.vertx.core.Future; -import io.vertx.core.Handler; import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -55,6 +55,8 @@ import org.prebid.server.proto.response.ExtAmpVideoResponse; import org.prebid.server.util.HttpUtil; import org.prebid.server.version.PrebidVersionProvider; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.time.Clock; import java.util.Collections; @@ -66,7 +68,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -public class AmpHandler implements Handler { +public class AmpHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(AmpHandler.class); private static final ConditionalLogger conditionalLogger = new ConditionalLogger(logger); @@ -111,6 +113,11 @@ public AmpHandler(AmpRequestFactory ampRequestFactory, this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/openrtb2/amp")); +} + @Override public void handle(RoutingContext routingContext) { // Prebid Server interprets request.tmax to be the maximum amount of time that a caller is willing to wait diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java index 41d21664aa3..9c2b28aa33f 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java @@ -5,7 +5,7 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -32,6 +32,8 @@ import org.prebid.server.privacy.model.PrivacyContext; import org.prebid.server.util.HttpUtil; import org.prebid.server.version.PrebidVersionProvider; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.time.Clock; import java.util.Collections; @@ -39,7 +41,7 @@ import java.util.Objects; import java.util.function.Consumer; -public class AuctionHandler implements Handler { +public class AuctionHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(AuctionHandler.class); private static final ConditionalLogger conditionalLogger = new ConditionalLogger(logger); @@ -75,6 +77,11 @@ public AuctionHandler(double logSamplingRate, this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/openrtb2/auction")); + } + @Override public void handle(RoutingContext routingContext) { // Prebid Server interprets request.tmax to be the maximum amount of time that a caller is willing to wait @@ -206,7 +213,6 @@ private void handleResult(AsyncResult responseResult, final TcfContext tcfContext = privacyContext != null ? privacyContext.getTcfContext() : TcfContext.empty(); respondWith(routingContext, status, body, startTime, requestType, metricRequestStatus, auctionEvent, tcfContext); - httpInteractionLogger.maybeLogOpenrtb2Auction(auctionContext, routingContext, status.code(), body); } diff --git a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java index 72b6bc0a0bd..3b49f80b94d 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java @@ -3,7 +3,7 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -32,6 +32,8 @@ import org.prebid.server.util.HttpUtil; import org.prebid.server.util.ObjectUtil; import org.prebid.server.version.PrebidVersionProvider; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import java.time.Clock; import java.util.ArrayList; @@ -41,7 +43,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -public class VideoHandler implements Handler { +public class VideoHandler implements ApplicationResource { private static final Logger logger = LoggerFactory.getLogger(VideoHandler.class); @@ -76,6 +78,11 @@ public VideoHandler(VideoRequestFactory videoRequestFactory, this.mapper = Objects.requireNonNull(mapper); } + @Override + public List endpoints() { + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/openrtb2/video")); + } + @Override public void handle(RoutingContext routingContext) { // Prebid Server interprets request.tmax to be the maximum amount of time that a caller is willing to wait diff --git a/src/main/java/org/prebid/server/optout/GoogleRecaptchaVerifier.java b/src/main/java/org/prebid/server/optout/GoogleRecaptchaVerifier.java index dcff4bade72..a37533586e7 100644 --- a/src/main/java/org/prebid/server/optout/GoogleRecaptchaVerifier.java +++ b/src/main/java/org/prebid/server/optout/GoogleRecaptchaVerifier.java @@ -10,8 +10,8 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.optout.model.RecaptchaResponse; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListService.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListService.java index 9fd20646478..6886e520fb4 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListService.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListService.java @@ -18,8 +18,8 @@ import org.prebid.server.exception.PreBidException; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.File; import java.nio.file.Files; diff --git a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2.java b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2.java index 567acf71527..ccd9c71b2eb 100644 --- a/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2.java +++ b/src/main/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2.java @@ -11,7 +11,7 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV2; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.io.IOException; import java.util.Collection; diff --git a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java index 262cceda164..72daa7e938d 100644 --- a/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java +++ b/src/main/java/org/prebid/server/settings/HttpApplicationSettings.java @@ -22,8 +22,8 @@ import org.prebid.server.settings.proto.response.HttpAccountsResponse; import org.prebid.server.settings.proto.response.HttpFetcherResponse; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java b/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java index ef53df54ec2..b50d2512953 100644 --- a/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java +++ b/src/main/java/org/prebid/server/settings/service/HttpPeriodicRefreshService.java @@ -15,8 +15,8 @@ import org.prebid.server.settings.proto.response.HttpRefreshResponse; import org.prebid.server.util.HttpUtil; import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Instant; import java.util.ArrayList; diff --git a/src/main/java/org/prebid/server/spring/config/AdminServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/AdminServerConfiguration.java deleted file mode 100644 index 4cc83bdfc5d..00000000000 --- a/src/main/java/org/prebid/server/spring/config/AdminServerConfiguration.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.prebid.server.spring.config; - -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpServer; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.handler.BodyHandler; -import org.prebid.server.handler.CustomizedAdminEndpoint; -import org.prebid.server.vertx.ContextRunner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; -import java.util.List; - -@Configuration -@ConditionalOnProperty(prefix = "admin", name = "port") -public class AdminServerConfiguration { - - private static final Logger logger = LoggerFactory.getLogger(AdminServerConfiguration.class); - - @Autowired - private ContextRunner contextRunner; - - @Autowired - private Vertx vertx; - - @Autowired - @Qualifier("adminRouter") - private Router adminRouter; - - @Value("${admin.port}") - private int adminPort; - - @Bean(name = "adminRouter") - Router adminRouter(BodyHandler bodyHandler, List customizedAdminEndpoints) { - final Router router = Router.router(vertx); - router.route().handler(bodyHandler); - - customizedAdminEndpoints.stream() - .filter(customizedAdminEndpoint -> !customizedAdminEndpoint.isOnApplicationPort()) - .forEach(customizedAdminEndpoint -> customizedAdminEndpoint.router(router)); - - return router; - } - - @PostConstruct - public void startAdminServer() { - logger.info("Starting Admin Server to serve requests on port {0,number,#}", adminPort); - - contextRunner.runOnServiceContext(future -> - vertx.createHttpServer().requestHandler(adminRouter).listen(adminPort, future)); - - logger.info("Successfully started Admin Server"); - } -} diff --git a/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java b/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java index 24f6098092d..b2dbf2cb0f5 100644 --- a/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/AnalyticsConfiguration.java @@ -12,7 +12,7 @@ import org.prebid.server.auction.PrivacyEnforcementService; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/src/main/java/org/prebid/server/spring/config/AopConfiguration.java b/src/main/java/org/prebid/server/spring/config/AopConfiguration.java index cdad8883732..736ca55a494 100644 --- a/src/main/java/org/prebid/server/spring/config/AopConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/AopConfiguration.java @@ -25,7 +25,7 @@ static class HealthMonitorAspect { @Autowired HealthMonitor healthMonitor; - @Around(value = "execution(* org.prebid.server.vertx.http.HttpClient.*(..)) " + @Around(value = "execution(* org.prebid.server.vertx.httpclient.HttpClient.*(..)) " + "|| execution(* org.prebid.server.settings.ApplicationSettings.*(..)) " + "|| execution(* org.prebid.server.geolocation.GeoLocationService.*(..))") public Future around(ProceedingJoinPoint joinPoint) { diff --git a/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java b/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java index 5b935ca1602..9403b75b304 100644 --- a/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java @@ -47,7 +47,7 @@ import org.prebid.server.settings.CachingApplicationSettings; import org.prebid.server.settings.SettingsCache; import org.prebid.server.vertx.ContextRunner; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; diff --git a/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java b/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java index a0b0498e16b..02035f3f5fe 100644 --- a/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java @@ -3,7 +3,7 @@ import org.prebid.server.metric.Metrics; import org.prebid.server.vertx.ContextRunner; import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ContextRefreshedEvent; diff --git a/src/main/java/org/prebid/server/spring/config/PriceFloorsConfiguration.java b/src/main/java/org/prebid/server/spring/config/PriceFloorsConfiguration.java index 67b4ce379ea..09be2779e22 100644 --- a/src/main/java/org/prebid/server/spring/config/PriceFloorsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/PriceFloorsConfiguration.java @@ -18,7 +18,7 @@ import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; import org.prebid.server.settings.ApplicationSettings; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java index e765deaf53f..c822a89ded7 100644 --- a/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/PrivacyServiceConfiguration.java @@ -33,7 +33,7 @@ import org.prebid.server.settings.model.Purposes; import org.prebid.server.settings.model.SpecialFeature; import org.prebid.server.settings.model.SpecialFeatures; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index 89d71262287..1faaef7a44f 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -101,9 +101,9 @@ import org.prebid.server.validation.VideoRequestValidator; import org.prebid.server.vast.VastModifier; import org.prebid.server.version.PrebidVersionProvider; -import org.prebid.server.vertx.http.BasicHttpClient; -import org.prebid.server.vertx.http.CircuitBreakerSecuredHttpClient; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.BasicHttpClient; +import org.prebid.server.vertx.httpclient.CircuitBreakerSecuredHttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; diff --git a/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java b/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java index 286d7e1bbd1..2c06b030d2c 100644 --- a/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/SettingsConfiguration.java @@ -27,7 +27,7 @@ import org.prebid.server.settings.service.JdbcPeriodicRefreshService; import org.prebid.server.spring.config.model.CircuitBreakerProperties; import org.prebid.server.vertx.ContextRunner; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.prebid.server.vertx.jdbc.BasicJdbcClient; import org.prebid.server.vertx.jdbc.CircuitBreakerSecuredJdbcClient; import org.prebid.server.vertx.jdbc.JdbcClient; diff --git a/src/main/java/org/prebid/server/spring/config/VerticleStarter.java b/src/main/java/org/prebid/server/spring/config/VerticleStarter.java new file mode 100644 index 00000000000..6869ad1a03e --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/VerticleStarter.java @@ -0,0 +1,24 @@ +package org.prebid.server.spring.config; + +import org.prebid.server.vertx.verticles.VerticleDefinition; +import org.prebid.server.vertx.verticles.VerticleDeployer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; +import java.util.List; + +@Configuration +public class VerticleStarter { + + @Autowired + private VerticleDeployer deployer; + + @Autowired + private List verticleDefinitions; + + @PostConstruct + public void startVerticles() { + verticleDefinitions.forEach(deployer::deploy); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java index fc8c7b6a4b1..e88efc0a3f3 100644 --- a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java @@ -13,6 +13,7 @@ import org.prebid.server.spring.config.metrics.MetricsConfiguration; import org.prebid.server.vertx.ContextRunner; import org.prebid.server.vertx.LocalMessageCodec; +import org.prebid.server.vertx.verticles.VerticleDeployer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -25,6 +26,7 @@ public class VertxConfiguration { @Bean Vertx vertx(@Value("${vertx.worker-pool-size}") int workerPoolSize, @Value("${vertx.enable-per-client-endpoint-metrics}") boolean enablePerClientEndpointMetrics) { + final DropwizardMetricsOptions metricsOptions = new DropwizardMetricsOptions() .setEnabled(true) .setRegistryName(MetricsConfiguration.METRIC_REGISTRY_NAME); @@ -60,8 +62,14 @@ BodyHandler bodyHandler(@Value("${vertx.uploads-dir}") String uploadsDir) { return BodyHandler.create(uploadsDir); } + // TODO: Remove this class entirely @Bean ContextRunner contextRunner(Vertx vertx, @Value("${vertx.init-timeout-ms}") long initTimeoutMs) { return new ContextRunner(vertx, initTimeoutMs); } + + @Bean + VerticleDeployer verticleDeployer(Vertx vertx) { + return new VerticleDeployer(vertx); + } } diff --git a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java index 77e0b942817..d6ec05d59bb 100644 --- a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java @@ -7,18 +7,18 @@ import io.prometheus.client.dropwizard.samplebuilder.SampleBuilder; import io.prometheus.client.vertx.MetricsHandler; import io.vertx.core.Vertx; -import io.vertx.core.http.HttpServer; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; +import io.vertx.core.net.SocketAddress; import io.vertx.ext.web.Router; import lombok.Data; import lombok.NoArgsConstructor; import org.prebid.server.metric.CounterType; import org.prebid.server.metric.Metrics; import org.prebid.server.metric.prometheus.NamespaceSubsystemSampleBuilder; -import org.prebid.server.vertx.ContextRunner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.prebid.server.vertx.verticles.VerticleDefinition; +import org.prebid.server.vertx.verticles.server.ServerVerticle; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -26,15 +26,33 @@ import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; -import javax.annotation.PostConstruct; import javax.validation.constraints.NotNull; import java.util.List; +import java.util.function.Supplier; @Configuration +@ConditionalOnProperty(prefix = "metrics.prometheus", name = "enabled", havingValue = "true") public class PrometheusConfiguration { + private static final Logger logger = LoggerFactory.getLogger(PrometheusConfiguration.class); + + // TODO: Decide how to integrate this with ability to serve requests on unix domain socket + @Bean + public VerticleDefinition prometheusHttpServerVerticleDefinition( + PrometheusConfigurationProperties prometheusConfigurationProperties, + @Qualifier("prometheusRouterFactory") Supplier routerFactory, + DropwizardExports dropwizardExports) { + + CollectorRegistry.defaultRegistry.register(dropwizardExports); + + return VerticleDefinition.ofSingleInstance( + () -> new ServerVerticle( + "Prometheus Http Server", + SocketAddress.inetSocketAddress(prometheusConfigurationProperties.getPort(), "0.0.0.0"), + routerFactory)); + } + @Bean - @ConditionalOnBean(PrometheusConfigurationProperties.class) public SampleBuilder sampleBuilder(PrometheusConfigurationProperties prometheusConfigurationProperties, List mapperConfigs) { @@ -44,51 +62,22 @@ public SampleBuilder sampleBuilder(PrometheusConfigurationProperties prometheusC mapperConfigs); } - @Configuration - @ConditionalOnBean(PrometheusConfigurationProperties.class) - public static class PrometheusServerConfiguration { - private static final Logger logger = LoggerFactory.getLogger(PrometheusServerConfiguration.class); - - @Autowired - private ContextRunner contextRunner; - - @Autowired - private Vertx vertx; - - @Autowired - private MetricRegistry metricRegistry; - - @Autowired - private Metrics metrics; - - @Autowired - private PrometheusConfigurationProperties prometheusConfigurationProperties; - - @Autowired - private SampleBuilder sampleBuilder; - - @PostConstruct - public void startPrometheusServer() { - logger.info( - "Starting Prometheus Server on port {0,number,#}", - prometheusConfigurationProperties.getPort()); + @Bean + DropwizardExports dropwizardExports(Metrics metrics, MetricRegistry metricRegistry, SampleBuilder sampleBuilder) { + if (metrics.getCounterType() == CounterType.flushingCounter) { + logger.warn("Prometheus metric system: Metric type is flushingCounter."); + } - if (metrics.getCounterType() == CounterType.flushingCounter) { - logger.warn("Prometheus metric system: Metric type is flushingCounter."); - } + return new DropwizardExports(metricRegistry, sampleBuilder); + } + @Bean("prometheusRouterFactory") + Supplier prometheusRouterFactory(Vertx vertx) { + return () -> { final Router router = Router.router(vertx); router.route("/metrics").handler(new MetricsHandler()); - - CollectorRegistry.defaultRegistry.register(new DropwizardExports(metricRegistry, sampleBuilder)); - - contextRunner.runOnServiceContext(promise -> - vertx.createHttpServer() - .requestHandler(router) - .listen(prometheusConfigurationProperties.getPort(), promise)); - - logger.info("Successfully started Prometheus Server"); - } + return router; + }; } @Data diff --git a/src/main/java/org/prebid/server/spring/config/model/ExternalConversionProperties.java b/src/main/java/org/prebid/server/spring/config/model/ExternalConversionProperties.java index b0206149f0d..914e1bcfc18 100644 --- a/src/main/java/org/prebid/server/spring/config/model/ExternalConversionProperties.java +++ b/src/main/java/org/prebid/server/spring/config/model/ExternalConversionProperties.java @@ -5,7 +5,7 @@ import lombok.Data; import org.prebid.server.json.JacksonMapper; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Min; diff --git a/src/main/java/org/prebid/server/spring/config/server/HttpServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/HttpServerConfiguration.java deleted file mode 100644 index c14dcf9c408..00000000000 --- a/src/main/java/org/prebid/server/spring/config/server/HttpServerConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.prebid.server.spring.config.server; - -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpServer; -import io.vertx.core.http.HttpServerOptions; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.ext.web.Router; -import org.prebid.server.handler.ExceptionHandler; -import org.prebid.server.vertx.ContextRunner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; - -@Configuration -@ConditionalOnProperty(name = "server.http.enabled", havingValue = "true") -public class HttpServerConfiguration { - - private static final Logger logger = LoggerFactory.getLogger(HttpServerConfiguration.class); - - @Autowired - private ContextRunner contextRunner; - - @Autowired - private Vertx vertx; - - @Autowired - private HttpServerOptions httpServerOptions; - - @Autowired - private ExceptionHandler exceptionHandler; - - @Autowired - @Qualifier("router") - private Router router; - - @Value("#{'${http.port:${server.http.port}}'}") - private Integer httpPort; - - // TODO: remove support for properties with http prefix after transition period - @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") - private Integer httpServerNum; - - @PostConstruct - public void startHttpServer() { - logger.info( - "Starting {0} instances of Http Server to serve requests on port {1,number,#}", - httpServerNum, - httpPort); - - contextRunner.runOnNewContext(httpServerNum, promise -> - vertx.createHttpServer(httpServerOptions) - .exceptionHandler(exceptionHandler) - .requestHandler(router) - .listen(httpPort, promise)); - - logger.info("Successfully started {0} instances of Http Server", httpServerNum); - } -} diff --git a/src/main/java/org/prebid/server/spring/config/server/UnixSocketServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/UnixSocketServerConfiguration.java deleted file mode 100644 index 54ae616f496..00000000000 --- a/src/main/java/org/prebid/server/spring/config/server/UnixSocketServerConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.prebid.server.spring.config.server; - -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpServer; -import io.vertx.core.http.HttpServerOptions; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.core.net.SocketAddress; -import io.vertx.ext.web.Router; -import org.prebid.server.handler.ExceptionHandler; -import org.prebid.server.vertx.ContextRunner; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Configuration; - -import javax.annotation.PostConstruct; - -@Configuration -@ConditionalOnProperty(name = "server.unix-socket.enabled", havingValue = "true") -public class UnixSocketServerConfiguration { - - private static final Logger logger = LoggerFactory.getLogger(UnixSocketServerConfiguration.class); - - @Autowired - private ContextRunner contextRunner; - - @Autowired - private Vertx vertx; - - @Autowired - private HttpServerOptions httpServerOptions; - - @Autowired - private ExceptionHandler exceptionHandler; - - @Autowired - @Qualifier("router") - private Router router; - - @Value("${server.unix-socket.path}") - private String socketPath; - - @Value("${server.unix-socket.server-instances}") - private Integer serverNum; - - @PostConstruct - public void startUnixSocketServer() { - logger.info( - "Starting {0} instances of Unix Socket Server to serve requests on socket {1}", - serverNum, - socketPath); - - contextRunner.runOnNewContext(serverNum, promise -> - vertx.createHttpServer(httpServerOptions) - .exceptionHandler(exceptionHandler) - .requestHandler(router) - .listen(SocketAddress.domainSocketAddress(socketPath), promise)); - - logger.info("Successfully started {0} instances of Unix Socket Server", serverNum); - } -} diff --git a/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java similarity index 66% rename from src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java rename to src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java index 1bd29c31a3d..79b10ce632d 100644 --- a/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java @@ -1,4 +1,4 @@ -package org.prebid.server.spring.config; +package org.prebid.server.spring.config.server.admin; import com.codahale.metrics.MetricRegistry; import lombok.Data; @@ -12,18 +12,18 @@ import org.prebid.server.deals.PlannerService; import org.prebid.server.deals.RegisterService; import org.prebid.server.deals.simulation.DealsSimulationAdminHandler; -import org.prebid.server.handler.AccountCacheInvalidationHandler; -import org.prebid.server.handler.CollectedMetricsHandler; -import org.prebid.server.handler.CurrencyRatesHandler; -import org.prebid.server.handler.CustomizedAdminEndpoint; -import org.prebid.server.handler.DealsStatusHandler; -import org.prebid.server.handler.ForceDealsUpdateHandler; -import org.prebid.server.handler.HttpInteractionLogHandler; -import org.prebid.server.handler.LineItemStatusHandler; -import org.prebid.server.handler.LoggerControlKnobHandler; -import org.prebid.server.handler.SettingsCacheNotificationHandler; -import org.prebid.server.handler.TracerLogHandler; -import org.prebid.server.handler.VersionHandler; +import org.prebid.server.handler.admin.AccountCacheInvalidationHandler; +import org.prebid.server.handler.admin.AdminResourceWrapper; +import org.prebid.server.handler.admin.CollectedMetricsHandler; +import org.prebid.server.handler.admin.CurrencyRatesHandler; +import org.prebid.server.handler.admin.DealsStatusHandler; +import org.prebid.server.handler.admin.ForceDealsUpdateHandler; +import org.prebid.server.handler.admin.HttpInteractionLogHandler; +import org.prebid.server.handler.admin.LineItemStatusHandler; +import org.prebid.server.handler.admin.LoggerControlKnobHandler; +import org.prebid.server.handler.admin.SettingsCacheNotificationHandler; +import org.prebid.server.handler.admin.TracerLogHandler; +import org.prebid.server.handler.admin.VersionHandler; import org.prebid.server.json.JacksonMapper; import org.prebid.server.log.CriteriaManager; import org.prebid.server.log.HttpInteractionLogger; @@ -31,6 +31,7 @@ import org.prebid.server.settings.CachingApplicationSettings; import org.prebid.server.settings.SettingsCache; import org.prebid.server.util.VersionInfo; +import org.prebid.server.vertx.verticles.server.admin.AdminResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -41,196 +42,171 @@ import org.springframework.stereotype.Component; import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.function.Predicate; @Configuration public class AdminEndpointsConfiguration { @Bean @ConditionalOnExpression("${admin-endpoints.version.enabled} == true") - CustomizedAdminEndpoint versionEndpoint( + AdminResource versionEndpoint( VersionInfo versionInfo, JacksonMapper mapper, @Value("${admin-endpoints.version.path}") String path, @Value("${admin-endpoints.version.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.version.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.version.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new VersionHandler(versionInfo.getVersion(), versionInfo.getCommitHash(), mapper, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new VersionHandler(versionInfo.getVersion(), versionInfo.getCommitHash(), mapper, path)); } @Bean @ConditionalOnExpression("${currency-converter.external-rates.enabled} == true" + " and ${admin-endpoints.currency-rates.enabled} == true") - CustomizedAdminEndpoint currencyConversionRatesEndpoint( + AdminResource currencyConversionRatesEndpoint( CurrencyConversionService currencyConversionRates, JacksonMapper mapper, @Value("${admin-endpoints.currency-rates.path}") String path, @Value("${admin-endpoints.currency-rates.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.currency-rates.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.currency-rates.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new CurrencyRatesHandler(currencyConversionRates, path, mapper), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new CurrencyRatesHandler(currencyConversionRates, path, mapper)); } @Bean @ConditionalOnExpression("${settings.in-memory-cache.notification-endpoints-enabled:false}" + " and ${admin-endpoints.storedrequest.enabled} == true") - CustomizedAdminEndpoint cacheNotificationEndpoint( + AdminResource cacheNotificationEndpoint( SettingsCache settingsCache, JacksonMapper mapper, @Value("${admin-endpoints.storedrequest.path}") String path, @Value("${admin-endpoints.storedrequest.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.storedrequest.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.storedrequest.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new SettingsCacheNotificationHandler(settingsCache, mapper, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new SettingsCacheNotificationHandler(settingsCache, mapper, path)); } @Bean @ConditionalOnExpression("${settings.in-memory-cache.notification-endpoints-enabled:false}" + " and ${admin-endpoints.storedrequest-amp.enabled} == true") - CustomizedAdminEndpoint ampCacheNotificationEndpoint( + AdminResource ampCacheNotificationEndpoint( SettingsCache ampSettingsCache, JacksonMapper mapper, @Value("${admin-endpoints.storedrequest-amp.path}") String path, @Value("${admin-endpoints.storedrequest-amp.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.storedrequest-amp.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.storedrequest-amp.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new SettingsCacheNotificationHandler(ampSettingsCache, mapper, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new SettingsCacheNotificationHandler(ampSettingsCache, mapper, path)); } @Bean @ConditionalOnExpression("${settings.in-memory-cache.notification-endpoints-enabled:false}" + " and ${admin-endpoints.cache-invalidation.enabled} == true") - CustomizedAdminEndpoint cacheInvalidateNotificationEndpoint( + AdminResource cacheInvalidateNotificationEndpoint( CachingApplicationSettings cachingApplicationSettings, @Value("${admin-endpoints.cache-invalidation.path}") String path, @Value("${admin-endpoints.cache-invalidation.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.cache-invalidation.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.cache-invalidation.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new AccountCacheInvalidationHandler(cachingApplicationSettings, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new AccountCacheInvalidationHandler(cachingApplicationSettings, path)); } @Bean @ConditionalOnExpression("${admin-endpoints.logging-httpinteraction.enabled} == true") - CustomizedAdminEndpoint loggingHttpInteractionEndpoint( + AdminResource loggingHttpInteractionEndpoint( @Value("${logging.http-interaction.max-limit}") int maxLimit, HttpInteractionLogger httpInteractionLogger, @Value("${admin-endpoints.logging-httpinteraction.path}") String path, @Value("${admin-endpoints.logging-httpinteraction.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.logging-httpinteraction.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.logging-httpinteraction.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new HttpInteractionLogHandler(maxLimit, httpInteractionLogger, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new HttpInteractionLogHandler(maxLimit, httpInteractionLogger, path)); } @Bean @ConditionalOnExpression("${admin-endpoints.logging-changelevel.enabled} == true") - CustomizedAdminEndpoint loggingChangeLevelEndpoint( + AdminResource loggingChangeLevelEndpoint( @Value("${logging.change-level.max-duration-ms}") long maxDuration, LoggerControlKnob loggerControlKnob, @Value("${admin-endpoints.logging-changelevel.path}") String path, @Value("${admin-endpoints.logging-changelevel.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.logging-changelevel.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.logging-changelevel.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new LoggerControlKnobHandler(maxDuration, loggerControlKnob, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new LoggerControlKnobHandler(maxDuration, loggerControlKnob, path)); } @Bean @ConditionalOnProperty(prefix = "admin-endpoints.tracelog", name = "enabled", havingValue = "true") - CustomizedAdminEndpoint tracerLogEndpoint( + AdminResource tracerLogEndpoint( CriteriaManager criteriaManager, @Value("${admin-endpoints.tracelog.path}") String path, @Value("${admin-endpoints.tracelog.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.tracelog.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.tracelog.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( - path, - new TracerLogHandler(criteriaManager), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + return new AdminResourceWrapper(path, isOnApplicationPort, isProtected, new TracerLogHandler(criteriaManager)); } @Bean @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.deals-status.enabled} == true") - CustomizedAdminEndpoint dealsStatusEndpoint( + AdminResource dealsStatusEndpoint( DeliveryProgressService deliveryProgressService, JacksonMapper mapper, @Value("${admin-endpoints.deals-status.path}") String path, @Value("${admin-endpoints.deals-status.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.deals-status.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.deals-status.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( - path, - new DealsStatusHandler(deliveryProgressService, mapper), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + return new AdminResourceWrapper( + path, isOnApplicationPort, isProtected, new DealsStatusHandler(deliveryProgressService, mapper)); } @Bean @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.lineitem-status.enabled} == true") - CustomizedAdminEndpoint lineItemStatusEndpoint( + AdminResource lineItemStatusEndpoint( DeliveryProgressService deliveryProgressService, JacksonMapper mapper, @Value("${admin-endpoints.lineitem-status.path}") String path, @Value("${admin-endpoints.lineitem-status.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.lineitem-status.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.lineitem-status.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new LineItemStatusHandler(deliveryProgressService, mapper, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new LineItemStatusHandler(deliveryProgressService, mapper, path)); } @Bean @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.force-deals-update.enabled} == true") - CustomizedAdminEndpoint forceDealsUpdateEndpoint( + AdminResource forceDealsUpdateEndpoint( DeliveryStatsService deliveryStatsService, PlannerService plannerService, RegisterService registerService, @@ -239,11 +215,12 @@ CustomizedAdminEndpoint forceDealsUpdateEndpoint( LineItemService lineItemService, @Value("${admin-endpoints.force-deals-update.path}") String path, @Value("${admin-endpoints.force-deals-update.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.force-deals-update.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.force-deals-update.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, + isOnApplicationPort, + isProtected, new ForceDealsUpdateHandler( deliveryStatsService, plannerService, @@ -251,46 +228,59 @@ CustomizedAdminEndpoint forceDealsUpdateEndpoint( alertHttpService, deliveryProgressService, lineItemService, - path), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + path)); } @Bean @ConditionalOnExpression("${deals.enabled} == true and ${deals.simulation.enabled} == true" + " and ${admin-endpoints.e2eadmin.enabled} == true") - CustomizedAdminEndpoint dealsSimulationAdminEndpoint( + AdminResource dealsSimulationAdminEndpoint( DealsSimulationAdminHandler dealsSimulationAdminHandler, @Value("${admin-endpoints.e2eadmin.path}") String path, @Value("${admin-endpoints.e2eadmin.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.e2eadmin.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.e2eadmin.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( - path, - dealsSimulationAdminHandler, - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + return new AdminResourceWrapper(path, isOnApplicationPort, isProtected, dealsSimulationAdminHandler); } @Bean @ConditionalOnExpression("${admin-endpoints.collected-metrics.enabled} == true") - CustomizedAdminEndpoint collectedMetricsAdminEndpoint( + AdminResource collectedMetricsAdminEndpoint( MetricRegistry metricRegistry, JacksonMapper mapper, @Value("${admin-endpoints.collected-metrics.path}") String path, @Value("${admin-endpoints.collected-metrics.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.collected-metrics.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { + @Value("${admin-endpoints.collected-metrics.protected}") boolean isProtected) { - return new CustomizedAdminEndpoint( + return new AdminResourceWrapper( path, - new CollectedMetricsHandler(metricRegistry, mapper, path), isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); + isProtected, + new CollectedMetricsHandler(metricRegistry, mapper, path)); + } + + @Bean(name = "applicationPortAdminResourcesBinder") + AdminResourcesBinder applicationPortAdminResourcesBinder( + @Autowired(required = false) Map adminEndpointCredentials, + List resources) { + + final List applicationPortAdminResources = resources.stream() + .filter(AdminResource::isOnApplicationPort) + .toList(); + + return new AdminResourcesBinder(adminEndpointCredentials, applicationPortAdminResources); + } + + @Bean(name = "adminPortAdminResourcesBinder") + AdminResourcesBinder adminPortAdminResourcesBinder( + @Autowired(required = false) Map adminEndpointCredentials, + List resources) { + + final List adminPortAdminResources = resources.stream() + .filter(Predicate.not(AdminResource::isOnApplicationPort)) + .toList(); + + return new AdminResourcesBinder(adminEndpointCredentials, adminPortAdminResources); } @Bean diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java new file mode 100644 index 00000000000..27914fa38d3 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java @@ -0,0 +1,40 @@ +package org.prebid.server.spring.config.server.admin; + +import io.vertx.ext.auth.AuthProvider; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BasicAuthHandler; +import org.prebid.server.vertx.verticles.server.admin.AdminResource; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class AdminResourcesBinder { + + private final Map credentials; + private final List resources; + + public AdminResourcesBinder(Map credentials, List resources) { + this.credentials = credentials; + this.resources = Objects.requireNonNull(resources); + } + + public void bind(Router router) { + resources.forEach(resource -> bindResource(router, resource)); + } + + private void bindResource(Router router, AdminResource resource) { + final String path = resource.path(); + + if (resource.isSecured()) { + if (credentials == null) { + throw new IllegalArgumentException("Credentials for admin endpoint is empty."); + } + + final AuthProvider authProvider = new AdminServerAuthProvider(credentials); + router.route(path).handler(BasicAuthHandler.create(authProvider)).handler(resource); + } else { + router.route(path).handler(resource); + } + } +} diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java new file mode 100644 index 00000000000..15629694ba0 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java @@ -0,0 +1,40 @@ +package org.prebid.server.spring.config.server.admin; + +import io.vertx.core.AsyncResult; +import io.vertx.core.Future; +import io.vertx.core.Handler; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.auth.AuthProvider; +import io.vertx.ext.auth.User; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; +import java.util.Objects; + +public class AdminServerAuthProvider implements AuthProvider { + + private final Map credentials; + + public AdminServerAuthProvider(Map credentials) { + this.credentials = credentials; + } + + @Override + public void authenticate(JsonObject authInfo, Handler> resultHandler) { + if (MapUtils.isEmpty(credentials)) { + resultHandler.handle(Future.failedFuture("Credentials not set in configuration.")); + return; + } + + final String requestUsername = authInfo.getString("username"); + final String requestPassword = StringUtils.chomp(authInfo.getString("password")); + + final String storedPassword = credentials.get(requestUsername); + if (StringUtils.isNotBlank(requestPassword) && Objects.equals(storedPassword, requestPassword)) { + resultHandler.handle(Future.succeededFuture()); + } else { + resultHandler.handle(Future.failedFuture("No such user, or password incorrect.")); + } + } +} diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java new file mode 100644 index 00000000000..25f0a2f80b8 --- /dev/null +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java @@ -0,0 +1,47 @@ +package org.prebid.server.spring.config.server.admin; + +import io.vertx.core.Vertx; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.BodyHandler; +import org.prebid.server.vertx.verticles.VerticleDefinition; +import org.prebid.server.vertx.verticles.server.ServerVerticle; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.function.Supplier; + +@Configuration +@ConditionalOnProperty(prefix = "admin", name = "port") +public class AdminServerConfiguration { + + @Bean("adminPortAdminServerRouterFactory") + Supplier adminPortAdminServerRouterFactory( + Vertx vertx, + @Qualifier("adminPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, + BodyHandler bodyHandler) { + + return () -> { + final Router router = Router.router(vertx); + router.route().handler(bodyHandler); + + adminResourcesBinder.bind(router); + return router; + }; + } + + @Bean + VerticleDefinition adminPortAdminHttpServerVerticleDefinition( + @Qualifier("adminPortAdminServerRouterFactory") Supplier routerFactory, + @Value("${admin.port}") int port) { + + return VerticleDefinition.ofSingleInstance( + () -> new ServerVerticle( + "Admin Http Server", + SocketAddress.inetSocketAddress(port, "0.0.0.0"), + routerFactory)); + } +} diff --git a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java similarity index 79% rename from src/main/java/org/prebid/server/spring/config/WebConfiguration.java rename to src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java index a80f4163670..7f28940662c 100644 --- a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java @@ -1,9 +1,11 @@ -package org.prebid.server.spring.config; +package org.prebid.server.spring.config.server.application; +import io.vertx.core.Verticle; import io.vertx.core.Vertx; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.net.JksOptions; +import io.vertx.core.net.SocketAddress; import io.vertx.ext.web.Router; import io.vertx.ext.web.handler.BodyHandler; import io.vertx.ext.web.handler.CorsHandler; @@ -28,7 +30,6 @@ import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.handler.BidderParamHandler; import org.prebid.server.handler.CookieSyncHandler; -import org.prebid.server.handler.CustomizedAdminEndpoint; import org.prebid.server.handler.ExceptionHandler; import org.prebid.server.handler.GetuidsHandler; import org.prebid.server.handler.NoCacheHandler; @@ -49,11 +50,17 @@ import org.prebid.server.optout.GoogleRecaptchaVerifier; import org.prebid.server.privacy.HostVendorTcfDefinerService; import org.prebid.server.settings.ApplicationSettings; +import org.prebid.server.spring.config.server.admin.AdminResourcesBinder; import org.prebid.server.util.HttpUtil; import org.prebid.server.validation.BidderParamValidator; import org.prebid.server.version.PrebidVersionProvider; +import org.prebid.server.vertx.verticles.VerticleDefinition; +import org.prebid.server.vertx.verticles.server.ServerVerticle; +import org.prebid.server.vertx.verticles.server.application.ApplicationResource; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -65,9 +72,11 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Supplier; @Configuration -public class WebConfiguration { +public class ApplicationServerConfiguration { @Value("${logging.sampling-rate:0.01}") private double logSamplingRate; @@ -75,6 +84,32 @@ public class WebConfiguration { @Autowired private Vertx vertx; + @Bean + @ConditionalOnProperty(name = "server.http.enabled", havingValue = "true") + VerticleDefinition httpApplicationServerVerticleDefinition( + @Value("#{'${http.port:${server.http.port}}'}") Integer port, + @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") Integer instances, + BiFunction applicationVerticleFactory) { + + return VerticleDefinition.ofMultiInstance( + () -> applicationVerticleFactory.apply( + "Application Http Server", SocketAddress.inetSocketAddress(port, "0.0.0.0")), + instances); + } + + @Bean + @ConditionalOnProperty(name = "server.unix-socket.enabled", havingValue = "true") + VerticleDefinition unixSocketApplicationServerVerticleDefinition( + @Value("${server.unix-socket.path}") String path, + @Value("${server.unix-socket.server-instances}") Integer instances, + BiFunction applicationVerticleFactory) { + + return VerticleDefinition.ofMultiInstance( + () -> applicationVerticleFactory.apply( + "Application Unix Socket Server", SocketAddress.domainSocketAddress(path)), + instances); + } + @Bean // TODO: remove support for properties with http prefix after transition period HttpServerOptions httpServerOptions( @Value("#{'${http.max-headers-size:${server.max-headers-size:}}'}") int maxHeaderSize, @@ -109,53 +144,42 @@ ExceptionHandler exceptionHandler(Metrics metrics) { return ExceptionHandler.create(metrics); } - @Bean("router") - Router router(BodyHandler bodyHandler, - NoCacheHandler noCacheHandler, - CorsHandler corsHandler, - org.prebid.server.handler.openrtb2.AuctionHandler openrtbAuctionHandler, - AmpHandler openrtbAmpHandler, - VideoHandler openrtbVideoHandler, - StatusHandler statusHandler, - CookieSyncHandler cookieSyncHandler, - SetuidHandler setuidHandler, - GetuidsHandler getuidsHandler, - VtrackHandler vtrackHandler, - OptoutHandler optoutHandler, - BidderParamHandler bidderParamHandler, - BiddersHandler biddersHandler, - BidderDetailsHandler bidderDetailsHandler, - NotificationEventHandler notificationEventHandler, - List customizedAdminEndpoints, - StaticHandler staticHandler) { - - final Router router = Router.router(vertx); - router.route().handler(bodyHandler); - router.route().handler(noCacheHandler); - router.route().handler(corsHandler); - router.post("/openrtb2/auction").handler(openrtbAuctionHandler); - router.get("/openrtb2/amp").handler(openrtbAmpHandler); - router.post("/openrtb2/video").handler(openrtbVideoHandler); - router.get("/status").handler(statusHandler); - router.post("/cookie_sync").handler(cookieSyncHandler); - router.get("/setuid").handler(setuidHandler); - router.get("/getuids").handler(getuidsHandler); - router.post("/vtrack").handler(vtrackHandler); - router.post("/optout").handler(optoutHandler); - router.get("/optout").handler(optoutHandler); - router.get("/bidders/params").handler(bidderParamHandler); - router.get("/info/bidders").handler(biddersHandler); - router.get("/info/bidders/:bidderName").handler(bidderDetailsHandler); - router.get("/event").handler(notificationEventHandler); - - customizedAdminEndpoints.stream() - .filter(CustomizedAdminEndpoint::isOnApplicationPort) - .forEach(customizedAdminEndpoint -> customizedAdminEndpoint.router(router)); - - router.get("/static/*").handler(staticHandler); - router.get("/").handler(staticHandler); // serves index.html by default - - return router; + @Bean + BiFunction applicationVerticleFactory( + @Qualifier("applicationServerRouterFactory") Supplier routerFactory, + HttpServerOptions httpServerOptions, + ExceptionHandler exceptionHandler) { + + return (name, address) -> new ServerVerticle( + name, httpServerOptions, address, routerFactory, exceptionHandler); + } + + @Bean("applicationServerRouterFactory") + Supplier applicationServerRouterFactory( + BodyHandler bodyHandler, + NoCacheHandler noCacheHandler, + CorsHandler corsHandler, + List resources, + @Qualifier("applicationPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, + StaticHandler staticHandler) { + + return () -> { + final Router router = Router.router(vertx); + router.route().handler(bodyHandler); + router.route().handler(noCacheHandler); + router.route().handler(corsHandler); + + resources.forEach(resource -> + resource.endpoints().forEach(endpoint -> + router.route(endpoint.getMethod(), endpoint.getPath()).handler(resource))); + + adminResourcesBinder.bind(router); + + router.get("/static/*").handler(staticHandler); + router.get("/").handler(staticHandler); // serves index.html by default + + return router; + }; } @Bean diff --git a/src/main/java/org/prebid/server/vertx/ContextRunner.java b/src/main/java/org/prebid/server/vertx/ContextRunner.java index ad18e40476c..7a61d516419 100644 --- a/src/main/java/org/prebid/server/vertx/ContextRunner.java +++ b/src/main/java/org/prebid/server/vertx/ContextRunner.java @@ -7,7 +7,6 @@ import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; -import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -23,56 +22,44 @@ public class ContextRunner { private static final Logger logger = LoggerFactory.getLogger(ContextRunner.class); - private final Vertx vertx; private final long timeoutMs; private final Context serviceContext; public ContextRunner(Vertx vertx, long timeoutMs) { - this.vertx = Objects.requireNonNull(vertx); this.timeoutMs = timeoutMs; this.serviceContext = vertx.getOrCreateContext(); } - /** - * Runs provided action specified number of times each in a new context. This method is handy for - * running several instances of {@link io.vertx.core.http.HttpServer} on different event loop threads. - */ - public void runOnNewContext(int times, Handler> action) { - runOnContext(vertx::getOrCreateContext, times, action); - } - /** * Runs provided action on a dedicated service context. */ public void runOnServiceContext(Handler> action) { - runOnContext(() -> serviceContext, 1, action); + runOnContext(() -> serviceContext, action); } - private void runOnContext(Supplier contextFactory, int times, Handler> action) { - final CountDownLatch completionLatch = new CountDownLatch(times); + private void runOnContext(Supplier contextFactory, Handler> action) { + final CountDownLatch completionLatch = new CountDownLatch(1); final AtomicBoolean actionFailed = new AtomicBoolean(false); - for (int i = 0; i < times; i++) { - final Context context = contextFactory.get(); + final Context context = contextFactory.get(); - final Promise promise = Promise.promise(); - promise.future().onComplete(ar -> { - if (ar.failed()) { - logger.fatal("Fatal error occurred while running action on Vertx context", ar.cause()); - actionFailed.compareAndSet(false, true); - } - completionLatch.countDown(); - }); + final Promise promise = Promise.promise(); + promise.future().onComplete(ar -> { + if (ar.failed()) { + logger.fatal("Fatal error occurred while running action on Vertx context", ar.cause()); + actionFailed.compareAndSet(false, true); + } + completionLatch.countDown(); + }); - context.runOnContext(v -> { - try { - action.handle(promise); - } catch (RuntimeException e) { - promise.fail(e); - } - }); - } + context.runOnContext(v -> { + try { + action.handle(promise); + } catch (RuntimeException e) { + promise.fail(e); + } + }); try { if (!completionLatch.await(timeoutMs, TimeUnit.MILLISECONDS)) { diff --git a/src/main/java/org/prebid/server/vertx/http/BasicHttpClient.java b/src/main/java/org/prebid/server/vertx/httpclient/BasicHttpClient.java similarity index 97% rename from src/main/java/org/prebid/server/vertx/http/BasicHttpClient.java rename to src/main/java/org/prebid/server/vertx/httpclient/BasicHttpClient.java index dfeb5c4a32e..bfdd4337fc1 100644 --- a/src/main/java/org/prebid/server/vertx/http/BasicHttpClient.java +++ b/src/main/java/org/prebid/server/vertx/httpclient/BasicHttpClient.java @@ -1,4 +1,4 @@ -package org.prebid.server.vertx.http; +package org.prebid.server.vertx.httpclient; import io.vertx.core.Future; import io.vertx.core.MultiMap; @@ -9,7 +9,7 @@ import io.vertx.core.http.HttpHeaders; import io.vertx.core.http.HttpMethod; import org.prebid.server.exception.PreBidException; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.Objects; import java.util.concurrent.TimeoutException; diff --git a/src/main/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClient.java b/src/main/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClient.java similarity index 98% rename from src/main/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClient.java rename to src/main/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClient.java index 767398b37ad..ad957912dac 100644 --- a/src/main/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClient.java +++ b/src/main/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClient.java @@ -1,4 +1,4 @@ -package org.prebid.server.vertx.http; +package org.prebid.server.vertx.httpclient; import com.github.benmanes.caffeine.cache.Caffeine; import io.vertx.core.Future; @@ -11,7 +11,7 @@ import org.prebid.server.log.ConditionalLogger; import org.prebid.server.metric.Metrics; import org.prebid.server.vertx.CircuitBreaker; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.net.MalformedURLException; import java.net.URL; diff --git a/src/main/java/org/prebid/server/vertx/http/HttpClient.java b/src/main/java/org/prebid/server/vertx/httpclient/HttpClient.java similarity index 94% rename from src/main/java/org/prebid/server/vertx/http/HttpClient.java rename to src/main/java/org/prebid/server/vertx/httpclient/HttpClient.java index d448f58b4bb..467cd43157c 100644 --- a/src/main/java/org/prebid/server/vertx/http/HttpClient.java +++ b/src/main/java/org/prebid/server/vertx/httpclient/HttpClient.java @@ -1,9 +1,9 @@ -package org.prebid.server.vertx.http; +package org.prebid.server.vertx.httpclient; import io.vertx.core.Future; import io.vertx.core.MultiMap; import io.vertx.core.http.HttpMethod; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; /** * Interface describes HTTP interactions. diff --git a/src/main/java/org/prebid/server/vertx/http/model/HttpClientResponse.java b/src/main/java/org/prebid/server/vertx/httpclient/model/HttpClientResponse.java similarity index 87% rename from src/main/java/org/prebid/server/vertx/http/model/HttpClientResponse.java rename to src/main/java/org/prebid/server/vertx/httpclient/model/HttpClientResponse.java index 654d987d8b4..7ed9056e62e 100644 --- a/src/main/java/org/prebid/server/vertx/http/model/HttpClientResponse.java +++ b/src/main/java/org/prebid/server/vertx/httpclient/model/HttpClientResponse.java @@ -1,4 +1,4 @@ -package org.prebid.server.vertx.http.model; +package org.prebid.server.vertx.httpclient.model; import io.vertx.core.MultiMap; import lombok.AllArgsConstructor; diff --git a/src/main/java/org/prebid/server/vertx/jdbc/BasicJdbcClient.java b/src/main/java/org/prebid/server/vertx/jdbc/BasicJdbcClient.java index 71fd24bd166..305740a4bf4 100644 --- a/src/main/java/org/prebid/server/vertx/jdbc/BasicJdbcClient.java +++ b/src/main/java/org/prebid/server/vertx/jdbc/BasicJdbcClient.java @@ -4,6 +4,7 @@ import io.vertx.core.Future; import io.vertx.core.Promise; import io.vertx.core.Vertx; +import io.vertx.core.eventbus.EventBus; import io.vertx.core.json.JsonArray; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java new file mode 100644 index 00000000000..f9b2703f318 --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java @@ -0,0 +1,26 @@ +package org.prebid.server.vertx.verticles; + +import io.vertx.core.Verticle; +import lombok.Value; + +import java.util.function.Supplier; + +@Value(staticConstructor = "of") +public class VerticleDefinition { + + Supplier factory; + + int amount; + + public static VerticleDefinition ofZeroInstances() { + return of(null, 0); + } + + public static VerticleDefinition ofSingleInstance(Supplier factory) { + return of(factory, 1); + } + + public static VerticleDefinition ofMultiInstance(Supplier factory, int amount) { + return of(factory, amount); + } +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java new file mode 100644 index 00000000000..73b70390e3f --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java @@ -0,0 +1,65 @@ +package org.prebid.server.vertx.verticles; + +import io.vertx.core.DeploymentOptions; +import io.vertx.core.Vertx; + +import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class VerticleDeployer { + + private static final int TIMEOUT_MILLIS = 5000; + + private final Vertx vertx; + + public VerticleDeployer(Vertx vertx) { + this.vertx = Objects.requireNonNull(vertx); + } + + public void deploy(VerticleDefinition definition) { + final int amount = definition.getAmount(); + if (amount <= 0) { + return; + } + + final CountDownLatch latch = new CountDownLatch(1); + final AtomicReference failureThrowable = new AtomicReference<>(); + final AtomicBoolean failed = new AtomicBoolean(); + + final DeploymentOptions deploymentOptions = new DeploymentOptions(); + deploymentOptions.setInstances(amount); + + vertx.deployVerticle(definition.getFactory(), deploymentOptions, result -> { + if (result.failed()) { + failureThrowable.set(result.cause()); + failed.set(true); + } + + latch.countDown(); + }); + + + try { + if (!latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Action has not completed within defined timeout %d ms".formatted(TIMEOUT_MILLIS)); + } + + if (failed.get()) { + final Throwable cause = failureThrowable.get(); + if (cause != null) { + throw new RuntimeException(cause); + } else { + throw new RuntimeException("Action failed"); + } + } + } catch ( + InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while waiting for action to complete", e); + } + } +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/HttpEndpoint.java b/src/main/java/org/prebid/server/vertx/verticles/server/HttpEndpoint.java new file mode 100644 index 00000000000..811f6a1aa1a --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/server/HttpEndpoint.java @@ -0,0 +1,12 @@ +package org.prebid.server.vertx.verticles.server; + +import io.vertx.core.http.HttpMethod; +import lombok.Value; + +@Value(staticConstructor = "of") +public class HttpEndpoint { + + HttpMethod method; + + String path; +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java new file mode 100644 index 00000000000..adb120db7c5 --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -0,0 +1,74 @@ +package org.prebid.server.vertx.verticles.server; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.AsyncResult; +import io.vertx.core.Context; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpServer; +import io.vertx.core.http.HttpServerOptions; +import io.vertx.core.logging.Logger; +import io.vertx.core.logging.LoggerFactory; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.web.Router; +import org.apache.commons.lang3.ObjectUtils; +import org.prebid.server.handler.ExceptionHandler; + +import java.util.Objects; +import java.util.function.Supplier; + +public class ServerVerticle extends AbstractVerticle { + + private static final Logger logger = LoggerFactory.getLogger(ServerVerticle.class); + + private final String name; + private final HttpServerOptions serverOptions; + private final SocketAddress address; + private final Router router; + private final ExceptionHandler exceptionHandler; + + public ServerVerticle(String name, + HttpServerOptions serverOptions, + SocketAddress address, + Supplier routerFactory, + ExceptionHandler exceptionHandler) { + + this.name = Objects.requireNonNull(name); + this.serverOptions = Objects.requireNonNull(serverOptions); + this.address = Objects.requireNonNull(address); + this.router = Objects.requireNonNull(routerFactory.get()); + this.exceptionHandler = Objects.requireNonNull(exceptionHandler); + } + + public ServerVerticle(String name, SocketAddress address, Supplier routerFactory) { + this.name = Objects.requireNonNull(name); + this.serverOptions = null; + this.address = Objects.requireNonNull(address); + this.router = Objects.requireNonNull(routerFactory.get()); + this.exceptionHandler = null; + } + + @Override + public void init(Vertx vertx, Context context) { + final HttpServerOptions httpServerOptions = ObjectUtils.defaultIfNull(serverOptions, new HttpServerOptions()); + final HttpServer server = vertx.createHttpServer(httpServerOptions) + .requestHandler(router); + + if (exceptionHandler != null) { + server.exceptionHandler(exceptionHandler); + } + + server.listen(address, this::onServerStarted); + } + + private void onServerStarted(AsyncResult result) { + if (result.succeeded()) { + logger.info( + "Successfully started {0} instance on address: {1}, thread: {2}", + name, + address, + Thread.currentThread().getName()); + } else { + throw new RuntimeException(result.cause()); + } + } +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/admin/AdminResource.java b/src/main/java/org/prebid/server/vertx/verticles/server/admin/AdminResource.java new file mode 100644 index 00000000000..0f901ec1167 --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/server/admin/AdminResource.java @@ -0,0 +1,13 @@ +package org.prebid.server.vertx.verticles.server.admin; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; + +public interface AdminResource extends Handler { + + String path(); + + boolean isOnApplicationPort(); + + boolean isSecured(); +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/application/ApplicationResource.java b/src/main/java/org/prebid/server/vertx/verticles/server/application/ApplicationResource.java new file mode 100644 index 00000000000..ee352dc9c99 --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/server/application/ApplicationResource.java @@ -0,0 +1,12 @@ +package org.prebid.server.vertx.verticles.server.application; + +import io.vertx.core.Handler; +import io.vertx.ext.web.RoutingContext; +import org.prebid.server.vertx.verticles.server.HttpEndpoint; + +import java.util.List; + +public interface ApplicationResource extends Handler { + + List endpoints(); +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0cb375abe32..31a899df69d 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -19,14 +19,16 @@ server: http: enabled: true port: 8080 - server-instances: 1 + server-instances: 10 admin: port: 8060 admin-endpoints: + credentials: + admin: admin version: - enabled: false + enabled: true path: /version - on-application-port: false + on-application-port: true protected: true currency-rates: enabled: false diff --git a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporterTest.java b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporterTest.java index d12201b0df4..69f1f46a4af 100644 --- a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporterTest.java +++ b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackAnalyticsReporterTest.java @@ -19,8 +19,8 @@ import org.prebid.server.analytics.reporter.pubstack.model.PubstackAnalyticsProperties; import org.prebid.server.analytics.reporter.pubstack.model.PubstackConfig; import org.prebid.server.exception.PreBidException; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; diff --git a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java index acc7a1cd113..3bd52b9cede 100644 --- a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java +++ b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java @@ -19,8 +19,8 @@ import org.prebid.server.deals.model.DeepDebugLog; import org.prebid.server.deals.model.TxnLog; import org.prebid.server.execution.Timeout; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import org.springframework.test.util.ReflectionTestUtils; import java.util.Set; diff --git a/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java b/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java index 8714a70c42c..1dba1ecccc9 100644 --- a/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java +++ b/src/test/java/org/prebid/server/auction/CurrencyConversionServiceTest.java @@ -21,8 +21,8 @@ import org.prebid.server.proto.openrtb.ext.request.ExtRequestCurrency; import org.prebid.server.proto.openrtb.ext.request.ExtRequestPrebid; import org.prebid.server.spring.config.model.ExternalConversionProperties; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.math.BigDecimal; import java.time.Clock; diff --git a/src/test/java/org/prebid/server/bidder/BidderErrorNotifierTest.java b/src/test/java/org/prebid/server/bidder/BidderErrorNotifierTest.java index f8d4f1162dc..dd7526ce0b9 100644 --- a/src/test/java/org/prebid/server/bidder/BidderErrorNotifierTest.java +++ b/src/test/java/org/prebid/server/bidder/BidderErrorNotifierTest.java @@ -15,8 +15,8 @@ import org.prebid.server.bidder.model.BidderError; import org.prebid.server.bidder.model.HttpRequest; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.concurrent.TimeoutException; diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 6a5d68a4762..927c44302e8 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -40,8 +40,8 @@ import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.time.Instant; diff --git a/src/test/java/org/prebid/server/cache/CacheServiceTest.java b/src/test/java/org/prebid/server/cache/CacheServiceTest.java index a2d56eb0a79..a097e40a08d 100644 --- a/src/test/java/org/prebid/server/cache/CacheServiceTest.java +++ b/src/test/java/org/prebid/server/cache/CacheServiceTest.java @@ -43,8 +43,8 @@ import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.vast.VastModifier; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.IOException; import java.net.MalformedURLException; diff --git a/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java b/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java index 3dd501bed23..c8055e2b826 100644 --- a/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java +++ b/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java @@ -16,7 +16,7 @@ import org.prebid.server.deals.model.AlertProxyProperties; import org.prebid.server.deals.model.AlertSource; import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import java.time.Clock; import java.time.Instant; diff --git a/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java b/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java index 07badbbc5c3..09c372a4ad8 100644 --- a/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java +++ b/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java @@ -20,8 +20,8 @@ import org.prebid.server.deals.proto.report.DeliveryProgressReportBatch; import org.prebid.server.deals.proto.report.LineItemStatus; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import org.springframework.test.util.ReflectionTestUtils; import java.io.BufferedReader; diff --git a/src/test/java/org/prebid/server/deals/PlannerServiceTest.java b/src/test/java/org/prebid/server/deals/PlannerServiceTest.java index 940f6c3628c..430ad42bfe1 100644 --- a/src/test/java/org/prebid/server/deals/PlannerServiceTest.java +++ b/src/test/java/org/prebid/server/deals/PlannerServiceTest.java @@ -21,8 +21,8 @@ import org.prebid.server.deals.proto.Token; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.math.BigDecimal; import java.time.Clock; diff --git a/src/test/java/org/prebid/server/deals/RegisterServiceTest.java b/src/test/java/org/prebid/server/deals/RegisterServiceTest.java index 1f65a78fd79..179349078b1 100644 --- a/src/test/java/org/prebid/server/deals/RegisterServiceTest.java +++ b/src/test/java/org/prebid/server/deals/RegisterServiceTest.java @@ -25,8 +25,8 @@ import org.prebid.server.deals.proto.report.DeliveryProgressReport; import org.prebid.server.exception.PreBidException; import org.prebid.server.health.HealthMonitor; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.math.BigDecimal; import java.time.Clock; diff --git a/src/test/java/org/prebid/server/deals/UserServiceTest.java b/src/test/java/org/prebid/server/deals/UserServiceTest.java index 241e00d99d4..378c9c79227 100644 --- a/src/test/java/org/prebid/server/deals/UserServiceTest.java +++ b/src/test/java/org/prebid/server/deals/UserServiceTest.java @@ -35,8 +35,8 @@ import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.IOException; import java.time.Clock; diff --git a/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java b/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java index 3287ca2e1a1..ac63a606841 100644 --- a/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java @@ -33,7 +33,7 @@ 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.response.BidType; -import org.prebid.server.vertx.http.HttpClient; +import org.prebid.server.vertx.httpclient.HttpClient; import org.springframework.test.util.ReflectionTestUtils; import java.math.BigDecimal; diff --git a/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java b/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java index 844baf28742..227317d62e9 100644 --- a/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java +++ b/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java @@ -15,8 +15,8 @@ import org.prebid.server.deals.model.PlannerProperties; import org.prebid.server.deals.proto.LineItemMetaData; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import org.springframework.test.util.ReflectionTestUtils; import java.time.Clock; diff --git a/src/test/java/org/prebid/server/floors/PriceFloorFetcherTest.java b/src/test/java/org/prebid/server/floors/PriceFloorFetcherTest.java index f84de82dbed..b0e5365f180 100644 --- a/src/test/java/org/prebid/server/floors/PriceFloorFetcherTest.java +++ b/src/test/java/org/prebid/server/floors/PriceFloorFetcherTest.java @@ -28,8 +28,8 @@ import org.prebid.server.settings.model.AccountAuctionConfig; import org.prebid.server.settings.model.AccountPriceFloorsConfig; import org.prebid.server.settings.model.AccountPriceFloorsFetchConfig; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.math.BigDecimal; import java.util.concurrent.TimeoutException; diff --git a/src/test/java/org/prebid/server/handler/AccountCacheInvalidationHandlerTest.java b/src/test/java/org/prebid/server/handler/AccountCacheInvalidationHandlerTest.java index ccde1aa16f2..9a6f07d7a83 100644 --- a/src/test/java/org/prebid/server/handler/AccountCacheInvalidationHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/AccountCacheInvalidationHandlerTest.java @@ -10,6 +10,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.AccountCacheInvalidationHandler; import org.prebid.server.settings.CachingApplicationSettings; import static org.mockito.ArgumentMatchers.any; diff --git a/src/test/java/org/prebid/server/handler/CustomizedAdminEndpointTest.java b/src/test/java/org/prebid/server/handler/AdminResourceWrapperTest.java similarity index 91% rename from src/test/java/org/prebid/server/handler/CustomizedAdminEndpointTest.java rename to src/test/java/org/prebid/server/handler/AdminResourceWrapperTest.java index 65a54d77a4c..1e7debd9738 100644 --- a/src/test/java/org/prebid/server/handler/CustomizedAdminEndpointTest.java +++ b/src/test/java/org/prebid/server/handler/AdminResourceWrapperTest.java @@ -12,6 +12,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.AdminResourceWrapper; import java.util.Collections; import java.util.Map; @@ -23,14 +24,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -public class CustomizedAdminEndpointTest extends VertxTest { +public class AdminResourceWrapperTest extends VertxTest { private static final String PATH = "test"; @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - private CustomizedAdminEndpoint target; + private AdminResourceWrapper target; @Mock private Handler handler; @@ -45,7 +46,7 @@ public class CustomizedAdminEndpointTest extends VertxTest { @Before public void setUp() { - target = new CustomizedAdminEndpoint(PATH, handler, true, true); + target = new AdminResourceWrapper(PATH, handler, true, true); given(router.route(any())).willReturn(route); given(route.handler(any())).willReturn(route); @@ -96,7 +97,7 @@ public void routeShouldCallRouterWhenProtectedAndNoCredentials() { @Test public void routeShouldCallRouterWhenNotProtectedAndCredentialsProvided() { // given - target = new CustomizedAdminEndpoint(PATH, handler, true, false); + target = new AdminResourceWrapper(PATH, handler, true, false); target.withCredentials(adminEndpointCredentials); // when diff --git a/src/test/java/org/prebid/server/handler/CollectedMetricsHandlerTest.java b/src/test/java/org/prebid/server/handler/CollectedMetricsHandlerTest.java index 59e3bdb0bf7..342c4b33ad0 100644 --- a/src/test/java/org/prebid/server/handler/CollectedMetricsHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/CollectedMetricsHandlerTest.java @@ -17,6 +17,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.CollectedMetricsHandler; import org.prebid.server.util.HttpUtil; import java.util.Collections; diff --git a/src/test/java/org/prebid/server/handler/CurrencyRatesHandlerTest.java b/src/test/java/org/prebid/server/handler/CurrencyRatesHandlerTest.java index bce27ba876a..fabb4bcb61b 100644 --- a/src/test/java/org/prebid/server/handler/CurrencyRatesHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/CurrencyRatesHandlerTest.java @@ -13,6 +13,7 @@ import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; import org.prebid.server.currency.CurrencyConversionService; +import org.prebid.server.handler.admin.CurrencyRatesHandler; import java.math.BigDecimal; import java.time.ZonedDateTime; diff --git a/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java b/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java index 68e4a2fed66..41d1d0cce51 100644 --- a/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java @@ -13,6 +13,7 @@ import org.prebid.server.VertxTest; import org.prebid.server.deals.DeliveryProgressService; import org.prebid.server.deals.proto.report.DeliveryProgressReport; +import org.prebid.server.handler.admin.DealsStatusHandler; import org.prebid.server.util.HttpUtil; import java.io.IOException; diff --git a/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java b/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java index 3a414d3eb36..c9174815e89 100644 --- a/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java @@ -16,6 +16,7 @@ import org.prebid.server.deals.PlannerService; import org.prebid.server.deals.RegisterService; import org.prebid.server.exception.PreBidException; +import org.prebid.server.handler.admin.ForceDealsUpdateHandler; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; diff --git a/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java b/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java index 3ac0f223ba1..669b235971a 100644 --- a/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/HttpInteractionLogHandlerTest.java @@ -10,6 +10,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.prebid.server.handler.admin.HttpInteractionLogHandler; import org.prebid.server.log.HttpInteractionLogger; import org.prebid.server.log.model.HttpLogSpec; diff --git a/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java b/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java index d05dbe49b76..a998e770a02 100644 --- a/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java @@ -14,6 +14,7 @@ import org.prebid.server.deals.DeliveryProgressService; import org.prebid.server.deals.proto.report.LineItemStatusReport; import org.prebid.server.exception.PreBidException; +import org.prebid.server.handler.admin.LineItemStatusHandler; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; diff --git a/src/test/java/org/prebid/server/handler/LoggerControlKnobHandlerTest.java b/src/test/java/org/prebid/server/handler/LoggerControlKnobHandlerTest.java index 6d244c0a0bc..5386e80835c 100644 --- a/src/test/java/org/prebid/server/handler/LoggerControlKnobHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/LoggerControlKnobHandlerTest.java @@ -10,6 +10,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.prebid.server.handler.admin.LoggerControlKnobHandler; import org.prebid.server.log.LoggerControlKnob; import java.time.Duration; diff --git a/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java b/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java index e8aa1cb8925..f309751fc6f 100644 --- a/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/SettingsCacheNotificationHandlerTest.java @@ -13,6 +13,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.SettingsCacheNotificationHandler; import org.prebid.server.settings.CacheNotificationListener; import org.prebid.server.settings.proto.request.InvalidateSettingsCacheRequest; import org.prebid.server.settings.proto.request.UpdateSettingsCacheRequest; diff --git a/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java b/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java index fe86539c68c..f763d410afd 100644 --- a/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java @@ -11,6 +11,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.TracerLogHandler; import org.prebid.server.log.CriteriaManager; import static org.mockito.ArgumentMatchers.any; diff --git a/src/test/java/org/prebid/server/handler/VersionHandlerTest.java b/src/test/java/org/prebid/server/handler/VersionHandlerTest.java index 5d3b9f62128..aba9e183ee8 100644 --- a/src/test/java/org/prebid/server/handler/VersionHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/VersionHandlerTest.java @@ -11,6 +11,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; +import org.prebid.server.handler.admin.VersionHandler; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; diff --git a/src/test/java/org/prebid/server/optout/GoogleRecaptchaVerifierTest.java b/src/test/java/org/prebid/server/optout/GoogleRecaptchaVerifierTest.java index 112235f9089..876cc216bfa 100644 --- a/src/test/java/org/prebid/server/optout/GoogleRecaptchaVerifierTest.java +++ b/src/test/java/org/prebid/server/optout/GoogleRecaptchaVerifierTest.java @@ -11,8 +11,8 @@ import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; import org.prebid.server.exception.PreBidException; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; diff --git a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java index 8426f478d68..66d8a84f394 100644 --- a/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java +++ b/src/test/java/org/prebid/server/privacy/gdpr/vendorlist/VendorListServiceV2Test.java @@ -24,8 +24,8 @@ import org.prebid.server.privacy.gdpr.vendorlist.proto.SpecialPurpose; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorListV2; import org.prebid.server.privacy.gdpr.vendorlist.proto.VendorV2; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.io.File; import java.util.Date; diff --git a/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java b/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java index ed6fca3c722..2b060418311 100644 --- a/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java +++ b/src/test/java/org/prebid/server/settings/HttpApplicationSettingsTest.java @@ -20,8 +20,8 @@ import org.prebid.server.settings.model.StoredResponseDataResult; import org.prebid.server.settings.proto.response.HttpAccountsResponse; import org.prebid.server.settings.proto.response.HttpFetcherResponse; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.time.Instant; diff --git a/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java b/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java index 7184a1968b4..547d1484199 100644 --- a/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java +++ b/src/test/java/org/prebid/server/settings/service/HttpPeriodicRefreshServiceTest.java @@ -14,8 +14,8 @@ import org.prebid.server.VertxTest; import org.prebid.server.settings.CacheNotificationListener; import org.prebid.server.settings.proto.response.HttpRefreshResponse; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.HttpClient; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.util.Map; diff --git a/src/test/java/org/prebid/server/vertx/http/BasicHttpClientTest.java b/src/test/java/org/prebid/server/vertx/httpclient/BasicHttpClientTest.java similarity index 99% rename from src/test/java/org/prebid/server/vertx/http/BasicHttpClientTest.java rename to src/test/java/org/prebid/server/vertx/httpclient/BasicHttpClientTest.java index 5cb36c68ccb..a11a4cb2265 100644 --- a/src/test/java/org/prebid/server/vertx/http/BasicHttpClientTest.java +++ b/src/test/java/org/prebid/server/vertx/httpclient/BasicHttpClientTest.java @@ -1,4 +1,4 @@ -package org.prebid.server.vertx.http; +package org.prebid.server.vertx.httpclient; import io.vertx.core.Future; import io.vertx.core.Handler; diff --git a/src/test/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClientTest.java b/src/test/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClientTest.java similarity index 98% rename from src/test/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClientTest.java rename to src/test/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClientTest.java index 9a1d4e72882..f46af11e7a3 100644 --- a/src/test/java/org/prebid/server/vertx/http/CircuitBreakerSecuredHttpClientTest.java +++ b/src/test/java/org/prebid/server/vertx/httpclient/CircuitBreakerSecuredHttpClientTest.java @@ -1,4 +1,4 @@ -package org.prebid.server.vertx.http; +package org.prebid.server.vertx.httpclient; import io.vertx.core.Future; import io.vertx.core.Vertx; @@ -18,7 +18,7 @@ import org.mockito.junit.MockitoRule; import org.prebid.server.exception.PreBidException; import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.model.HttpClientResponse; +import org.prebid.server.vertx.httpclient.model.HttpClientResponse; import java.time.Clock; import java.time.Instant; From 0d0b767dd746e44024740aaeca21e6d12313be52 Mon Sep 17 00:00:00 2001 From: Danylo Date: Fri, 1 Mar 2024 02:40:46 +0200 Subject: [PATCH 2/9] Remove PG code. --- docs/config-app.md | 52 +- docs/deals.md | 152 --- docs/metrics.md | 26 - .../analytics/model/NotificationEvent.java | 2 - .../server/auction/BidResponseCreator.java | 236 ++--- .../server/auction/ExchangeService.java | 122 +-- .../auction/WinningBidComparatorFactory.java | 72 +- .../server/auction/model/AuctionContext.java | 8 - .../prebid/server/auction/model/BidInfo.java | 4 - .../server/auction/model/BidderRequest.java | 6 - .../requestfactory/AmpRequestFactory.java | 8 +- .../requestfactory/AuctionRequestFactory.java | 15 +- .../requestfactory/Ortb2RequestFactory.java | 66 +- .../requestfactory/VideoRequestFactory.java | 14 +- ...BidderRequestCompletionTrackerFactory.java | 96 -- .../org/prebid/server/cache/CacheService.java | 40 +- .../server/deals/AdminCentralService.java | 239 ----- .../prebid/server/deals/AlertHttpService.java | 143 --- .../org/prebid/server/deals/DealsService.java | 318 ------ .../deals/DeliveryProgressReportFactory.java | 313 ------ .../server/deals/DeliveryProgressService.java | 208 ---- .../server/deals/DeliveryStatsService.java | 294 ------ .../prebid/server/deals/LineItemService.java | 591 ----------- .../prebid/server/deals/PlannerService.java | 239 ----- .../prebid/server/deals/RegisterService.java | 187 ---- .../org/prebid/server/deals/Suspendable.java | 6 - .../prebid/server/deals/TargetingService.java | 335 ------- .../deals/UserAdditionalInfoService.java | 319 ------ .../org/prebid/server/deals/UserService.java | 294 ------ .../deals/deviceinfo/DeviceInfoService.java | 16 - .../deals/events/AdminEventProcessor.java | 8 - .../deals/events/AdminEventService.java | 30 - .../events/ApplicationEventProcessor.java | 17 - .../deals/events/ApplicationEventService.java | 57 -- .../deals/events/EventServiceInitializer.java | 53 - .../server/deals/lineitem/DeliveryPlan.java | 184 ---- .../deals/lineitem/DeliveryProgress.java | 349 ------- .../server/deals/lineitem/DeliveryToken.java | 72 -- .../server/deals/lineitem/LineItem.java | 276 ------ .../server/deals/lineitem/LineItemStatus.java | 167 ---- .../server/deals/lineitem/LostToLineItem.java | 15 - .../server/deals/model/AdminAccounts.java | 13 - .../deals/model/AdminCentralResponse.java | 25 - .../server/deals/model/AdminLineItems.java | 13 - .../prebid/server/deals/model/AlertEvent.java | 25 - .../server/deals/model/AlertPriority.java | 6 - .../deals/model/AlertProxyProperties.java | 23 - .../server/deals/model/AlertSource.java | 25 - .../prebid/server/deals/model/Command.java | 14 - .../server/deals/model/DeepDebugLog.java | 45 - .../model/DeliveryProgressProperties.java | 13 - .../deals/model/DeliveryStatsProperties.java | 31 - .../deals/model/DeploymentProperties.java | 25 - .../prebid/server/deals/model/DeviceInfo.java | 35 - .../prebid/server/deals/model/DeviceType.java | 43 - .../prebid/server/deals/model/ExtUser.java | 15 - .../server/deals/model/LogCriteriaFilter.java | 19 - .../prebid/server/deals/model/LogTracer.java | 19 - .../deals/model/MatchLineItemsResult.java | 14 - .../server/deals/model/PlannerProperties.java | 26 - .../prebid/server/deals/model/Segment.java | 11 - .../server/deals/model/ServicesCommand.java | 11 - .../deals/model/SimulationProperties.java | 15 - .../org/prebid/server/deals/model/TxnLog.java | 60 -- .../org/prebid/server/deals/model/User.java | 15 - .../prebid/server/deals/model/UserData.java | 17 - .../server/deals/model/UserDetails.java | 21 - .../deals/model/UserDetailsProperties.java | 23 - .../deals/model/UserDetailsRequest.java | 15 - .../deals/model/UserDetailsResponse.java | 11 - .../org/prebid/server/deals/model/UserId.java | 13 - .../prebid/server/deals/model/UserIdRule.java | 19 - .../deals/model/WinEventNotification.java | 37 - .../deals/proto/CurrencyServiceState.java | 13 - .../server/deals/proto/DeliverySchedule.java | 30 - .../server/deals/proto/FrequencyCap.java | 23 - .../server/deals/proto/LineItemMetaData.java | 57 -- .../server/deals/proto/LineItemSize.java | 16 - .../org/prebid/server/deals/proto/Price.java | 15 - .../server/deals/proto/RegisterRequest.java | 24 - .../org/prebid/server/deals/proto/Status.java | 18 - .../org/prebid/server/deals/proto/Token.java | 16 - .../proto/report/DeliveryProgressReport.java | 37 - .../report/DeliveryProgressReportBatch.java | 21 - .../deals/proto/report/DeliverySchedule.java | 26 - .../server/deals/proto/report/Event.java | 15 - .../deals/proto/report/LineItemStatus.java | 77 -- .../proto/report/LineItemStatusReport.java | 33 - .../deals/proto/report/LostToLineItem.java | 18 - .../server/deals/proto/report/Token.java | 18 - .../DealsSimulationAdminHandler.java | 165 ---- ...imulationAwareDeliveryProgressService.java | 74 -- .../SimulationAwareDeliveryStatsService.java | 52 - .../SimulationAwareHttpBidderRequester.java | 177 ---- .../SimulationAwareLineItemService.java | 62 -- .../SimulationAwarePlannerService.java | 107 -- .../SimulationAwareRegisterService.java | 61 -- .../SimulationAwareUserService.java | 57 -- .../deals/targeting/RequestContext.java | 422 -------- .../deals/targeting/TargetingDefinition.java | 10 - .../server/deals/targeting/interpret/And.java | 27 - .../DomainMetricAwareExpression.java | 25 - .../deals/targeting/interpret/Expression.java | 8 - .../server/deals/targeting/interpret/In.java | 30 - .../deals/targeting/interpret/InIntegers.java | 21 - .../deals/targeting/interpret/InStrings.java | 48 - .../deals/targeting/interpret/Intersects.java | 31 - .../interpret/IntersectsIntegers.java | 21 - .../targeting/interpret/IntersectsSizes.java | 22 - .../interpret/IntersectsStrings.java | 28 - .../deals/targeting/interpret/Matches.java | 44 - .../interpret/NonTerminalExpression.java | 4 - .../server/deals/targeting/interpret/Not.java | 21 - .../server/deals/targeting/interpret/Or.java | 27 - .../interpret/TerminalExpression.java | 4 - .../deals/targeting/interpret/Within.java | 49 - .../deals/targeting/model/GeoLocation.java | 13 - .../deals/targeting/model/GeoRegion.java | 17 - .../deals/targeting/model/LookupResult.java | 33 - .../server/deals/targeting/model/Size.java | 13 - .../targeting/syntax/BooleanOperator.java | 29 - .../targeting/syntax/MatchingFunction.java | 34 - .../targeting/syntax/TargetingCategory.java | 132 --- .../prebid/server/events/EventRequest.java | 2 - .../org/prebid/server/events/EventUtil.java | 7 - .../prebid/server/events/EventsService.java | 27 +- .../exception/TargetingSyntaxException.java | 12 - .../server/handler/DealsStatusHandler.java | 48 - .../handler/ForceDealsUpdateHandler.java | 104 -- .../server/handler/LineItemStatusHandler.java | 76 -- .../handler/NotificationEventHandler.java | 106 +- .../server/handler/TracerLogHandler.java | 19 +- .../server/handler/openrtb2/AmpHandler.java | 9 +- .../handler/openrtb2/AuctionHandler.java | 28 +- .../server/handler/openrtb2/VideoHandler.java | 1 + .../java/org/prebid/server/log/Criteria.java | 64 +- .../prebid/server/log/CriteriaLogManager.java | 23 +- .../prebid/server/log/CriteriaManager.java | 42 +- .../org/prebid/server/metric/MetricName.java | 26 - .../org/prebid/server/metric/Metrics.java | 70 -- .../org/prebid/server/metric/PgMetrics.java | 10 - .../ext/response/ExtDebugPgmetrics.java | 41 - .../openrtb/ext/response/ExtDebugTrace.java | 14 - .../ext/response/ExtResponseDebug.java | 5 - .../openrtb/ext/response/ExtTraceDeal.java | 40 - .../config/AdminEndpointsConfiguration.java | 93 -- .../spring/config/DealsConfiguration.java | 914 ------------------ .../spring/config/ServiceConfiguration.java | 21 +- .../spring/config/WebConfiguration.java | 26 +- .../java/org/prebid/server/util/HttpUtil.java | 54 +- .../org/prebid/server/util/LineItemUtil.java | 76 -- .../validation/ResponseBidValidator.java | 193 +--- .../org/prebid/server/vast/VastModifier.java | 8 +- src/main/resources/application.yaml | 15 - 154 files changed, 281 insertions(+), 10564 deletions(-) delete mode 100644 docs/deals.md delete mode 100644 src/main/java/org/prebid/server/bidder/DealsBidderRequestCompletionTrackerFactory.java delete mode 100644 src/main/java/org/prebid/server/deals/AdminCentralService.java delete mode 100644 src/main/java/org/prebid/server/deals/AlertHttpService.java delete mode 100644 src/main/java/org/prebid/server/deals/DealsService.java delete mode 100644 src/main/java/org/prebid/server/deals/DeliveryProgressReportFactory.java delete mode 100644 src/main/java/org/prebid/server/deals/DeliveryProgressService.java delete mode 100644 src/main/java/org/prebid/server/deals/DeliveryStatsService.java delete mode 100644 src/main/java/org/prebid/server/deals/LineItemService.java delete mode 100644 src/main/java/org/prebid/server/deals/PlannerService.java delete mode 100644 src/main/java/org/prebid/server/deals/RegisterService.java delete mode 100644 src/main/java/org/prebid/server/deals/Suspendable.java delete mode 100644 src/main/java/org/prebid/server/deals/TargetingService.java delete mode 100644 src/main/java/org/prebid/server/deals/UserAdditionalInfoService.java delete mode 100644 src/main/java/org/prebid/server/deals/UserService.java delete mode 100644 src/main/java/org/prebid/server/deals/deviceinfo/DeviceInfoService.java delete mode 100644 src/main/java/org/prebid/server/deals/events/AdminEventProcessor.java delete mode 100644 src/main/java/org/prebid/server/deals/events/AdminEventService.java delete mode 100644 src/main/java/org/prebid/server/deals/events/ApplicationEventProcessor.java delete mode 100644 src/main/java/org/prebid/server/deals/events/ApplicationEventService.java delete mode 100644 src/main/java/org/prebid/server/deals/events/EventServiceInitializer.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/DeliveryPlan.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/DeliveryProgress.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/DeliveryToken.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/LineItem.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/LineItemStatus.java delete mode 100644 src/main/java/org/prebid/server/deals/lineitem/LostToLineItem.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AdminAccounts.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AdminCentralResponse.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AdminLineItems.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AlertEvent.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AlertPriority.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AlertProxyProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/AlertSource.java delete mode 100644 src/main/java/org/prebid/server/deals/model/Command.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeepDebugLog.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeliveryProgressProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeliveryStatsProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeploymentProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeviceInfo.java delete mode 100644 src/main/java/org/prebid/server/deals/model/DeviceType.java delete mode 100644 src/main/java/org/prebid/server/deals/model/ExtUser.java delete mode 100644 src/main/java/org/prebid/server/deals/model/LogCriteriaFilter.java delete mode 100644 src/main/java/org/prebid/server/deals/model/LogTracer.java delete mode 100644 src/main/java/org/prebid/server/deals/model/MatchLineItemsResult.java delete mode 100644 src/main/java/org/prebid/server/deals/model/PlannerProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/Segment.java delete mode 100644 src/main/java/org/prebid/server/deals/model/ServicesCommand.java delete mode 100644 src/main/java/org/prebid/server/deals/model/SimulationProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/TxnLog.java delete mode 100644 src/main/java/org/prebid/server/deals/model/User.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserData.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserDetails.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserDetailsProperties.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserDetailsRequest.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserDetailsResponse.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserId.java delete mode 100644 src/main/java/org/prebid/server/deals/model/UserIdRule.java delete mode 100644 src/main/java/org/prebid/server/deals/model/WinEventNotification.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/CurrencyServiceState.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/DeliverySchedule.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/FrequencyCap.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/LineItemMetaData.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/LineItemSize.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/Price.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/RegisterRequest.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/Status.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/Token.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReport.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReportBatch.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/DeliverySchedule.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/Event.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/LineItemStatus.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/LineItemStatusReport.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/LostToLineItem.java delete mode 100644 src/main/java/org/prebid/server/deals/proto/report/Token.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandler.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryProgressService.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareLineItemService.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java delete mode 100644 src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/RequestContext.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/TargetingDefinition.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/And.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/DomainMetricAwareExpression.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Expression.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/In.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/InIntegers.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/InStrings.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Intersects.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegers.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsSizes.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsStrings.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Matches.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/NonTerminalExpression.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Not.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Or.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/TerminalExpression.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/interpret/Within.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/model/GeoLocation.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/model/GeoRegion.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/model/LookupResult.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/model/Size.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/syntax/BooleanOperator.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/syntax/MatchingFunction.java delete mode 100644 src/main/java/org/prebid/server/deals/targeting/syntax/TargetingCategory.java delete mode 100644 src/main/java/org/prebid/server/exception/TargetingSyntaxException.java delete mode 100644 src/main/java/org/prebid/server/handler/DealsStatusHandler.java delete mode 100644 src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java delete mode 100644 src/main/java/org/prebid/server/handler/LineItemStatusHandler.java delete mode 100644 src/main/java/org/prebid/server/metric/PgMetrics.java delete mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugPgmetrics.java delete mode 100644 src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtTraceDeal.java delete mode 100644 src/main/java/org/prebid/server/spring/config/DealsConfiguration.java delete mode 100644 src/main/java/org/prebid/server/util/LineItemUtil.java diff --git a/docs/config-app.md b/docs/config-app.md index 79cbf9f85ef..0ae973cf9f5 100644 --- a/docs/config-app.md +++ b/docs/config-app.md @@ -202,17 +202,7 @@ Also, each bidder could have its own bidder-specific options. - `admin-endpoints.tracelog.enabled` - if equals to `true` the endpoint will be available. - `admin-endpoints.tracelog.path` - the server context path where the endpoint will be accessible. - `admin-endpoints.tracelog.on-application-port` - when equals to `false` endpoint will be bound to `admin.port`. -- `admin-endpoints.tracelog.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` - -- `admin-endpoints.deals-status.enabled` - if equals to `true` the endpoint will be available. -- `admin-endpoints.deals-status.path` - the server context path where the endpoint will be accessible. -- `admin-endpoints.deals-status.on-application-port` - when equals to `false` endpoint will be bound to `admin.port`. -- `admin-endpoints.deals-status.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` - -- `admin-endpoints.lineitem-status.enabled` - if equals to `true` the endpoint will be available. -- `admin-endpoints.lineitem-status.path` - the server context path where the endpoint will be accessible. -- `admin-endpoints.lineitem-status.on-application-port` - when equals to `false` endpoint will be bound to `admin.port`. -- `admin-endpoints.lineitem-status.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` +- `admin-endpoints.tracelog.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` - `admin-endpoints.e2eadmin.enabled` - if equals to `true` the endpoint will be available. - `admin-endpoints.e2eadmin.path` - the server context path where the endpoint will be accessible. @@ -224,11 +214,6 @@ Also, each bidder could have its own bidder-specific options. - `admin-endpoints.collected-metrics.on-application-port` - when equals to `false` endpoint will be bound to `admin.port`. - `admin-endpoints.collected-metrics.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` -- `admin-endpoints.force-deals-update.enabled` - if equals to `true` the endpoint will be available. -- `admin-endpoints.force-deals-update.path` - the server context path where the endpoint will be accessible. -- `admin-endpoints.force-deals-update.on-application-port` - when equals to `false` endpoint will be bound to `admin.port`. -- `admin-endpoints.force-deals-update.protected` - when equals to `true` endpoint will be protected by basic authentication configured in `admin-endpoints.credentials` - - `admin-endpoints.credentials` - user and password for access to admin endpoints if `admin-endpoints.[NAME].protected` is true`. ## Metrics @@ -442,41 +427,6 @@ If not defined in config all other Health Checkers would be disabled and endpoin - `analytics.pubstack.buffers.count` - threshold in events count for buffer to send events - `analytics.pubstack.buffers.report-ttl-ms` - max period between two reports. -## Programmatic Guaranteed Delivery -- `deals.planner.plan-endpoint` - planner endpoint to get plans from. -- `deals.planner.update-period` - cron expression to start job for requesting Line Item metadata updates from the Planner. -- `deals.planner.plan-advance-period` - cron expression to start job for advancing Line Items to the next plan. -- `deals.planner.retry-period-sec` - how long (in seconds) to wait before re-sending a request to the Planner that previously failed with 5xx HTTP error code. -- `deals.planner.timeout-ms` - default operation timeout for requests to planner's endpoints. -- `deals.planner.register-endpoint` - register endpoint to get plans from. -- `deals.planner.register-period-sec` - time period (in seconds) to send register request to the Planner. -- `deals.planner.username` - username for planner BasicAuth. -- `deals.planner.password` - password for planner BasicAuth. -- `deals.delivery-stats.delivery-period` - cron expression to start job for sending delivery progress to planner. -- `deals.delivery-stats.cached-reports-number` - how many reports to cache while planner is unresponsive. -- `deals.delivery-stats.timeout-ms` - default operation timeout for requests to delivery progress endpoints. -- `deals.delivery-stats.username` - username for delivery progress BasicAuth. -- `deals.delivery-stats.password` - password for delivery progress BasicAuth. -- `deals.delivery-stats.line-items-per-report` - max number of line items in each report to split for batching. Default is 25. -- `deals.delivery-stats.reports-interval-ms` - interval in ms between consecutive reports. Default is 0. -- `deals.delivery-stats.batches-interval-ms` - interval in ms between consecutive batches. Default is 1000. -- `deals.delivery-stats.request-compression-enabled` - enables request gzip compression when set to true. -- `deals.delivery-progress.line-item-status-ttl-sec` - how long to store line item's metrics after it was expired. -- `deals.delivery-progress.cached-plans-number` - how many plans to store in metrics per line item. -- `deals.delivery-progress.report-reset-period`- cron expression to start job for closing current delivery progress and starting new one. -- `deals.delivery-progress-report.competitors-number`- number of line items top competitors to send in delivery progress report. -- `deals.user-data.user-details-endpoint` - user Data Store endpoint to get user details from. -- `deals.user-data.win-event-endpoint` - user Data Store endpoint to which win events should be sent. -- `deals.user-data.timeout` - time to wait (in milliseconds) for User Data Service response. -- `deals.user-data.user-ids` - list of Rules for determining user identifiers to send to User Data Store. -- `deals.max-deals-per-bidder` - maximum number of deals to send to each bidder. -- `deals.alert-proxy.enabled` - enable alert proxy service if `true`. -- `deals.alert-proxy.url` - alert service endpoint to send alerts to. -- `deals.alert-proxy.timeout-sec` - default operation timeout for requests to alert service endpoint. -- `deals.alert-proxy.username` - username for alert proxy BasicAuth. -- `deals.alert-proxy.password` - password for alert proxy BasicAuth. -- `deals.alert-proxy.alert-types` - key value pair of alert type and sampling factor to send high priority alert. - ## Debugging - `debug.override-token` - special string token for overriding Prebid Server account and/or adapter debug information presence in the auction response. diff --git a/docs/deals.md b/docs/deals.md deleted file mode 100644 index fca8c585e26..00000000000 --- a/docs/deals.md +++ /dev/null @@ -1,152 +0,0 @@ -# Deals - -## Planner and Register services - -### Planner service - -Periodically request Line Item metadata from the Planner. Line Item metadata includes: -1. Line Item details -2. Targeting -3. Frequency caps -4. Delivery schedule - -### Register service - -Each Prebid Server instance register itself with the General Planner with a health index -(QoS indicator based on its internal counters like circuit breaker trip counters, timeouts, etc.) -and KPI like ad requests per second. - -Also allows planner send command to PBS admin endpoint to stored request caches and tracelogs. - -### Planner and register service configuration - -```yaml -planner: - register-endpoint: - plan-endpoint: - update-period: "0 */1 * * * *" - register-period-sec: 60 - timeout-ms: 8000 - username: - password: -``` - -## Deals stats service - -Supports sending reports to delivery stats serving with following metrics: - -1. Number of client requests seen since start-up -2. For each Line Item -- Number of tokens spent so far at each token class within active and expired plans -- Number of times the account made requests (this will be the same across all LineItem for the account) -- Number of win notifications -- Number of times the domain part of the target matched -- Number of times impressions matched whole target -- Number of times impressions matched the target but was frequency capped -- Number of times impressions matched the target but the fcap lookup failed -- Number of times LineItem was sent to the bidder -- Number of times LineItem was sent to the bidder as the top match -- Number of times LineItem came back from the bidder -- Number of times the LineItem response was invalidated -- Number of times the LineItem was sent to the client -- Number of times the LineItem was sent to the client as the top match -- Array of top 10 competing LineItems sent to client - -### Deals stats service configuration - -```yaml -delivery-stats: - endpoint: - delivery-period: "0 */1 * * * *" - cached-reports-number: 20 - line-item-status-ttl-sec: 3600 - timeout-ms: 8000 - username: - password: -``` - -## Alert service - -Sends out alerts when PBS cannot talk to general planner and other critical situations. Alerts are simply JSON messages -over HTTP sent to a central proxy server. - -```yaml - alert-proxy: - enabled: truew - timeout-sec: 10 - url: - username: - password: - alert-types: - : - pbs-planner-empty-response-error: 15 -``` - -## GeoLocation service - -This service currently has 1 implementation: -- MaxMind - -In order to support targeting by geographical attributes the service will provide the following information: - -1. `continent` - Continent code -2. `region` - Region code using ISO-3166-2 -3. `metro` - Nielsen DMAs -4. `city` - city using provider specific encoding -5. `lat` - latitude from -90.0 to +90.0, where negative is south -6. `lon` - longitude from -180.0 to +180.0, where negative is west - -### GeoLocation service configuration for MaxMind - -```yaml -geolocation: - enabled: true - type: maxmind - maxmind: - remote-file-syncer: - download-url: - save-filepath: - tmp-filepath: - retry-count: 3 - retry-interval-ms: 3000 - timeout-ms: 300000 - update-interval-ms: 0 - http-client: - connect-timeout-ms: 2500 - max-redirects: 3 -``` - -## User Service - -This service is responsible for: -- Requesting user targeting segments and frequency capping status from the User Data Store -- Reporting to User Data Store when users finally see ads to aid in correctly enforcing frequency caps - -### User service configuration - -```yaml - user-data: - win-event-endpoint: - user-details-endpoint: - timeout: 1000 - user-ids: - - location: rubicon - source: uid - type: khaos -``` -1. khaos, adnxs - types of the ids that will be specified in requests to User Data Store -2. source - source of the id, the only supported value so far is “uids” which stands for uids cookie -3. location - where exactly in the source to look for id - -## Device Info Service - -DeviceInfoService returns device-related attributes based on User-Agent for use in targeting: -- deviceClass: desktop, tablet, phone, ctv -- os: windows, ios, android, osx, unix, chromeos -- osVersion -- browser: chrome, firefox, edge, safari -- browserVersion - -## See also - -- [Configuration](config.md) diff --git a/docs/metrics.md b/docs/metrics.md index 102e9ecc77a..eac489aefe6 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -135,29 +135,3 @@ Following metrics are collected and submitted if account is configured with `det - `analytics..(auction|amp|video|cookie_sync|event|setuid).timeout` - number of event requests, failed with timeout cause - `analytics..(auction|amp|video|cookie_sync|event|setuid).err` - number of event requests, failed with errors - `analytics..(auction|amp|video|cookie_sync|event|setuid).badinput` - number of event requests, rejected with bad input cause - -## win notifications -- `win_notifications` - total number of win notifications. -- `win_requests` - total number of requests sent to user service for win notifications. -- `win_request_preparation_failed` - number of request failed validation and were not sent. -- `win_request_time` - latency between request to user service and response for win notifications. -- `win_request_failed` - number of failed request sent to user service for win notifications. -- `win_request_successful` - number of successful request sent to user service for win notifications. - -## user details -- `user_details_requests` - total number of requests sent to user service to get user details. -- `user_details_request_preparation_failed` - number of request failed validation and were not sent. -- `user_details_request_time` - latency between request to user service and response to get user details. -- `user_details_request_failed` - number of failed request sent to user service to get user details. -- `user_details_request_successful` - number of successful request sent to user service to get user details. - -## Programmatic guaranteed metrics -- `pg.planner_lineitems_received` - number of line items received from general planner. -- `pg.planner_requests` - total number of requests sent to general planner. -- `pg.planner_request_failed` - number of failed request sent to general planner. -- `pg.planner_request_successful` - number of successful requests sent to general planner. -- `pg.planner_request_time` - latency between request to general planner and its successful (200 OK) response. -- `pg.delivery_requests` - total number of requests to delivery stats service. -- `pg.delivery_request_failed` - number of failed requests to delivery stats service. -- `pg.delivery_request_successful` - number of successful requests to delivery stats service. -- `pg.delivery_request_time` - latency between request to delivery stats and its successful (200 OK) response. diff --git a/src/main/java/org/prebid/server/analytics/model/NotificationEvent.java b/src/main/java/org/prebid/server/analytics/model/NotificationEvent.java index 090dd818f07..9bbfdc88845 100644 --- a/src/main/java/org/prebid/server/analytics/model/NotificationEvent.java +++ b/src/main/java/org/prebid/server/analytics/model/NotificationEvent.java @@ -20,8 +20,6 @@ public class NotificationEvent { Account account; - String lineItemId; - String bidder; Long timestamp; diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index 30aed97692f..ee42b2982ed 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -46,8 +46,6 @@ import org.prebid.server.cache.model.CacheInfo; import org.prebid.server.cache.model.CacheServiceResult; import org.prebid.server.cache.model.DebugHttpCall; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.events.EventsContext; import org.prebid.server.events.EventsService; import org.prebid.server.exception.InvalidRequestException; @@ -61,7 +59,6 @@ import org.prebid.server.identity.IdGeneratorType; import org.prebid.server.json.DecodeException; import org.prebid.server.json.JacksonMapper; -import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; import org.prebid.server.proto.openrtb.ext.request.ExtImp; import org.prebid.server.proto.openrtb.ext.request.ExtImpAuctionEnvironment; import org.prebid.server.proto.openrtb.ext.request.ExtImpPrebid; @@ -81,13 +78,11 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidResponseFledge; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponsePrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; -import org.prebid.server.proto.openrtb.ext.response.ExtDebugPgmetrics; import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; import org.prebid.server.proto.openrtb.ext.response.ExtResponseDebug; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInfrastructure; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.NonBid; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.SeatNonBid; @@ -98,7 +93,6 @@ import org.prebid.server.settings.model.AccountEventsConfig; import org.prebid.server.settings.model.AccountTargetingConfig; import org.prebid.server.settings.model.VideoStoredDataResult; -import org.prebid.server.util.LineItemUtil; import org.prebid.server.util.StreamUtil; import org.prebid.server.vast.VastModifier; @@ -190,42 +184,40 @@ Future create(AuctionContext auctionContext, BidRequestCacheInfo cacheInfo, Map bidderToMultiBids) { - final List auctionParticipations = auctionContext.getAuctionParticipations(); - final List imps = auctionContext.getBidRequest().getImp(); + return videoStoredDataResult(auctionContext) + .compose(videoStoredData -> create(videoStoredData, auctionContext, cacheInfo, bidderToMultiBids)) + .map(bidResponse -> populateSeatNonBid(auctionContext, bidResponse)); + } + + private Future create(VideoStoredDataResult videoStoredDataResult, + AuctionContext auctionContext, + BidRequestCacheInfo cacheInfo, + Map bidderToMultiBids) { + final EventsContext eventsContext = createEventsContext(auctionContext); - final List bidderResponses = auctionParticipations.stream() + final List bidderResponses = auctionContext.getAuctionParticipations().stream() .filter(auctionParticipation -> !auctionParticipation.isRequestBlocked()) .map(AuctionParticipation::getBidderResponse) .toList(); - return videoStoredDataResult(auctionContext).compose(videoStoredDataResult -> - invokeProcessedBidderResponseHooks( - updateBids(bidderResponses, videoStoredDataResult, auctionContext, eventsContext, imps), - auctionContext) - - .compose(updatedResponses -> - invokeAllProcessedBidResponsesHook(updatedResponses, auctionContext)) - - .compose(updatedResponses -> - createCategoryMapping(auctionContext, updatedResponses)) - - .compose(categoryMappingResult -> cacheBidsAndCreateResponse( - toBidderResponseInfos(categoryMappingResult, imps), - auctionContext, - cacheInfo, - bidderToMultiBids, - videoStoredDataResult, - eventsContext)) - - .map(bidResponse -> populateSeatNonBid(auctionContext, bidResponse))); + return updateBids(bidderResponses, videoStoredDataResult, auctionContext, eventsContext) + .compose(updatedResponses -> invokeProcessedBidderResponseHooks(updatedResponses, auctionContext)) + .compose(updatedResponses -> invokeAllProcessedBidResponsesHook(updatedResponses, auctionContext)) + .compose(updatedResponses -> createCategoryMapping(auctionContext, updatedResponses)) + .compose(categoryMappingResult -> cacheBidsAndCreateResponse( + toBidderResponseInfos(categoryMappingResult, auctionContext.getBidRequest().getImp()), + auctionContext, + cacheInfo, + bidderToMultiBids, + videoStoredDataResult, + eventsContext)); } - private List updateBids(List bidderResponses, - VideoStoredDataResult videoStoredDataResult, - AuctionContext auctionContext, - EventsContext eventsContext, - List imps) { + private Future> updateBids(List bidderResponses, + VideoStoredDataResult videoStoredDataResult, + AuctionContext auctionContext, + EventsContext eventsContext) { final List result = new ArrayList<>(); @@ -238,12 +230,8 @@ private List updateBids(List bidderResponses, final Bid receivedBid = bidderBid.getBid(); final BidType bidType = bidderBid.getType(); - final Imp correspondingImp = correspondingImp(receivedBid, imps); - final ExtDealLine extDealLine = LineItemUtil.extDealLineFrom(receivedBid, correspondingImp, mapper); - final String lineItemId = extDealLine != null ? extDealLine.getLineItemId() : null; - final Bid updatedBid = updateBid( - receivedBid, bidType, bidder, videoStoredDataResult, auctionContext, eventsContext, lineItemId); + receivedBid, bidType, bidder, videoStoredDataResult, auctionContext, eventsContext); modifiedBidderBids.add(bidderBid.toBuilder().bid(updatedBid).build()); } @@ -251,7 +239,7 @@ private List updateBids(List bidderResponses, result.add(bidderResponse.with(modifiedSeatBid)); } - return result; + return Future.succeededFuture(result); } private Bid updateBid(Bid bid, @@ -259,8 +247,7 @@ private Bid updateBid(Bid bid, String bidder, VideoStoredDataResult videoStoredDataResult, AuctionContext auctionContext, - EventsContext eventsContext, - String lineItemId) { + EventsContext eventsContext) { final Account account = auctionContext.getAccount(); final List debugWarnings = auctionContext.getDebugWarnings(); @@ -277,8 +264,7 @@ private Bid updateBid(Bid bid, account, eventsContext, effectiveBidId, - debugWarnings, - lineItemId)) + debugWarnings)) .ext(updateBidExt( bid, bidType, @@ -287,8 +273,7 @@ private Bid updateBid(Bid bid, videoStoredDataResult, eventsContext, generatedBidId, - effectiveBidId, - lineItemId)) + effectiveBidId)) .build(); } @@ -298,8 +283,7 @@ private String updateBidAdm(Bid bid, Account account, EventsContext eventsContext, String effectiveBidId, - List debugWarnings, - String lineItemId) { + List debugWarnings) { final String bidAdm = bid.getAdm(); return BidType.video.equals(bidType) @@ -310,8 +294,7 @@ private String updateBidAdm(Bid bid, effectiveBidId, account.getId(), eventsContext, - debugWarnings, - lineItemId) + debugWarnings) : bidAdm; } @@ -322,8 +305,7 @@ private ObjectNode updateBidExt(Bid bid, VideoStoredDataResult videoStoredDataResult, EventsContext eventsContext, String generatedBidId, - String effectiveBidId, - String lineItemId) { + String effectiveBidId) { final ExtBidPrebid updatedExtBidPrebid = updateBidExtPrebid( bid, @@ -333,8 +315,7 @@ private ObjectNode updateBidExt(Bid bid, videoStoredDataResult, eventsContext, generatedBidId, - effectiveBidId, - lineItemId); + effectiveBidId); final ObjectNode existingBidExt = bid.getExt(); final ObjectNode updatedBidExt = mapper.mapper().createObjectNode(); @@ -355,11 +336,10 @@ private ExtBidPrebid updateBidExtPrebid(Bid bid, VideoStoredDataResult videoStoredDataResult, EventsContext eventsContext, String generatedBidId, - String effectiveBidId, - String lineItemId) { + String effectiveBidId) { final Video storedVideo = videoStoredDataResult.getImpIdToStoredVideo().get(bid.getImpid()); - final Events events = createEvents(bidder, account, effectiveBidId, eventsContext, lineItemId); + final Events events = createEvents(bidder, account, effectiveBidId, eventsContext); final ExtBidPrebidVideo extBidPrebidVideo = getExtBidPrebidVideo(bid.getExt()).orElse(null); final ExtBidPrebid.ExtBidPrebidBuilder extBidPrebidBuilder = getExtPrebid(bid.getExt(), ExtBidPrebid.class) @@ -422,16 +402,11 @@ private BidInfo toBidInfo(Bid bid, String bidder, CategoryMappingResult categoryMappingResult) { - final Imp correspondingImp = correspondingImp(bid, imps); - final ExtDealLine extDealLine = LineItemUtil.extDealLineFrom(bid, correspondingImp, mapper); - final String lineItemId = extDealLine != null ? extDealLine.getLineItemId() : null; - return BidInfo.builder() .bid(bid) .bidType(type) .bidder(bidder) - .correspondingImp(correspondingImp) - .lineItemId(lineItemId) + .correspondingImp(correspondingImp(bid, imps)) .category(categoryMappingResult.getCategory(bid)) .satisfiedPriority(categoryMappingResult.isBidSatisfiesPriority(bid)) .build(); @@ -474,12 +449,11 @@ private static BidderResponse rejectBidderResponseOrProceed( HookStageExecutionResult stageResult, BidderResponse bidderResponse) { - final List bids = - stageResult.isShouldReject() ? Collections.emptyList() : stageResult.getPayload().bids(); + final List bids = stageResult.isShouldReject() + ? Collections.emptyList() + : stageResult.getPayload().bids(); - return bidderResponse - .with(bidderResponse.getSeatBid() - .with(bids)); + return bidderResponse.with(bidderResponse.getSeatBid().with(bids)); } private Future createCategoryMapping(AuctionContext auctionContext, @@ -535,10 +509,9 @@ private Future cacheBidsAndCreateResponse(List } final ExtRequestTargeting targeting = targeting(bidRequest); - final TxnLog txnLog = auctionContext.getTxnLog(); final List bidderResponseInfos = toBidderResponseWithTargetingBidInfos( - bidderResponses, bidderToMultiBids, preferDeals(targeting), txnLog); + bidderResponses, bidderToMultiBids, preferDeals(targeting)); final Set bidInfos = bidderResponseInfos.stream() .map(BidderResponseInfo::getSeatBid) @@ -553,8 +526,6 @@ private Future cacheBidsAndCreateResponse(List .filter(bidInfo -> bidInfo.getTargetingInfo().isWinningBid()) .collect(Collectors.toSet()); - updateSentToClientTxnLog(txnLog, bidInfos); - final Set bidsToCache = cacheInfo.isShouldCacheWinningBidsOnly() ? winningBidInfos : bidInfos; return cacheBids(bidsToCache, auctionContext, cacheInfo, eventsContext) @@ -581,8 +552,7 @@ private static boolean preferDeals(ExtRequestTargeting targeting) { private List toBidderResponseWithTargetingBidInfos( List bidderResponses, Map bidderToMultiBids, - boolean preferDeals, - TxnLog txnLog) { + boolean preferDeals) { final Map> bidderResponseToReducedBidInfos = bidderResponses.stream() .collect(Collectors.toMap( @@ -611,13 +581,6 @@ private List toBidderResponseWithTargetingBidInfos( .ifPresent(winningBids::add); } - final Map> impIdToLineItemIds = impIdToBidderToBidInfos.entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - impIdToBidderToBidInfoEntry -> toLineItemIds(impIdToBidderToBidInfoEntry.getValue().values()))); - - updateTopMatchAndLostAuctionLineItemsMetric(winningBids, txnLog, impIdToLineItemIds); - return bidderResponseToReducedBidInfos.entrySet().stream() .map(responseToBidInfos -> injectBidInfoWithTargeting( responseToBidInfos.getKey(), @@ -652,33 +615,6 @@ private List sortReducedBidInfo(List bidInfos, int limit, bool .toList(); } - private static Set toLineItemIds(Collection> bidInfos) { - return bidInfos.stream() - .flatMap(Collection::stream) - .map(BidInfo::getLineItemId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - - /** - * Updates sent to client as top match and auction lost to line item metric. - */ - private static void updateTopMatchAndLostAuctionLineItemsMetric(Set winningBidInfos, - TxnLog txnLog, - Map> impToLineItemIds) { - for (BidInfo winningBidInfo : winningBidInfos) { - final String winningLineItemId = winningBidInfo.getLineItemId(); - if (winningLineItemId != null) { - txnLog.lineItemSentToClientAsTopMatch().add(winningLineItemId); - - final String impIdOfWinningBid = winningBidInfo.getBid().getImpid(); - impToLineItemIds.get(impIdOfWinningBid).stream() - .filter(lineItemId -> !Objects.equals(lineItemId, winningLineItemId)) - .forEach(lineItemId -> txnLog.lostAuctionToLineItems().get(lineItemId).add(winningLineItemId)); - } - } - } - private static BidderResponseInfo injectBidInfoWithTargeting(BidderResponseInfo bidderResponseInfo, List bidderBidInfos, Map bidderToMultiBids, @@ -744,16 +680,6 @@ private static List injectTargeting(List bidderImpIdBidInfos, return result; } - /** - * Increments sent to client metrics for each bid with deal. - */ - private static void updateSentToClientTxnLog(TxnLog txnLog, Set bidInfos) { - bidInfos.stream() - .map(BidInfo::getLineItemId) - .filter(Objects::nonNull) - .forEach(lineItemId -> txnLog.lineItemsSentToClient().add(lineItemId)); - } - /** * Returns {@link ExtBidResponse} object, populated with response time, errors and debug info (if requested) * from all bidders. @@ -853,13 +779,10 @@ private static ExtResponseDebug toExtResponseDebug(List bidd : null; final BidRequest bidRequest = debugEnabled ? auctionContext.getBidRequest() : null; - - final ExtDebugPgmetrics extDebugPgmetrics = debugEnabled ? toExtDebugPgmetrics( - auctionContext.getTxnLog()) : null; final ExtDebugTrace extDebugTrace = toExtDebugTrace(auctionContext); - return ObjectUtils.anyNotNull(httpCalls, bidRequest, extDebugPgmetrics, extDebugTrace) - ? ExtResponseDebug.of(httpCalls, bidRequest, extDebugPgmetrics, extDebugTrace) + return ObjectUtils.anyNotNull(httpCalls, bidRequest, extDebugTrace) + ? ExtResponseDebug.of(httpCalls, bidRequest, extDebugTrace) : null; } @@ -963,54 +886,16 @@ private static ExtHttpCall toExtHttpCall(DebugHttpCall debugHttpCall) { .build(); } - private static ExtDebugPgmetrics toExtDebugPgmetrics(TxnLog txnLog) { - final ExtDebugPgmetrics extDebugPgmetrics = ExtDebugPgmetrics.builder() - .matchedDomainTargeting(nullIfEmpty(txnLog.lineItemsMatchedDomainTargeting())) - .matchedWholeTargeting(nullIfEmpty(txnLog.lineItemsMatchedWholeTargeting())) - .matchedTargetingFcapped(nullIfEmpty(txnLog.lineItemsMatchedTargetingFcapped())) - .matchedTargetingFcapLookupFailed(nullIfEmpty(txnLog.lineItemsMatchedTargetingFcapLookupFailed())) - .readyToServe(nullIfEmpty(txnLog.lineItemsReadyToServe())) - .pacingDeferred(nullIfEmpty(txnLog.lineItemsPacingDeferred())) - .sentToBidder(nullIfEmpty(txnLog.lineItemsSentToBidder())) - .sentToBidderAsTopMatch(nullIfEmpty(txnLog.lineItemsSentToBidderAsTopMatch())) - .receivedFromBidder(nullIfEmpty(txnLog.lineItemsReceivedFromBidder())) - .responseInvalidated(nullIfEmpty(txnLog.lineItemsResponseInvalidated())) - .sentToClient(nullIfEmpty(txnLog.lineItemsSentToClient())) - .sentToClientAsTopMatch(nullIfEmpty(txnLog.lineItemSentToClientAsTopMatch())) - .build(); - return extDebugPgmetrics.equals(ExtDebugPgmetrics.EMPTY) ? null : extDebugPgmetrics; - } - private static ExtDebugTrace toExtDebugTrace(AuctionContext auctionContext) { - final DeepDebugLog deepDebugLog = auctionContext.getDeepDebugLog(); - - final boolean dealsTraceEnabled = deepDebugLog.isDeepDebugEnabled(); - final boolean activityInfrastructureTraceEnabled = auctionContext.getDebugContext().getTraceLevel() != null; - if (!dealsTraceEnabled && !activityInfrastructureTraceEnabled) { + if (auctionContext.getDebugContext().getTraceLevel() == null) { return null; } - final List entries = dealsTraceEnabled ? deepDebugLog.entries() : null; - final List dealsTrace = dealsTraceEnabled - ? entries.stream() - .filter(extTraceDeal -> StringUtils.isEmpty(extTraceDeal.getLineItemId())) - .toList() - : null; - final Map> lineItemsTrace = dealsTraceEnabled - ? entries.stream() - .filter(extTraceDeal -> StringUtils.isNotEmpty(extTraceDeal.getLineItemId())) - .collect(Collectors.groupingBy(ExtTraceDeal::getLineItemId, Collectors.toList())) - : null; - - final List activityInfrastructureTrace = activityInfrastructureTraceEnabled - ? new ArrayList<>(auctionContext.getActivityInfrastructure().debugTrace()) - : null; + final List activityInfrastructureTrace = + new ArrayList<>(auctionContext.getActivityInfrastructure().debugTrace()); - return CollectionUtils.isNotEmpty(entries) || CollectionUtils.isNotEmpty(activityInfrastructureTrace) - ? ExtDebugTrace.of( - CollectionUtils.isEmpty(dealsTrace) ? null : dealsTrace, - MapUtils.isEmpty(lineItemsTrace) ? null : lineItemsTrace, - CollectionUtils.isEmpty(activityInfrastructureTrace) ? null : activityInfrastructureTrace) + return CollectionUtils.isNotEmpty(activityInfrastructureTrace) + ? ExtDebugTrace.of(activityInfrastructureTrace) : null; } @@ -1160,6 +1045,7 @@ private static Map> toExtBidderWarnings( List bidderResponses, AuctionContext auctionContext, Map> bidWarnings) { + final Map> warnings = new HashMap<>(); warnings.putAll(extractContextWarnings(auctionContext)); @@ -1598,20 +1484,13 @@ private static String integrationFrom(AuctionContext auctionContext) { private Events createEvents(String bidder, Account account, String bidId, - EventsContext eventsContext, - String lineItemId) { + EventsContext eventsContext) { - if (!eventsContext.isEnabledForAccount()) { - return null; - } - - return eventsContext.isEnabledForRequest() || StringUtils.isNotEmpty(lineItemId) + return eventsContext.isEnabledForAccount() && eventsContext.isEnabledForRequest() ? eventsService.createEvent( bidId, bidder, account.getId(), - lineItemId, - eventsContext.isEnabledForRequest(), eventsContext) : null; } @@ -1824,13 +1703,6 @@ private static Set nullIfEmpty(Set set) { return Collections.unmodifiableSet(set); } - private static Map nullIfEmpty(Map map) { - if (map.isEmpty()) { - return null; - } - return Collections.unmodifiableMap(map); - } - /** * Creates {@link ExtBidPrebidVideo} from bid extension. */ diff --git a/src/main/java/org/prebid/server/auction/ExchangeService.java b/src/main/java/org/prebid/server/auction/ExchangeService.java index 2bce6efeeeb..e184f5f414e 100644 --- a/src/main/java/org/prebid/server/auction/ExchangeService.java +++ b/src/main/java/org/prebid/server/auction/ExchangeService.java @@ -8,7 +8,6 @@ import com.iab.openrtb.request.App; import com.iab.openrtb.request.BidRequest; import com.iab.openrtb.request.Content; -import com.iab.openrtb.request.Deal; import com.iab.openrtb.request.Dooh; import com.iab.openrtb.request.Eid; import com.iab.openrtb.request.Imp; @@ -59,9 +58,6 @@ import org.prebid.server.bidder.model.BidderSeatBid; import org.prebid.server.cookie.UidsCookie; import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.DealsService; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.Timeout; @@ -124,7 +120,6 @@ import org.prebid.server.proto.openrtb.ext.response.ExtModulesTraceStageOutcome; import org.prebid.server.settings.model.Account; import org.prebid.server.util.HttpUtil; -import org.prebid.server.util.LineItemUtil; import org.prebid.server.util.ObjectUtil; import org.prebid.server.util.StreamUtil; import org.prebid.server.validation.ResponseBidValidator; @@ -145,9 +140,7 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; /** @@ -172,7 +165,6 @@ public class ExchangeService { private final double logSamplingRate; private final BidderCatalog bidderCatalog; private final StoredResponseProcessor storedResponseProcessor; - private final DealsService dealsService; private final PrivacyEnforcementService privacyEnforcementService; private final FpdResolver fpdResolver; private final SupplyChainResolver supplyChainResolver; @@ -186,7 +178,6 @@ public class ExchangeService { private final ResponseBidValidator responseBidValidator; private final CurrencyConversionService currencyService; private final BidResponseCreator bidResponseCreator; - private final ApplicationEventService applicationEventService; private final BidResponsePostProcessor bidResponsePostProcessor; private final HookStageExecutor hookStageExecutor; private final HttpInteractionLogger httpInteractionLogger; @@ -203,7 +194,6 @@ public class ExchangeService { public ExchangeService(double logSamplingRate, BidderCatalog bidderCatalog, StoredResponseProcessor storedResponseProcessor, - DealsService dealsService, PrivacyEnforcementService privacyEnforcementService, FpdResolver fpdResolver, SupplyChainResolver supplyChainResolver, @@ -219,7 +209,6 @@ public ExchangeService(double logSamplingRate, BidResponseCreator bidResponseCreator, BidResponsePostProcessor bidResponsePostProcessor, HookStageExecutor hookStageExecutor, - ApplicationEventService applicationEventService, HttpInteractionLogger httpInteractionLogger, PriceFloorAdjuster priceFloorAdjuster, PriceFloorEnforcer priceFloorEnforcer, @@ -234,7 +223,6 @@ public ExchangeService(double logSamplingRate, this.logSamplingRate = logSamplingRate; this.bidderCatalog = Objects.requireNonNull(bidderCatalog); this.storedResponseProcessor = Objects.requireNonNull(storedResponseProcessor); - this.dealsService = dealsService; this.privacyEnforcementService = Objects.requireNonNull(privacyEnforcementService); this.fpdResolver = Objects.requireNonNull(fpdResolver); this.supplyChainResolver = Objects.requireNonNull(supplyChainResolver); @@ -250,7 +238,6 @@ public ExchangeService(double logSamplingRate, this.bidResponseCreator = Objects.requireNonNull(bidResponseCreator); this.bidResponsePostProcessor = Objects.requireNonNull(bidResponsePostProcessor); this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor); - this.applicationEventService = applicationEventService; this.httpInteractionLogger = Objects.requireNonNull(httpInteractionLogger); this.priceFloorAdjuster = Objects.requireNonNull(priceFloorAdjuster); this.priceFloorEnforcer = Objects.requireNonNull(priceFloorEnforcer); @@ -301,11 +288,8 @@ private Future runAuction(AuctionContext receivedContext) { return storedResponseProcessor.getStoredResponseResult(bidRequest.getImp(), timeout) .map(storedResponseResult -> populateStoredResponse(storedResponseResult, storedAuctionResponses)) .compose(storedResponseResult -> extractAuctionParticipations( - receivedContext, storedResponseResult, aliases, bidderToMultiBid)) - - .map(auctionParticipations -> matchAndPopulateDeals(auctionParticipations, aliases, receivedContext)) - .map(auctionParticipations -> postProcessDeals(auctionParticipations, receivedContext)) - .map(auctionParticipations -> fillContext(receivedContext, auctionParticipations)) + receivedContext, storedResponseResult, aliases, bidderToMultiBid) + .map(receivedContext::with)) .map(context -> updateRequestMetric(context, uidsCookie, aliases, account, requestTypeMetric)) @@ -330,9 +314,11 @@ private Future runAuction(AuctionContext receivedContext) { // produce response from bidder results .compose(context -> bidResponseCreator.create(context, cacheInfo, bidderToMultiBid) - .map(bidResponse -> publishAuctionEvent(bidResponse, context)) - .map(bidResponse -> criteriaLogManager.traceResponse(logger, bidResponse, - context.getBidRequest(), context.getDebugContext().isDebugEnabled())) + .map(bidResponse -> criteriaLogManager.traceResponse( + logger, + bidResponse, + context.getBidRequest(), + context.getDebugContext().isDebugEnabled())) .compose(bidResponse -> bidResponsePostProcessor.postProcess( context.getHttpRequest(), uidsCookie, bidRequest, bidResponse, account)) .map(context::with)); @@ -538,8 +524,13 @@ private Future> extractAuctionParticipations( final Map> impBidderToStoredBidResponse = storedResponseResult.getImpBidderToStoredBidResponse(); - return makeAuctionParticipation(bidders, context, aliases, impBidderToStoredBidResponse, - imps, bidderToMultiBid); + return makeAuctionParticipation( + bidders, + context, + aliases, + impBidderToStoredBidResponse, + imps, + bidderToMultiBid); } private Set bidderNamesFromImpExt(Imp imp, BidderAliases aliases) { @@ -603,9 +594,15 @@ private Future> makeAuctionParticipation( prepareUsers(bidders, context, aliases, biddersToConfigs, eidPermissions); return privacyEnforcementService.mask(context, bidderToUser, bidders, aliases) - .map(bidderToPrivacyResult -> - getAuctionParticipation(bidderToPrivacyResult, bidRequest, impBidderToStoredResponse, imps, - bidderToMultiBid, biddersToConfigs, aliases, context)); + .map(bidderToPrivacyResult -> getAuctionParticipation( + bidderToPrivacyResult, + bidRequest, + impBidderToStoredResponse, + imps, + bidderToMultiBid, + biddersToConfigs, + aliases, + context)); } private Map getBiddersToConfigs(ExtRequestPrebid prebid) { @@ -1219,32 +1216,6 @@ private ObjectNode prepareBidderParameters(ExtRequestPrebid prebid, String bidde return params != null ? mapper.mapper().createObjectNode().set(bidder, params) : null; } - private List matchAndPopulateDeals(List auctionParticipants, - BidderAliases aliases, - AuctionContext context) { - - if (dealsService == null) { - return auctionParticipants; - } - - final List updatedBidderRequests = auctionParticipants.stream() - .map(auctionParticipation -> !auctionParticipation.isRequestBlocked() - ? dealsService.matchAndPopulateDeals(auctionParticipation.getBidderRequest(), aliases, context) - : null) - .toList(); - - return IntStream.range(0, auctionParticipants.size()) - .mapToObj(i -> auctionParticipants.get(i).toBuilder() - .bidderRequest(updatedBidderRequests.get(i)) - .build()) - .toList(); - } - - private static List postProcessDeals(List auctionParticipations, - AuctionContext context) { - return DealsService.removePgDealsOnlyImpsWithoutDeals(auctionParticipations, context); - } - /** * Updates 'account.*.request', 'request' and 'no_cookie_requests' metrics for each {@link AuctionParticipation} . */ @@ -1278,26 +1249,6 @@ private AuctionContext updateRequestMetric(AuctionContext context, return context; } - private static AuctionContext fillContext(AuctionContext context, - List auctionParticipations) { - - final Map> impIdToDeals = new HashMap<>(); - auctionParticipations.stream() - .map(AuctionParticipation::getBidderRequest) - .map(BidderRequest::getImpIdToDeals) - .filter(Objects::nonNull) - .map(Map::entrySet) - .flatMap(Collection::stream) - .forEach(entry -> impIdToDeals - .computeIfAbsent(entry.getKey(), key -> new ArrayList<>()) - .addAll(entry.getValue())); - - return context.toBuilder() - .bidRequest(DealsService.populateDeals(context.getBidRequest(), impIdToDeals)) - .auctionParticipations(auctionParticipations) - .build(); - } - private Future processAndRequestBids(AuctionContext auctionContext, BidderRequest bidderRequest, Timeout timeout, @@ -1514,13 +1465,8 @@ private AuctionParticipation validBidderResponse(AuctionParticipation auctionPar final List bids = seatBid.getBids(); final List validBids = new ArrayList<>(bids.size()); - final TxnLog txnLog = auctionContext.getTxnLog(); - final String bidder = bidderResponse.getBidder(); for (final BidderBid bid : bids) { - final String lineItemId = LineItemUtil.lineItemIdFrom(bid.getBid(), bidRequest.getImp(), mapper); - maybeRecordInTxnLog(lineItemId, () -> txnLog.lineItemsReceivedFromBidder().get(bidder)); - final ValidationResult validationResult = responseBidValidator.validate( bid, bidderResponse.getBidder(), @@ -1531,11 +1477,6 @@ private AuctionParticipation validBidderResponse(AuctionParticipation auctionPar errors.add(makeValidationBidderError(bid.getBid(), validationResult)); } - if (validationResult.hasErrors()) { - maybeRecordInTxnLog(lineItemId, txnLog::lineItemsResponseInvalidated); - continue; - } - if (!validationResult.hasErrors()) { validBids.add(bid); } @@ -1562,19 +1503,6 @@ private BidderError makeValidationBidderError(Bid bid, ValidationResult validati return BidderError.invalidBid("BidId `" + bidId + "` validation messages: " + validationErrors); } - private static void maybeRecordInTxnLog(String lineItemId, Supplier> metricSupplier) { - if (lineItemId != null) { - metricSupplier.get().add(lineItemId); - } - } - - private BidResponse publishAuctionEvent(BidResponse bidResponse, AuctionContext auctionContext) { - if (applicationEventService != null) { - applicationEventService.publishAuctionEvent(auctionContext); - } - return bidResponse; - } - /** * Performs changes on {@link Bid}s price depends on different between adServerCurrency and bidCurrency, * and adjustment factor. Will drop bid if currency conversion is needed but not possible. @@ -1716,8 +1644,8 @@ private List updateResponsesMetrics(List WINNING_BID_PRICE_COMPARATOR = new WinningBidPriceComparator(); private static final Comparator WINNING_BID_DEAL_COMPARATOR = new WinningBidDealComparator(); - private static final Comparator WINNING_BID_PG_COMPARATOR = new WinningBidPgComparator(); - private static final Comparator BID_INFO_COMPARATOR = WINNING_BID_PG_COMPARATOR - .thenComparing(WINNING_BID_DEAL_COMPARATOR) + private static final Comparator BID_INFO_COMPARATOR = WINNING_BID_DEAL_COMPARATOR .thenComparing(WINNING_BID_PRICE_COMPARATOR); - private static final Comparator PREFER_PRICE_COMPARATOR = WINNING_BID_PG_COMPARATOR - .thenComparing(WINNING_BID_PRICE_COMPARATOR); + private static final Comparator PREFER_PRICE_COMPARATOR = WINNING_BID_PRICE_COMPARATOR; public Comparator create(boolean preferDeals) { return preferDeals @@ -43,63 +35,9 @@ private static class WinningBidDealComparator implements Comparator { @Override public int compare(BidInfo bidInfo1, BidInfo bidInfo2) { - final boolean isPresentBidDealId1 = bidInfo1.getBid().getDealid() != null; - final boolean isPresentBidDealId2 = bidInfo2.getBid().getDealid() != null; - - if (!Boolean.logicalXor(isPresentBidDealId1, isPresentBidDealId2)) { - return 0; - } - - return isPresentBidDealId1 ? 1 : -1; - } - } - - /** - * Compares two {@link BidInfo} arguments for order based on PG deal priority. - * Returns negative integer when first does not have a pg deal and second has, or when both have a pg deal, - * but first has higher index in deals array that means lower priority. - * Returns positive integer when first has a pg deal and second does not, or when both have a pg deal, - * but first has lower index in deals array that means higher priority. - * Returns zero when both dont have pg deals. - */ - private static class WinningBidPgComparator implements Comparator { - - private final Comparator dealIndexComparator = Comparator.comparingInt(Integer::intValue).reversed(); - - @Override - public int compare(BidInfo bidInfo1, BidInfo bidInfo2) { - final Imp imp = bidInfo1.getCorrespondingImp(); - final Pmp pmp = imp.getPmp(); - final List impDeals = pmp != null ? pmp.getDeals() : null; - - if (CollectionUtils.isEmpty(impDeals)) { - return 0; - } - - final Bid bid1 = bidInfo1.getBid(); - final Bid bid2 = bidInfo2.getBid(); - - int indexOfBidDealId1 = -1; - int indexOfBidDealId2 = -1; - - // search for indexes of deals - for (int i = 0; i < impDeals.size(); i++) { - final String dealId = impDeals.get(i).getId(); - if (Objects.equals(dealId, bid1.getDealid())) { - indexOfBidDealId1 = i; - } - if (Objects.equals(dealId, bid2.getDealid())) { - indexOfBidDealId2 = i; - } - } - - final boolean isPresentImpDealId1 = indexOfBidDealId1 != -1; - final boolean isPresentImpDealId2 = indexOfBidDealId2 != -1; - - final boolean isOneOrBothDealIdNotPresent = !isPresentImpDealId1 || !isPresentImpDealId2; - return isOneOrBothDealIdNotPresent - ? isPresentImpDealId1 ? 1 : -1 // case when no deal IDs found is covered by response validator - : dealIndexComparator.compare(indexOfBidDealId1, indexOfBidDealId2); + final int bidDeal1Weight = bidInfo1.getBid().getDealid() != null ? 1 : 0; + final int bidDeal2Weight = bidInfo2.getBid().getDealid() != null ? 1 : 0; + return bidDeal1Weight - bidDeal2Weight; } } diff --git a/src/main/java/org/prebid/server/auction/model/AuctionContext.java b/src/main/java/org/prebid/server/auction/model/AuctionContext.java index 39a2b09b81c..34820274916 100644 --- a/src/main/java/org/prebid/server/auction/model/AuctionContext.java +++ b/src/main/java/org/prebid/server/auction/model/AuctionContext.java @@ -10,8 +10,6 @@ import org.prebid.server.auction.model.debug.DebugContext; import org.prebid.server.cache.model.DebugHttpCall; import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.geolocation.model.GeoInfo; import org.prebid.server.hooks.execution.model.HookExecutionContext; import org.prebid.server.metric.MetricName; @@ -68,12 +66,6 @@ public class AuctionContext { boolean requestRejected; - @JsonIgnore - TxnLog txnLog; - - @JsonIgnore - DeepDebugLog deepDebugLog; - CachedDebugLog cachedDebugLog; public AuctionContext with(Account account) { diff --git a/src/main/java/org/prebid/server/auction/model/BidInfo.java b/src/main/java/org/prebid/server/auction/model/BidInfo.java index 025de675be2..2b0c452fa88 100644 --- a/src/main/java/org/prebid/server/auction/model/BidInfo.java +++ b/src/main/java/org/prebid/server/auction/model/BidInfo.java @@ -25,10 +25,6 @@ public class BidInfo { CacheInfo cacheInfo; - String lineItemId; - - String lineItemSource; - TargetingInfo targetingInfo; String category; diff --git a/src/main/java/org/prebid/server/auction/model/BidderRequest.java b/src/main/java/org/prebid/server/auction/model/BidderRequest.java index 1d18519a0f8..ad60230e54b 100644 --- a/src/main/java/org/prebid/server/auction/model/BidderRequest.java +++ b/src/main/java/org/prebid/server/auction/model/BidderRequest.java @@ -1,14 +1,10 @@ package org.prebid.server.auction.model; import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; import lombok.Builder; import lombok.Value; import org.prebid.server.auction.versionconverter.OrtbVersion; -import java.util.List; -import java.util.Map; - @Builder(toBuilder = true) @Value public class BidderRequest { @@ -19,8 +15,6 @@ public class BidderRequest { String storedResponse; - Map> impIdToDeals; - BidRequest bidRequest; public BidderRequest with(BidRequest bidRequest) { diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java index a96c26d6776..67c8c6d71e7 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AmpRequestFactory.java @@ -154,17 +154,15 @@ public Future fromRequest(RoutingContext routingContext, long st .compose(auctionContext -> ampPrivacyContextFactory.contextFrom(auctionContext) .map(auctionContext::with)) - .map(auctionContext -> auctionContext.with( - ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext))) + .compose(auctionContext -> ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext) + .map(auctionContext::with)) .compose(auctionContext -> ortb2RequestFactory.executeProcessedAuctionRequestHooks(auctionContext) .map(auctionContext::with)) - .compose(ortb2RequestFactory::populateUserAdditionalInfo) - .map(ortb2RequestFactory::enrichWithPriceFloors) - .map(auctionContext -> ortb2RequestFactory.updateTimeout(auctionContext, startTime)) + .map(ortb2RequestFactory::updateTimeout) .recover(ortb2RequestFactory::restoreResultFromRejection); } diff --git a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java index 56efcd97f02..4b4429a381e 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/AuctionRequestFactory.java @@ -96,7 +96,6 @@ public Future fromRequest(RoutingContext routingContext, long st return ortb2RequestFactory.executeEntrypointHooks(routingContext, body, initialAuctionContext) .compose(httpRequest -> parseBidRequest(httpRequest, initialAuctionContext.getPrebidErrors()) - .map(bidRequest -> ortb2RequestFactory .enrichAuctionContext(initialAuctionContext, httpRequest, bidRequest, startTime) .with(requestTypeMetric(bidRequest)))) @@ -121,17 +120,15 @@ public Future fromRequest(RoutingContext routingContext, long st .compose(auctionContext -> privacyEnforcementService.contextFromBidRequest(auctionContext) .map(auctionContext::with)) - .map(auctionContext -> auctionContext.with( - ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext))) + .compose(auctionContext -> ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext) + .map(auctionContext::with)) .compose(auctionContext -> ortb2RequestFactory.executeProcessedAuctionRequestHooks(auctionContext) .map(auctionContext::with)) - .compose(ortb2RequestFactory::populateUserAdditionalInfo) - .map(ortb2RequestFactory::enrichWithPriceFloors) - .map(auctionContext -> ortb2RequestFactory.updateTimeout(auctionContext, startTime)) + .map(ortb2RequestFactory::updateTimeout) .recover(ortb2RequestFactory::restoreResultFromRejection); } @@ -216,14 +213,12 @@ private Regs fillRegsWithValuesFromHttpRequest(Regs regs, HttpRequestContext htt */ private Future updateAndValidateBidRequest(AuctionContext auctionContext) { final Account account = auctionContext.getAccount(); + final HttpRequestContext httpRequest = auctionContext.getHttpRequest(); final List debugWarnings = auctionContext.getDebugWarnings(); return storedRequestProcessor.processAuctionRequest(account.getId(), auctionContext.getBidRequest()) .compose(auctionStoredResult -> updateBidRequest(auctionStoredResult, auctionContext)) - .compose(bidRequest -> ortb2RequestFactory.validateRequest( - bidRequest, - auctionContext.getHttpRequest(), - debugWarnings)) + .compose(bidRequest -> ortb2RequestFactory.validateRequest(bidRequest, httpRequest, debugWarnings)) .map(interstitialProcessor::process); } diff --git a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java index 67bd1dd38b7..8a062380041 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactory.java @@ -13,6 +13,7 @@ import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; +import lombok.Getter; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.ObjectUtils; @@ -27,9 +28,6 @@ import org.prebid.server.auction.model.TimeoutContext; import org.prebid.server.auction.model.debug.DebugContext; import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.deals.UserAdditionalInfoService; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.exception.BlacklistedAccountException; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.exception.PreBidException; @@ -61,7 +59,6 @@ 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.ExtRequestTargeting; -import org.prebid.server.proto.openrtb.ext.request.TraceLevel; import org.prebid.server.settings.ApplicationSettings; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; @@ -75,7 +72,6 @@ import org.prebid.server.validation.RequestValidator; import org.prebid.server.validation.model.ValidationResult; -import java.time.Clock; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -102,13 +98,11 @@ public class Ortb2RequestFactory { private final TimeoutFactory timeoutFactory; private final StoredRequestProcessor storedRequestProcessor; private final ApplicationSettings applicationSettings; - private final UserAdditionalInfoService userAdditionalInfoService; private final IpAddressHelper ipAddressHelper; private final HookStageExecutor hookStageExecutor; private final PriceFloorProcessor priceFloorProcessor; private final CountryCodeMapper countryCodeMapper; private final Metrics metrics; - private final Clock clock; public Ortb2RequestFactory(boolean enforceValidAccount, int timeoutAdjustmentFactor, @@ -123,11 +117,9 @@ public Ortb2RequestFactory(boolean enforceValidAccount, ApplicationSettings applicationSettings, IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, - UserAdditionalInfoService userAdditionalInfoService, PriceFloorProcessor priceFloorProcessor, CountryCodeMapper countryCodeMapper, - Metrics metrics, - Clock clock) { + Metrics metrics) { if (timeoutAdjustmentFactor < 0 || timeoutAdjustmentFactor > 100) { throw new IllegalArgumentException("Expected timeout adjustment factor should be in [0, 100]."); @@ -146,11 +138,9 @@ public Ortb2RequestFactory(boolean enforceValidAccount, this.applicationSettings = Objects.requireNonNull(applicationSettings); this.ipAddressHelper = Objects.requireNonNull(ipAddressHelper); this.hookStageExecutor = Objects.requireNonNull(hookStageExecutor); - this.userAdditionalInfoService = userAdditionalInfoService; this.priceFloorProcessor = Objects.requireNonNull(priceFloorProcessor); this.countryCodeMapper = Objects.requireNonNull(countryCodeMapper); this.metrics = Objects.requireNonNull(metrics); - this.clock = Objects.requireNonNull(clock); } public AuctionContext createAuctionContext(Endpoint endpoint, MetricName requestTypeMetric) { @@ -161,7 +151,6 @@ public AuctionContext createAuctionContext(Endpoint endpoint, MetricName request .hookExecutionContext(HookExecutionContext.of(endpoint)) .debugContext(DebugContext.empty()) .requestRejected(false) - .txnLog(TxnLog.create()) .debugHttpCalls(new HashMap<>()) .bidRejectionTrackers(new TreeMap<>(String.CASE_INSENSITIVE_ORDER)) .build(); @@ -177,7 +166,6 @@ public AuctionContext enrichAuctionContext(AuctionContext auctionContext, .uidsCookie(uidsCookieService.parseFromRequest(httpRequest)) .bidRequest(bidRequest) .timeoutContext(TimeoutContext.of(startTime, timeout(bidRequest, startTime), timeoutAdjustmentFactor)) - .deepDebugLog(createDeepDebugLog(bidRequest)) .build(); } @@ -221,29 +209,30 @@ public Future validateRequest(BidRequest bidRequest, : Future.succeededFuture(bidRequest); } - public BidRequest enrichBidRequestWithAccountAndPrivacyData(AuctionContext auctionContext) { + public Future enrichBidRequestWithAccountAndPrivacyData(AuctionContext auctionContext) { final BidRequest bidRequest = auctionContext.getBidRequest(); final Account account = auctionContext.getAccount(); final PrivacyContext privacyContext = auctionContext.getPrivacyContext(); - final ExtRequest requestExt = bidRequest.getExt(); - final ExtRequest enrichedRequestExt = enrichExtRequest(requestExt, account); - final Device device = bidRequest.getDevice(); final Device enrichedDevice = enrichDevice(device, privacyContext); final Regs regs = bidRequest.getRegs(); final Regs enrichedRegs = enrichRegs(regs, privacyContext, account); - if (enrichedRequestExt != null || enrichedDevice != null || enrichedRegs != null) { - return bidRequest.toBuilder() - .ext(ObjectUtils.defaultIfNull(enrichedRequestExt, requestExt)) - .device(ObjectUtils.defaultIfNull(enrichedDevice, device)) - .regs(ObjectUtils.defaultIfNull(enrichedRegs, regs)) - .build(); + final ExtRequest requestExt = bidRequest.getExt(); + final ExtRequest enrichedRequestExt = enrichExtRequest(requestExt, account); + + if (enrichedRequestExt == null && enrichedDevice == null && enrichedRegs == null) { + return Future.succeededFuture(bidRequest); } - return bidRequest; + final BidRequest enrichedBidRequest = bidRequest.toBuilder() + .device(ObjectUtils.defaultIfNull(enrichedDevice, device)) + .regs(ObjectUtils.defaultIfNull(enrichedRegs, regs)) + .ext(ObjectUtils.defaultIfNull(enrichedRequestExt, requestExt)) + .build(); + return Future.succeededFuture(enrichedBidRequest); } private static Regs enrichRegs(Regs regs, PrivacyContext privacyContext, Account account) { @@ -355,18 +344,13 @@ private static BidRequest toBidRequest(HookStageExecutionResult populateUserAdditionalInfo(AuctionContext auctionContext) { - return userAdditionalInfoService != null - ? userAdditionalInfoService.populate(auctionContext) - : Future.succeededFuture(auctionContext); - } - public AuctionContext enrichWithPriceFloors(AuctionContext auctionContext) { return priceFloorProcessor.enrichWithPriceFloors(auctionContext); } - public AuctionContext updateTimeout(AuctionContext auctionContext, long startTime) { + public AuctionContext updateTimeout(AuctionContext auctionContext) { final TimeoutContext timeoutContext = auctionContext.getTimeoutContext(); + final long startTime = timeoutContext.getStartTime(); final Timeout currentTimeout = timeoutContext.getTimeout(); final BidRequest bidRequest = auctionContext.getBidRequest(); @@ -679,19 +663,7 @@ private static CaseInsensitiveMultiMap toCaseInsensitiveMultiMap(MultiMap origin return mapBuilder.build(); } - private DeepDebugLog createDeepDebugLog(BidRequest bidRequest) { - final ExtRequest ext = bidRequest.getExt(); - return DeepDebugLog.create(ext != null && isDeepDebugEnabled(ext), clock); - } - - /** - * Determines deep debug flag from {@link ExtRequest}. - */ - private static boolean isDeepDebugEnabled(ExtRequest extRequest) { - final ExtRequestPrebid extRequestPrebid = extRequest != null ? extRequest.getPrebid() : null; - return extRequestPrebid != null && extRequestPrebid.getTrace() == TraceLevel.verbose; - } - + @Getter static class RejectedRequestException extends RuntimeException { private final AuctionContext auctionContext; @@ -699,10 +671,6 @@ static class RejectedRequestException extends RuntimeException { RejectedRequestException(AuctionContext auctionContext) { this.auctionContext = auctionContext; } - - public AuctionContext getAuctionContext() { - return auctionContext; - } } private record TargetingValueResolver(ExtRequestTargeting targeting, diff --git a/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java index 9f8fb7547dc..e3d43b49c45 100644 --- a/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java +++ b/src/main/java/org/prebid/server/auction/requestfactory/VideoRequestFactory.java @@ -108,9 +108,9 @@ public Future> fromRequest(RoutingContext routingC createBidRequest(httpRequest) .compose(bidRequest -> validateRequest( - bidRequest, - httpRequest, - initialAuctionContext.getDebugWarnings())) + bidRequest, + httpRequest, + initialAuctionContext.getDebugWarnings())) .map(bidRequestWithErrors -> populatePodErrors( bidRequestWithErrors.getPodErrors(), podErrors, bidRequestWithErrors)) @@ -129,17 +129,15 @@ public Future> fromRequest(RoutingContext routingC .compose(auctionContext -> privacyEnforcementService.contextFromBidRequest(auctionContext) .map(auctionContext::with)) - .map(auctionContext -> auctionContext.with( - ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext))) + .compose(auctionContext -> ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(auctionContext) + .map(auctionContext::with)) .compose(auctionContext -> ortb2RequestFactory.executeProcessedAuctionRequestHooks(auctionContext) .map(auctionContext::with)) - .compose(ortb2RequestFactory::populateUserAdditionalInfo) - .map(ortb2RequestFactory::enrichWithPriceFloors) - .map(auctionContext -> ortb2RequestFactory.updateTimeout(auctionContext, startTime)) + .map(ortb2RequestFactory::updateTimeout) .recover(ortb2RequestFactory::restoreResultFromRejection) diff --git a/src/main/java/org/prebid/server/bidder/DealsBidderRequestCompletionTrackerFactory.java b/src/main/java/org/prebid/server/bidder/DealsBidderRequestCompletionTrackerFactory.java deleted file mode 100644 index 8be85f88415..00000000000 --- a/src/main/java/org/prebid/server/bidder/DealsBidderRequestCompletionTrackerFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.prebid.server.bidder; - -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; -import com.iab.openrtb.response.Bid; -import io.vertx.core.Future; -import io.vertx.core.Promise; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.bidder.model.BidderBid; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class DealsBidderRequestCompletionTrackerFactory implements BidderRequestCompletionTrackerFactory { - - public BidderRequestCompletionTracker create(BidRequest bidRequest) { - final Map impToTopDealMap = new HashMap<>(); - for (final Imp imp : bidRequest.getImp()) { - final Pmp pmp = imp.getPmp(); - final List deals = pmp != null ? pmp.getDeals() : null; - final Deal topDeal = CollectionUtils.isNotEmpty(deals) ? deals.get(0) : null; - - impToTopDealMap.put(imp.getId(), topDeal != null ? topDeal.getId() : null); - } - - return !impToTopDealMap.containsValue(null) - ? new TopDealsReceivedTracker(impToTopDealMap) - : new NeverCompletedTracker(); - } - - private static class NeverCompletedTracker implements BidderRequestCompletionTracker { - - @Override - public Future future() { - return Future.failedFuture("No deals to wait for"); - } - - @Override - public void processBids(List bids) { - // no need to process bid when no deals to wait for - } - } - - private static class TopDealsReceivedTracker implements BidderRequestCompletionTracker { - - private final Map impToTopDealMap; - - private final Promise completionPromise; - - private TopDealsReceivedTracker(Map impToTopDealMap) { - this.impToTopDealMap = new HashMap<>(impToTopDealMap); - this.completionPromise = Promise.promise(); - } - - @Override - public Future future() { - return completionPromise.future(); - } - - @Override - public void processBids(List bids) { - if (completionPromise.future().isComplete()) { - return; - } - - bids.stream() - .map(BidderBid::getBid) - .filter(Objects::nonNull) - .map(this::toImpIdIfTopDeal) - .filter(Objects::nonNull) - .forEach(impToTopDealMap::remove); - - if (impToTopDealMap.isEmpty()) { - completionPromise.tryComplete(); - } - } - - private String toImpIdIfTopDeal(Bid bid) { - final String impId = bid.getImpid(); - final String dealId = bid.getDealid(); - if (StringUtils.isNoneBlank(impId, dealId)) { - final String topDealForImp = impToTopDealMap.get(impId); - if (topDealForImp != null && Objects.equals(dealId, topDealForImp)) { - return impId; - } - } - - return null; - } - } -} diff --git a/src/main/java/org/prebid/server/cache/CacheService.java b/src/main/java/org/prebid/server/cache/CacheService.java index 255144d0df9..a19b9f9fd71 100644 --- a/src/main/java/org/prebid/server/cache/CacheService.java +++ b/src/main/java/org/prebid/server/cache/CacheService.java @@ -64,7 +64,7 @@ /** * Client stores values in Prebid Cache. *

- * For more info, see https://github.com/prebid/prebid-cache project. + * For more info, see Prebid Cache project. */ public class CacheService { @@ -471,12 +471,11 @@ private CachedCreative createJsonPutObjectOpenrtb(CacheBid cacheBid, final Bid bid = bidInfo.getBid(); final ObjectNode bidObjectNode = mapper.mapper().valueToTree(bid); - final String eventUrl = - generateWinUrl(bidInfo.getBidId(), - bidInfo.getBidder(), - accountId, - eventsContext, - bidInfo.getLineItemId()); + final String eventUrl = generateWinUrl( + bidInfo.getBidId(), + bidInfo.getBidder(), + accountId, + eventsContext); if (eventUrl != null) { bidObjectNode.put(BID_WURL_ATTRIBUTE, eventUrl); } @@ -521,24 +520,15 @@ private static String resolveCustomCacheKey(String hbCacheId, String category) { private String generateWinUrl(String bidId, String bidder, String accountId, - EventsContext eventsContext, - String lineItemId) { - - if (!eventsContext.isEnabledForAccount()) { - return null; - } - - if (eventsContext.isEnabledForRequest() || StringUtils.isNotBlank(lineItemId)) { - return eventsService.winUrl( - bidId, - bidder, - accountId, - lineItemId, - eventsContext.isEnabledForRequest(), - eventsContext); - } - - return null; + EventsContext eventsContext) { + + return eventsContext.isEnabledForAccount() && eventsContext.isEnabledForRequest() + ? eventsService.winUrl( + bidId, + bidder, + accountId, + eventsContext) + : null; } /** diff --git a/src/main/java/org/prebid/server/deals/AdminCentralService.java b/src/main/java/org/prebid/server/deals/AdminCentralService.java deleted file mode 100644 index f5bd033b051..00000000000 --- a/src/main/java/org/prebid/server/deals/AdminCentralService.java +++ /dev/null @@ -1,239 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; -import org.apache.commons.collections4.MapUtils; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.deals.events.AdminEventProcessor; -import org.prebid.server.deals.model.AdminAccounts; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.deals.model.AdminLineItems; -import org.prebid.server.deals.model.Command; -import org.prebid.server.deals.model.LogTracer; -import org.prebid.server.deals.model.ServicesCommand; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.CriteriaManager; -import org.prebid.server.settings.CachingApplicationSettings; -import org.prebid.server.settings.SettingsCache; -import org.prebid.server.settings.proto.request.InvalidateSettingsCacheRequest; -import org.prebid.server.settings.proto.request.UpdateSettingsCacheRequest; -import org.prebid.server.util.ObjectUtil; - -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class AdminCentralService implements AdminEventProcessor { - - private static final Logger logger = LoggerFactory.getLogger(AdminCentralService.class); - - private static final String START = "start"; - private static final String STOP = "stop"; - private static final String INVALIDATE = "invalidate"; - private static final String SAVE = "save"; - private static final String STORED_REQUEST_CACHE = "stored request cache"; - private static final String AMP_STORED_REQUEST_CACHE = "amp stored request cache"; - - private final CriteriaManager criteriaManager; - private final LineItemService lineItemService; - private final DeliveryProgressService deliveryProgressService; - private final SettingsCache settingsCache; - private final SettingsCache ampSettingsCache; - private final CachingApplicationSettings cachingApplicationSettings; - private final JacksonMapper mapper; - private final List suspendableServices; - - public AdminCentralService(CriteriaManager criteriaManager, - LineItemService lineItemService, - DeliveryProgressService deliveryProgressService, - SettingsCache settingsCache, - SettingsCache ampSettingsCache, - CachingApplicationSettings cachingApplicationSettings, - JacksonMapper mapper, - List suspendableServices) { - this.criteriaManager = Objects.requireNonNull(criteriaManager); - this.lineItemService = Objects.requireNonNull(lineItemService); - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.settingsCache = settingsCache; - this.ampSettingsCache = ampSettingsCache; - this.cachingApplicationSettings = cachingApplicationSettings; - this.mapper = Objects.requireNonNull(mapper); - this.suspendableServices = Objects.requireNonNull(suspendableServices); - } - - @Override - public void processAdminCentralEvent(AdminCentralResponse centralAdminResponse) { - final LogTracer logTracer = centralAdminResponse.getTracer(); - if (logTracer != null) { - handleLogTracer(centralAdminResponse.getTracer()); - } - - final Command lineItemsCommand = centralAdminResponse.getLineItems(); - if (lineItemsCommand != null) { - handleLineItems(lineItemsCommand); - } - - final Command storedRequestCommand = centralAdminResponse.getStoredRequest(); - if (storedRequestCommand != null && settingsCache != null) { - handleStoredRequest(settingsCache, storedRequestCommand, STORED_REQUEST_CACHE); - } - - final Command storedRequestAmpCommand = centralAdminResponse.getStoredRequestAmp(); - if (storedRequestAmpCommand != null && ampSettingsCache != null) { - handleStoredRequest(ampSettingsCache, storedRequestAmpCommand, AMP_STORED_REQUEST_CACHE); - } - - final Command accountCommand = centralAdminResponse.getAccount(); - if (accountCommand != null && cachingApplicationSettings != null) { - handleAccountCommand(accountCommand); - } - - final ServicesCommand servicesCommand = centralAdminResponse.getServices(); - if (servicesCommand != null) { - handleServiceCommand(servicesCommand); - } - } - - private void handleAccountCommand(Command accountCommand) { - final String cmd = accountCommand.getCmd(); - if (StringUtils.isBlank(cmd)) { - logger.warn("Command for account action was not defined in register response"); - return; - } - - if (!Objects.equals(cmd, INVALIDATE)) { - logger.warn("Account commands supports only `invalidate` command, but received {0}", cmd); - return; - } - - final ObjectNode body = accountCommand.getBody(); - final AdminAccounts adminAccounts; - try { - adminAccounts = body != null - ? mapper.mapper().convertValue(body, AdminAccounts.class) - : null; - } catch (IllegalArgumentException e) { - logger.warn("Can't parse admin accounts body, failed with exception message : {0}", e.getMessage()); - return; - } - - final List accounts = ObjectUtil.getIfNotNull(adminAccounts, AdminAccounts::getAccounts); - if (CollectionUtils.isNotEmpty(accounts)) { - accounts.forEach(cachingApplicationSettings::invalidateAccountCache); - } else { - cachingApplicationSettings.invalidateAllAccountCache(); - } - } - - private void handleLineItems(Command lineItemsCommand) { - final String cmd = lineItemsCommand.getCmd(); - if (StringUtils.isBlank(cmd)) { - logger.warn("Command for line-items action was not defined in register response."); - return; - } - - if (!Objects.equals(cmd, INVALIDATE)) { - logger.warn("Line Items section supports only `invalidate` command, but received {0}", cmd); - return; - } - - final ObjectNode body = lineItemsCommand.getBody(); - final AdminLineItems adminLineItems; - try { - adminLineItems = body != null - ? mapper.mapper().convertValue(body, AdminLineItems.class) - : null; - } catch (IllegalArgumentException e) { - logger.warn("Can't parse admin line items body, failed with exception message : {0}", e.getMessage()); - return; - } - - final List lineItemIds = ObjectUtil.getIfNotNull(adminLineItems, AdminLineItems::getIds); - - if (CollectionUtils.isNotEmpty(lineItemIds)) { - lineItemService.invalidateLineItemsByIds(lineItemIds); - deliveryProgressService.invalidateLineItemsByIds(lineItemIds); - } else { - lineItemService.invalidateLineItems(); - deliveryProgressService.invalidateLineItems(); - } - } - - private void handleStoredRequest(SettingsCache settingsCache, Command storedRequestCommand, String serviceName) { - final String cmd = storedRequestCommand.getCmd(); - if (StringUtils.isBlank(cmd)) { - logger.warn("Command for {0} was not defined.", serviceName); - return; - } - - final ObjectNode body = storedRequestCommand.getBody(); - if (body == null) { - logger.warn("Command body for {0} was not defined.", serviceName); - return; - } - - switch (cmd) { - case INVALIDATE -> invalidateStoredRequests(settingsCache, serviceName, body); - case SAVE -> saveStoredRequests(settingsCache, serviceName, body); - default -> logger.warn("Command for {0} should has value 'save' or 'invalidate' but was {1}.", - serviceName, cmd); - } - } - - private void saveStoredRequests(SettingsCache settingsCache, String serviceName, ObjectNode body) { - final UpdateSettingsCacheRequest saveRequest; - try { - saveRequest = mapper.mapper().convertValue(body, UpdateSettingsCacheRequest.class); - } catch (IllegalArgumentException e) { - logger.warn("Can't parse save settings cache request object for {0}," - + " failed with exception message : {1}", serviceName, e.getMessage()); - return; - } - final Map storedRequests = MapUtils.emptyIfNull(saveRequest.getRequests()); - final Map storedImps = MapUtils.emptyIfNull(saveRequest.getImps()); - settingsCache.save(storedRequests, storedImps); - logger.info("Stored request with ids {0} and stored impressions with ids {1} were successfully saved", - String.join(", ", storedRequests.keySet()), String.join(", ", storedImps.keySet())); - } - - private void invalidateStoredRequests(SettingsCache settingsCache, String serviceName, ObjectNode body) { - final InvalidateSettingsCacheRequest invalidateRequest; - try { - invalidateRequest = mapper.mapper().convertValue(body, InvalidateSettingsCacheRequest.class); - } catch (IllegalArgumentException e) { - logger.warn("Can't parse invalidate settings cache request object for {0}," - + " failed with exception message : {1}", serviceName, e.getMessage()); - return; - } - final List requestIds = ListUtils.emptyIfNull(invalidateRequest.getRequests()); - final List impIds = ListUtils.emptyIfNull(invalidateRequest.getImps()); - settingsCache.invalidate(requestIds, impIds); - logger.info("Stored requests with ids {0} and impression with ids {1} were successfully invalidated", - String.join(", ", requestIds), String.join(", ", impIds)); - } - - private void handleLogTracer(LogTracer logTracer) { - final String command = logTracer.getCmd(); - if (StringUtils.isBlank(command)) { - logger.warn("Command for traceLogger was not defined"); - return; - } - - switch (command) { - case START -> criteriaManager.addCriteria(logTracer.getFilters(), logTracer.getDurationInSeconds()); - case STOP -> criteriaManager.stop(); - default -> logger.warn("Command for trace logger should has value 'start' or 'stop' but was {0}.", command); - } - } - - private void handleServiceCommand(ServicesCommand servicesCommand) { - final String command = servicesCommand.getCmd(); - if (command != null && command.equalsIgnoreCase(STOP)) { - suspendableServices.forEach(Suspendable::suspend); - } - logger.info("PBS services were successfully suspended"); - } -} diff --git a/src/main/java/org/prebid/server/deals/AlertHttpService.java b/src/main/java/org/prebid/server/deals/AlertHttpService.java deleted file mode 100644 index 3b89b0f2bd8..00000000000 --- a/src/main/java/org/prebid/server/deals/AlertHttpService.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.prebid.server.deals; - -import io.netty.handler.codec.http.HttpHeaderValues; -import io.vertx.core.AsyncResult; -import io.vertx.core.MultiMap; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.prebid.server.deals.model.AlertEvent; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.AlertProxyProperties; -import org.prebid.server.deals.model.AlertSource; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.json.EncodeException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class AlertHttpService { - - private static final Logger logger = LoggerFactory.getLogger(AlertHttpService.class); - private static final String RAISE = "RAISE"; - private static final Long DEFAULT_HIGH_ALERT_PERIOD = 15L; - - private final JacksonMapper mapper; - private final HttpClient httpClient; - private final Clock clock; - private final AlertProxyProperties alertProxyProperties; - private final AlertSource alertSource; - private final boolean enabled; - private final String url; - private final long timeoutMillis; - private final String authHeaderValue; - private final Map alertTypes; - private final Map alertTypesCounters; - - public AlertHttpService(JacksonMapper mapper, HttpClient httpClient, Clock clock, - DeploymentProperties deploymentProperties, - AlertProxyProperties alertProxyProperties) { - this.mapper = Objects.requireNonNull(mapper); - this.httpClient = Objects.requireNonNull(httpClient); - this.clock = Objects.requireNonNull(clock); - this.alertProxyProperties = Objects.requireNonNull(alertProxyProperties); - this.alertSource = makeSource(Objects.requireNonNull(deploymentProperties)); - this.enabled = alertProxyProperties.isEnabled(); - this.timeoutMillis = TimeUnit.SECONDS.toMillis(alertProxyProperties.getTimeoutSec()); - this.url = HttpUtil.validateUrl(Objects.requireNonNull(alertProxyProperties.getUrl())); - this.authHeaderValue = HttpUtil.makeBasicAuthHeaderValue(alertProxyProperties.getUsername(), - alertProxyProperties.getPassword()); - this.alertTypes = new ConcurrentHashMap<>(alertProxyProperties.getAlertTypes()); - this.alertTypesCounters = new ConcurrentHashMap<>(alertTypes.keySet().stream() - .collect(Collectors.toMap(Function.identity(), s -> 0L))); - } - - private static AlertSource makeSource(DeploymentProperties deploymentProperties) { - return AlertSource.builder() - .env(deploymentProperties.getProfile()) - .region(deploymentProperties.getPbsRegion()) - .dataCenter(deploymentProperties.getDataCenter()) - .subSystem(deploymentProperties.getSubSystem()) - .system(deploymentProperties.getSystem()) - .hostId(deploymentProperties.getPbsHostId()) - .build(); - } - - public void alertWithPeriod(String serviceName, String alertType, AlertPriority alertPriority, String message) { - if (alertTypes.get(alertType) == null) { - alertTypes.put(alertType, DEFAULT_HIGH_ALERT_PERIOD); - alertTypesCounters.put(alertType, 0L); - } - - long count = alertTypesCounters.get(alertType); - final long period = alertTypes.get(alertType); - - alertTypesCounters.put(alertType, ++count); - final String formattedMessage = "Service %s failed to send request %s time(s) with error message : %s" - .formatted(serviceName, count, message); - if (count == 1) { - alert(alertType, alertPriority, formattedMessage); - } else if (count % period == 0) { - alert(alertType, AlertPriority.HIGH, formattedMessage); - } - } - - public void resetAlertCount(String alertType) { - alertTypesCounters.put(alertType, 0L); - } - - public void alert(String name, AlertPriority alertPriority, String message) { - if (!enabled) { - logger.warn("Alert to proxy is not enabled in pbs configuration"); - return; - } - - final AlertEvent alertEvent = makeEvent(RAISE, alertPriority, name, message, alertSource); - - try { - httpClient.post(alertProxyProperties.getUrl(), headers(), - mapper.encodeToString(Collections.singletonList(alertEvent)), timeoutMillis) - .onComplete(this::handleResponse); - } catch (EncodeException e) { - logger.warn("Can't parse alert proxy payload: {0}", e.getMessage()); - } - } - - private AlertEvent makeEvent(String action, AlertPriority priority, String name, String details, - AlertSource alertSource) { - return AlertEvent.builder() - .id(UUID.randomUUID().toString()) - .action(action.toUpperCase()) - .priority(priority) - .name(name) - .details(details) - .updatedAt(ZonedDateTime.now(clock)) - .source(alertSource) - .build(); - } - - private MultiMap headers() { - return MultiMap.caseInsensitiveMultiMap() - .add(HttpUtil.PG_TRX_ID, UUID.randomUUID().toString()) - .add(HttpUtil.CONTENT_TYPE_HEADER, HttpHeaderValues.APPLICATION_JSON) - .add(HttpUtil.AUTHORIZATION_HEADER, authHeaderValue); - } - - private void handleResponse(AsyncResult httpClientResponseResult) { - if (httpClientResponseResult.failed()) { - logger.error("Error occurred during sending alert to proxy at {0}::{1} ", url, - httpClientResponseResult.cause().getMessage()); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/DealsService.java b/src/main/java/org/prebid/server/deals/DealsService.java deleted file mode 100644 index 662b6b8dc14..00000000000 --- a/src/main/java/org/prebid/server/deals/DealsService.java +++ /dev/null @@ -1,318 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.auction.model.AuctionParticipation; -import org.prebid.server.auction.model.BidderRequest; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.MatchLineItemsResult; -import org.prebid.server.deals.proto.LineItemSize; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.proto.openrtb.ext.request.ExtDeal; -import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; -import org.prebid.server.util.ObjectUtil; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.BiFunction; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -public class DealsService { - - private static final Logger logger = LoggerFactory.getLogger(DealsService.class); - - private static final String LINE_FIELD = "line"; - private static final String LINE_BIDDER_FIELD = "bidder"; - private static final String BIDDER_FIELD = "bidder"; - private static final String PG_DEALS_ONLY = "pgdealsonly"; - - private final LineItemService lineItemService; - private final JacksonMapper mapper; - private final CriteriaLogManager criteriaLogManager; - - public DealsService(LineItemService lineItemService, - JacksonMapper mapper, - CriteriaLogManager criteriaLogManager) { - - this.lineItemService = Objects.requireNonNull(lineItemService); - this.mapper = Objects.requireNonNull(mapper); - this.criteriaLogManager = Objects.requireNonNull(criteriaLogManager); - } - - public BidderRequest matchAndPopulateDeals(BidderRequest bidderRequest, - BidderAliases aliases, - AuctionContext context) { - - final String bidder = bidderRequest.getBidder(); - final BidRequest bidRequest = bidderRequest.getBidRequest(); - - final Map> impIdToDeals = match(bidRequest, bidder, aliases, context); - final BidRequest modifiedRequest = populateDeals(bidRequest, impIdToDeals, combinerFor(bidder, aliases)); - - return bidderRequest.toBuilder() - .impIdToDeals(impIdToDeals) - .bidRequest(modifiedRequest) - .build(); - } - - private Map> match(BidRequest bidRequest, - String bidder, - BidderAliases aliases, - AuctionContext context) { - - final boolean accountHasDeals = lineItemService.accountHasDeals(context); - if (!accountHasDeals) { - return Collections.emptyMap(); - } - - final Map> impIdToDeals = new HashMap<>(); - for (Imp imp : bidRequest.getImp()) { - final MatchLineItemsResult matchResult = lineItemService.findMatchingLineItems( - bidRequest, imp, bidder, aliases, context); - final List lineItems = matchResult.getLineItems(); - - final List deals = lineItems.stream() - .peek(this::logLineItem) - .map(lineItem -> toDeal(lineItem, imp)) - .toList(); - - if (!deals.isEmpty()) { - impIdToDeals.put(imp.getId(), deals); - } - } - - return impIdToDeals; - } - - private void logLineItem(LineItem lineItem) { - criteriaLogManager.log( - logger, - lineItem.getAccountId(), - lineItem.getSource(), - lineItem.getLineItemId(), - "LineItem %s is ready to be served".formatted(lineItem.getLineItemId()), logger::debug); - } - - private Deal toDeal(LineItem lineItem, Imp imp) { - return Deal.builder() - .id(lineItem.getDealId()) - .ext(mapper.mapper().valueToTree(ExtDeal.of(toExtDealLine(imp, lineItem)))) - .build(); - } - - private static ExtDealLine toExtDealLine(Imp imp, LineItem lineItem) { - final List formats = ObjectUtil.getIfNotNull(imp.getBanner(), Banner::getFormat); - final List lineItemSizes = lineItem.getSizes(); - - final List lineSizes = CollectionUtils.isNotEmpty(formats) && CollectionUtils.isNotEmpty(lineItemSizes) - ? intersectionOf(formats, lineItemSizes) - : null; - - return ExtDealLine.of(lineItem.getLineItemId(), lineItem.getExtLineItemId(), lineSizes, lineItem.getSource()); - } - - private static List intersectionOf(List formats, List lineItemSizes) { - final Set formatsSet = new HashSet<>(formats); - final Set lineItemFormatsSet = lineItemSizes.stream() - .map(size -> Format.builder().w(size.getW()).h(size.getH()).build()) - .collect(Collectors.toSet()); - - final List matchedSizes = lineItemFormatsSet.stream() - .filter(formatsSet::contains) - .toList(); - - return CollectionUtils.isNotEmpty(matchedSizes) ? matchedSizes : null; - } - - private static BiFunction, List, List> combinerFor(String bidder, BidderAliases aliases) { - return (originalDeals, matchedDeals) -> - Stream.concat( - originalDeals.stream().filter(deal -> isDealCorrespondsToBidder(deal, bidder, aliases)), - matchedDeals.stream()) - .map(DealsService::prepareDealForExchange) - .toList(); - } - - private static boolean isDealCorrespondsToBidder(Deal deal, String bidder, BidderAliases aliases) { - final JsonNode extLineBidder = extLineBidder(deal); - if (!isTextual(extLineBidder)) { - return true; - } - - return aliases.isSame(extLineBidder.textValue(), bidder); - } - - private static JsonNode extLineBidder(Deal deal) { - final ObjectNode ext = deal != null ? deal.getExt() : null; - final JsonNode extLine = ext != null ? ext.get(LINE_FIELD) : null; - return extLine != null ? extLine.get(LINE_BIDDER_FIELD) : null; - } - - private static boolean isTextual(JsonNode jsonNode) { - return jsonNode != null && jsonNode.isTextual(); - } - - private static Deal prepareDealForExchange(Deal deal) { - final JsonNode extLineBidder = extLineBidder(deal); - if (!isTextual(extLineBidder)) { - return deal; - } - - final ObjectNode updatedExt = deal.getExt().deepCopy(); - - final ObjectNode updatedExtLine = (ObjectNode) updatedExt.get(LINE_FIELD); - updatedExtLine.remove(LINE_BIDDER_FIELD); - - if (updatedExtLine.isEmpty()) { - updatedExt.remove(LINE_FIELD); - } - - return deal.toBuilder().ext(!updatedExt.isEmpty() ? updatedExt : null).build(); - } - - public static BidRequest populateDeals(BidRequest bidRequest, Map> impIdToDeals) { - return populateDeals(bidRequest, impIdToDeals, ListUtils::union); - } - - private static BidRequest populateDeals(BidRequest bidRequest, - Map> impIdToDeals, - BiFunction, List, List> dealsCombiner) { - - final List originalImps = bidRequest.getImp(); - final List updatedImp = originalImps.stream() - .map(imp -> populateDeals(imp, impIdToDeals.get(imp.getId()), dealsCombiner)) - .toList(); - - if (updatedImp.stream().allMatch(Objects::isNull)) { - return bidRequest; - } - - return bidRequest.toBuilder() - .imp(IntStream.range(0, originalImps.size()) - .mapToObj(i -> ObjectUtils.defaultIfNull(updatedImp.get(i), originalImps.get(i))) - .toList()) - .build(); - } - - private static Imp populateDeals(Imp imp, - List matchedDeals, - BiFunction, List, List> dealsCombiner) { - - final Pmp pmp = imp.getPmp(); - final List originalDeal = pmp != null ? pmp.getDeals() : null; - - final List combinedDeals = dealsCombiner.apply( - ListUtils.emptyIfNull(originalDeal), - ListUtils.emptyIfNull(matchedDeals)); - if (CollectionUtils.isEmpty(combinedDeals)) { - return null; - } - - final Pmp.PmpBuilder pmpBuilder = pmp != null ? pmp.toBuilder() : Pmp.builder(); - return imp.toBuilder() - .pmp(pmpBuilder.deals(combinedDeals).build()) - .build(); - } - - public static List removePgDealsOnlyImpsWithoutDeals( - List auctionParticipations, - AuctionContext context) { - - return auctionParticipations.stream() - .map(auctionParticipation -> removePgDealsOnlyImpsWithoutDeals(auctionParticipation, context)) - .filter(Objects::nonNull) - .toList(); - } - - private static AuctionParticipation removePgDealsOnlyImpsWithoutDeals(AuctionParticipation auctionParticipation, - AuctionContext context) { - - final BidderRequest bidderRequest = auctionParticipation.getBidderRequest(); - final String bidder = bidderRequest.getBidder(); - final BidRequest bidRequest = bidderRequest.getBidRequest(); - final List imps = bidRequest.getImp(); - - final Set impsIndicesToRemove = IntStream.range(0, imps.size()) - .filter(i -> isPgDealsOnly(imps.get(i))) - .filter(i -> !havePgDeal(imps.get(i), bidderRequest.getImpIdToDeals())) - .boxed() - .collect(Collectors.toSet()); - - if (impsIndicesToRemove.isEmpty()) { - return auctionParticipation; - } - if (impsIndicesToRemove.size() == imps.size()) { - logImpsExclusion(context, bidder, imps); - return null; - } - - final List impsToRemove = new ArrayList<>(); - final List filteredImps = new ArrayList<>(); - for (int i = 0; i < imps.size(); i++) { - final Imp imp = imps.get(i); - if (impsIndicesToRemove.contains(i)) { - impsToRemove.add(imp); - } else { - filteredImps.add(imp); - } - } - - logImpsExclusion(context, bidder, impsToRemove); - - return auctionParticipation.toBuilder() - .bidderRequest(bidderRequest.toBuilder() - .bidRequest(bidRequest.toBuilder() - .imp(filteredImps) - .build()) - .build()) - .build(); - } - - private static boolean isPgDealsOnly(Imp imp) { - final JsonNode extBidder = imp.getExt().get(BIDDER_FIELD); - if (extBidder == null || !extBidder.isObject()) { - return false; - } - - final JsonNode pgDealsOnlyNode = extBidder.path(PG_DEALS_ONLY); - return pgDealsOnlyNode.isBoolean() && pgDealsOnlyNode.asBoolean(); - } - - private static boolean havePgDeal(Imp imp, Map> impIdToDeals) { - return impIdToDeals != null && CollectionUtils.isNotEmpty(impIdToDeals.get(imp.getId())); - } - - private static void logImpsExclusion(AuctionContext context, - String bidder, - List imps) { - - final String impsIds = imps.stream() - .map(Imp::getId) - .collect(Collectors.joining(", ")); - context.getDebugWarnings().add( - "Not calling %s bidder for impressions %s due to %s flag and no available PG line items." - .formatted(bidder, impsIds, PG_DEALS_ONLY)); - } -} diff --git a/src/main/java/org/prebid/server/deals/DeliveryProgressReportFactory.java b/src/main/java/org/prebid/server/deals/DeliveryProgressReportFactory.java deleted file mode 100644 index 85d3089b79a..00000000000 --- a/src/main/java/org/prebid/server/deals/DeliveryProgressReportFactory.java +++ /dev/null @@ -1,313 +0,0 @@ -package org.prebid.server.deals; - -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.deals.lineitem.DeliveryPlan; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.lineitem.DeliveryToken; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.DeliveryProgressReportBatch; -import org.prebid.server.deals.proto.report.DeliverySchedule; -import org.prebid.server.deals.proto.report.LineItemStatus; -import org.prebid.server.deals.proto.report.LostToLineItem; -import org.prebid.server.deals.proto.report.Token; -import org.prebid.server.util.ObjectUtil; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -public class DeliveryProgressReportFactory { - - private static final Logger logger = LoggerFactory.getLogger(DeliveryProgressReportFactory.class); - - private static final LostToLineItemComparator LOST_TO_LINE_ITEM_COMPARATOR = new LostToLineItemComparator(); - - private final DeploymentProperties deploymentProperties; - private final int competitorsNumber; - private final LineItemService lineItemService; - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - public DeliveryProgressReportFactory( - DeploymentProperties deploymentProperties, int competitorsNumber, LineItemService lineItemService) { - this.deploymentProperties = Objects.requireNonNull(deploymentProperties); - this.competitorsNumber = competitorsNumber; - this.lineItemService = Objects.requireNonNull(lineItemService); - } - - public DeliveryProgressReport fromDeliveryProgress( - DeliveryProgress deliveryProgress, - ZonedDateTime now, - boolean isOverall) { - final List lineItemStatuses = - new ArrayList<>(deliveryProgress.getLineItemStatuses().values()); - return DeliveryProgressReport.builder() - .reportId(UUID.randomUUID().toString()) - .reportTimeStamp(now != null ? formatTimeStamp(now) : null) - .dataWindowStartTimeStamp(isOverall ? null : formatTimeStamp(deliveryProgress.getStartTimeStamp())) - .dataWindowEndTimeStamp(isOverall ? null : formatTimeStamp(deliveryProgress.getEndTimeStamp())) - .instanceId(deploymentProperties.getPbsHostId()) - .region(deploymentProperties.getPbsRegion()) - .vendor(deploymentProperties.getPbsVendor()) - .clientAuctions(deliveryProgress.getRequests().sum()) - .lineItemStatus(makeLineItemStatusReports(deliveryProgress, lineItemStatuses, - deliveryProgress.getLineItemStatuses(), isOverall)) - .build(); - } - - public DeliveryProgressReportBatch batchFromDeliveryProgress( - DeliveryProgress deliveryProgress, - Map overallLineItemStatuses, - ZonedDateTime now, - int batchSize, - boolean isOverall) { - final List lineItemStatuses - = new ArrayList<>(deliveryProgress.getLineItemStatuses().values()); - final String reportId = UUID.randomUUID().toString(); - final String reportTimeStamp = now != null ? formatTimeStamp(now) : null; - final String dataWindowStartTimeStamp = isOverall - ? null - : formatTimeStamp(deliveryProgress.getStartTimeStamp()); - final String dataWindowEndTimeStamp = isOverall ? null : formatTimeStamp(deliveryProgress.getEndTimeStamp()); - final long clientAuctions = deliveryProgress.getRequests().sum(); - - final int lineItemsCount = lineItemStatuses.size(); - final int batchesNumber = lineItemsCount / batchSize + (lineItemsCount % batchSize > 0 ? 1 : 0); - final Set reportsBatch = IntStream.range(0, batchesNumber) - .mapToObj(batchNumber -> updateReportWithLineItems(deliveryProgress, lineItemStatuses, - overallLineItemStatuses, lineItemsCount, batchNumber, batchSize, isOverall)) - .map(deliveryProgressReport -> deliveryProgressReport - .reportId(reportId) - .reportTimeStamp(reportTimeStamp) - .dataWindowStartTimeStamp(dataWindowStartTimeStamp) - .dataWindowEndTimeStamp(dataWindowEndTimeStamp) - .clientAuctions(clientAuctions) - .instanceId(deploymentProperties.getPbsHostId()) - .region(deploymentProperties.getPbsRegion()) - .vendor(deploymentProperties.getPbsVendor()) - .build()) - .collect(Collectors.toSet()); - - logNotDeliveredLineItems(deliveryProgress, reportsBatch); - return DeliveryProgressReportBatch.of(reportsBatch, reportId, dataWindowEndTimeStamp); - } - - private DeliveryProgressReport.DeliveryProgressReportBuilder updateReportWithLineItems( - DeliveryProgress deliveryProgress, - List lineItemStatuses, - Map overallLineItemStatuses, - int lineItemsCount, - int batchNumber, - int batchSize, - boolean isOverall) { - final int startBatchIndex = batchNumber * batchSize; - final int endBatchIndex = (batchNumber + 1) * batchSize; - final List batchList = - lineItemStatuses.subList(startBatchIndex, Math.min(endBatchIndex, lineItemsCount)); - return DeliveryProgressReport.builder() - .lineItemStatus(makeLineItemStatusReports(deliveryProgress, batchList, - overallLineItemStatuses, isOverall)); - } - - private Set makeLineItemStatusReports( - DeliveryProgress deliveryProgress, - List lineItemStatuses, - Map overallLineItemStatuses, - boolean isOverall) { - - return lineItemStatuses.stream() - .map(lineItemStatus -> toLineItemStatusReport(lineItemStatus, - overallLineItemStatuses != null - ? overallLineItemStatuses.get(lineItemStatus.getLineItemId()) - : null, - deliveryProgress, isOverall)) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - - private static void logNotDeliveredLineItems(DeliveryProgress deliveryProgress, - Set reportsBatch) { - final Set reportedLineItems = reportsBatch.stream() - .map(DeliveryProgressReport::getLineItemStatus) - .flatMap(Collection::stream) - .map(LineItemStatus::getLineItemId) - .collect(Collectors.toSet()); - - final String notDeliveredLineItems = deliveryProgress.getLineItemStatuses().keySet().stream() - .filter(id -> !reportedLineItems.contains(id)) - .collect(Collectors.joining(", ")); - if (StringUtils.isNotBlank(notDeliveredLineItems)) { - logger.info("Line item with id {0} will not be reported," - + " as it does not have active delivery schedules during report window.", notDeliveredLineItems); - } - } - - DeliveryProgressReport updateReportTimeStamp(DeliveryProgressReport deliveryProgressReport, ZonedDateTime now) { - return deliveryProgressReport.toBuilder().reportTimeStamp(formatTimeStamp(now)).build(); - } - - private LineItemStatus toLineItemStatusReport(org.prebid.server.deals.lineitem.LineItemStatus lineItemStatus, - org.prebid.server.deals.lineitem.LineItemStatus overallLineItemStatus, - DeliveryProgress deliveryProgress, boolean isOverall) { - final String lineItemId = lineItemStatus.getLineItemId(); - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - if (isOverall && lineItem == null) { - return null; - } - final DeliveryPlan activeDeliveryPlan = ObjectUtil.getIfNotNull(lineItem, LineItem::getActiveDeliveryPlan); - final Set deliverySchedules = deliverySchedule(lineItemStatus, overallLineItemStatus, - activeDeliveryPlan); - if (CollectionUtils.isEmpty(deliverySchedules) && !isOverall) { - return null; - } - - return LineItemStatus.builder() - .lineItemSource(ObjectUtil.firstNonNull(lineItemStatus::getSource, - () -> ObjectUtil.getIfNotNull(lineItem, LineItem::getSource))) - .lineItemId(lineItemId) - .dealId(ObjectUtil.firstNonNull(lineItemStatus::getDealId, - () -> ObjectUtil.getIfNotNull(lineItem, LineItem::getDealId))) - .extLineItemId(ObjectUtil.firstNonNull(lineItemStatus::getExtLineItemId, - () -> ObjectUtil.getIfNotNull(lineItem, LineItem::getExtLineItemId))) - .accountAuctions(accountRequests(ObjectUtil.firstNonNull(lineItemStatus::getAccountId, - () -> ObjectUtil.getIfNotNull(lineItem, LineItem::getAccountId)), deliveryProgress)) - .domainMatched(lineItemStatus.getDomainMatched().sum()) - .targetMatched(lineItemStatus.getTargetMatched().sum()) - .targetMatchedButFcapped(lineItemStatus.getTargetMatchedButFcapped().sum()) - .targetMatchedButFcapLookupFailed(lineItemStatus.getTargetMatchedButFcapLookupFailed().sum()) - .pacingDeferred(lineItemStatus.getPacingDeferred().sum()) - .sentToBidder(lineItemStatus.getSentToBidder().sum()) - .sentToBidderAsTopMatch(lineItemStatus.getSentToBidderAsTopMatch().sum()) - .receivedFromBidder(lineItemStatus.getReceivedFromBidder().sum()) - .receivedFromBidderInvalidated(lineItemStatus.getReceivedFromBidderInvalidated().sum()) - .sentToClient(lineItemStatus.getSentToClient().sum()) - .sentToClientAsTopMatch(lineItemStatus.getSentToClientAsTopMatch().sum()) - .lostToLineItems(lostToLineItems(lineItemStatus, deliveryProgress)) - .events(lineItemStatus.getEvents()) - .deliverySchedule(deliverySchedules) - .readyAt(isOverall ? toReadyAt(lineItem) : null) - .spentTokens(isOverall && activeDeliveryPlan != null ? activeDeliveryPlan.getSpentTokens() : null) - .pacingFrequency(isOverall && activeDeliveryPlan != null - ? activeDeliveryPlan.getDeliveryRateInMilliseconds() - : null) - .build(); - } - - private String toReadyAt(LineItem lineItem) { - final ZonedDateTime readyAt = ObjectUtil.getIfNotNull(lineItem, LineItem::getReadyAt); - return readyAt != null ? UTC_MILLIS_FORMATTER.format(readyAt) : null; - } - - private Long accountRequests(String accountId, DeliveryProgress deliveryProgress) { - final LongAdder accountRequests = accountId != null - ? deliveryProgress.getRequestsPerAccount().get(accountId) - : null; - return accountRequests != null ? accountRequests.sum() : null; - } - - private Set lostToLineItems(org.prebid.server.deals.lineitem.LineItemStatus lineItemStatus, - DeliveryProgress deliveryProgress) { - final Map lostTo = - deliveryProgress.getLineItemIdToLost().get(lineItemStatus.getLineItemId()); - - if (lostTo != null) { - return lostTo.values().stream() - .sorted(LOST_TO_LINE_ITEM_COMPARATOR.reversed()) - .map(this::toLostToLineItems) - .limit(competitorsNumber) - .collect(Collectors.toSet()); - } - - return null; - } - - private LostToLineItem toLostToLineItems(org.prebid.server.deals.lineitem.LostToLineItem lostToLineItem) { - final String lineItemId = lostToLineItem.getLineItemId(); - return LostToLineItem.of( - ObjectUtil.getIfNotNull(lineItemService.getLineItemById(lineItemId), LineItem::getSource), lineItemId, - lostToLineItem.getCount().sum()); - } - - private static Set deliverySchedule( - org.prebid.server.deals.lineitem.LineItemStatus lineItemStatus, - org.prebid.server.deals.lineitem.LineItemStatus overallLineItemStatus, - DeliveryPlan activeDeliveryPlan) { - - final Map idToDeliveryPlan = overallLineItemStatus != null - ? overallLineItemStatus.getDeliveryPlans().stream() - .collect(Collectors.toMap(DeliveryPlan::getPlanId, Function.identity())) - : Collections.emptyMap(); - - final Set deliverySchedules = lineItemStatus.getDeliveryPlans().stream() - .map(deliveryPlan -> toDeliverySchedule(deliveryPlan, idToDeliveryPlan.get(deliveryPlan.getPlanId()))) - .collect(Collectors.toSet()); - - if (CollectionUtils.isEmpty(deliverySchedules)) { - if (activeDeliveryPlan != null) { - deliverySchedules.add(DeliveryProgressReportFactory - .toDeliverySchedule(activeDeliveryPlan.withoutSpentTokens())); - } - } - return deliverySchedules; - } - - static DeliverySchedule toDeliverySchedule(DeliveryPlan deliveryPlan) { - return toDeliverySchedule(deliveryPlan, null); - } - - private static DeliverySchedule toDeliverySchedule(DeliveryPlan plan, DeliveryPlan overallPlan) { - final Map priorityClassToTotalSpent = overallPlan != null - ? overallPlan.getDeliveryTokens().stream() - .collect(Collectors.toMap(DeliveryToken::getPriorityClass, deliveryToken -> deliveryToken.getSpent() - .sum())) - : Collections.emptyMap(); - - final Set tokens = plan.getDeliveryTokens().stream() - .map(token -> Token.of(token.getPriorityClass(), token.getTotal(), - token.getSpent().sum(), priorityClassToTotalSpent.get(token.getPriorityClass()))) - .collect(Collectors.toSet()); - - return DeliverySchedule.builder() - .planId(plan.getPlanId()) - .planStartTimeStamp(formatTimeStamp(plan.getStartTimeStamp())) - .planExpirationTimeStamp(formatTimeStamp(plan.getEndTimeStamp())) - .planUpdatedTimeStamp(formatTimeStamp(plan.getUpdatedTimeStamp())) - .tokens(tokens) - .build(); - } - - private static String formatTimeStamp(ZonedDateTime zonedDateTime) { - return zonedDateTime != null - ? UTC_MILLIS_FORMATTER.format(zonedDateTime) - : null; - } - - private static class LostToLineItemComparator implements - Comparator { - - @Override - public int compare(org.prebid.server.deals.lineitem.LostToLineItem lostToLineItem1, - org.prebid.server.deals.lineitem.LostToLineItem lostToLineItem2) { - return Long.compare(lostToLineItem1.getCount().sum(), lostToLineItem2.getCount().sum()); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/DeliveryProgressService.java b/src/main/java/org/prebid/server/deals/DeliveryProgressService.java deleted file mode 100644 index ab65595ea47..00000000000 --- a/src/main/java/org/prebid/server/deals/DeliveryProgressService.java +++ /dev/null @@ -1,208 +0,0 @@ -package org.prebid.server.deals; - -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.events.ApplicationEventProcessor; -import org.prebid.server.deals.lineitem.DeliveryPlan; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.lineitem.LineItemStatus; -import org.prebid.server.deals.model.DeliveryProgressProperties; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.DeliverySchedule; -import org.prebid.server.deals.proto.report.LineItemStatusReport; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.log.CriteriaLogManager; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -/** - * Tracks {@link LineItem}s' progress. - */ -public class DeliveryProgressService implements ApplicationEventProcessor { - - private static final Logger logger = LoggerFactory.getLogger(DeliveryProgressService.class); - - private final DeliveryProgressProperties deliveryProgressProperties; - private final LineItemService lineItemService; - private final DeliveryStatsService deliveryStatsService; - private final DeliveryProgressReportFactory deliveryProgressReportFactory; - private final Clock clock; - private final CriteriaLogManager criteriaLogManager; - - private final long lineItemStatusTtl; - - protected final DeliveryProgress overallDeliveryProgress; - protected DeliveryProgress currentDeliveryProgress; - - public DeliveryProgressService(DeliveryProgressProperties deliveryProgressProperties, - LineItemService lineItemService, - DeliveryStatsService deliveryStatsService, - DeliveryProgressReportFactory deliveryProgressReportFactory, - Clock clock, - CriteriaLogManager criteriaLogManager) { - this.deliveryProgressProperties = Objects.requireNonNull(deliveryProgressProperties); - this.lineItemService = Objects.requireNonNull(lineItemService); - this.deliveryStatsService = Objects.requireNonNull(deliveryStatsService); - this.deliveryProgressReportFactory = Objects.requireNonNull(deliveryProgressReportFactory); - this.clock = Objects.requireNonNull(clock); - this.criteriaLogManager = Objects.requireNonNull(criteriaLogManager); - - this.lineItemStatusTtl = TimeUnit.SECONDS.toMillis(deliveryProgressProperties.getLineItemStatusTtlSeconds()); - - final ZonedDateTime now = ZonedDateTime.now(clock); - overallDeliveryProgress = DeliveryProgress.of(now, lineItemService); - currentDeliveryProgress = DeliveryProgress.of(now, lineItemService); - } - - public void shutdown() { - createDeliveryProgressReports(ZonedDateTime.now(clock)); - deliveryStatsService.sendDeliveryProgressReports(); - } - - /** - * Updates copy of overall {@link DeliveryProgress} with current delivery progress and - * creates {@link DeliveryProgressReport}. - */ - public DeliveryProgressReport getOverallDeliveryProgressReport() { - final DeliveryProgress overallDeliveryProgressCopy = - overallDeliveryProgress.copyWithOriginalPlans(); - - lineItemService.getLineItems() - .forEach(lineItem -> overallDeliveryProgressCopy.getLineItemStatuses() - .putIfAbsent(lineItem.getLineItemId(), LineItemStatus.of(lineItem.getLineItemId(), - lineItem.getSource(), lineItem.getDealId(), lineItem.getExtLineItemId(), - lineItem.getAccountId()))); - - overallDeliveryProgressCopy.mergeFrom(currentDeliveryProgress); - return deliveryProgressReportFactory.fromDeliveryProgress(overallDeliveryProgressCopy, ZonedDateTime.now(clock), - true); - } - - /** - * Updates delivery progress from {@link AuctionContext} statistics. - */ - @Override - public void processAuctionEvent(AuctionContext auctionContext) { - processAuctionEvent(auctionContext.getTxnLog(), auctionContext.getAccount().getId(), ZonedDateTime.now(clock)); - } - - /** - * Updates delivery progress from {@link AuctionContext} statistics for defined date. - */ - protected void processAuctionEvent(TxnLog txnLog, String accountId, ZonedDateTime now) { - final Map planIdToTokenPriority = new HashMap<>(); - - txnLog.lineItemSentToClientAsTopMatch().stream() - .map(lineItemService::getLineItemById) - .filter(Objects::nonNull) - .filter(lineItem -> lineItem.getActiveDeliveryPlan() != null) - .forEach(lineItem -> incrementTokens(lineItem, now, planIdToTokenPriority)); - - currentDeliveryProgress.recordTransactionLog(txnLog, planIdToTokenPriority, accountId); - } - - /** - * Updates delivery progress with win event. - */ - @Override - public void processLineItemWinEvent(String lineItemId) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - if (lineItem != null) { - currentDeliveryProgress.recordWinEvent(lineItemId); - criteriaLogManager.log(logger, lineItem.getAccountId(), lineItem.getSource(), lineItemId, - "Win event for LineItem with id %s was recorded".formatted(lineItemId), logger::debug); - } - } - - @Override - public void processDeliveryProgressUpdateEvent() { - lineItemService.getLineItems() - .stream() - .filter(lineItem -> lineItem.getActiveDeliveryPlan() != null) - .forEach(this::mergePlanFromLineItem); - } - - private void mergePlanFromLineItem(LineItem lineItem) { - overallDeliveryProgress.upsertPlanReferenceFromLineItem(lineItem); - currentDeliveryProgress.mergePlanFromLineItem(lineItem); - } - - /** - * Prepare report from statuses to send it to delivery stats. - */ - public void createDeliveryProgressReports(ZonedDateTime now) { - final DeliveryProgress deliveryProgressToReport = currentDeliveryProgress; - - currentDeliveryProgress = DeliveryProgress.of(now, lineItemService); - - deliveryProgressToReport.setEndTimeStamp(now); - deliveryProgressToReport.updateWithActiveLineItems(lineItemService.getLineItems()); - - overallDeliveryProgress.mergeFrom(deliveryProgressToReport); - - deliveryStatsService.addDeliveryProgress(deliveryProgressToReport, - overallDeliveryProgress.getLineItemStatuses()); - - overallDeliveryProgress.cleanLineItemStatuses( - now, lineItemStatusTtl, deliveryProgressProperties.getCachedPlansNumber()); - } - - public void invalidateLineItemsByIds(List lineItemIds) { - overallDeliveryProgress.getLineItemStatuses().entrySet() - .removeIf(stringLineItemEntry -> lineItemIds.contains(stringLineItemEntry.getKey())); - currentDeliveryProgress.getLineItemStatuses().entrySet() - .removeIf(stringLineItemEntry -> lineItemIds.contains(stringLineItemEntry.getKey())); - } - - public void invalidateLineItems() { - overallDeliveryProgress.getLineItemStatuses().clear(); - currentDeliveryProgress.getLineItemStatuses().clear(); - } - - /** - * Increments tokens for specified in parameters lineItem, plan and class priority. - */ - protected void incrementTokens(LineItem lineItem, ZonedDateTime now, Map planIdToTokenPriority) { - final Integer classPriority = lineItem.incSpentToken(now); - if (classPriority != null) { - planIdToTokenPriority.put(lineItem.getActiveDeliveryPlan().getPlanId(), classPriority); - } - } - - /** - * Returns {@link LineItemStatusReport} for the given {@link LineItem}'s ID. - */ - public LineItemStatusReport getLineItemStatusReport(String lineItemId) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - if (lineItem == null) { - throw new PreBidException("LineItem not found: " + lineItemId); - } - - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - if (activeDeliveryPlan == null) { - return LineItemStatusReport.builder() - .lineItemId(lineItemId) - .build(); - } - - final DeliverySchedule deliverySchedule = DeliveryProgressReportFactory.toDeliverySchedule(activeDeliveryPlan); - return LineItemStatusReport.builder() - .lineItemId(lineItemId) - .deliverySchedule(deliverySchedule) - .readyToServeTimestamp(lineItem.getReadyAt()) - .spentTokens(activeDeliveryPlan.getSpentTokens()) - .pacingFrequency(activeDeliveryPlan.getDeliveryRateInMilliseconds()) - .accountId(lineItem.getAccountId()) - .target(lineItem.getTargeting()) - .build(); - } -} diff --git a/src/main/java/org/prebid/server/deals/DeliveryStatsService.java b/src/main/java/org/prebid/server/deals/DeliveryStatsService.java deleted file mode 100644 index 8fe8973b394..00000000000 --- a/src/main/java/org/prebid/server/deals/DeliveryStatsService.java +++ /dev/null @@ -1,294 +0,0 @@ -package org.prebid.server.deals; - -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.http.HttpHeaders; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.lineitem.LineItemStatus; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeliveryStatsProperties; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.DeliveryProgressReportBatch; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.MetricName; -import org.prebid.server.metric.Metrics; -import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.Base64; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Map; -import java.util.NavigableSet; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentSkipListSet; -import java.util.zip.GZIPOutputStream; - -public class DeliveryStatsService implements Suspendable { - - private static final Logger logger = LoggerFactory.getLogger(DeliveryStatsService.class); - - private static final String BASIC_AUTH_PATTERN = "Basic %s"; - private static final String PG_TRX_ID = "pg-trx-id"; - private static final String PBS_DELIVERY_CLIENT_ERROR = "pbs-delivery-stats-client-error"; - private static final String SERVICE_NAME = "deliveryStats"; - public static final String GZIP = "gzip"; - - private final DeliveryStatsProperties deliveryStatsProperties; - private final DeliveryProgressReportFactory deliveryProgressReportFactory; - private final AlertHttpService alertHttpService; - private final HttpClient httpClient; - private final Metrics metrics; - private final Clock clock; - private final Vertx vertx; - private final JacksonMapper mapper; - - private final String basicAuthHeader; - private final NavigableSet requiredBatches; - private volatile boolean isSuspended; - - public DeliveryStatsService(DeliveryStatsProperties deliveryStatsProperties, - DeliveryProgressReportFactory deliveryProgressReportFactory, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - Vertx vertx, - JacksonMapper mapper) { - - this.deliveryStatsProperties = Objects.requireNonNull(deliveryStatsProperties); - this.deliveryProgressReportFactory = Objects.requireNonNull(deliveryProgressReportFactory); - this.alertHttpService = Objects.requireNonNull(alertHttpService); - this.httpClient = Objects.requireNonNull(httpClient); - this.clock = Objects.requireNonNull(clock); - this.vertx = Objects.requireNonNull(vertx); - this.metrics = Objects.requireNonNull(metrics); - this.mapper = Objects.requireNonNull(mapper); - this.basicAuthHeader = authHeader(deliveryStatsProperties.getUsername(), deliveryStatsProperties.getPassword()); - - requiredBatches = new ConcurrentSkipListSet<>(Comparator - .comparing(DeliveryProgressReportBatch::getDataWindowEndTimeStamp) - .thenComparing(DeliveryProgressReportBatch::hashCode)); - } - - @Override - public void suspend() { - isSuspended = true; - } - - public void addDeliveryProgress(DeliveryProgress deliveryProgress, - Map overallLineItemStatuses) { - requiredBatches.add(deliveryProgressReportFactory.batchFromDeliveryProgress(deliveryProgress, - overallLineItemStatuses, null, deliveryStatsProperties.getLineItemsPerReport(), false)); - } - - public void sendDeliveryProgressReports() { - sendDeliveryProgressReports(ZonedDateTime.now(clock)); - } - - public void sendDeliveryProgressReports(ZonedDateTime now) { - if (isSuspended) { - logger.warn("Report will not be sent, as service was suspended from register response"); - return; - } - final long batchesIntervalMs = deliveryStatsProperties.getBatchesIntervalMs(); - final int batchesCount = requiredBatches.size(); - final Set sentBatches = new HashSet<>(); - requiredBatches.stream() - .reduce(Future.succeededFuture(), - (future, batch) -> future.compose(v -> sendBatch(batch, now) - .map(aVoid -> sentBatches.add(batch)) - .compose(aVoid -> batchesIntervalMs > 0 && batchesCount > sentBatches.size() - ? setInterval(batchesIntervalMs) - : Future.succeededFuture())), - // combiner does not do any useful operations, just required for this type of reduce operation - (a, b) -> Promise.promise().future()) - .onComplete(result -> handleDeliveryResult(result, batchesCount, sentBatches)); - } - - protected Future sendBatch(DeliveryProgressReportBatch deliveryProgressReportBatch, ZonedDateTime now) { - final Promise promise = Promise.promise(); - final MultiMap headers = headers(); - final Set sentReports = new HashSet<>(); - final long reportIntervalMs = deliveryStatsProperties.getReportsIntervalMs(); - final Set reports = deliveryProgressReportBatch.getReports(); - final int reportsCount = reports.size(); - reports.stream() - .reduce(Future.succeededFuture(), - (future, report) -> future.compose(v -> sendReport(report, headers, now) - .map(aVoid -> sentReports.add(report))) - .compose(aVoid -> reportIntervalMs > 0 && reportsCount > sentReports.size() - ? setInterval(reportIntervalMs) - : Future.succeededFuture()), - (a, b) -> Promise.promise().future()) - .onComplete(result -> handleBatchDelivery(result, deliveryProgressReportBatch, sentReports, promise)); - return promise.future(); - } - - protected Future sendReport(DeliveryProgressReport deliveryProgressReport, MultiMap headers, - ZonedDateTime now) { - final Promise promise = Promise.promise(); - final long startTime = clock.millis(); - if (isSuspended) { - logger.warn("Report will not be sent, as service was suspended from register response"); - promise.complete(); - return promise.future(); - } - - final String body = mapper.encodeToString(deliveryProgressReportFactory - .updateReportTimeStamp(deliveryProgressReport, now)); - - logger.info("Sending delivery progress report to Delivery Stats, {0} is {1}", PG_TRX_ID, - headers.get(PG_TRX_ID)); - logger.debug("Delivery progress report is: {0}", body); - if (deliveryStatsProperties.isRequestCompressionEnabled()) { - headers.add(HttpHeaders.CONTENT_ENCODING, GZIP); - httpClient.request(HttpMethod.POST, deliveryStatsProperties.getEndpoint(), headers, gzipBody(body), - deliveryStatsProperties.getTimeoutMs()) - .onComplete(result -> handleDeliveryProgressReport(result, deliveryProgressReport, promise, - startTime)); - } else { - httpClient.post(deliveryStatsProperties.getEndpoint(), headers, body, - deliveryStatsProperties.getTimeoutMs()) - .onComplete(result -> handleDeliveryProgressReport(result, deliveryProgressReport, promise, - startTime)); - } - - return promise.future(); - } - - /** - * Handles delivery report response from Planner. - */ - private void handleDeliveryProgressReport(AsyncResult result, - DeliveryProgressReport deliveryProgressReport, - Promise promise, - long startTime) { - metrics.updateRequestTimeMetric(MetricName.delivery_request_time, clock.millis() - startTime); - if (result.failed()) { - logger.warn("Cannot send delivery progress report to delivery stats service", result.cause()); - promise.fail(new PreBidException("Sending report with id = %s failed in a reason: %s" - .formatted(deliveryProgressReport.getReportId(), result.cause().getMessage()))); - } else { - final int statusCode = result.result().getStatusCode(); - final String reportId = deliveryProgressReport.getReportId(); - if (statusCode == 200 || statusCode == 409) { - handleSuccessfulResponse(deliveryProgressReport, promise, statusCode, reportId); - } else { - logger.warn("HTTP status code {0}", statusCode); - promise.fail(new PreBidException( - "Delivery stats service responded with status code = %s for report with id = %s" - .formatted(statusCode, deliveryProgressReport.getReportId()))); - } - } - } - - private void handleSuccessfulResponse(DeliveryProgressReport deliveryProgressReport, Promise promise, - int statusCode, String reportId) { - metrics.updateDeliveryRequestMetric(true); - promise.complete(); - if (statusCode == 409) { - logger.info("Delivery stats service respond with 409 duplicated, report with {0} line items and id = {1}" - + " was already delivered before and will be removed from from delivery queue", - deliveryProgressReport.getLineItemStatus().size(), reportId); - } else { - logger.info("Delivery progress report with {0} line items and id = {1} was successfully sent to" - + " delivery stats service", deliveryProgressReport.getLineItemStatus().size(), reportId); - } - } - - private Future setInterval(long interval) { - final Promise promise = Promise.promise(); - vertx.setTimer(interval, event -> promise.complete()); - return promise.future(); - } - - private void handleDeliveryResult(AsyncResult result, int reportBatchesNumber, - Set sentBatches) { - if (result.failed()) { - logger.warn("Failed to send {0} report batches, {1} report batches left to send." - + " Reason is: {2}", reportBatchesNumber, reportBatchesNumber - sentBatches.size(), - result.cause().getMessage()); - alertHttpService.alertWithPeriod( - SERVICE_NAME, - PBS_DELIVERY_CLIENT_ERROR, - AlertPriority.MEDIUM, - "Report was not send to delivery stats service with a reason: " + result.cause().getMessage()); - requiredBatches.removeAll(sentBatches); - handleFailedReportDelivery(); - } else { - requiredBatches.clear(); - alertHttpService.resetAlertCount(PBS_DELIVERY_CLIENT_ERROR); - logger.info("{0} report batches were successfully sent.", reportBatchesNumber); - } - } - - private void handleBatchDelivery(AsyncResult result, - DeliveryProgressReportBatch deliveryProgressReportBatch, - Set sentReports, - Promise promise) { - final String reportId = deliveryProgressReportBatch.getReportId(); - final String endTimeWindow = deliveryProgressReportBatch.getDataWindowEndTimeStamp(); - final int batchSize = deliveryProgressReportBatch.getReports().size(); - final int sentSize = sentReports.size(); - if (result.succeeded()) { - logger.info("Batch of reports with reports id = {0}, end time window = {1} and size {2} was successfully" - + " sent", reportId, endTimeWindow, batchSize); - promise.complete(); - } else { - logger.warn("Failed to sent batch of reports with reports id = {0} end time windows = {1}." - + " {2} out of {3} were sent.", reportId, endTimeWindow, sentSize, batchSize); - deliveryProgressReportBatch.removeReports(sentReports); - promise.fail(result.cause().getMessage()); - } - } - - protected MultiMap headers() { - return MultiMap.caseInsensitiveMultiMap() - .add(HttpUtil.AUTHORIZATION_HEADER, basicAuthHeader) - .add(HttpUtil.CONTENT_TYPE_HEADER, HttpUtil.APPLICATION_JSON_CONTENT_TYPE) - .add(PG_TRX_ID, UUID.randomUUID().toString()); - } - - /** - * Creates Authorization header value from username and password. - */ - private static String authHeader(String username, String password) { - return BASIC_AUTH_PATTERN - .formatted(Base64.getEncoder().encodeToString((username + ':' + password).getBytes())); - } - - private static byte[] gzipBody(String body) { - try ( - ByteArrayOutputStream obj = new ByteArrayOutputStream(); - GZIPOutputStream gzip = new GZIPOutputStream(obj)) { - gzip.write(body.getBytes(StandardCharsets.UTF_8)); - gzip.finish(); - return obj.toByteArray(); - } catch (IOException e) { - throw new PreBidException("Failed to gzip request with a reason : " + e.getMessage()); - } - } - - private void handleFailedReportDelivery() { - metrics.updateDeliveryRequestMetric(false); - while (requiredBatches.size() > deliveryStatsProperties.getCachedReportsNumber()) { - requiredBatches.pollFirst(); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/LineItemService.java b/src/main/java/org/prebid/server/deals/LineItemService.java deleted file mode 100644 index 1fafdadfa9b..00000000000 --- a/src/main/java/org/prebid/server/deals/LineItemService.java +++ /dev/null @@ -1,591 +0,0 @@ -package org.prebid.server.deals; - -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Imp; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.lineitem.DeliveryPlan; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.MatchLineItemsResult; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.deals.targeting.TargetingDefinition; -import org.prebid.server.exception.TargetingSyntaxException; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category; -import org.prebid.server.util.HttpUtil; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * Works with {@link LineItem} related information. - */ -public class LineItemService { - - private static final Logger logger = LoggerFactory.getLogger(LineItemService.class); - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String ACTIVE = "active"; - private static final String PG_IGNORE_PACING_VALUE = "1"; - - private final Comparator lineItemComparator = Comparator - .comparing(LineItem::getHighestUnspentTokensClass, Comparator.nullsLast(Comparator.naturalOrder())) - .thenComparing(LineItem::getRelativePriority, Comparator.nullsLast(Comparator.naturalOrder())) - .thenComparing(LineItem::getCpm, Comparator.nullsLast(Comparator.reverseOrder())); - - private final int maxDealsPerBidder; - private final TargetingService targetingService; - private final CurrencyConversionService conversionService; - protected final ApplicationEventService applicationEventService; - private final String adServerCurrency; - private final Clock clock; - private final CriteriaLogManager criteriaLogManager; - - protected final Map idToLineItems; - protected volatile boolean isPlannerResponsive; - - public LineItemService(int maxDealsPerBidder, - TargetingService targetingService, - CurrencyConversionService conversionService, - ApplicationEventService applicationEventService, - String adServerCurrency, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - this.maxDealsPerBidder = maxDealsPerBidder; - this.targetingService = Objects.requireNonNull(targetingService); - this.conversionService = Objects.requireNonNull(conversionService); - this.applicationEventService = Objects.requireNonNull(applicationEventService); - this.adServerCurrency = Objects.requireNonNull(adServerCurrency); - this.clock = Objects.requireNonNull(clock); - this.criteriaLogManager = Objects.requireNonNull(criteriaLogManager); - - idToLineItems = new ConcurrentHashMap<>(); - } - - /** - * Returns {@link LineItem} by its id. - */ - public LineItem getLineItemById(String lineItemId) { - return idToLineItems.get(lineItemId); - } - - /** - * Returns true when account has at least one active {@link LineItem}. - */ - public boolean accountHasDeals(AuctionContext auctionContext) { - return accountHasDeals(auctionContext.getAccount().getId(), ZonedDateTime.now(clock)); - } - - /** - * Returns true when account has at least one active {@link LineItem} in the given time. - */ - public boolean accountHasDeals(String account, ZonedDateTime now) { - return StringUtils.isNotEmpty(account) - && idToLineItems.values().stream().anyMatch(lineItem -> Objects.equals(lineItem.getAccountId(), account) - && lineItem.isActive(now)); - } - - /** - * Finds among active Line Items those matching Imp of the OpenRTB2 request - * taking into account Line Items’ targeting and delivery progress. - */ - public MatchLineItemsResult findMatchingLineItems(BidRequest bidRequest, - Imp imp, - String bidder, - BidderAliases aliases, - AuctionContext auctionContext) { - - final ZonedDateTime now = ZonedDateTime.now(clock); - return findMatchingLineItems(bidRequest, imp, bidder, aliases, auctionContext, now); - } - - /** - * Finds among active Line Items those matching Imp of the OpenRTB2 request - * taking into account Line Items’ targeting and delivery progress by the given time. - */ - protected MatchLineItemsResult findMatchingLineItems(BidRequest bidRequest, - Imp imp, - String bidder, - BidderAliases aliases, - AuctionContext auctionContext, - ZonedDateTime now) { - - final List matchedLineItems = - getPreMatchedLineItems(auctionContext.getAccount().getId(), bidder, aliases).stream() - .filter(lineItem -> isTargetingMatched(lineItem, bidRequest, imp, auctionContext)) - .toList(); - - return MatchLineItemsResult.of( - postProcessMatchedLineItems(matchedLineItems, bidRequest, imp, auctionContext, now)); - } - - public void updateIsPlannerResponsive(boolean isPlannerResponsive) { - this.isPlannerResponsive = isPlannerResponsive; - } - - /** - * Updates metadata, starts tracking new {@link LineItem}s and {@link DeliverySchedule}s - * and remove from tracking expired. - */ - public void updateLineItems(List planResponse, boolean isPlannerResponsive) { - updateLineItems(planResponse, isPlannerResponsive, ZonedDateTime.now(clock)); - } - - public void updateLineItems(List planResponse, boolean isPlannerResponsive, ZonedDateTime now) { - this.isPlannerResponsive = isPlannerResponsive; - if (isPlannerResponsive) { - final List lineItemsMetaData = ListUtils.emptyIfNull(planResponse).stream() - .filter(lineItemMetaData -> !isExpired(now, lineItemMetaData.getEndTimeStamp())) - .filter(lineItemMetaData -> Objects.equals(lineItemMetaData.getStatus(), ACTIVE)) - .toList(); - - removeInactiveLineItems(planResponse, now); - lineItemsMetaData.forEach(lineItemMetaData -> updateLineItem(lineItemMetaData, now)); - } - } - - public void invalidateLineItemsByIds(List lineItemIds) { - idToLineItems.entrySet().removeIf(stringLineItemEntry -> lineItemIds.contains(stringLineItemEntry.getKey())); - logger.info("Line Items with ids {0} were removed", String.join(", ", lineItemIds)); - } - - public void invalidateLineItems() { - final String lineItemsToRemove = String.join(", ", idToLineItems.keySet()); - idToLineItems.clear(); - logger.info("Line Items with ids {0} were removed", lineItemsToRemove); - } - - private boolean isExpired(ZonedDateTime now, ZonedDateTime endTime) { - return now.isAfter(endTime); - } - - private void removeInactiveLineItems(List planResponse, ZonedDateTime now) { - final Set lineItemsToRemove = ListUtils.emptyIfNull(planResponse).stream() - .filter(lineItemMetaData -> !Objects.equals(lineItemMetaData.getStatus(), ACTIVE) - || isExpired(now, lineItemMetaData.getEndTimeStamp())) - .map(LineItemMetaData::getLineItemId) - .collect(Collectors.toSet()); - - idToLineItems.entrySet().stream() - .filter(entry -> isExpired(now, entry.getValue().getEndTimeStamp())) - .map(Map.Entry::getKey) - .collect(Collectors.toCollection(() -> lineItemsToRemove)); - - if (CollectionUtils.isNotEmpty(lineItemsToRemove)) { - logger.info("Line Items {0} were dropped as expired or inactive", String.join(", ", lineItemsToRemove)); - } - idToLineItems.entrySet().removeIf(entry -> lineItemsToRemove.contains(entry.getKey())); - } - - protected Collection getLineItems() { - return idToLineItems.values(); - } - - protected void updateLineItem(LineItemMetaData lineItemMetaData, ZonedDateTime now) { - final TargetingDefinition targetingDefinition = makeTargeting(lineItemMetaData); - final Price normalizedPrice = normalizedPrice(lineItemMetaData); - - idToLineItems.compute(lineItemMetaData.getLineItemId(), (id, li) -> li != null - ? li.withUpdatedMetadata(lineItemMetaData, normalizedPrice, targetingDefinition, li.getReadyAt(), now) - : LineItem.of(lineItemMetaData, normalizedPrice, targetingDefinition, now)); - } - - public void advanceToNextPlan(ZonedDateTime now) { - final Collection lineItems = idToLineItems.values(); - for (LineItem lineItem : lineItems) { - lineItem.advanceToNextPlan(now, isPlannerResponsive); - } - applicationEventService.publishDeliveryUpdateEvent(); - } - - /** - * Creates {@link TargetingDefinition} from {@link LineItemMetaData} targeting json node. - */ - private TargetingDefinition makeTargeting(LineItemMetaData lineItemMetaData) { - TargetingDefinition targetingDefinition; - try { - targetingDefinition = targetingService.parseTargetingDefinition(lineItemMetaData.getTargeting(), - lineItemMetaData.getLineItemId()); - } catch (TargetingSyntaxException e) { - criteriaLogManager.log( - logger, - lineItemMetaData.getAccountId(), - lineItemMetaData.getSource(), - lineItemMetaData.getLineItemId(), - "Line item targeting parsing failed with a reason: " + e.getMessage(), - logger::warn); - targetingDefinition = null; - } - return targetingDefinition; - } - - /** - * Returns {@link Price} with converted lineItem cpm to adServerCurrency. - */ - private Price normalizedPrice(LineItemMetaData lineItemMetaData) { - final Price price = lineItemMetaData.getPrice(); - if (price == null) { - return null; - } - - final String receivedCur = price.getCurrency(); - if (StringUtils.equals(adServerCurrency, receivedCur)) { - return price; - } - final BigDecimal updatedCpm = conversionService - .convertCurrency(price.getCpm(), Collections.emptyMap(), receivedCur, adServerCurrency, null); - - return Price.of(updatedCpm, adServerCurrency); - } - - private List getPreMatchedLineItems(String accountId, String bidder, BidderAliases aliases) { - if (StringUtils.isBlank(accountId)) { - return Collections.emptyList(); - } - - final List accountsLineItems = idToLineItems.values().stream() - .filter(lineItem -> lineItem.getAccountId().equals(accountId)) - .toList(); - - if (accountsLineItems.isEmpty()) { - criteriaLogManager.log( - logger, - accountId, - "There are no line items for account " + accountId, - logger::debug); - return Collections.emptyList(); - } - - return accountsLineItems.stream() - .filter(lineItem -> aliases.isSame(bidder, lineItem.getSource())) - .toList(); - } - - /** - * Returns true if {@link LineItem}s {@link TargetingDefinition} matches to {@link Imp}. - *

- * Updates deep debug log with matching information. - */ - private boolean isTargetingMatched(LineItem lineItem, - BidRequest bidRequest, - Imp imp, - AuctionContext auctionContext) { - - final TargetingDefinition targetingDefinition = lineItem.getTargetingDefinition(); - final String accountId = auctionContext.getAccount().getId(); - final String source = lineItem.getSource(); - final String lineItemId = lineItem.getLineItemId(); - if (targetingDefinition == null) { - deepDebug( - auctionContext, - Category.targeting, - "Line Item %s targeting was not defined or has incorrect format".formatted(lineItemId), - accountId, - source, - lineItemId); - return false; - } - - final boolean matched = targetingService.matchesTargeting( - bidRequest, imp, lineItem.getTargetingDefinition(), auctionContext); - - final String debugMessage = matched - ? "Line Item %s targeting matched imp with id %s".formatted(lineItemId, imp.getId()) - : "Line Item %s targeting did not match imp with id %s".formatted(lineItemId, imp.getId()); - deepDebug( - auctionContext, - Category.targeting, - debugMessage, - accountId, - source, - lineItemId); - - return matched; - } - - /** - * Filters {@link LineItem}s by next parameters: fcaps, readyAt, limit per bidder, same deal line items. - */ - private List postProcessMatchedLineItems(List lineItems, - BidRequest bidRequest, - Imp imp, - AuctionContext auctionContext, - ZonedDateTime now) { - - final TxnLog txnLog = auctionContext.getTxnLog(); - final List fcapIds = bidRequest.getUser().getExt().getFcapIds(); - - return lineItems.stream() - .peek(lineItem -> txnLog.lineItemsMatchedWholeTargeting().add(lineItem.getLineItemId())) - .filter(lineItem -> isNotFrequencyCapped(fcapIds, lineItem, auctionContext, txnLog)) - .filter(lineItem -> planHasTokensIfPresent(lineItem, auctionContext)) - .filter(lineItem -> isReadyAtInPast(now, lineItem, auctionContext, txnLog)) - .peek(lineItem -> txnLog.lineItemsReadyToServe().add(lineItem.getLineItemId())) - .collect(Collectors.groupingBy(lineItem -> lineItem.getSource().toLowerCase())) - .values().stream() - .map(valueAsLineItems -> filterLineItemPerBidder(valueAsLineItems, auctionContext, imp)) - .filter(CollectionUtils::isNotEmpty) - .peek(lineItemsForBidder -> recordInTxnSentToBidderAsTopMatch(txnLog, lineItemsForBidder)) - .flatMap(Collection::stream) - .peek(lineItem -> txnLog.lineItemsSentToBidder().get(lineItem.getSource()) - .add(lineItem.getLineItemId())) - .toList(); - } - - private boolean planHasTokensIfPresent(LineItem lineItem, AuctionContext auctionContext) { - if (hasUnspentTokens(lineItem) || ignorePacing(auctionContext)) { - return true; - } - - final String lineItemId = lineItem.getLineItemId(); - final String lineItemSource = lineItem.getSource(); - auctionContext.getTxnLog().lineItemsPacingDeferred().add(lineItemId); - deepDebug( - auctionContext, - Category.pacing, - "Matched Line Item %s for bidder %s does not have unspent tokens to be served" - .formatted(lineItemId, lineItemSource), - auctionContext.getAccount().getId(), - lineItemSource, - lineItemId); - - return false; - } - - private boolean hasUnspentTokens(LineItem lineItem) { - final DeliveryPlan deliveryPlan = lineItem.getActiveDeliveryPlan(); - return deliveryPlan == null || deliveryPlan.getDeliveryTokens().stream() - .anyMatch(deliveryToken -> deliveryToken.getUnspent() > 0); - } - - private static boolean ignorePacing(AuctionContext auctionContext) { - return PG_IGNORE_PACING_VALUE - .equals(auctionContext.getHttpRequest().getHeaders().get(HttpUtil.PG_IGNORE_PACING)); - } - - private boolean isReadyAtInPast(ZonedDateTime now, - LineItem lineItem, - AuctionContext auctionContext, - TxnLog txnLog) { - - final ZonedDateTime readyAt = lineItem.getReadyAt(); - final boolean ready = (readyAt != null && isBeforeOrEqual(readyAt, now)) || ignorePacing(auctionContext); - final String accountId = auctionContext.getAccount().getId(); - final String lineItemSource = lineItem.getSource(); - final String lineItemId = lineItem.getLineItemId(); - - if (ready) { - deepDebug( - auctionContext, - Category.pacing, - "Matched Line Item %s for bidder %s ready to serve. relPriority %d" - .formatted(lineItemId, lineItemSource, lineItem.getRelativePriority()), - accountId, - lineItemSource, - lineItemId); - } else { - txnLog.lineItemsPacingDeferred().add(lineItemId); - deepDebug( - auctionContext, - Category.pacing, - "Matched Line Item %s for bidder %s not ready to serve. Will be ready at %s, current time is %s" - .formatted( - lineItemId, - lineItemSource, - readyAt != null ? UTC_MILLIS_FORMATTER.format(readyAt) : "never", - UTC_MILLIS_FORMATTER.format(now)), - accountId, - lineItemSource, - lineItemId); - } - - return ready; - } - - private static boolean isBeforeOrEqual(ZonedDateTime before, ZonedDateTime after) { - return before.isBefore(after) || before.isEqual(after); - } - - /** - * Returns false if {@link LineItem} has fcaps defined and either - * - one of them present in the list of fcaps reached - * - list of fcaps reached is null which means that calling User Data Store failed - *

- * Otherwise returns true - *

- * Has side effect - records discarded line item id in the transaction log - */ - private boolean isNotFrequencyCapped(List frequencyCappedByIds, - LineItem lineItem, - AuctionContext auctionContext, - TxnLog txnLog) { - - if (CollectionUtils.isEmpty(lineItem.getFcapIds())) { - return true; - } - - final String lineItemId = lineItem.getLineItemId(); - final String accountId = auctionContext.getAccount().getId(); - final String lineItemSource = lineItem.getSource(); - - if (frequencyCappedByIds == null) { - txnLog.lineItemsMatchedTargetingFcapLookupFailed().add(lineItemId); - final String message = """ - Failed to match fcap for Line Item %s bidder %s in a reason of bad \ - response from user data service""".formatted(lineItemId, lineItemSource); - deepDebug(auctionContext, Category.pacing, message, accountId, lineItemSource, lineItemId); - criteriaLogManager.log( - logger, - lineItem.getAccountId(), - lineItem.getSource(), - lineItemId, - "Failed to match fcap for lineItem %s in a reason of bad response from user data service" - .formatted(lineItemId), - logger::debug); - - return false; - } else if (!frequencyCappedByIds.isEmpty()) { - final Optional fcapIdOptional = lineItem.getFcapIds().stream() - .filter(frequencyCappedByIds::contains).findFirst(); - if (fcapIdOptional.isPresent()) { - final String fcapId = fcapIdOptional.get(); - txnLog.lineItemsMatchedTargetingFcapped().add(lineItemId); - final String message = "Matched Line Item %s for bidder %s is frequency capped by fcap id %s." - .formatted(lineItemId, lineItemSource, fcapId); - deepDebug(auctionContext, Category.pacing, message, accountId, lineItemSource, lineItemId); - criteriaLogManager.log( - logger, lineItem.getAccountId(), lineItem.getSource(), lineItemId, message, logger::debug); - return false; - } - } - - return true; - } - - /** - * Filters {@link LineItem} with the same deal id and cuts {@link List} by maxDealsPerBidder value. - */ - private List filterLineItemPerBidder(List lineItems, AuctionContext auctionContext, Imp imp) { - final List sortedLineItems = new ArrayList<>(lineItems); - Collections.shuffle(sortedLineItems); - sortedLineItems.sort(lineItemComparator); - - final List filteredLineItems = uniqueBySentToBidderAsTopMatch(sortedLineItems, auctionContext, imp); - updateLostToLineItems(filteredLineItems, auctionContext.getTxnLog()); - - final Set dealIds = new HashSet<>(); - final List resolvedLineItems = new ArrayList<>(); - for (final LineItem lineItem : filteredLineItems) { - final String dealId = lineItem.getDealId(); - if (!dealIds.contains(dealId)) { - dealIds.add(dealId); - resolvedLineItems.add(lineItem); - } - } - return resolvedLineItems.size() > maxDealsPerBidder - ? cutLineItemsToDealMaxNumber(resolvedLineItems) - : resolvedLineItems; - } - - /** - * Removes from consideration any line items that have already been sent to bidder as the TopMatch - * in a previous impression for auction. - */ - private List uniqueBySentToBidderAsTopMatch(List lineItems, - AuctionContext auctionContext, - Imp imp) { - - final TxnLog txnLog = auctionContext.getTxnLog(); - final Set topMatchedLineItems = txnLog.lineItemsSentToBidderAsTopMatch().values().stream() - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - - final List result = new ArrayList<>(lineItems); - for (LineItem lineItem : lineItems) { - final String lineItemId = lineItem.getLineItemId(); - if (!topMatchedLineItems.contains(lineItemId)) { - return result; - } - result.remove(lineItem); - deepDebug( - auctionContext, - Category.cleanup, - "LineItem %s was dropped from imp with id %s because it was top match in another imp" - .formatted(lineItemId, imp.getId()), - auctionContext.getAccount().getId(), - lineItem.getSource(), - lineItemId); - } - return result; - } - - private List cutLineItemsToDealMaxNumber(List resolvedLineItems) { - resolvedLineItems.subList(maxDealsPerBidder, resolvedLineItems.size()) - .forEach(lineItem -> criteriaLogManager.log( - logger, - lineItem.getAccountId(), - lineItem.getSource(), - lineItem.getLineItemId(), - "LineItem %s was dropped by max deal per bidder limit %s" - .formatted(lineItem.getLineItemId(), maxDealsPerBidder), - logger::debug)); - return resolvedLineItems.subList(0, maxDealsPerBidder); - } - - private void updateLostToLineItems(List lineItems, TxnLog txnLog) { - for (int i = 1; i < lineItems.size(); i++) { - final LineItem lineItem = lineItems.get(i); - final Set lostTo = lineItems.subList(0, i).stream() - .map(LineItem::getLineItemId) - .collect(Collectors.toSet()); - txnLog.lostMatchingToLineItems().put(lineItem.getLineItemId(), lostTo); - } - } - - private void deepDebug(AuctionContext auctionContext, - Category category, - String message, - String accountId, - String bidder, - String lineItemId) { - - criteriaLogManager.log(logger, accountId, bidder, lineItemId, message, logger::debug); - auctionContext.getDeepDebugLog().add(lineItemId, category, () -> message); - } - - private static void recordInTxnSentToBidderAsTopMatch(TxnLog txnLog, List lineItemsForBidder) { - final LineItem topLineItem = lineItemsForBidder.get(0); - txnLog.lineItemsSentToBidderAsTopMatch() - .get(topLineItem.getSource()) - .add(topLineItem.getLineItemId()); - } -} diff --git a/src/main/java/org/prebid/server/deals/PlannerService.java b/src/main/java/org/prebid/server/deals/PlannerService.java deleted file mode 100644 index e719ad314f2..00000000000 --- a/src/main/java/org/prebid/server/deals/PlannerService.java +++ /dev/null @@ -1,239 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.type.TypeReference; -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.json.DecodeException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.MetricName; -import org.prebid.server.metric.Metrics; -import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.time.Clock; -import java.util.Base64; -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Class manages line item metadata retrieving from planner and reporting. - */ -public class PlannerService implements Suspendable { - - private static final Logger logger = LoggerFactory.getLogger(PlannerService.class); - - protected static final TypeReference> LINE_ITEM_METADATA_TYPE_REFERENCE = - new TypeReference<>() { - }; - - private static final String BASIC_AUTH_PATTERN = "Basic %s"; - private static final String PG_TRX_ID = "pg-trx-id"; - private static final String INSTANCE_ID_PARAMETER = "instanceId"; - private static final String REGION_PARAMETER = "region"; - private static final String VENDOR_PARAMETER = "vendor"; - private static final String SERVICE_NAME = "planner"; - private static final String PBS_PLANNER_CLIENT_ERROR = "pbs-planner-client-error"; - private static final String PBS_PLANNER_EMPTY_RESPONSE = "pbs-planner-empty-response-error"; - - private final LineItemService lineItemService; - private final DeliveryProgressService deliveryProgressService; - private final AlertHttpService alertHttpService; - protected final HttpClient httpClient; - private final Metrics metrics; - private final Clock clock; - private final JacksonMapper mapper; - - protected final String planEndpoint; - private final long plannerTimeout; - private final String basicAuthHeader; - - protected final AtomicBoolean isPlannerResponsive; - private volatile boolean isSuspended; - - public PlannerService(PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - LineItemService lineItemService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - JacksonMapper mapper) { - this.lineItemService = Objects.requireNonNull(lineItemService); - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.alertHttpService = Objects.requireNonNull(alertHttpService); - this.httpClient = Objects.requireNonNull(httpClient); - this.metrics = Objects.requireNonNull(metrics); - this.clock = Objects.requireNonNull(clock); - this.mapper = Objects.requireNonNull(mapper); - - this.planEndpoint = buildPlannerMetaDataUrl(plannerProperties.getPlanEndpoint(), - deploymentProperties.getPbsHostId(), - deploymentProperties.getPbsRegion(), - deploymentProperties.getPbsVendor()); - this.plannerTimeout = plannerProperties.getTimeoutMs(); - this.basicAuthHeader = authHeader(plannerProperties.getUsername(), plannerProperties.getPassword()); - - this.isPlannerResponsive = new AtomicBoolean(true); - } - - @Override - public void suspend() { - isSuspended = true; - } - - /** - * Fetches line items meta data from Planner - */ - protected Future> fetchLineItemMetaData(String plannerUrl, MultiMap headers) { - logger.info("Requesting line items metadata and plans from Planner, {0} is {1}", PG_TRX_ID, - headers.get(PG_TRX_ID)); - final long startTime = clock.millis(); - return httpClient.get(plannerUrl, headers, plannerTimeout) - .map(httpClientResponse -> processLineItemMetaDataResponse(httpClientResponse, startTime)); - } - - protected MultiMap headers() { - return MultiMap.caseInsensitiveMultiMap() - .add(HttpUtil.AUTHORIZATION_HEADER, basicAuthHeader) - .add(PG_TRX_ID, UUID.randomUUID().toString()); - } - - /** - * Processes response from planner. - * If status code == 4xx - stop fetching process. - * If status code =! 2xx - start retry fetching process. - * If status code == 200 - parse response. - */ - protected List processLineItemMetaDataResponse(HttpClientResponse response, long startTime) { - final int statusCode = response.getStatusCode(); - if (statusCode != 200) { - throw new PreBidException("Failed to fetch data from Planner, HTTP status code " + statusCode); - } - - final String body = response.getBody(); - if (body == null) { - throw new PreBidException("Failed to fetch data from planner, response can't be null"); - } - - metrics.updateRequestTimeMetric(MetricName.planner_request_time, clock.millis() - startTime); - - logger.debug("Received line item metadata and plans from Planner: {0}", body); - - try { - final List lineItemMetaData = mapper.decodeValue(body, - LINE_ITEM_METADATA_TYPE_REFERENCE); - validateForEmptyResponse(lineItemMetaData); - metrics.updateLineItemsNumberMetric(lineItemMetaData.size()); - logger.info("Received line item metadata from Planner, amount: {0}", lineItemMetaData.size()); - - return lineItemMetaData; - } catch (DecodeException e) { - final String errorMessage = "Cannot parse response: " + body; - throw new PreBidException(errorMessage, e); - } - } - - private void validateForEmptyResponse(List lineItemMetaData) { - if (CollectionUtils.isEmpty(lineItemMetaData)) { - alertHttpService.alertWithPeriod(SERVICE_NAME, PBS_PLANNER_EMPTY_RESPONSE, AlertPriority.LOW, - "Response without line items was received from planner"); - } else { - alertHttpService.resetAlertCount(PBS_PLANNER_EMPTY_RESPONSE); - } - } - - /** - * Creates Authorization header value from username and password. - */ - private static String authHeader(String username, String password) { - return BASIC_AUTH_PATTERN - .formatted(Base64.getEncoder().encodeToString((username + ':' + password).getBytes())); - } - - /** - * Builds url for fetching metadata from planner - */ - private static String buildPlannerMetaDataUrl(String plannerMetaDataUrl, String pbsHostname, String pbsRegion, - String pbsVendor) { - return "%s?%s=%s&%s=%s&%s=%s".formatted( - plannerMetaDataUrl, - INSTANCE_ID_PARAMETER, - pbsHostname, - REGION_PARAMETER, - pbsRegion, - VENDOR_PARAMETER, - pbsVendor); - } - - /** - * Fetches line item metadata from planner during the regular, not retry flow. - */ - public void updateLineItemMetaData() { - if (isSuspended) { - logger.warn("Fetch request was not sent to general planner, as planner service is suspended from" - + " register endpoint."); - return; - } - - final MultiMap headers = headers(); - fetchLineItemMetaData(planEndpoint, headers) - .recover(ignored -> startRecoveryProcess(planEndpoint, headers)) - .onComplete(this::handleInitializationResult); - } - - private Future> startRecoveryProcess(String planEndpoint, MultiMap headers) { - metrics.updatePlannerRequestMetric(false); - logger.info("Retry to fetch line items from general planner by uri = {0}", planEndpoint); - - return fetchLineItemMetaData(planEndpoint, headers); - } - - /** - * Handles result of initialization process. Sets metadata if request was successful. - */ - protected void handleInitializationResult(AsyncResult> plannerResponse) { - if (plannerResponse.succeeded()) { - handleSuccessInitialization(plannerResponse); - } else { - handleFailedInitialization(plannerResponse); - } - } - - private void handleSuccessInitialization(AsyncResult> plannerResponse) { - alertHttpService.resetAlertCount(PBS_PLANNER_CLIENT_ERROR); - metrics.updatePlannerRequestMetric(true); - isPlannerResponsive.set(true); - lineItemService.updateIsPlannerResponsive(true); - updateMetaData(plannerResponse.result()); - } - - private void handleFailedInitialization(AsyncResult> plannerResponse) { - final String message = "Failed to retrieve line items from GP. Reason: " + plannerResponse.cause().getMessage(); - alertHttpService.alertWithPeriod(SERVICE_NAME, PBS_PLANNER_CLIENT_ERROR, AlertPriority.MEDIUM, message); - logger.warn(message); - isPlannerResponsive.set(false); - lineItemService.updateIsPlannerResponsive(false); - metrics.updatePlannerRequestMetric(false); - } - - /** - * Overwrites maps with metadata - */ - private void updateMetaData(List metaData) { - lineItemService.updateLineItems(metaData, isPlannerResponsive.get()); - deliveryProgressService.processDeliveryProgressUpdateEvent(); - } -} diff --git a/src/main/java/org/prebid/server/deals/RegisterService.java b/src/main/java/org/prebid/server/deals/RegisterService.java deleted file mode 100644 index fd77aa00248..00000000000 --- a/src/main/java/org/prebid/server/deals/RegisterService.java +++ /dev/null @@ -1,187 +0,0 @@ -package org.prebid.server.deals; - -import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.AsyncResult; -import io.vertx.core.MultiMap; -import io.vertx.core.Vertx; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.events.AdminEventService; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.proto.CurrencyServiceState; -import org.prebid.server.deals.proto.RegisterRequest; -import org.prebid.server.deals.proto.Status; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.health.HealthMonitor; -import org.prebid.server.json.DecodeException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.Initializable; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.math.BigDecimal; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.Base64; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -public class RegisterService implements Initializable, Suspendable { - - private static final Logger logger = LoggerFactory.getLogger(RegisterService.class); - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String BASIC_AUTH_PATTERN = "Basic %s"; - private static final String PG_TRX_ID = "pg-trx-id"; - private static final String PBS_REGISTER_CLIENT_ERROR = "pbs-register-client-error"; - private static final String SERVICE_NAME = "register"; - - private final PlannerProperties plannerProperties; - private final DeploymentProperties deploymentProperties; - private final AdminEventService adminEventService; - private final DeliveryProgressService deliveryProgressService; - private final AlertHttpService alertHttpService; - private final HealthMonitor healthMonitor; - private final CurrencyConversionService currencyConversionService; - private final HttpClient httpClient; - private final Vertx vertx; - private final JacksonMapper mapper; - - private final long registerTimeout; - private final long registerPeriod; - private final String basicAuthHeader; - private volatile long registerTimerId; - private volatile boolean isSuspended; - - public RegisterService(PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - AdminEventService adminEventService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HealthMonitor healthMonitor, - CurrencyConversionService currencyConversionService, - HttpClient httpClient, - Vertx vertx, - JacksonMapper mapper) { - this.plannerProperties = Objects.requireNonNull(plannerProperties); - this.deploymentProperties = Objects.requireNonNull(deploymentProperties); - this.adminEventService = Objects.requireNonNull(adminEventService); - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.alertHttpService = Objects.requireNonNull(alertHttpService); - this.healthMonitor = Objects.requireNonNull(healthMonitor); - this.currencyConversionService = Objects.requireNonNull(currencyConversionService); - this.httpClient = Objects.requireNonNull(httpClient); - this.vertx = Objects.requireNonNull(vertx); - this.mapper = Objects.requireNonNull(mapper); - - this.registerTimeout = plannerProperties.getTimeoutMs(); - this.registerPeriod = TimeUnit.SECONDS.toMillis(plannerProperties.getRegisterPeriodSeconds()); - this.basicAuthHeader = authHeader(plannerProperties.getUsername(), plannerProperties.getPassword()); - } - - /** - * Creates Authorization header value from username and password. - */ - private static String authHeader(String username, String password) { - return BASIC_AUTH_PATTERN - .formatted(Base64.getEncoder().encodeToString((username + ':' + password).getBytes())); - } - - @Override - public void suspend() { - isSuspended = true; - vertx.cancelTimer(registerTimerId); - } - - @Override - public void initialize() { - registerTimerId = vertx.setPeriodic(registerPeriod, ignored -> performRegistration()); - performRegistration(); - } - - public void performRegistration() { - register(headers()); - } - - protected void register(MultiMap headers) { - if (isSuspended) { - logger.warn("Register request was not sent to general planner, as planner service is suspended from" - + " register endpoint."); - return; - } - - final BigDecimal healthIndex = healthMonitor.calculateHealthIndex(); - final ZonedDateTime currencyLastUpdate = currencyConversionService.getLastUpdated(); - final RegisterRequest request = RegisterRequest.of( - healthIndex, - Status.of(currencyLastUpdate != null - ? CurrencyServiceState.of(UTC_MILLIS_FORMATTER.format(currencyLastUpdate)) - : null, - deliveryProgressService.getOverallDeliveryProgressReport()), - deploymentProperties.getPbsHostId(), - deploymentProperties.getPbsRegion(), - deploymentProperties.getPbsVendor()); - final String body = mapper.encodeToString(request); - - logger.info("Sending register request to Planner, {0} is {1}", PG_TRX_ID, headers.get(PG_TRX_ID)); - logger.debug("Register request payload: {0}", body); - - httpClient.post(plannerProperties.getRegisterEndpoint(), headers, body, registerTimeout) - .onComplete(this::handleRegister); - } - - protected MultiMap headers() { - return MultiMap.caseInsensitiveMultiMap() - .add(HttpUtil.AUTHORIZATION_HEADER, basicAuthHeader) - .add(PG_TRX_ID, UUID.randomUUID().toString()); - } - - private void handleRegister(AsyncResult asyncResult) { - if (asyncResult.failed()) { - final Throwable cause = asyncResult.cause(); - final String errorMessage = "Error occurred while registering with the Planner: " + cause; - alert(errorMessage, logger::warn); - } else { - final HttpClientResponse response = asyncResult.result(); - final int statusCode = response.getStatusCode(); - final String responseBody = response.getBody(); - if (statusCode == HttpResponseStatus.OK.code()) { - if (StringUtils.isNotBlank(responseBody)) { - adminEventService.publishAdminCentralEvent(parseRegisterResponse(responseBody)); - } - alertHttpService.resetAlertCount(PBS_REGISTER_CLIENT_ERROR); - } else { - final String errorMessage = "Planner responded with non-successful code %s, response: %s" - .formatted(statusCode, responseBody); - alert(errorMessage, logger::warn); - } - } - } - - private AdminCentralResponse parseRegisterResponse(String responseBody) { - try { - return mapper.decodeValue(responseBody, AdminCentralResponse.class); - } catch (DecodeException e) { - final String errorMessage = "Cannot parse register response: " + responseBody; - alert(errorMessage, logger::warn); - throw new PreBidException(errorMessage, e); - } - } - - private void alert(String message, Consumer logger) { - alertHttpService.alertWithPeriod(SERVICE_NAME, PBS_REGISTER_CLIENT_ERROR, AlertPriority.MEDIUM, message); - logger.accept(message); - } -} diff --git a/src/main/java/org/prebid/server/deals/Suspendable.java b/src/main/java/org/prebid/server/deals/Suspendable.java deleted file mode 100644 index b834b4badfe..00000000000 --- a/src/main/java/org/prebid/server/deals/Suspendable.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.prebid.server.deals; - -public interface Suspendable { - - void suspend(); -} diff --git a/src/main/java/org/prebid/server/deals/TargetingService.java b/src/main/java/org/prebid/server/deals/TargetingService.java deleted file mode 100644 index 17adefbafe5..00000000000 --- a/src/main/java/org/prebid/server/deals/TargetingService.java +++ /dev/null @@ -1,335 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeType; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Imp; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.TargetingDefinition; -import org.prebid.server.deals.targeting.interpret.And; -import org.prebid.server.deals.targeting.interpret.DomainMetricAwareExpression; -import org.prebid.server.deals.targeting.interpret.Expression; -import org.prebid.server.deals.targeting.interpret.InIntegers; -import org.prebid.server.deals.targeting.interpret.InStrings; -import org.prebid.server.deals.targeting.interpret.IntersectsIntegers; -import org.prebid.server.deals.targeting.interpret.IntersectsSizes; -import org.prebid.server.deals.targeting.interpret.IntersectsStrings; -import org.prebid.server.deals.targeting.interpret.Matches; -import org.prebid.server.deals.targeting.interpret.Not; -import org.prebid.server.deals.targeting.interpret.Or; -import org.prebid.server.deals.targeting.interpret.Within; -import org.prebid.server.deals.targeting.model.GeoRegion; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.BooleanOperator; -import org.prebid.server.deals.targeting.syntax.MatchingFunction; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; -import org.prebid.server.exception.TargetingSyntaxException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.StreamUtil; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * Responsible for parsing and interpreting targeting defined in the Line Items’ metadata - * and determining if individual requests match those targeting conditions. - */ -public class TargetingService { - - private final JacksonMapper mapper; - - public TargetingService(JacksonMapper mapper) { - this.mapper = Objects.requireNonNull(mapper); - } - - /** - * Accepts targeting definition expressed in JSON syntax (see below), - * parses it and transforms it into an object supporting efficient evaluation - * of the targeting rules against the OpenRTB2 request. - */ - public TargetingDefinition parseTargetingDefinition(JsonNode targetingDefinition, String lineItemId) { - return TargetingDefinition.of(parseNode(targetingDefinition, lineItemId)); - } - - /** - * Accepts OpenRTB2 request and particular Imp object to evaluate Line Item targeting - * definition against and returns whether it is matched or not. - */ - public boolean matchesTargeting(BidRequest bidRequest, - Imp imp, - TargetingDefinition targetingDefinition, - AuctionContext auctionContext) { - - final RequestContext requestContext = new RequestContext(bidRequest, imp, auctionContext.getTxnLog(), mapper); - return targetingDefinition.getRootExpression().matches(requestContext); - } - - private Expression parseNode(JsonNode node, String lineItemId) { - final Map.Entry field = validateIsSingleElementObject(node); - final String fieldName = field.getKey(); - - if (BooleanOperator.isBooleanOperator(fieldName)) { - return parseBooleanOperator(fieldName, field.getValue(), lineItemId); - } else if (TargetingCategory.isTargetingCategory(fieldName)) { - return parseTargetingCategory(fieldName, field.getValue(), lineItemId); - } else { - throw new TargetingSyntaxException( - "Expected either boolean operator or targeting category, got " + fieldName); - } - } - - private Expression parseBooleanOperator(String fieldName, JsonNode value, String lineItemId) { - final BooleanOperator operator = BooleanOperator.fromString(fieldName); - return switch (operator) { - case AND -> new And(parseArray(value, node -> parseNode(node, lineItemId))); - case OR -> new Or(parseArray(value, node -> parseNode(node, lineItemId))); - case NOT -> new Not(parseNode(value, lineItemId)); - }; - } - - private Expression parseTargetingCategory(String fieldName, JsonNode value, String lineItemId) { - final TargetingCategory category = TargetingCategory.fromString(fieldName); - return switch (category.type()) { - case size -> new IntersectsSizes(category, - parseArrayFunction(value, MatchingFunction.INTERSECTS, this::parseSize)); - case mediaType, userSegment -> new IntersectsStrings(category, - parseArrayFunction(value, MatchingFunction.INTERSECTS, TargetingService::parseString)); - case domain -> prepareDomainExpression(category, value, lineItemId); - case publisherDomain -> new DomainMetricAwareExpression(parseStringFunction(category, value), lineItemId); - case referrer, appBundle, adslot -> parseStringFunction(category, value); - case pagePosition, dow, hour -> new InIntegers(category, - parseArrayFunction(value, MatchingFunction.IN, TargetingService::parseInteger)); - case deviceGeoExt, deviceExt -> new InStrings(category, - parseArrayFunction(value, MatchingFunction.IN, TargetingService::parseString)); - case location -> new Within(category, parseSingleObjectFunction(value, MatchingFunction.WITHIN, - this::parseGeoRegion)); - case bidderParam, userFirstPartyData, siteFirstPartyData -> parseTypedFunction(category, value); - }; - } - - private static Or prepareDomainExpression(TargetingCategory category, JsonNode value, String lineItemId) { - final DomainMetricAwareExpression domainExpression = - new DomainMetricAwareExpression(parseStringFunction(category, value), lineItemId); - - final TargetingCategory publisherDomainCategory = new TargetingCategory(TargetingCategory.Type.publisherDomain); - final DomainMetricAwareExpression publisherDomainExpression = - new DomainMetricAwareExpression(parseStringFunction(publisherDomainCategory, value), lineItemId); - - return new Or(List.of(domainExpression, publisherDomainExpression)); - } - - private static List parseArrayFunction(JsonNode value, MatchingFunction function, - Function mapper) { - - return parseArray(validateIsFunction(value, function), mapper); - } - - private static T parseSingleObjectFunction( - JsonNode value, MatchingFunction function, Function mapper) { - - return mapper.apply(validateIsFunction(value, function)); - } - - private static Expression parseStringFunction(TargetingCategory category, JsonNode value) { - final Map.Entry field = validateIsSingleElementObject(value); - final MatchingFunction function = - validateCompatibleFunction(field, MatchingFunction.MATCHES, MatchingFunction.IN); - - return switch (function) { - case MATCHES -> new Matches(category, parseString(field.getValue())); - case IN -> createInStringsFunction(category, field.getValue()); - default -> throw new IllegalStateException("Unexpected string function " + function.value()); - }; - } - - private static Expression parseTypedFunction(TargetingCategory category, JsonNode value) { - final Map.Entry field = validateIsSingleElementObject(value); - final MatchingFunction function = validateCompatibleFunction(field, - MatchingFunction.MATCHES, MatchingFunction.IN, MatchingFunction.INTERSECTS); - - final JsonNode functionValue = field.getValue(); - return switch (function) { - case MATCHES -> new Matches(category, parseString(functionValue)); - case IN -> parseTypedInFunction(category, functionValue); - case INTERSECTS -> parseTypedIntersectsFunction(category, functionValue); - default -> throw new IllegalStateException("Unexpected typed function " + function.value()); - }; - } - - private Size parseSize(JsonNode node) { - validateIsObject(node); - - final Size size; - try { - size = mapper.mapper().treeToValue(node, Size.class); - } catch (JsonProcessingException e) { - throw new TargetingSyntaxException( - "Exception occurred while parsing size: " + e.getMessage(), e); - } - - if (size.getH() == null || size.getW() == null) { - throw new TargetingSyntaxException("Height and width in size definition could not be null or missing"); - } - - return size; - } - - private static String parseString(JsonNode node) { - validateIsString(node); - - final String value = node.textValue(); - if (StringUtils.isEmpty(value)) { - throw new TargetingSyntaxException("String value could not be empty"); - } - return value; - } - - private static Integer parseInteger(JsonNode node) { - validateIsInteger(node); - - return node.intValue(); - } - - private GeoRegion parseGeoRegion(JsonNode node) { - validateIsObject(node); - - final GeoRegion region; - try { - region = mapper.mapper().treeToValue(node, GeoRegion.class); - } catch (JsonProcessingException e) { - throw new TargetingSyntaxException( - "Exception occurred while parsing geo region: " + e.getMessage(), e); - } - - if (region.getLat() == null || region.getLon() == null || region.getRadiusMiles() == null) { - throw new TargetingSyntaxException( - "Lat, lon and radiusMiles in geo region definition could not be null or missing"); - } - - return region; - } - - private static List parseArray(JsonNode node, Function mapper) { - validateIsArray(node); - - return StreamUtil.asStream(node.spliterator()).map(mapper).toList(); - } - - private static Expression parseTypedInFunction(TargetingCategory category, JsonNode value) { - return parseTypedArrayFunction(category, value, TargetingService::createInIntegersFunction, - TargetingService::createInStringsFunction); - } - - private static Expression parseTypedIntersectsFunction(TargetingCategory category, JsonNode value) { - return parseTypedArrayFunction(category, value, TargetingService::createIntersectsIntegersFunction, - TargetingService::createIntersectsStringsFunction); - } - - private static Expression parseTypedArrayFunction( - TargetingCategory category, JsonNode value, - BiFunction integerCreator, - BiFunction stringCreator) { - - validateIsArray(value); - - final Iterator iterator = value.iterator(); - - final JsonNodeType dataType = iterator.hasNext() ? iterator.next().getNodeType() : JsonNodeType.STRING; - return switch (dataType) { - case NUMBER -> integerCreator.apply(category, value); - case STRING -> stringCreator.apply(category, value); - default -> throw new TargetingSyntaxException("Expected integer or string, got " + dataType); - }; - } - - private static Expression createInIntegersFunction(TargetingCategory category, JsonNode value) { - return new InIntegers(category, parseArray(value, TargetingService::parseInteger)); - } - - private static InStrings createInStringsFunction(TargetingCategory category, JsonNode value) { - return new InStrings(category, parseArray(value, TargetingService::parseString)); - } - - private static Expression createIntersectsStringsFunction(TargetingCategory category, JsonNode value) { - return new IntersectsStrings(category, parseArray(value, TargetingService::parseString)); - } - - private static Expression createIntersectsIntegersFunction(TargetingCategory category, JsonNode value) { - return new IntersectsIntegers(category, parseArray(value, TargetingService::parseInteger)); - } - - private static void validateIsObject(JsonNode value) { - if (!value.isObject()) { - throw new TargetingSyntaxException("Expected object, got " + value.getNodeType()); - } - } - - private static Map.Entry validateIsSingleElementObject(JsonNode value) { - validateIsObject(value); - - if (value.size() != 1) { - throw new TargetingSyntaxException( - "Expected only one element in the object, got " + value.size()); - } - - return value.fields().next(); - } - - private static void validateIsArray(JsonNode value) { - if (!value.isArray()) { - throw new TargetingSyntaxException("Expected array, got " + value.getNodeType()); - } - } - - private static void validateIsString(JsonNode value) { - if (!value.isTextual()) { - throw new TargetingSyntaxException("Expected string, got " + value.getNodeType()); - } - } - - private static void validateIsInteger(JsonNode value) { - if (!value.isInt()) { - throw new TargetingSyntaxException("Expected integer, got " + value.getNodeType()); - } - } - - private static JsonNode validateIsFunction(JsonNode value, MatchingFunction function) { - final Map.Entry field = validateIsSingleElementObject(value); - final String fieldName = field.getKey(); - - if (!MatchingFunction.isMatchingFunction(fieldName)) { - throw new TargetingSyntaxException("Expected matching function, got " + fieldName); - } else if (MatchingFunction.fromString(fieldName) != function) { - throw new TargetingSyntaxException( - "Expected %s matching function, got %s".formatted(function.value(), fieldName)); - } - - return field.getValue(); - } - - private static MatchingFunction validateCompatibleFunction(Map.Entry field, - MatchingFunction... compatibleFunctions) { - final String fieldName = field.getKey(); - - if (!MatchingFunction.isMatchingFunction(fieldName)) { - throw new TargetingSyntaxException("Expected matching function, got " + fieldName); - } - - final MatchingFunction function = MatchingFunction.fromString(fieldName); - if (!Arrays.asList(compatibleFunctions).contains(function)) { - throw new TargetingSyntaxException("Expected one of %s matching functions, got %s".formatted( - Arrays.stream(compatibleFunctions).map(MatchingFunction::value).collect(Collectors.joining(", ")), - fieldName)); - } - return function; - } -} diff --git a/src/main/java/org/prebid/server/deals/UserAdditionalInfoService.java b/src/main/java/org/prebid/server/deals/UserAdditionalInfoService.java deleted file mode 100644 index 58892f3142d..00000000000 --- a/src/main/java/org/prebid/server/deals/UserAdditionalInfoService.java +++ /dev/null @@ -1,319 +0,0 @@ -package org.prebid.server.deals; - -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Data; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Segment; -import com.iab.openrtb.request.User; -import io.vertx.core.CompositeFuture; -import io.vertx.core.Future; -import io.vertx.core.Promise; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.ListUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.auction.model.Tuple3; -import org.prebid.server.deals.deviceinfo.DeviceInfoService; -import org.prebid.server.deals.model.DeviceInfo; -import org.prebid.server.deals.model.UserData; -import org.prebid.server.deals.model.UserDetails; -import org.prebid.server.execution.Timeout; -import org.prebid.server.geolocation.GeoLocationService; -import org.prebid.server.geolocation.model.GeoInfo; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.proto.openrtb.ext.request.ExtDevice; -import org.prebid.server.proto.openrtb.ext.request.ExtDeviceVendor; -import org.prebid.server.proto.openrtb.ext.request.ExtGeo; -import org.prebid.server.proto.openrtb.ext.request.ExtGeoVendor; -import org.prebid.server.proto.openrtb.ext.request.ExtUser; -import org.prebid.server.proto.openrtb.ext.request.ExtUserTime; -import org.prebid.server.util.ObjectUtil; - -import java.time.Clock; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.temporal.WeekFields; -import java.util.List; -import java.util.Objects; - -public class UserAdditionalInfoService { - - private static final Logger logger = LoggerFactory.getLogger(UserAdditionalInfoService.class); - - private final LineItemService lineItemService; - private final DeviceInfoService deviceInfoService; - private final GeoLocationService geoLocationService; - private final UserService userService; - private final Clock clock; - private final JacksonMapper mapper; - private final CriteriaLogManager criteriaLogManager; - - public UserAdditionalInfoService(LineItemService lineItemService, - DeviceInfoService deviceInfoService, - GeoLocationService geoLocationService, - UserService userService, - Clock clock, - JacksonMapper mapper, - CriteriaLogManager criteriaLogManager) { - - this.lineItemService = Objects.requireNonNull(lineItemService); - this.deviceInfoService = deviceInfoService; - this.geoLocationService = geoLocationService; - this.userService = Objects.requireNonNull(userService); - this.clock = Objects.requireNonNull(clock); - this.mapper = Objects.requireNonNull(mapper); - this.criteriaLogManager = Objects.requireNonNull(criteriaLogManager); - } - - public Future populate(AuctionContext context) { - final boolean accountHasDeals = lineItemService.accountHasDeals(context); - final String accountId = context.getAccount().getId(); - if (!accountHasDeals) { - criteriaLogManager.log( - logger, accountId, "Account %s does not have deals".formatted(accountId), logger::debug); - - return Future.succeededFuture(context); - } - - final Device device = context.getBidRequest().getDevice(); - final Timeout timeout = context.getTimeoutContext().getTimeout(); - final GeoInfo geoInfo = context.getGeoInfo(); - - final CompositeFuture compositeFuture = CompositeFuture.join( - lookupDeviceInfo(device), - geoInfo != null ? Future.succeededFuture(geoInfo) : lookupGeoInfo(device, timeout), - userService.getUserDetails(context, timeout)); - - // AsyncResult has atomic nature: its result() method returns null when at least one future fails. - // So, in handler it is ignored and original CompositeFuture used to process obtained results - // to avoid explicit casting to CompositeFuture implementation. - final Promise> promise = Promise.promise(); - compositeFuture.onComplete(ignored -> handleInfos(compositeFuture, promise, context.getAccount().getId())); - return promise.future().map(tuple -> enrichAuctionContext(context, tuple)); - } - - private Future lookupDeviceInfo(Device device) { - return deviceInfoService != null - ? deviceInfoService.getDeviceInfo(device.getUa()) - : Future.failedFuture("Device info is disabled by configuration"); - } - - private Future lookupGeoInfo(Device device, Timeout timeout) { - return geoLocationService != null - ? geoLocationService.lookup(ObjectUtils.defaultIfNull(device.getIp(), device.getIpv6()), timeout) - : Future.failedFuture("Geo location is disabled by configuration"); - } - - private void handleInfos(CompositeFuture compositeFuture, - Promise> resultPromise, - String account) { - - DeviceInfo deviceInfo = null; - GeoInfo geoInfo = null; - UserDetails userDetails = null; - - for (int i = 0; i < compositeFuture.list().size(); i++) { - final Object o = compositeFuture.resultAt(i); - if (o == null) { - criteriaLogManager.log( - logger, - account, - "Deals processing error: " + compositeFuture.cause(i), - logger::warn); - continue; - } - - if (o instanceof DeviceInfo) { - deviceInfo = (DeviceInfo) o; - } else if (o instanceof GeoInfo) { - geoInfo = (GeoInfo) o; - } else if (o instanceof UserDetails) { - userDetails = (UserDetails) o; - } - } - - resultPromise.complete(Tuple3.of(deviceInfo, geoInfo, userDetails)); - } - - private AuctionContext enrichAuctionContext(AuctionContext auctionContext, - Tuple3 tuple) { - - final DeviceInfo deviceInfo = tuple.getLeft(); - final GeoInfo geoInfo = tuple.getMiddle(); - final UserDetails userDetails = tuple.getRight(); - - final BidRequest bidRequest = auctionContext.getBidRequest(); - final Device originalDevice = bidRequest.getDevice(); - - final BidRequest enrichedBidRequest = bidRequest.toBuilder() - .device(deviceInfo != null || geoInfo != null - ? updateDevice(originalDevice, deviceInfo, geoInfo) - : originalDevice) - .user(updateUser(bidRequest.getUser(), userDetails, geoInfo)) - .build(); - - return auctionContext.toBuilder() - .bidRequest(enrichedBidRequest) - .geoInfo(geoInfo) - .build(); - } - - private Device updateDevice(Device device, DeviceInfo deviceInfo, GeoInfo geoInfo) { - final ExtDevice updatedExtDevice = - fillExtDeviceWith( - fillExtDeviceWith( - ObjectUtil.getIfNotNull(device, Device::getExt), - ObjectUtil.getIfNotNull(deviceInfo, DeviceInfo::getVendor), - extDeviceVendorFrom(deviceInfo)), - ObjectUtil.getIfNotNull(geoInfo, GeoInfo::getVendor), - extDeviceVendorFrom(geoInfo)); - final Geo updatedGeo = updateDeviceGeo(ObjectUtil.getIfNotNull(device, Device::getGeo), geoInfo); - - final Device.DeviceBuilder deviceBuilder = device != null ? device.toBuilder() : Device.builder(); - return deviceBuilder - .geo(updatedGeo) - .ext(updatedExtDevice) - .build(); - } - - private ExtDevice fillExtDeviceWith(ExtDevice extDevice, String vendor, ExtDeviceVendor extDeviceVendor) { - if (extDeviceVendor.equals(ExtDeviceVendor.EMPTY)) { - return extDevice; - } - - final ExtDevice effectiveExtDevice = extDevice != null ? extDevice : ExtDevice.empty(); - effectiveExtDevice.addProperty(vendor, mapper.mapper().valueToTree(extDeviceVendor)); - - return effectiveExtDevice; - } - - private static ExtDeviceVendor extDeviceVendorFrom(DeviceInfo deviceInfo) { - return deviceInfo != null - ? ExtDeviceVendor.builder() - .type(deviceInfo.getDeviceTypeRaw()) - .osfamily(null) - .os(deviceInfo.getOs()) - .osver(deviceInfo.getOsVersion()) - .browser(deviceInfo.getBrowser()) - .browserver(deviceInfo.getBrowserVersion()) - .make(deviceInfo.getManufacturer()) - .model(deviceInfo.getModel()) - .language(deviceInfo.getLanguage()) - .carrier(deviceInfo.getCarrier()) - .build() - : ExtDeviceVendor.EMPTY; - } - - private static ExtDeviceVendor extDeviceVendorFrom(GeoInfo geoInfo) { - return geoInfo != null - ? ExtDeviceVendor.builder() - .connspeed(geoInfo.getConnectionSpeed()) - .build() - : ExtDeviceVendor.EMPTY; - } - - private Geo updateDeviceGeo(Geo geo, GeoInfo geoInfo) { - if (geoInfo == null) { - return geo; - } - - final ExtGeo updatedExtGeo = fillExtGeoWith( - ObjectUtil.getIfNotNull(geo, Geo::getExt), - geoInfo.getVendor(), - extGeoVendorFrom(geoInfo)); - - final Geo.GeoBuilder geoBuilder = geo != null ? geo.toBuilder() : Geo.builder(); - return geoBuilder - .country(geoInfo.getCountry()) - .region(geoInfo.getRegion()) - .metro(geoInfo.getMetroGoogle()) - .lat(geoInfo.getLat()) - .lon(geoInfo.getLon()) - .ext(updatedExtGeo) - .build(); - } - - private ExtGeo fillExtGeoWith(ExtGeo extGeo, String vendor, ExtGeoVendor extGeoVendor) { - if (extGeoVendor.equals(ExtGeoVendor.EMPTY)) { - return extGeo; - } - - final ExtGeo effectiveExtGeo = extGeo != null ? extGeo : ExtGeo.of(); - effectiveExtGeo.addProperty(vendor, mapper.mapper().valueToTree(extGeoVendor)); - - return effectiveExtGeo; - } - - private static ExtGeoVendor extGeoVendorFrom(GeoInfo geoInfo) { - return ExtGeoVendor.builder() - .continent(geoInfo.getContinent()) - .country(geoInfo.getCountry()) - .region(geoInfo.getRegionCode()) - .metro(geoInfo.getMetroNielsen()) - .city(geoInfo.getCity()) - .zip(geoInfo.getZip()) - .build(); - } - - private User updateUser(User user, UserDetails userDetails, GeoInfo geoInfo) { - final User.UserBuilder userBuilder = user != null ? user.toBuilder() : User.builder(); - return userBuilder - .data(userDetails != null ? makeData(userDetails) : null) - .ext(updateExtUser(ObjectUtil.getIfNotNull(user, User::getExt), userDetails, geoInfo)) - .build(); - } - - private static List makeData(UserDetails userDetails) { - final List userData = userDetails.getUserData(); - return userData != null - ? userData.stream() - .map(userDataElement -> Data.builder() - .id(userDataElement.getName()) - .segment(makeSegments(userDataElement.getSegment())) - .build()) - .toList() - : null; - } - - private static List makeSegments(List segments) { - return segments != null - ? segments.stream() - .map(segment -> Segment.builder().id(segment.getId()).build()) - .toList() - : null; - } - - private ExtUser updateExtUser(ExtUser extUser, UserDetails userDetails, GeoInfo geoInfo) { - final ExtUser.ExtUserBuilder extUserBuilder = extUser != null ? extUser.toBuilder() : ExtUser.builder(); - return extUserBuilder - .fcapIds(ObjectUtils.defaultIfNull( - resolveFcapIds(userDetails), - ObjectUtil.getIfNotNull(extUser, ExtUser::getFcapIds))) - .time(resolveExtUserTime(geoInfo)) - .build(); - } - - private static List resolveFcapIds(UserDetails userDetails) { - return userDetails != null - // Indicate that the call to User Data Store has been made successfully even if the user is not frequency - // capped - ? ListUtils.emptyIfNull(userDetails.getFcapIds()) - // otherwise leave cappedIds null to indicate that call to User Data Store failed - : null; - } - - private ExtUserTime resolveExtUserTime(GeoInfo geoInfo) { - final ZoneId timeZone = ObjectUtils.firstNonNull( - ObjectUtil.getIfNotNull(geoInfo, GeoInfo::getTimeZone), - clock.getZone()); - - final ZonedDateTime dateTime = ZonedDateTime.now(clock).withZoneSameInstant(timeZone); - - return ExtUserTime.of( - dateTime.getDayOfWeek().get(WeekFields.SUNDAY_START.dayOfWeek()), - dateTime.getHour()); - } -} diff --git a/src/main/java/org/prebid/server/deals/UserService.java b/src/main/java/org/prebid/server/deals/UserService.java deleted file mode 100644 index 41e0b300b67..00000000000 --- a/src/main/java/org/prebid/server/deals/UserService.java +++ /dev/null @@ -1,294 +0,0 @@ -package org.prebid.server.deals; - -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.cache.model.DebugHttpCall; -import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.cookie.model.UidWithExpiry; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.User; -import org.prebid.server.deals.model.UserDetails; -import org.prebid.server.deals.model.UserDetailsProperties; -import org.prebid.server.deals.model.UserDetailsRequest; -import org.prebid.server.deals.model.UserDetailsResponse; -import org.prebid.server.deals.model.UserId; -import org.prebid.server.deals.model.UserIdRule; -import org.prebid.server.deals.model.WinEventNotification; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.execution.Timeout; -import org.prebid.server.handler.NotificationEventHandler; -import org.prebid.server.json.DecodeException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.MetricName; -import org.prebid.server.metric.Metrics; -import org.prebid.server.util.HttpUtil; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -/** - * Works with user related information. - */ -public class UserService { - - private static final Logger logger = LoggerFactory.getLogger(UserService.class); - private static final String USER_SERVICE = "userservice"; - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private final LineItemService lineItemService; - private final HttpClient httpClient; - private final Clock clock; - private final Metrics metrics; - private final JacksonMapper mapper; - - private final String userDetailsUrl; - private final String winEventUrl; - private final long timeout; - private final List userIdRules; - private final String dataCenterRegion; - - public UserService(UserDetailsProperties userDetailsProperties, - String dataCenterRegion, - LineItemService lineItemService, - HttpClient httpClient, - Clock clock, - Metrics metrics, - JacksonMapper mapper) { - - this.lineItemService = Objects.requireNonNull(lineItemService); - this.httpClient = Objects.requireNonNull(httpClient); - this.clock = Objects.requireNonNull(clock); - this.metrics = Objects.requireNonNull(metrics); - - this.userDetailsUrl = Objects.requireNonNull( - HttpUtil.validateUrl(userDetailsProperties.getUserDetailsEndpoint())); - this.winEventUrl = Objects.requireNonNull(HttpUtil.validateUrl(userDetailsProperties.getWinEventEndpoint())); - this.timeout = userDetailsProperties.getTimeout(); - this.userIdRules = Objects.requireNonNull(userDetailsProperties.getUserIds()); - this.dataCenterRegion = Objects.requireNonNull(dataCenterRegion); - this.mapper = Objects.requireNonNull(mapper); - } - - /** - * Fetches {@link UserDetails} from the User Data Store. - */ - public Future getUserDetails(AuctionContext context, Timeout timeout) { - final Map uidsMap = context.getUidsCookie().getCookieUids().getUids(); - if (CollectionUtils.isEmpty(uidsMap.values())) { - metrics.updateUserDetailsRequestPreparationFailed(); - context.getDebugHttpCalls().put(USER_SERVICE, Collections.singletonList(DebugHttpCall.empty())); - return Future.succeededFuture(UserDetails.empty()); - } - - final List userIds = getUserIds(uidsMap); - if (CollectionUtils.isEmpty(userIds)) { - metrics.updateUserDetailsRequestPreparationFailed(); - context.getDebugHttpCalls().put(USER_SERVICE, Collections.singletonList(DebugHttpCall.empty())); - return Future.succeededFuture(UserDetails.empty()); - } - - final UserDetailsRequest userDetailsRequest = UserDetailsRequest.of( - UTC_MILLIS_FORMATTER.format(ZonedDateTime.now(clock)), userIds); - final String body = mapper.encodeToString(userDetailsRequest); - - final long requestTimeout = Math.min(this.timeout, timeout.remaining()); - - final long startTime = clock.millis(); - return httpClient.post(userDetailsUrl, body, requestTimeout) - .map(httpClientResponse -> toUserServiceResult(httpClientResponse, context, - userDetailsUrl, body, startTime)) - .recover(throwable -> failGetDetailsResponse(throwable, context, userDetailsUrl, body, startTime)); - } - - /** - * Retrieves the UID from UIDs Map by each {@link UserIdRule#getLocation()} and if UID is present - creates a - * {@link UserId} object that contains {@link UserIdRule#getType()} and UID and adds it to UserId list. - */ - private List getUserIds(Map bidderToUid) { - final List userIds = new ArrayList<>(); - for (UserIdRule rule : userIdRules) { - final UidWithExpiry uid = bidderToUid.get(rule.getLocation()); - if (uid != null) { - userIds.add(UserId.of(rule.getType(), uid.getUid())); - } - } - return userIds; - } - - /** - * Transforms response from User Data Store into {@link Future} of {@link UserDetails}. - *

- * Throws {@link PreBidException} if an error occurs during response body deserialization. - */ - private UserDetails toUserServiceResult(HttpClientResponse clientResponse, AuctionContext context, - String requestUrl, String requestBody, long startTime) { - final int responseStatusCode = clientResponse.getStatusCode(); - verifyStatusCode(responseStatusCode); - - final String responseBody = clientResponse.getBody(); - final User user; - final int responseTime = responseTime(startTime); - try { - user = parseUserDetailsResponse(responseBody); - } finally { - context.getDebugHttpCalls().put(USER_SERVICE, Collections.singletonList( - DebugHttpCall.builder() - .requestUri(requestUrl) - .requestBody(requestBody) - .responseStatus(responseStatusCode) - .responseBody(responseBody) - .responseTimeMillis(responseTime) - .build())); - } - metrics.updateRequestTimeMetric(MetricName.user_details_request_time, responseTime); - metrics.updateUserDetailsRequestMetric(true); - return UserDetails.of(user.getData(), user.getExt().getFcapIds()); - } - - private User parseUserDetailsResponse(String responseBody) { - final UserDetailsResponse userDetailsResponse; - try { - userDetailsResponse = mapper.decodeValue(responseBody, UserDetailsResponse.class); - } catch (DecodeException e) { - throw new PreBidException("Cannot parse response: " + responseBody, e); - } - - final User user = userDetailsResponse.getUser(); - if (user == null) { - throw new PreBidException("Field 'user' is missing in response: " + responseBody); - } - - if (user.getData() == null) { - throw new PreBidException("Field 'user.data' is missing in response: " + responseBody); - } - - if (user.getExt() == null) { - throw new PreBidException("Field 'user.ext' is missing in response: " + responseBody); - } - return user; - } - - /** - * Throw {@link PreBidException} if response status is not 200. - */ - private static void verifyStatusCode(int statusCode) { - if (statusCode != 200) { - throw new PreBidException("Bad response status code: " + statusCode); - } - } - - /** - * Handles errors that occurred during getUserDetails HTTP request or response processing. - */ - private Future failGetDetailsResponse(Throwable exception, AuctionContext context, String requestUrl, - String requestBody, long startTime) { - final int responseTime = responseTime(startTime); - context.getDebugHttpCalls().putIfAbsent(USER_SERVICE, - Collections.singletonList( - DebugHttpCall.builder() - .requestUri(requestUrl) - .requestBody(requestBody) - .responseTimeMillis(responseTime) - .build())); - metrics.updateUserDetailsRequestMetric(false); - metrics.updateRequestTimeMetric(MetricName.user_details_request_time, responseTime); - logger.warn("Error occurred while fetching user details", exception); - return Future.failedFuture(exception); - } - - /** - * Calculates execution time since the given start time. - */ - private int responseTime(long startTime) { - return Math.toIntExact(clock.millis() - startTime); - } - - /** - * Accepts lineItemId and bidId from the {@link NotificationEventHandler}, - * joins event data with corresponding Line Item metadata (provided by LineItemService) - * and passes this information to the User Data Store to facilitate frequency capping. - */ - public void processWinEvent(String lineItemId, String bidId, UidsCookie uids) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - final List userIds = getUserIds(uids.getCookieUids().getUids()); - - if (!hasRequiredData(lineItem, userIds, lineItemId)) { - metrics.updateWinRequestPreparationFailed(); - return; - } - - final String body = mapper.encodeToString(WinEventNotification.builder() - .bidderCode(lineItem.getSource()) - .bidId(bidId) - .lineItemId(lineItemId) - .region(dataCenterRegion) - .userIds(userIds) - .winEventDateTime(ZonedDateTime.now(clock)) - .lineUpdatedDateTime(lineItem.getUpdatedTimeStamp()) - .frequencyCaps(lineItem.getFrequencyCaps()) - .build()); - - metrics.updateWinNotificationMetric(); - final long startTime = clock.millis(); - httpClient.post(winEventUrl, body, timeout) - .onComplete(result -> handleWinResponse(result, startTime)); - } - - /** - * Verify that all necessary data is present and log error if something is missing. - */ - private static boolean hasRequiredData(LineItem lineItem, List userIds, String lineItemId) { - if (lineItem == null) { - logger.error("Meta Data for Line Item Id {0} does not exist", lineItemId); - return false; - } - - if (CollectionUtils.isEmpty(userIds)) { - logger.error("User Ids cannot be empty"); - return false; - } - return true; - } - - /** - * Checks response from User Data Store. - */ - private void handleWinResponse(AsyncResult asyncResult, long startTime) { - metrics.updateWinRequestTime(responseTime(startTime)); - if (asyncResult.succeeded()) { - try { - verifyStatusCode(asyncResult.result().getStatusCode()); - metrics.updateWinEventRequestMetric(true); - } catch (PreBidException e) { - metrics.updateWinEventRequestMetric(false); - logWinEventError(e); - } - } else { - metrics.updateWinEventRequestMetric(false); - logWinEventError(asyncResult.cause()); - } - } - - /** - * Logs errors that occurred during processWinEvent HTTP request or bad response code. - */ - private static void logWinEventError(Throwable exception) { - logger.warn("Error occurred while pushing win event notification", exception); - } -} diff --git a/src/main/java/org/prebid/server/deals/deviceinfo/DeviceInfoService.java b/src/main/java/org/prebid/server/deals/deviceinfo/DeviceInfoService.java deleted file mode 100644 index 1e680ebd51f..00000000000 --- a/src/main/java/org/prebid/server/deals/deviceinfo/DeviceInfoService.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.prebid.server.deals.deviceinfo; - -import io.vertx.core.Future; -import org.prebid.server.deals.model.DeviceInfo; - -/** - * Processes device related information. - */ -@FunctionalInterface -public interface DeviceInfoService { - - /** - * Provides information about device based on User-Agent string and other available attributes. - */ - Future getDeviceInfo(String ua); -} diff --git a/src/main/java/org/prebid/server/deals/events/AdminEventProcessor.java b/src/main/java/org/prebid/server/deals/events/AdminEventProcessor.java deleted file mode 100644 index dbf9133a902..00000000000 --- a/src/main/java/org/prebid/server/deals/events/AdminEventProcessor.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.prebid.server.deals.events; - -import org.prebid.server.deals.model.AdminCentralResponse; - -public interface AdminEventProcessor { - - void processAdminCentralEvent(AdminCentralResponse adminCentralResponse); -} diff --git a/src/main/java/org/prebid/server/deals/events/AdminEventService.java b/src/main/java/org/prebid/server/deals/events/AdminEventService.java deleted file mode 100644 index f8f6130c6b5..00000000000 --- a/src/main/java/org/prebid/server/deals/events/AdminEventService.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.deals.events; - -import io.vertx.core.eventbus.DeliveryOptions; -import io.vertx.core.eventbus.EventBus; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.vertx.LocalMessageCodec; - -import java.util.Objects; - -public class AdminEventService { - - private static final String ADDRESS_ADMIN_CENTRAL_COMMAND = "event.admin-central"; - - private static final DeliveryOptions DELIVERY_OPTIONS = - new DeliveryOptions() - .setCodecName(LocalMessageCodec.codecName()); - - private final EventBus eventBus; - - public AdminEventService(EventBus eventBus) { - this.eventBus = Objects.requireNonNull(eventBus); - } - - /** - * Publishes admin central event. - */ - public void publishAdminCentralEvent(AdminCentralResponse adminCentralResponse) { - eventBus.publish(ADDRESS_ADMIN_CENTRAL_COMMAND, adminCentralResponse, DELIVERY_OPTIONS); - } -} diff --git a/src/main/java/org/prebid/server/deals/events/ApplicationEventProcessor.java b/src/main/java/org/prebid/server/deals/events/ApplicationEventProcessor.java deleted file mode 100644 index ed1595d1eda..00000000000 --- a/src/main/java/org/prebid/server/deals/events/ApplicationEventProcessor.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.deals.events; - -import org.prebid.server.auction.model.AuctionContext; - -/** - * Interface for the components able to consume application events. - * - * @see ApplicationEventService - */ -public interface ApplicationEventProcessor { - - void processAuctionEvent(AuctionContext auctionContext); - - void processLineItemWinEvent(String lineItemId); - - void processDeliveryProgressUpdateEvent(); -} diff --git a/src/main/java/org/prebid/server/deals/events/ApplicationEventService.java b/src/main/java/org/prebid/server/deals/events/ApplicationEventService.java deleted file mode 100644 index 78dec0ae622..00000000000 --- a/src/main/java/org/prebid/server/deals/events/ApplicationEventService.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.prebid.server.deals.events; - -import io.vertx.core.eventbus.DeliveryOptions; -import io.vertx.core.eventbus.EventBus; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.vertx.LocalMessageCodec; - -import java.util.Objects; - -/** - * Main purpose of this service is decoupling of application events delivery from their generators to consumers. - *

- * This service is essentially a facade for Vert.x {@link EventBus}, it encapsulates addressing and consumers - * configuration concerns and provides type-safe API for publishing different application events which are consumed - * by all {@link ApplicationEventProcessor}s registered in the application. - *

- * Implementation notes: - * Communication through {@link EventBus} is performed only locally, that's why no serialization/deserialization - * happens for objects passed over the bus and hence no implied performance penalty (see {@link LocalMessageCodec}). - */ -public class ApplicationEventService { - - private static final String ADDRESS_EVENT_OPENRTB2_AUCTION = "event.openrtb2-auction"; - private static final String ADDRESS_EVENT_LINE_ITEM_WIN = "event.line-item-win"; - private static final String ADDRESS_EVENT_DELIVERY_UPDATE = "event.delivery-update"; - - private static final DeliveryOptions DELIVERY_OPTIONS = - new DeliveryOptions() - .setCodecName(LocalMessageCodec.codecName()); - - private final EventBus eventBus; - - public ApplicationEventService(EventBus eventBus) { - this.eventBus = Objects.requireNonNull(eventBus); - } - - /** - * Publishes auction event. - */ - public void publishAuctionEvent(AuctionContext auctionContext) { - eventBus.publish(ADDRESS_EVENT_OPENRTB2_AUCTION, auctionContext, DELIVERY_OPTIONS); - } - - /** - * Publishes line item win event. - */ - public void publishLineItemWinEvent(String lineItemId) { - eventBus.publish(ADDRESS_EVENT_LINE_ITEM_WIN, lineItemId); - } - - /** - * Publishes delivery update event. - */ - public void publishDeliveryUpdateEvent() { - eventBus.publish(ADDRESS_EVENT_DELIVERY_UPDATE, null); - } -} diff --git a/src/main/java/org/prebid/server/deals/events/EventServiceInitializer.java b/src/main/java/org/prebid/server/deals/events/EventServiceInitializer.java deleted file mode 100644 index 93802bbadd0..00000000000 --- a/src/main/java/org/prebid/server/deals/events/EventServiceInitializer.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.prebid.server.deals.events; - -import io.vertx.core.eventbus.EventBus; -import io.vertx.core.eventbus.Message; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.vertx.Initializable; - -import java.util.List; -import java.util.Objects; - -public class EventServiceInitializer implements Initializable { - - private static final String ADDRESS_EVENT_OPENRTB2_AUCTION = "event.openrtb2-auction"; - private static final String ADDRESS_EVENT_LINE_ITEM_WIN = "event.line-item-win"; - private static final String ADDRESS_EVENT_DELIVERY_UPDATE = "event.delivery-update"; - private static final String ADDRESS_ADMIN_CENTRAL_COMMAND = "event.admin-central"; - - private final List applicationEventProcessors; - private final List adminEventProcessors; - private final EventBus eventBus; - - public EventServiceInitializer(List applicationEventProcessors, - List adminEventProcessors, - EventBus eventBus) { - this.applicationEventProcessors = Objects.requireNonNull(applicationEventProcessors); - this.adminEventProcessors = Objects.requireNonNull(adminEventProcessors); - this.eventBus = Objects.requireNonNull(eventBus); - } - - @Override - public void initialize() { - eventBus.localConsumer( - ADDRESS_EVENT_OPENRTB2_AUCTION, - (Message message) -> applicationEventProcessors.forEach( - recorder -> recorder.processAuctionEvent(message.body()))); - - eventBus.localConsumer( - ADDRESS_EVENT_LINE_ITEM_WIN, - (Message message) -> applicationEventProcessors.forEach( - recorder -> recorder.processLineItemWinEvent(message.body()))); - - eventBus.localConsumer( - ADDRESS_EVENT_DELIVERY_UPDATE, - (Message message) -> applicationEventProcessors.forEach( - ApplicationEventProcessor::processDeliveryProgressUpdateEvent)); - - eventBus.localConsumer( - ADDRESS_ADMIN_CENTRAL_COMMAND, - (Message message) -> adminEventProcessors.forEach( - recorder -> recorder.processAdminCentralEvent(message.body()))); - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/DeliveryPlan.java b/src/main/java/org/prebid/server/deals/lineitem/DeliveryPlan.java deleted file mode 100644 index fe373f114f5..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/DeliveryPlan.java +++ /dev/null @@ -1,184 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import org.apache.commons.collections4.SetUtils; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.Token; - -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class DeliveryPlan { - - private final DeliverySchedule deliverySchedule; - - private final Set deliveryTokens; - - private DeliveryPlan(DeliverySchedule deliverySchedule) { - this(Objects.requireNonNull(deliverySchedule), toDeliveryTokens(deliverySchedule.getTokens())); - } - - private DeliveryPlan(DeliverySchedule deliverySchedule, Set deliveryTokens) { - this.deliverySchedule = Objects.requireNonNull(deliverySchedule); - this.deliveryTokens = Objects.requireNonNull(deliveryTokens); - } - - public static DeliveryPlan of(DeliverySchedule deliverySchedule) { - return new DeliveryPlan(deliverySchedule); - } - - /** - * Returns number of not spent tokens in {@link DeliveryPlan}. - */ - public int getUnspentTokens() { - return deliveryTokens.stream().mapToInt(DeliveryToken::getUnspent).sum(); - } - - /** - * Returns number of spent tokens in {@link DeliveryPlan}. - */ - public long getSpentTokens() { - return deliveryTokens.stream().map(DeliveryToken::getSpent).mapToLong(LongAdder::sum).sum(); - } - - public long getTotalTokens() { - return deliveryTokens.stream().mapToLong(DeliveryToken::getTotal).sum(); - } - - /** - * Returns lowest (which means highest priority) token's class value with unspent tokens. - */ - public Integer getHighestUnspentTokensClass() { - return deliveryTokens.stream() - .filter(token -> token.getUnspent() > 0) - .map(DeliveryToken::getPriorityClass) - .findFirst() - .orElse(null); - } - - /** - * Increments tokens in {@link DeliveryToken} with highest priority within {@link DeliveryPlan} - * - * @return class of the token incremented - */ - public Integer incSpentToken() { - final DeliveryToken unspentToken = deliveryTokens.stream() - .filter(token -> token.getUnspent() > 0) - .findFirst() - .orElse(null); - if (unspentToken != null) { - unspentToken.inc(); - return unspentToken.getPriorityClass(); - } - - return null; - } - - /** - * Merges tokens from expired {@link DeliveryPlan} to the next one. - */ - public DeliveryPlan mergeWithNextDeliverySchedule(DeliverySchedule nextDeliverySchedule, boolean sumTotal) { - - final Map nextTokensByClass = nextDeliverySchedule.getTokens().stream() - .collect(Collectors.toMap(Token::getPriorityClass, Function.identity())); - - final Set mergedTokens = new TreeSet<>(); - - for (final DeliveryToken expiredToken : deliveryTokens) { - final Integer priorityClass = expiredToken.getPriorityClass(); - final Token nextToken = nextTokensByClass.get(priorityClass); - - mergedTokens.add(expiredToken.mergeWithToken(nextToken, sumTotal)); - - nextTokensByClass.remove(priorityClass); - } - - // add remaining (not merged) tokens - nextTokensByClass.values().stream().map(DeliveryToken::of).forEach(mergedTokens::add); - - return new DeliveryPlan(nextDeliverySchedule, mergedTokens); - } - - public DeliveryPlan mergeWithNextDeliveryPlan(DeliveryPlan anotherPlan) { - return mergeWithNextDeliverySchedule(anotherPlan.deliverySchedule, false); - } - - public DeliveryPlan withoutSpentTokens() { - return new DeliveryPlan(deliverySchedule, deliveryTokens.stream() - .map(DeliveryToken::of) - .collect(Collectors.toSet())); - } - - public void incTokenWithPriority(Integer tokenPriority) { - deliveryTokens.stream() - .filter(token -> Objects.equals(token.getPriorityClass(), tokenPriority)) - .findAny() - .ifPresent(DeliveryToken::inc); - } - - /** - * Calculates readyAt from expirationDate and number of unspent tokens. - */ - public ZonedDateTime calculateReadyAt() { - final ZonedDateTime planStartTime = deliverySchedule.getStartTimeStamp(); - final long spentTokens = getSpentTokens(); - final long unspentTokens = getUnspentTokens(); - final long timeShift = spentTokens * ((deliverySchedule.getEndTimeStamp().toInstant().toEpochMilli() - - planStartTime.toInstant().toEpochMilli()) / getTotalTokens()); - return unspentTokens > 0 - ? ZonedDateTime.ofInstant(planStartTime.toInstant().plusMillis(timeShift), ZoneOffset.UTC) - : null; - } - - public Long getDeliveryRateInMilliseconds() { - return getUnspentTokens() > 0 - ? (deliverySchedule.getEndTimeStamp().toInstant().toEpochMilli() - - deliverySchedule.getStartTimeStamp().toInstant().toEpochMilli()) - / getTotalTokens() - : null; - } - - public boolean isUpdated(DeliverySchedule deliverySchedule) { - final ZonedDateTime currentPlanUpdatedDate = this.deliverySchedule.getUpdatedTimeStamp(); - final ZonedDateTime newPlanUpdatedDate = deliverySchedule.getUpdatedTimeStamp(); - return !(currentPlanUpdatedDate == null && newPlanUpdatedDate == null) - && (currentPlanUpdatedDate == null || newPlanUpdatedDate == null - || currentPlanUpdatedDate.isBefore(newPlanUpdatedDate)); - } - - public String getPlanId() { - return deliverySchedule.getPlanId(); - } - - public ZonedDateTime getStartTimeStamp() { - return deliverySchedule.getStartTimeStamp(); - } - - public ZonedDateTime getEndTimeStamp() { - return deliverySchedule.getEndTimeStamp(); - } - - public ZonedDateTime getUpdatedTimeStamp() { - return deliverySchedule.getUpdatedTimeStamp(); - } - - public Set getDeliveryTokens() { - return deliveryTokens; - } - - public DeliverySchedule getDeliverySchedule() { - return deliverySchedule; - } - - private static Set toDeliveryTokens(Set tokens) { - return SetUtils.emptyIfNull(tokens).stream() - .map(DeliveryToken::of) - .collect(Collectors.toCollection(TreeSet::new)); - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/DeliveryProgress.java b/src/main/java/org/prebid/server/deals/lineitem/DeliveryProgress.java deleted file mode 100644 index f14dbef4a07..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/DeliveryProgress.java +++ /dev/null @@ -1,349 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.report.Event; - -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Collection; -import java.util.Comparator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Consumer; -import java.util.stream.Collectors; - -public class DeliveryProgress { - - private static final String WIN_EVENT_TYPE = "win"; - - private final Map lineItemStatuses; - private final Map requestsPerAccount; - private final Map> lineItemIdToLost; - private final LongAdder requests; - private ZonedDateTime startTimeStamp; - private ZonedDateTime endTimeStamp; - private final LineItemService lineItemService; - - private DeliveryProgress(ZonedDateTime startTimeStamp, LineItemService lineItemService) { - this.startTimeStamp = Objects.requireNonNull(startTimeStamp); - this.lineItemStatuses = new ConcurrentHashMap<>(); - this.requests = new LongAdder(); - this.requestsPerAccount = new ConcurrentHashMap<>(); - this.lineItemIdToLost = new ConcurrentHashMap<>(); - this.lineItemService = Objects.requireNonNull(lineItemService); - } - - public static DeliveryProgress of(ZonedDateTime startTimeStamp, LineItemService lineItemService) { - return new DeliveryProgress(startTimeStamp, lineItemService); - } - - public DeliveryProgress copyWithOriginalPlans() { - final DeliveryProgress progress = DeliveryProgress.of(this.getStartTimeStamp(), - this.lineItemService); - - for (final LineItemStatus originalStatus : this.lineItemStatuses.values()) { - progress.lineItemStatuses.put(originalStatus.getLineItemId(), createStatusWithPlans(originalStatus)); - } - - progress.mergeFrom(this); - - return progress; - } - - private LineItemStatus createStatusWithPlans(LineItemStatus originalStatus) { - final LineItemStatus status = createLineItemStatus(originalStatus.getLineItemId()); - status.getDeliveryPlans().addAll(originalStatus.getDeliveryPlans()); - return status; - } - - /** - * Updates delivery progress from {@link TxnLog}. - */ - public void recordTransactionLog(TxnLog txnLog, Map planIdToTokenPriority, String accountId) { - accountRequests(accountId).increment(); - requests.increment(); - - txnLog.lineItemSentToClientAsTopMatch() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incSentToClientAsTopMatch)); - txnLog.lineItemsSentToClient() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incSentToClient)); - txnLog.lineItemsMatchedDomainTargeting() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incDomainMatched)); - txnLog.lineItemsMatchedWholeTargeting() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incTargetMatched)); - txnLog.lineItemsMatchedTargetingFcapped() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incTargetMatchedButFcapped)); - txnLog.lineItemsMatchedTargetingFcapLookupFailed() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incTargetMatchedButFcapLookupFailed)); - txnLog.lineItemsPacingDeferred() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incPacingDeferred)); - txnLog.lineItemsSentToBidder().values().forEach(idList -> idList - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incSentToBidder))); - txnLog.lineItemsSentToBidderAsTopMatch().values().forEach(bidderList -> bidderList - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incSentToBidderAsTopMatch))); - txnLog.lineItemsReceivedFromBidder().values().forEach(idList -> idList - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incReceivedFromBidder))); - txnLog.lineItemsResponseInvalidated() - .forEach(lineItemId -> increment(lineItemId, LineItemStatus::incReceivedFromBidderInvalidated)); - - txnLog.lineItemSentToClientAsTopMatch() - .forEach(lineItemId -> incToken(lineItemId, planIdToTokenPriority)); - - txnLog.lostMatchingToLineItems().forEach((lineItemId, lostToLineItemsIds) -> - updateLostToEachLineItem(lineItemId, lostToLineItemsIds, lineItemIdToLost)); - txnLog.lostAuctionToLineItems().forEach((lineItemId, lostToLineItemsIds) -> - updateLostToEachLineItem(lineItemId, lostToLineItemsIds, lineItemIdToLost)); - } - - /** - * Increments {@link LineItemStatus} win type {@link Event} counter. Creates new {@link LineItemStatus} if not - * exists. - */ - public void recordWinEvent(String lineItemId) { - final LineItemStatus lineItemStatus = lineItemStatuses.computeIfAbsent(lineItemId, this::createLineItemStatus); - final Event winEvent = lineItemStatus.getEvents().stream() - .filter(event -> event.getType().equals(WIN_EVENT_TYPE)) - .findAny() - .orElseGet(() -> Event.of(WIN_EVENT_TYPE, new LongAdder())); - - winEvent.getCount().increment(); - lineItemStatus.getEvents().add(winEvent); - } - - private LineItemStatus createLineItemStatus(String lineItemId) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - return lineItem != null - ? LineItemStatus.of(lineItem) - : LineItemStatus.of(lineItemId); - } - - /** - * Updates delivery progress from another {@link DeliveryProgress}. - */ - public void mergeFrom(DeliveryProgress another) { - requests.add(another.requests.sum()); - - another.requestsPerAccount.forEach((accountId, requestsCount) -> - mergeRequestsCount(accountId, requestsCount, requestsPerAccount)); - - another.lineItemStatuses.forEach((lineItemId, lineItemStatus) -> - lineItemStatuses.computeIfAbsent(lineItemId, this::createLineItemStatus).merge(lineItemStatus)); - - another.lineItemIdToLost.forEach((lineItemId, currentLineItemLost) -> - mergeCurrentLineItemLostReportToOverall(lineItemId, currentLineItemLost, lineItemIdToLost)); - } - - public void upsertPlanReferenceFromLineItem(LineItem lineItem) { - final String lineItemId = lineItem.getLineItemId(); - final LineItemStatus existingLineItemStatus = lineItemStatuses.get(lineItemId); - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - if (existingLineItemStatus == null) { - final LineItemStatus lineItemStatus = createLineItemStatus(lineItem.getLineItemId()); - lineItemStatus.getDeliveryPlans().add(activeDeliveryPlan); - lineItemStatuses.put(lineItemId, lineItemStatus); - } else { - updateLineItemStatusWithActiveDeliveryPlan(existingLineItemStatus, activeDeliveryPlan); - } - } - - /** - * Updates {@link LineItemStatus} with current {@link DeliveryPlan}. - */ - public void mergePlanFromLineItem(LineItem lineItem) { - final LineItemStatus currentLineItemStatus = lineItemStatuses.computeIfAbsent(lineItem.getLineItemId(), - this::createLineItemStatus); - final DeliveryPlan updatedDeliveryPlan = lineItem.getActiveDeliveryPlan(); - - final Set deliveryPlans = currentLineItemStatus.getDeliveryPlans(); - final DeliveryPlan currentPlan = deliveryPlans.stream() - .filter(plan -> Objects.equals(plan.getPlanId(), updatedDeliveryPlan.getPlanId())) - .findFirst() - .orElse(null); - - if (currentPlan == null) { - deliveryPlans.add(updatedDeliveryPlan.withoutSpentTokens()); - } else if (currentPlan.isUpdated(updatedDeliveryPlan.getDeliverySchedule())) { - final DeliveryPlan updatedPlan = currentPlan.mergeWithNextDeliveryPlan(updatedDeliveryPlan); - deliveryPlans.remove(currentPlan); - deliveryPlans.add(updatedPlan); - } - } - - /** - * Remove stale {@link LineItemStatus} from statistic. - */ - public void cleanLineItemStatuses(ZonedDateTime now, long lineItemStatusTtl, int maxPlanNumberInDeliveryProgress) { - lineItemStatuses.entrySet().removeIf(entry -> isLineItemStatusExpired(entry.getKey(), now, lineItemStatusTtl)); - - lineItemStatuses.values().forEach( - lineItemStatus -> cutCachedDeliveryPlans(lineItemStatus, maxPlanNumberInDeliveryProgress)); - } - - /** - * Returns true when lineItem is not in metaData and it is expired for more then defined in configuration time. - */ - private boolean isLineItemStatusExpired(String lineItemId, ZonedDateTime now, long lineItemStatusTtl) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - - return lineItem == null || ChronoUnit.MILLIS.between(lineItem.getEndTimeStamp(), now) > lineItemStatusTtl; - } - - /** - * Cuts number of plans in {@link LineItemStatus} from overall statistic by number defined in configuration. - */ - private void cutCachedDeliveryPlans(LineItemStatus lineItemStatus, int maxPlanNumberInDeliveryProgress) { - final Set deliveryPlans = lineItemStatus.getDeliveryPlans(); - if (deliveryPlans.size() > maxPlanNumberInDeliveryProgress) { - final Set plansToRemove = deliveryPlans.stream() - .sorted(Comparator.comparing(DeliveryPlan::getEndTimeStamp)) - .limit(deliveryPlans.size() - maxPlanNumberInDeliveryProgress) - .collect(Collectors.toSet()); - plansToRemove.forEach(deliveryPlans::remove); - } - } - - /** - * Updates {@link LineItemStatus} with active {@link DeliveryPlan}. - */ - private void updateLineItemStatusWithActiveDeliveryPlan(LineItemStatus lineItemStatus, - DeliveryPlan updatedDeliveryPlan) { - final Set deliveryPlans = lineItemStatus.getDeliveryPlans(); - final DeliveryPlan currentPlan = deliveryPlans.stream() - .filter(plan -> Objects.equals(plan.getPlanId(), updatedDeliveryPlan.getPlanId())) - .filter(plan -> plan.isUpdated(updatedDeliveryPlan.getDeliverySchedule())) - .findAny() - .orElse(null); - if (currentPlan != null) { - if (!Objects.equals(currentPlan.getUpdatedTimeStamp(), updatedDeliveryPlan.getUpdatedTimeStamp())) { - deliveryPlans.add(updatedDeliveryPlan); - deliveryPlans.remove(currentPlan); - } - } else { - deliveryPlans.add(updatedDeliveryPlan); - } - } - - public void updateWithActiveLineItems(Collection lineItems) { - lineItems.forEach(lineItem -> lineItemStatuses.putIfAbsent(lineItem.getLineItemId(), - createLineItemStatus(lineItem.getLineItemId()))); - } - - public Map getLineItemStatuses() { - return lineItemStatuses; - } - - public Map getRequestsPerAccount() { - return requestsPerAccount; - } - - public Map> getLineItemIdToLost() { - return lineItemIdToLost; - } - - public LongAdder getRequests() { - return requests; - } - - public ZonedDateTime getStartTimeStamp() { - return startTimeStamp; - } - - public void setStartTimeStamp(ZonedDateTime startTimeStamp) { - this.startTimeStamp = startTimeStamp; - } - - public void setEndTimeStamp(ZonedDateTime endTimeStamp) { - this.endTimeStamp = endTimeStamp; - } - - public ZonedDateTime getEndTimeStamp() { - return endTimeStamp; - } - - private LongAdder accountRequests(String account) { - return requestsPerAccount.computeIfAbsent(account, ignored -> new LongAdder()); - } - - /** - * Increments {@link LineItemStatus} metric, creates line item status if does not exist. - */ - private void increment(String lineItemId, Consumer inc) { - inc.accept(lineItemStatuses.computeIfAbsent(lineItemId, this::createLineItemStatus)); - } - - /** - * Increment tokens in active delivery report. - */ - private void incToken(String lineItemId, Map planIdToTokenPriority) { - final LineItemStatus lineItemStatus = lineItemStatuses.get(lineItemId); - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - final DeliveryPlan lineItemActivePlan = lineItem.getActiveDeliveryPlan(); - if (lineItemActivePlan != null) { - DeliveryPlan reportActivePlan = lineItemStatus.getDeliveryPlans().stream() - .filter(plan -> Objects.equals(plan.getPlanId(), lineItemActivePlan.getPlanId())) - .findFirst() - .orElse(null); - if (reportActivePlan == null) { - reportActivePlan = lineItemActivePlan.withoutSpentTokens(); - lineItemStatus.getDeliveryPlans().add(reportActivePlan); - } - - final Integer tokenPriority = planIdToTokenPriority.get(reportActivePlan.getPlanId()); - if (tokenPriority != null) { - reportActivePlan.incTokenWithPriority(tokenPriority); - } - } - } - - /** - * Updates lostToLineItem metric for line item specified by lineItemId parameter against line item ids from - * parameter lostToLineItemIds - */ - private void updateLostToEachLineItem(String lineItemId, Set lostToLineItemsIds, - Map> lostToLineItemTimes) { - final Map lostToLineItemsTimes = lostToLineItemTimes - .computeIfAbsent(lineItemId, key -> new ConcurrentHashMap<>()); - lostToLineItemsIds.forEach(lostToLineItemId -> incLostToLineItemTimes(lostToLineItemId, lostToLineItemsTimes)); - } - - /** - * Updates listToLineItem metric against line item specified in parameter lostToLineItemId - */ - private void incLostToLineItemTimes(String lostToLineItemId, Map lostToLineItemsTimes) { - final LostToLineItem lostToLineItem = lostToLineItemsTimes.computeIfAbsent(lostToLineItemId, - ignored -> LostToLineItem.of(lostToLineItemId, new LongAdder())); - lostToLineItem.getCount().increment(); - } - - /** - * Merges requests per account to overall statistics. - */ - private void mergeRequestsCount(String accountId, LongAdder requestsCount, - Map requestsPerAccount) { - requestsPerAccount.computeIfPresent(accountId, (key, oldValue) -> { - oldValue.add(requestsCount.sum()); - return oldValue; - }); - requestsPerAccount.putIfAbsent(accountId, requestsCount); - } - - private void mergeCurrentLineItemLostReportToOverall( - String lineItemId, - Map currentLineItemLost, - Map> overallLineItemIdToLost) { - final Map overallLineItemLost = overallLineItemIdToLost - .computeIfAbsent(lineItemId, ignored -> new ConcurrentHashMap<>()); - currentLineItemLost.forEach((lineItemIdLostTo, currentLostToLineItem) -> - overallLineItemLost.merge(lineItemIdLostTo, currentLostToLineItem, this::addToCount) - ); - } - - private LostToLineItem addToCount(LostToLineItem mergeTo, LostToLineItem mergeFrom) { - mergeTo.getCount().add(mergeFrom.getCount().sum()); - return mergeTo; - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/DeliveryToken.java b/src/main/java/org/prebid/server/deals/lineitem/DeliveryToken.java deleted file mode 100644 index 67188cc96e9..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/DeliveryToken.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import org.prebid.server.deals.proto.Token; - -import java.util.Comparator; -import java.util.Objects; -import java.util.concurrent.atomic.LongAdder; - -public class DeliveryToken implements Comparable { - - private static final Comparator COMPARATOR = Comparator.comparing(DeliveryToken::getPriorityClass); - - private final Token token; - - private final LongAdder spent; - - private DeliveryToken(Token token) { - this(token, new LongAdder()); - } - - private DeliveryToken(Token token, LongAdder spent) { - this.token = Objects.requireNonNull(token); - this.spent = Objects.requireNonNull(spent); - } - - public static DeliveryToken of(DeliveryToken deliveryToken) { - return new DeliveryToken(deliveryToken.token); - } - - public static DeliveryToken of(Token token) { - return new DeliveryToken(token); - } - - /** - * Return unspent tokens from {@link DeliveryToken}. - */ - public int getUnspent() { - return (int) (token.getTotal() - spent.sum()); - } - - public void inc() { - spent.increment(); - } - - public DeliveryToken mergeWithToken(Token nextToken, boolean sumTotal) { - if (nextToken == null) { - return this; - } else { - final int total = sumTotal - ? getTotal() + nextToken.getTotal() - : nextToken.getTotal(); - return new DeliveryToken(Token.of(getPriorityClass(), total), spent); - } - } - - public LongAdder getSpent() { - return spent; - } - - public Integer getTotal() { - return token.getTotal(); - } - - public Integer getPriorityClass() { - return token.getPriorityClass(); - } - - @Override - public int compareTo(DeliveryToken another) { - return COMPARATOR.compare(this, another); - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/LineItem.java b/src/main/java/org/prebid/server/deals/lineitem/LineItem.java deleted file mode 100644 index 58554ab6cdd..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/LineItem.java +++ /dev/null @@ -1,276 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.collections4.ListUtils; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.FrequencyCap; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.LineItemSize; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.deals.targeting.TargetingDefinition; - -import java.math.BigDecimal; -import java.time.ZonedDateTime; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -public class LineItem { - - private static final Logger logger = LoggerFactory.getLogger(LineItem.class); - - private final LineItemMetaData metaData; - - private final Price normalizedPrice; - - private final List fcapIds; - - private final TargetingDefinition targetingDefinition; - - private final AtomicReference activeDeliveryPlan; - - private final AtomicReference readyAt; - - private LineItem(LineItemMetaData metaData, Price normalizedPrice, TargetingDefinition targetingDefinition) { - this.metaData = Objects.requireNonNull(metaData); - this.normalizedPrice = normalizedPrice; - this.targetingDefinition = targetingDefinition; - - this.fcapIds = extractFcapIds(metaData); - - activeDeliveryPlan = new AtomicReference<>(); - readyAt = new AtomicReference<>(); - } - - private LineItem(LineItemMetaData metaData, - Price normalizedPrice, - TargetingDefinition targetingDefinition, - ZonedDateTime readyAt, - ZonedDateTime now, - DeliveryPlan currentPlan) { - this(metaData, normalizedPrice, targetingDefinition); - this.readyAt.set(readyAt); - - updateOrAdvanceActivePlan(now, true, currentPlan); - } - - private LineItem(LineItemMetaData metaData, - Price normalizedPrice, - TargetingDefinition targetingDefinition, - ZonedDateTime now) { - this(metaData, normalizedPrice, targetingDefinition, null, now, null); - } - - public static LineItem of(LineItemMetaData metaData, - Price normalizedPrice, - TargetingDefinition targetingDefinition, - ZonedDateTime now) { - return new LineItem(metaData, normalizedPrice, targetingDefinition, now); - } - - public LineItem withUpdatedMetadata(LineItemMetaData metaData, - Price normalizedPrice, - TargetingDefinition targetingDefinition, - ZonedDateTime readyAt, - ZonedDateTime now) { - return new LineItem(metaData, normalizedPrice, targetingDefinition, readyAt, now, getActiveDeliveryPlan()); - } - - public void advanceToNextPlan(ZonedDateTime now, boolean isPlannerResponsive) { - updateOrAdvanceActivePlan(now, isPlannerResponsive, getActiveDeliveryPlan()); - } - - /** - * Increments tokens in {@link DeliveryToken} with highest priority within {@link DeliveryPlan}. - * - * @return class of the token incremented. - */ - public Integer incSpentToken(ZonedDateTime now) { - return incSpentToken(now, 0); - } - - public Integer incSpentToken(ZonedDateTime now, long adjustment) { - final DeliveryPlan deliveryPlan = activeDeliveryPlan.get(); - - if (deliveryPlan != null) { - final Integer tokenClassIncremented = deliveryPlan.incSpentToken(); - ZonedDateTime readyAtNewValue = deliveryPlan.calculateReadyAt(); - readyAtNewValue = readyAtNewValue != null && adjustment != 0 - ? readyAtNewValue.plusNanos(TimeUnit.MILLISECONDS.toNanos(adjustment)) - : readyAtNewValue; - readyAt.set(readyAtNewValue); - if (logger.isDebugEnabled()) { - logger.debug("ReadyAt for lineItem {0} plan {1} was updated to {2} after token was spent. Total number" - + " of unspent token is {3}. Current time is {4}", - getLineItemId(), deliveryPlan.getPlanId(), - readyAt.get(), deliveryPlan.getUnspentTokens(), now); - } - return tokenClassIncremented; - } - return null; - } - - public Integer getHighestUnspentTokensClass() { - final DeliveryPlan activeDeliveryPlan = getActiveDeliveryPlan(); - return activeDeliveryPlan != null ? activeDeliveryPlan.getHighestUnspentTokensClass() : null; - } - - public boolean isActive(ZonedDateTime now) { - return dateBetween(now, metaData.getStartTimeStamp(), metaData.getEndTimeStamp()); - } - - public DeliveryPlan getActiveDeliveryPlan() { - return activeDeliveryPlan.get(); - } - - public ZonedDateTime getReadyAt() { - return readyAt.get(); - } - - public BigDecimal getCpm() { - if (normalizedPrice != null) { - return normalizedPrice.getCpm(); - } - return null; - } - - public String getCurrency() { - if (normalizedPrice != null) { - return normalizedPrice.getCurrency(); - } - return null; - } - - public String getLineItemId() { - return metaData.getLineItemId(); - } - - public String getExtLineItemId() { - return metaData.getExtLineItemId(); - } - - public String getDealId() { - return metaData.getDealId(); - } - - public String getAccountId() { - return metaData.getAccountId(); - } - - public String getSource() { - return metaData.getSource(); - } - - public Integer getRelativePriority() { - return metaData.getRelativePriority(); - } - - public ZonedDateTime getEndTimeStamp() { - return metaData.getEndTimeStamp(); - } - - public ZonedDateTime getStartTimeStamp() { - return metaData.getStartTimeStamp(); - } - - public ZonedDateTime getUpdatedTimeStamp() { - return metaData.getUpdatedTimeStamp(); - } - - public List getFrequencyCaps() { - return metaData.getFrequencyCaps(); - } - - public List getSizes() { - return metaData.getSizes(); - } - - public ObjectNode getTargeting() { - return metaData.getTargeting(); - } - - public TargetingDefinition getTargetingDefinition() { - return targetingDefinition; - } - - public List getFcapIds() { - return fcapIds; - } - - private static List extractFcapIds(LineItemMetaData metaData) { - return CollectionUtils.emptyIfNull(metaData.getFrequencyCaps()).stream() - .map(FrequencyCap::getFcapId) - .toList(); - } - - private void updateOrAdvanceActivePlan(ZonedDateTime now, boolean isPlannerResponsive, DeliveryPlan currentPlan) { - final DeliverySchedule currentSchedule = ListUtils.emptyIfNull(metaData.getDeliverySchedules()).stream() - .filter(schedule -> dateBetween(now, schedule.getStartTimeStamp(), schedule.getEndTimeStamp())) - .findFirst() - .orElse(null); - - if (currentSchedule != null) { - final DeliveryPlan resolvedPlan = resolveActivePlan(currentPlan, currentSchedule, isPlannerResponsive); - final ZonedDateTime readyAtBeforeUpdate = readyAt.get(); - if (currentPlan != resolvedPlan) { - readyAt.set(currentPlan == null || !Objects.equals(currentSchedule.getPlanId(), currentPlan.getPlanId()) - ? calculateReadyAfterMovingToNextPlan(now, resolvedPlan) - : calculateReadyAtAfterPlanUpdated(now, resolvedPlan)); - logger.info("ReadyAt for Line Item `{0}` was updated from plan {1} to {2} and readyAt from {3} to {4}" - + " at time is {5}", getLineItemId(), - currentPlan != null ? currentPlan.getPlanId() : " no plan ", resolvedPlan.getPlanId(), - readyAtBeforeUpdate, getReadyAt(), now); - if (logger.isDebugEnabled()) { - logger.debug("Unspent tokens number for plan {0} is {1}", resolvedPlan.getPlanId(), - resolvedPlan.getUnspentTokens()); - } - } - activeDeliveryPlan.set(resolvedPlan); - } else { - activeDeliveryPlan.set(null); - readyAt.set(null); - logger.info("Active plan for Line Item `{0}` was not found at time is {1}, readyAt updated with 'never'," - + " until active plan become available", getLineItemId(), now); - } - } - - private ZonedDateTime calculateReadyAtAfterPlanUpdated(ZonedDateTime now, DeliveryPlan resolvedPlan) { - final ZonedDateTime resolvedReadyAt = resolvedPlan.calculateReadyAt(); - logger.debug("Current plan for Line Item `{0}` was considered as updated from GP response and readyAt will be " - + "updated from {1} to {2} at time is {3}", getLineItemId(), getReadyAt(), resolvedReadyAt, now); - return resolvedReadyAt; - } - - private ZonedDateTime calculateReadyAfterMovingToNextPlan(ZonedDateTime now, DeliveryPlan resolvedPlan) { - return resolvedPlan.getDeliveryTokens().stream().anyMatch(deliveryToken -> deliveryToken.getTotal() > 0) - ? now - : null; - } - - private static DeliveryPlan resolveActivePlan(DeliveryPlan currentPlan, - DeliverySchedule currentSchedule, - boolean isPlannerResponsive) { - if (currentPlan != null) { - if (Objects.equals(currentPlan.getPlanId(), currentSchedule.getPlanId())) { - return currentPlan.getUpdatedTimeStamp().isBefore(currentSchedule.getUpdatedTimeStamp()) - ? currentPlan.mergeWithNextDeliverySchedule(currentSchedule, false) - : currentPlan; - } else if (!isPlannerResponsive) { - return currentPlan.mergeWithNextDeliverySchedule(currentSchedule, true); - } - } - - return DeliveryPlan.of(currentSchedule); - } - - /** - * Returns true when now parameter is after startDate and before expirationDate. - */ - private static boolean dateBetween(ZonedDateTime now, ZonedDateTime startDate, ZonedDateTime expirationDate) { - return (now.isEqual(startDate) || now.isAfter(startDate)) && now.isBefore(expirationDate); - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/LineItemStatus.java b/src/main/java/org/prebid/server/deals/lineitem/LineItemStatus.java deleted file mode 100644 index e05cd399d0d..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/LineItemStatus.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import io.vertx.core.impl.ConcurrentHashSet; -import lombok.Value; -import org.prebid.server.deals.proto.report.Event; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Value -public class LineItemStatus { - - String lineItemId; - - String source; - - String dealId; - - String extLineItemId; - - String accountId; - - LongAdder domainMatched; - - LongAdder targetMatched; - - LongAdder targetMatchedButFcapped; - - LongAdder targetMatchedButFcapLookupFailed; - - LongAdder pacingDeferred; - - LongAdder sentToBidder; - - LongAdder sentToBidderAsTopMatch; - - LongAdder receivedFromBidder; - - LongAdder receivedFromBidderInvalidated; - - LongAdder sentToClient; - - LongAdder sentToClientAsTopMatch; - - Set lostToLineItems; - - Set events; - - Set deliveryPlans; - - private LineItemStatus(String lineItemId, String source, String dealId, String extLineItemId, String accountId) { - this.lineItemId = lineItemId; - this.source = source; - this.dealId = dealId; - this.extLineItemId = extLineItemId; - this.accountId = accountId; - - domainMatched = new LongAdder(); - targetMatched = new LongAdder(); - targetMatchedButFcapped = new LongAdder(); - targetMatchedButFcapLookupFailed = new LongAdder(); - pacingDeferred = new LongAdder(); - sentToBidder = new LongAdder(); - sentToBidderAsTopMatch = new LongAdder(); - receivedFromBidder = new LongAdder(); - receivedFromBidderInvalidated = new LongAdder(); - sentToClient = new LongAdder(); - sentToClientAsTopMatch = new LongAdder(); - - lostToLineItems = new ConcurrentHashSet<>(); - events = new ConcurrentHashSet<>(); - deliveryPlans = new ConcurrentHashSet<>(); - } - - public static LineItemStatus of(String lineItemId, String source, String dealId, String extLineItemId, - String accountId) { - return new LineItemStatus(lineItemId, source, dealId, extLineItemId, accountId); - } - - public static LineItemStatus of(LineItem lineItem) { - return new LineItemStatus(lineItem.getLineItemId(), lineItem.getSource(), lineItem.getDealId(), - lineItem.getExtLineItemId(), lineItem.getAccountId()); - } - - public static LineItemStatus of(String lineItemId) { - return new LineItemStatus(lineItemId, null, null, null, null); - } - - public void incDomainMatched() { - domainMatched.increment(); - } - - public void incTargetMatched() { - targetMatched.increment(); - } - - public void incTargetMatchedButFcapped() { - targetMatchedButFcapped.increment(); - } - - public void incTargetMatchedButFcapLookupFailed() { - targetMatchedButFcapLookupFailed.increment(); - } - - public void incPacingDeferred() { - pacingDeferred.increment(); - } - - public void incSentToBidder() { - sentToBidder.increment(); - } - - public void incSentToBidderAsTopMatch() { - sentToBidderAsTopMatch.increment(); - } - - public void incReceivedFromBidder() { - receivedFromBidder.increment(); - } - - public void incReceivedFromBidderInvalidated() { - receivedFromBidderInvalidated.increment(); - } - - public void incSentToClient() { - sentToClient.increment(); - } - - public void incSentToClientAsTopMatch() { - sentToClientAsTopMatch.increment(); - } - - public void merge(LineItemStatus other) { - domainMatched.add(other.domainMatched.sum()); - targetMatched.add(other.targetMatched.sum()); - targetMatchedButFcapped.add(other.targetMatchedButFcapped.sum()); - targetMatchedButFcapLookupFailed.add(other.getTargetMatchedButFcapLookupFailed().sum()); - pacingDeferred.add(other.pacingDeferred.sum()); - sentToBidder.add(other.sentToBidder.sum()); - sentToBidderAsTopMatch.add(other.sentToBidderAsTopMatch.sum()); - receivedFromBidder.add(other.receivedFromBidder.sum()); - receivedFromBidderInvalidated.add(other.receivedFromBidderInvalidated.sum()); - sentToClient.add(other.sentToClient.sum()); - sentToClientAsTopMatch.add(other.sentToClientAsTopMatch.sum()); - mergeEvents(other); - } - - private void mergeEvents(LineItemStatus other) { - final Map typesToEvent = other.events.stream() - .collect(Collectors.toMap(Event::getType, Function.identity())); - typesToEvent.forEach(this::addOrUpdateEvent); - } - - private void addOrUpdateEvent(String type, Event distEvent) { - final Event sameTypeEvent = events.stream() - .filter(event -> event.getType().equals(type)) - .findFirst().orElse(null); - if (sameTypeEvent != null) { - sameTypeEvent.getCount().add(distEvent.getCount().sum()); - } else { - events.add(distEvent); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/lineitem/LostToLineItem.java b/src/main/java/org/prebid/server/deals/lineitem/LostToLineItem.java deleted file mode 100644 index 0b7be6d1f21..00000000000 --- a/src/main/java/org/prebid/server/deals/lineitem/LostToLineItem.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.concurrent.atomic.LongAdder; - -@AllArgsConstructor(staticName = "of") -@Value -public class LostToLineItem { - - String lineItemId; - - LongAdder count; -} diff --git a/src/main/java/org/prebid/server/deals/model/AdminAccounts.java b/src/main/java/org/prebid/server/deals/model/AdminAccounts.java deleted file mode 100644 index b5829dab3e6..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AdminAccounts.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@Value -@AllArgsConstructor(staticName = "of") -public class AdminAccounts { - - List accounts; -} diff --git a/src/main/java/org/prebid/server/deals/model/AdminCentralResponse.java b/src/main/java/org/prebid/server/deals/model/AdminCentralResponse.java deleted file mode 100644 index 034389ddd78..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AdminCentralResponse.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class AdminCentralResponse { - - LogTracer tracer; - - @JsonProperty("storedrequest") - Command storedRequest; - - @JsonProperty("storedrequest-amp") - Command storedRequestAmp; - - @JsonProperty("line-items") - Command lineItems; - - Command account; - - ServicesCommand services; -} diff --git a/src/main/java/org/prebid/server/deals/model/AdminLineItems.java b/src/main/java/org/prebid/server/deals/model/AdminLineItems.java deleted file mode 100644 index 14f2ecca150..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AdminLineItems.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@Value -@AllArgsConstructor(staticName = "of") -public class AdminLineItems { - - List ids; -} diff --git a/src/main/java/org/prebid/server/deals/model/AlertEvent.java b/src/main/java/org/prebid/server/deals/model/AlertEvent.java deleted file mode 100644 index 157ab84c41f..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AlertEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.Value; - -import java.time.ZonedDateTime; - -@Builder -@Value -public class AlertEvent { - - String id; - - String action; - - AlertPriority priority; - - ZonedDateTime updatedAt; - - String name; - - String details; - - AlertSource source; -} diff --git a/src/main/java/org/prebid/server/deals/model/AlertPriority.java b/src/main/java/org/prebid/server/deals/model/AlertPriority.java deleted file mode 100644 index 074fa5e164c..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AlertPriority.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.prebid.server.deals.model; - -public enum AlertPriority { - - HIGH, MEDIUM, LOW -} diff --git a/src/main/java/org/prebid/server/deals/model/AlertProxyProperties.java b/src/main/java/org/prebid/server/deals/model/AlertProxyProperties.java deleted file mode 100644 index 28d076129da..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AlertProxyProperties.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.Value; - -import java.util.Map; - -@Builder -@Value -public class AlertProxyProperties { - - boolean enabled; - - String url; - - int timeoutSec; - - Map alertTypes; - - String username; - - String password; -} diff --git a/src/main/java/org/prebid/server/deals/model/AlertSource.java b/src/main/java/org/prebid/server/deals/model/AlertSource.java deleted file mode 100644 index a673a18cb5b..00000000000 --- a/src/main/java/org/prebid/server/deals/model/AlertSource.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -@Builder -@Value -public class AlertSource { - - String env; - - @JsonProperty("data-center") - String dataCenter; - - String region; - - String system; - - @JsonProperty("sub-system") - String subSystem; - - @JsonProperty("host-id") - String hostId; -} diff --git a/src/main/java/org/prebid/server/deals/model/Command.java b/src/main/java/org/prebid/server/deals/model/Command.java deleted file mode 100644 index 7acbec5e4c0..00000000000 --- a/src/main/java/org/prebid/server/deals/model/Command.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class Command { - - String cmd; - - ObjectNode body; -} diff --git a/src/main/java/org/prebid/server/deals/model/DeepDebugLog.java b/src/main/java/org/prebid/server/deals/model/DeepDebugLog.java deleted file mode 100644 index 597c55f63b0..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeepDebugLog.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.prebid.server.deals.model; - -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; - -public class DeepDebugLog { - - private final boolean deepDebugEnabled; - - private final List entries; - - private final Clock clock; - - private DeepDebugLog(boolean deepDebugEnabled, Clock clock) { - this.deepDebugEnabled = deepDebugEnabled; - this.entries = deepDebugEnabled ? new LinkedList<>() : null; - this.clock = Objects.requireNonNull(clock); - } - - public static DeepDebugLog create(boolean deepDebugEnabled, Clock clock) { - return new DeepDebugLog(deepDebugEnabled, clock); - } - - public void add(String lineItemId, Category category, Supplier messageSupplier) { - if (deepDebugEnabled) { - entries.add(ExtTraceDeal.of(lineItemId, ZonedDateTime.now(clock), category, messageSupplier.get())); - } - } - - public boolean isDeepDebugEnabled() { - return deepDebugEnabled; - } - - public List entries() { - return entries == null ? Collections.emptyList() : Collections.unmodifiableList(entries); - } -} diff --git a/src/main/java/org/prebid/server/deals/model/DeliveryProgressProperties.java b/src/main/java/org/prebid/server/deals/model/DeliveryProgressProperties.java deleted file mode 100644 index 95007f33ea0..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeliveryProgressProperties.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class DeliveryProgressProperties { - - long lineItemStatusTtlSeconds; - - int cachedPlansNumber; -} diff --git a/src/main/java/org/prebid/server/deals/model/DeliveryStatsProperties.java b/src/main/java/org/prebid/server/deals/model/DeliveryStatsProperties.java deleted file mode 100644 index 237c094a33b..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeliveryStatsProperties.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.NonNull; -import lombok.Value; - -@Builder -@Value -public class DeliveryStatsProperties { - - @NonNull - String endpoint; - - int cachedReportsNumber; - - long timeoutMs; - - int lineItemsPerReport; - - int reportsIntervalMs; - - int batchesIntervalMs; - - boolean requestCompressionEnabled; - - @NonNull - String username; - - @NonNull - String password; -} diff --git a/src/main/java/org/prebid/server/deals/model/DeploymentProperties.java b/src/main/java/org/prebid/server/deals/model/DeploymentProperties.java deleted file mode 100644 index afd08710145..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeploymentProperties.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.Value; - -@Builder -@Value -public class DeploymentProperties { - - String pbsHostId; - - String pbsRegion; - - String pbsVendor; - - String profile; - - String infra; - - String dataCenter; - - String system; - - String subSystem; -} diff --git a/src/main/java/org/prebid/server/deals/model/DeviceInfo.java b/src/main/java/org/prebid/server/deals/model/DeviceInfo.java deleted file mode 100644 index e58f9bcedf9..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeviceInfo.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.NonNull; -import lombok.Value; - -@Builder -@Value -public class DeviceInfo { - - @NonNull - String vendor; - - DeviceType deviceType; - - String deviceTypeRaw; - - String osfamily; - - String os; - - String osVersion; - - String manufacturer; - - String model; - - String browser; - - String browserVersion; - - String carrier; - - String language; -} diff --git a/src/main/java/org/prebid/server/deals/model/DeviceType.java b/src/main/java/org/prebid/server/deals/model/DeviceType.java deleted file mode 100644 index 04acc900bce..00000000000 --- a/src/main/java/org/prebid/server/deals/model/DeviceType.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.prebid.server.deals.model; - -public enum DeviceType { - - MOBILE("mobile"), - DESKTOP("desktop"), - TV("connected tv"), - PHONE("phone"), - DEVICE("connected device"), - SET_TOP_BOX("set top box"), - TABLET("tablet"); - - private final String name; - - DeviceType(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public static DeviceType resolveDeviceType(String deviceType) { - if (deviceType == null) { - return null; - } - - return switch (deviceType) { - case "Mobile Phone", "Mobile", "SmartPhone", "SmallScreen" -> MOBILE; - case "Desktop", "Single-board Computer" -> DESKTOP; - case "TV", "Tv" -> TV; - case "Fixed Wireless Phone", "Vehicle Phone" -> PHONE; - case "Tablet" -> TABLET; - case "Digital Home Assistant", "Digital Signage Media Player", - "eReader", "EReader", "Console", "Games Console", "Media Player", - "Payment Terminal", "Refrigerator", "Vehicle Multimedia System", - "Weighing Scale", "Wristwatch", "SmartWatch" -> DEVICE; - // might not be correct for 51degrees (https://51degrees.com/resources/property-dictionary) - case "Set Top Box", "MediaHub" -> SET_TOP_BOX; - default -> null; - }; - } -} diff --git a/src/main/java/org/prebid/server/deals/model/ExtUser.java b/src/main/java/org/prebid/server/deals/model/ExtUser.java deleted file mode 100644 index 26f6d610fa3..00000000000 --- a/src/main/java/org/prebid/server/deals/model/ExtUser.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class ExtUser { - - @JsonProperty("fcapIds") - List fcapIds; -} diff --git a/src/main/java/org/prebid/server/deals/model/LogCriteriaFilter.java b/src/main/java/org/prebid/server/deals/model/LogCriteriaFilter.java deleted file mode 100644 index 758a40a6282..00000000000 --- a/src/main/java/org/prebid/server/deals/model/LogCriteriaFilter.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class LogCriteriaFilter { - - @JsonProperty("accountId") - String accountId; - - @JsonProperty("bidderCode") - String bidderCode; - - @JsonProperty("lineItemId") - String lineItemId; -} diff --git a/src/main/java/org/prebid/server/deals/model/LogTracer.java b/src/main/java/org/prebid/server/deals/model/LogTracer.java deleted file mode 100644 index fb5c2e9c456..00000000000 --- a/src/main/java/org/prebid/server/deals/model/LogTracer.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class LogTracer { - - String cmd; - - Boolean raw; - - @JsonProperty("durationInSeconds") - Long durationInSeconds; - - LogCriteriaFilter filters; -} diff --git a/src/main/java/org/prebid/server/deals/model/MatchLineItemsResult.java b/src/main/java/org/prebid/server/deals/model/MatchLineItemsResult.java deleted file mode 100644 index 22d1cd01078..00000000000 --- a/src/main/java/org/prebid/server/deals/model/MatchLineItemsResult.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; -import org.prebid.server.deals.lineitem.LineItem; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class MatchLineItemsResult { - - List lineItems; -} diff --git a/src/main/java/org/prebid/server/deals/model/PlannerProperties.java b/src/main/java/org/prebid/server/deals/model/PlannerProperties.java deleted file mode 100644 index f7eac001842..00000000000 --- a/src/main/java/org/prebid/server/deals/model/PlannerProperties.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.NonNull; -import lombok.Value; - -@Builder -@Value -public class PlannerProperties { - - @NonNull - String planEndpoint; - - @NonNull - String registerEndpoint; - - long timeoutMs; - - long registerPeriodSeconds; - - @NonNull - String username; - - @NonNull - String password; -} diff --git a/src/main/java/org/prebid/server/deals/model/Segment.java b/src/main/java/org/prebid/server/deals/model/Segment.java deleted file mode 100644 index 648e3cf5f0c..00000000000 --- a/src/main/java/org/prebid/server/deals/model/Segment.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class Segment { - - String id; -} diff --git a/src/main/java/org/prebid/server/deals/model/ServicesCommand.java b/src/main/java/org/prebid/server/deals/model/ServicesCommand.java deleted file mode 100644 index f58c26791d5..00000000000 --- a/src/main/java/org/prebid/server/deals/model/ServicesCommand.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class ServicesCommand { - - String cmd; -} diff --git a/src/main/java/org/prebid/server/deals/model/SimulationProperties.java b/src/main/java/org/prebid/server/deals/model/SimulationProperties.java deleted file mode 100644 index fc520afbbcf..00000000000 --- a/src/main/java/org/prebid/server/deals/model/SimulationProperties.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.Builder; -import lombok.Value; - -@Builder -@Value -public class SimulationProperties { - - boolean enabled; - - boolean winEventsEnabled; - - boolean userDetailsEnabled; -} diff --git a/src/main/java/org/prebid/server/deals/model/TxnLog.java b/src/main/java/org/prebid/server/deals/model/TxnLog.java deleted file mode 100644 index f4a4ae34c48..00000000000 --- a/src/main/java/org/prebid/server/deals/model/TxnLog.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; -import lombok.experimental.FieldDefaults; -import org.apache.commons.collections4.Factory; -import org.apache.commons.collections4.MapUtils; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; - -@Getter -@Accessors(fluent = true, chain = true) -@NoArgsConstructor(staticName = "create") -@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) -@EqualsAndHashCode -public class TxnLog { - - Set lineItemsMatchedDomainTargeting = new HashSet<>(); - - Set lineItemsMatchedWholeTargeting = new HashSet<>(); - - Set lineItemsMatchedTargetingFcapped = new HashSet<>(); - - Set lineItemsMatchedTargetingFcapLookupFailed = new HashSet<>(); - - Set lineItemsReadyToServe = new HashSet<>(); - - Set lineItemsPacingDeferred = new HashSet<>(); - - Map> lineItemsSentToBidder = MapUtils.lazyMap( - new TreeMap<>(String.CASE_INSENSITIVE_ORDER), - (Factory>) HashSet::new); - - Map> lineItemsSentToBidderAsTopMatch = MapUtils.lazyMap( - new TreeMap<>(String.CASE_INSENSITIVE_ORDER), - (Factory>) HashSet::new); - - Map> lineItemsReceivedFromBidder = MapUtils.lazyMap( - new TreeMap<>(String.CASE_INSENSITIVE_ORDER), - (Factory>) HashSet::new); - - Set lineItemsResponseInvalidated = new HashSet<>(); - - Set lineItemsSentToClient = new HashSet<>(); - - Map> lostMatchingToLineItems = MapUtils.lazyMap(new HashMap<>(), - (Factory>) HashSet::new); - - Map> lostAuctionToLineItems = MapUtils.lazyMap(new HashMap<>(), - (Factory>) HashSet::new); - - Set lineItemSentToClientAsTopMatch = new HashSet<>(); -} diff --git a/src/main/java/org/prebid/server/deals/model/User.java b/src/main/java/org/prebid/server/deals/model/User.java deleted file mode 100644 index fcb777fb957..00000000000 --- a/src/main/java/org/prebid/server/deals/model/User.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class User { - - List data; - - ExtUser ext; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserData.java b/src/main/java/org/prebid/server/deals/model/UserData.java deleted file mode 100644 index e25f41ab6ff..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserData.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserData { - - String id; - - String name; - - List segment; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserDetails.java b/src/main/java/org/prebid/server/deals/model/UserDetails.java deleted file mode 100644 index 5ded7d3a481..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserDetails.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserDetails { - - private static final UserDetails EMPTY = UserDetails.of(null, null); - - List userData; - - List fcapIds; - - public static UserDetails empty() { - return EMPTY; - } -} diff --git a/src/main/java/org/prebid/server/deals/model/UserDetailsProperties.java b/src/main/java/org/prebid/server/deals/model/UserDetailsProperties.java deleted file mode 100644 index 2a01b7a1208..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserDetailsProperties.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.NonNull; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserDetailsProperties { - - @NonNull - String userDetailsEndpoint; - - @NonNull - String winEventEndpoint; - - long timeout; - - @NonNull - List userIds; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserDetailsRequest.java b/src/main/java/org/prebid/server/deals/model/UserDetailsRequest.java deleted file mode 100644 index b17091924a1..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserDetailsRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.List; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserDetailsRequest { - - String time; - - List ids; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserDetailsResponse.java b/src/main/java/org/prebid/server/deals/model/UserDetailsResponse.java deleted file mode 100644 index 09e83e5ef11..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserDetailsResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserDetailsResponse { - - User user; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserId.java b/src/main/java/org/prebid/server/deals/model/UserId.java deleted file mode 100644 index 4ab19e907ba..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserId.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserId { - - String type; - - String id; -} diff --git a/src/main/java/org/prebid/server/deals/model/UserIdRule.java b/src/main/java/org/prebid/server/deals/model/UserIdRule.java deleted file mode 100644 index 674cd05f04b..00000000000 --- a/src/main/java/org/prebid/server/deals/model/UserIdRule.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.deals.model; - -import lombok.AllArgsConstructor; -import lombok.NonNull; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class UserIdRule { - - @NonNull - String type; - - @NonNull - String source; - - @NonNull - String location; -} diff --git a/src/main/java/org/prebid/server/deals/model/WinEventNotification.java b/src/main/java/org/prebid/server/deals/model/WinEventNotification.java deleted file mode 100644 index 06e4dbcd85f..00000000000 --- a/src/main/java/org/prebid/server/deals/model/WinEventNotification.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.prebid.server.deals.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; -import org.prebid.server.deals.proto.FrequencyCap; - -import java.time.ZonedDateTime; -import java.util.List; - -@Builder(toBuilder = true) -@Value -public class WinEventNotification { - - @JsonProperty("bidderCode") - String bidderCode; - - @JsonProperty("bidId") - String bidId; - - @JsonProperty("lineItemId") - String lineItemId; - - String region; - - @JsonProperty("userIds") - List userIds; - - @JsonProperty("winEventDateTime") - ZonedDateTime winEventDateTime; - - @JsonProperty("lineUpdatedDateTime") - ZonedDateTime lineUpdatedDateTime; - - @JsonProperty("frequencyCaps") - List frequencyCaps; -} diff --git a/src/main/java/org/prebid/server/deals/proto/CurrencyServiceState.java b/src/main/java/org/prebid/server/deals/proto/CurrencyServiceState.java deleted file mode 100644 index 937ccdc5c39..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/CurrencyServiceState.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class CurrencyServiceState { - - @JsonProperty("lastUpdate") - String lastUpdate; -} diff --git a/src/main/java/org/prebid/server/deals/proto/DeliverySchedule.java b/src/main/java/org/prebid/server/deals/proto/DeliverySchedule.java deleted file mode 100644 index 32f7b779fa2..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/DeliverySchedule.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -import java.time.ZonedDateTime; -import java.util.Set; - -/** - * Defines the contract for lineItems[].deliverySchedules[]. - */ -@Builder -@Value -public class DeliverySchedule { - - @JsonProperty("planId") - String planId; - - @JsonProperty("startTimeStamp") - ZonedDateTime startTimeStamp; - - @JsonProperty("endTimeStamp") - ZonedDateTime endTimeStamp; - - @JsonProperty("updatedTimeStamp") - ZonedDateTime updatedTimeStamp; - - Set tokens; -} diff --git a/src/main/java/org/prebid/server/deals/proto/FrequencyCap.java b/src/main/java/org/prebid/server/deals/proto/FrequencyCap.java deleted file mode 100644 index 053a9331fab..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/FrequencyCap.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -/** - * Defines the contract for lineItems[].frequencyCap. - */ -@Builder -@Value -public class FrequencyCap { - - @JsonProperty("fcapId") - String fcapId; - - Long count; - - Integer periods; - - @JsonProperty("periodType") - String periodType; -} diff --git a/src/main/java/org/prebid/server/deals/proto/LineItemMetaData.java b/src/main/java/org/prebid/server/deals/proto/LineItemMetaData.java deleted file mode 100644 index 8bba4760ba1..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/LineItemMetaData.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.Builder; -import lombok.Value; - -import java.time.ZonedDateTime; -import java.util.List; - -/** - * Defines the contract for lineItems[]. - */ -@Builder(toBuilder = true) -@Value -public class LineItemMetaData { - - @JsonProperty("lineItemId") - String lineItemId; - - @JsonProperty("extLineItemId") - String extLineItemId; - - @JsonProperty("dealId") - String dealId; - - List sizes; - - @JsonProperty("accountId") - String accountId; - - String source; - - Price price; - - @JsonProperty("relativePriority") - Integer relativePriority; - - @JsonProperty("startTimeStamp") - ZonedDateTime startTimeStamp; - - @JsonProperty("endTimeStamp") - ZonedDateTime endTimeStamp; - - @JsonProperty("updatedTimeStamp") - ZonedDateTime updatedTimeStamp; - - String status; - - @JsonProperty("frequencyCaps") - List frequencyCaps; - - @JsonProperty("deliverySchedules") - List deliverySchedules; - - ObjectNode targeting; -} diff --git a/src/main/java/org/prebid/server/deals/proto/LineItemSize.java b/src/main/java/org/prebid/server/deals/proto/LineItemSize.java deleted file mode 100644 index 8715d22a59a..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/LineItemSize.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.prebid.server.deals.proto; - -import lombok.AllArgsConstructor; -import lombok.Value; - -/** - * Defines the contract for lineItems[].sizes[]. - */ -@AllArgsConstructor(staticName = "of") -@Value -public class LineItemSize { - - Integer w; - - Integer h; -} diff --git a/src/main/java/org/prebid/server/deals/proto/Price.java b/src/main/java/org/prebid/server/deals/proto/Price.java deleted file mode 100644 index 15c3c5f1963..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/Price.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.proto; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.math.BigDecimal; - -@AllArgsConstructor(staticName = "of") -@Value -public class Price { - - BigDecimal cpm; - - String currency; -} diff --git a/src/main/java/org/prebid/server/deals/proto/RegisterRequest.java b/src/main/java/org/prebid/server/deals/proto/RegisterRequest.java deleted file mode 100644 index 4895468c6b7..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/RegisterRequest.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.math.BigDecimal; - -@AllArgsConstructor(staticName = "of") -@Value -public class RegisterRequest { - - @JsonProperty("healthIndex") - BigDecimal healthIndex; - - Status status; - - @JsonProperty("hostInstanceId") - String hostInstanceId; - - String region; - - String vendor; -} diff --git a/src/main/java/org/prebid/server/deals/proto/Status.java b/src/main/java/org/prebid/server/deals/proto/Status.java deleted file mode 100644 index 974ae7fe0f2..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/Status.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; - -@AllArgsConstructor(staticName = "of") -@Value -public class Status { - - @JsonProperty("currencyRates") - CurrencyServiceState currencyRates; - - @JsonProperty("dealsStatus") - DeliveryProgressReport deliveryProgressReport; - -} diff --git a/src/main/java/org/prebid/server/deals/proto/Token.java b/src/main/java/org/prebid/server/deals/proto/Token.java deleted file mode 100644 index ab004798820..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/Token.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.prebid.server.deals.proto; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Value; - -/** - * Defines the contract for lineItems[].deliverySchedule[].tokens[]. - */ -@Value(staticConstructor = "of") -public class Token { - - @JsonProperty("class") - Integer priorityClass; - - Integer total; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReport.java b/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReport.java deleted file mode 100644 index b1a133b2299..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReport.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -import java.util.Set; - -@Builder(toBuilder = true) -@Value -public class DeliveryProgressReport { - - @JsonProperty("reportId") - String reportId; - - @JsonProperty("reportTimeStamp") - String reportTimeStamp; - - @JsonProperty("dataWindowStartTimeStamp") - String dataWindowStartTimeStamp; - - @JsonProperty("dataWindowEndTimeStamp") - String dataWindowEndTimeStamp; - - @JsonProperty("instanceId") - String instanceId; - - String vendor; - - String region; - - @JsonProperty("clientAuctions") - Long clientAuctions; - - @JsonProperty("lineItemStatus") - Set lineItemStatus; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReportBatch.java b/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReportBatch.java deleted file mode 100644 index 91226ef7d32..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/DeliveryProgressReportBatch.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.Set; - -@Value -@AllArgsConstructor(staticName = "of") -public class DeliveryProgressReportBatch { - - Set reports; - - String reportId; - - String dataWindowEndTimeStamp; - - public void removeReports(Set reports) { - this.reports.removeAll(reports); - } -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/DeliverySchedule.java b/src/main/java/org/prebid/server/deals/proto/report/DeliverySchedule.java deleted file mode 100644 index de1e2df8427..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/DeliverySchedule.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -import java.util.Set; - -@Builder(toBuilder = true) -@Value -public class DeliverySchedule { - - @JsonProperty("planId") - String planId; - - @JsonProperty("planStartTimeStamp") - String planStartTimeStamp; - - @JsonProperty("planExpirationTimeStamp") - String planExpirationTimeStamp; - - @JsonProperty("planUpdatedTimeStamp") - String planUpdatedTimeStamp; - - Set tokens; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/Event.java b/src/main/java/org/prebid/server/deals/proto/report/Event.java deleted file mode 100644 index 686f84b0e96..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/Event.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.util.concurrent.atomic.LongAdder; - -@AllArgsConstructor(staticName = "of") -@Value -public class Event { - - String type; - - LongAdder count; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/LineItemStatus.java b/src/main/java/org/prebid/server/deals/proto/report/LineItemStatus.java deleted file mode 100644 index cb5f1629848..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/LineItemStatus.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Builder; -import lombok.Value; - -import java.util.Set; - -@Builder -@Value -public class LineItemStatus { - - @JsonProperty("lineItemSource") - String lineItemSource; - - @JsonProperty("lineItemId") - String lineItemId; - - @JsonProperty("dealId") - String dealId; - - @JsonProperty("extLineItemId") - String extLineItemId; - - @JsonProperty("accountAuctions") - Long accountAuctions; - - @JsonProperty("domainMatched") - Long domainMatched; - - @JsonProperty("targetMatched") - Long targetMatched; - - @JsonProperty("targetMatchedButFcapped") - Long targetMatchedButFcapped; - - @JsonProperty("targetMatchedButFcapLookupFailed") - Long targetMatchedButFcapLookupFailed; - - @JsonProperty("pacingDeferred") - Long pacingDeferred; - - @JsonProperty("sentToBidder") - Long sentToBidder; - - @JsonProperty("sentToBidderAsTopMatch") - Long sentToBidderAsTopMatch; - - @JsonProperty("receivedFromBidder") - Long receivedFromBidder; - - @JsonProperty("receivedFromBidderInvalidated") - Long receivedFromBidderInvalidated; - - @JsonProperty("sentToClient") - Long sentToClient; - - @JsonProperty("sentToClientAsTopMatch") - Long sentToClientAsTopMatch; - - @JsonProperty("lostToLineItems") - Set lostToLineItems; - - Set events; - - @JsonProperty("deliverySchedule") - Set deliverySchedule; - - @JsonProperty("readyAt") - String readyAt; - - @JsonProperty("spentTokens") - Long spentTokens; - - @JsonProperty("pacingFrequency") - Long pacingFrequency; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/LineItemStatusReport.java b/src/main/java/org/prebid/server/deals/proto/report/LineItemStatusReport.java deleted file mode 100644 index d301993e6d1..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/LineItemStatusReport.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.Builder; -import lombok.Value; - -import java.time.ZonedDateTime; - -@Builder -@Value -public class LineItemStatusReport { - - @JsonProperty("lineItemId") - String lineItemId; - - @JsonProperty("deliverySchedule") - DeliverySchedule deliverySchedule; - - @JsonProperty("spentTokens") - Long spentTokens; - - @JsonProperty("readyToServeTimestamp") - ZonedDateTime readyToServeTimestamp; - - @JsonProperty("pacingFrequency") - Long pacingFrequency; - - @JsonProperty("accountId") - String accountId; - - ObjectNode target; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/LostToLineItem.java b/src/main/java/org/prebid/server/deals/proto/report/LostToLineItem.java deleted file mode 100644 index 137f3cc8f4a..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/LostToLineItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@AllArgsConstructor(staticName = "of") -@Value -public class LostToLineItem { - - @JsonProperty("lineItemSource") - String lineItemSource; - - @JsonProperty("lineItemId") - String lineItemId; - - Long count; -} diff --git a/src/main/java/org/prebid/server/deals/proto/report/Token.java b/src/main/java/org/prebid/server/deals/proto/report/Token.java deleted file mode 100644 index 7e17ece8b8e..00000000000 --- a/src/main/java/org/prebid/server/deals/proto/report/Token.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.prebid.server.deals.proto.report; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Value; - -@Value(staticConstructor = "of") -public class Token { - - @JsonProperty("class") - Integer priorityClass; - - Integer total; - - Long spent; - - @JsonProperty("totalSpent") - Long totalSpent; -} diff --git a/src/main/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandler.java b/src/main/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandler.java deleted file mode 100644 index 18444679938..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandler.java +++ /dev/null @@ -1,165 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.fasterxml.jackson.core.type.TypeReference; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.ext.web.RoutingContext; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.exception.InvalidRequestException; -import org.prebid.server.json.DecodeException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.HttpUtil; - -import java.time.ZonedDateTime; -import java.util.Map; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DealsSimulationAdminHandler implements Handler { - - private static final TypeReference> BID_RATES_TYPE_REFERENCE = - new TypeReference<>() { - }; - - private static final Logger logger = LoggerFactory.getLogger(DealsSimulationAdminHandler.class); - - private static final Pattern URL_SUFFIX_PATTERN = Pattern.compile("/pbs-admin/e2eAdmin(.*)"); - private static final String PLANNER_REGISTER_PATH = "/planner/register"; - private static final String PLANNER_FETCH_PATH = "/planner/fetchLineItems"; - private static final String ADVANCE_PLAN_PATH = "/advancePlans"; - private static final String REPORT_PATH = "/dealstats/report"; - private static final String BID_RATE_PATH = "/bidRate"; - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - - private final SimulationAwareRegisterService registerService; - private final SimulationAwarePlannerService plannerService; - private final SimulationAwareDeliveryProgressService deliveryProgressService; - private final SimulationAwareDeliveryStatsService deliveryStatsService; - private final SimulationAwareHttpBidderRequester httpBidderRequester; - private final JacksonMapper mapper; - private final String endpoint; - - public DealsSimulationAdminHandler( - SimulationAwareRegisterService registerService, - SimulationAwarePlannerService plannerService, - SimulationAwareDeliveryProgressService deliveryProgressService, - SimulationAwareDeliveryStatsService deliveryStatsService, - SimulationAwareHttpBidderRequester httpBidderRequester, - JacksonMapper mapper, - String endpoint) { - - this.registerService = Objects.requireNonNull(registerService); - this.plannerService = Objects.requireNonNull(plannerService); - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.deliveryStatsService = Objects.requireNonNull(deliveryStatsService); - this.httpBidderRequester = httpBidderRequester; - this.mapper = Objects.requireNonNull(mapper); - this.endpoint = Objects.requireNonNull(endpoint); - } - - @Override - public void handle(RoutingContext routingContext) { - final HttpServerRequest request = routingContext.request(); - final Matcher matcher = URL_SUFFIX_PATTERN.matcher(request.uri()); - - if (!matcher.find() || StringUtils.isBlank(matcher.group(1))) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.NOT_FOUND.code()) - .end("Requested url was not found")); - return; - } - - try { - final String endpointPath = matcher.group(1); - final ZonedDateTime now = getPgSimDate(endpointPath, request.headers()); - handleEndpoint(routingContext, endpointPath, now); - - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.OK.code()) - .end()); - } catch (InvalidRequestException e) { - logger.error(e.getMessage(), e); - respondWith(routingContext, HttpResponseStatus.BAD_REQUEST, e.getMessage()); - } catch (NotFoundException e) { - logger.error(e.getMessage(), e); - respondWith(routingContext, HttpResponseStatus.NOT_FOUND, e.getMessage()); - } catch (Exception e) { - logger.error(e.getMessage(), e); - respondWith(routingContext, HttpResponseStatus.INTERNAL_SERVER_ERROR, e.getMessage()); - } - } - - private ZonedDateTime getPgSimDate(String endpointPath, MultiMap headers) { - ZonedDateTime now = null; - if (!endpointPath.equals(BID_RATE_PATH)) { - now = HttpUtil.getDateFromHeader(headers, PG_SIM_TIMESTAMP); - if (now == null) { - throw new InvalidRequestException( - "pg-sim-timestamp with simulated current date is required for endpoints: %s, %s, %s, %s" - .formatted(PLANNER_REGISTER_PATH, PLANNER_FETCH_PATH, ADVANCE_PLAN_PATH, REPORT_PATH)); - } - } - return now; - } - - private void handleEndpoint(RoutingContext routingContext, String endpointPath, ZonedDateTime now) { - if (endpointPath.startsWith(PLANNER_REGISTER_PATH)) { - registerService.performRegistration(now); - - } else if (endpointPath.startsWith(PLANNER_FETCH_PATH)) { - plannerService.initiateLineItemsFetching(now); - - } else if (endpointPath.startsWith(ADVANCE_PLAN_PATH)) { - plannerService.advancePlans(now); - - } else if (endpointPath.startsWith(REPORT_PATH)) { - deliveryProgressService.createDeliveryProgressReport(now); - deliveryStatsService.sendDeliveryProgressReports(now); - - } else if (endpointPath.startsWith(BID_RATE_PATH)) { - if (httpBidderRequester != null) { - handleBidRatesEndpoint(routingContext); - } else { - throw new InvalidRequestException(""" - Calling %s is not make sense since Prebid Server configured \ - to use real bidder exchanges in simulation mode""".formatted(BID_RATE_PATH)); - } - } else { - throw new NotFoundException("Requested url %s was not found".formatted(endpointPath)); - } - } - - private void handleBidRatesEndpoint(RoutingContext routingContext) { - final Buffer body = routingContext.getBody(); - if (body == null) { - throw new InvalidRequestException("Body is required for %s endpoint".formatted(BID_RATE_PATH)); - } - - try { - httpBidderRequester.setBidRates(mapper.decodeValue(body, BID_RATES_TYPE_REFERENCE)); - } catch (DecodeException e) { - throw new InvalidRequestException("Failed to parse bid rates body: " + e.getMessage()); - } - } - - private void respondWith(RoutingContext routingContext, HttpResponseStatus status, String body) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(status.code()) - .end(body)); - } - - private static class NotFoundException extends RuntimeException { - NotFoundException(String message) { - super(message); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryProgressService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryProgressService.java deleted file mode 100644 index 511c37207fb..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryProgressService.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.prebid.server.deals.simulation; - -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.DeliveryProgressReportFactory; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.DeliveryProgressProperties; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.util.HttpUtil; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.Map; - -public class SimulationAwareDeliveryProgressService extends DeliveryProgressService { - - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - - private final long readyAtAdjustment; - private volatile boolean firstReportUpdate; - - public SimulationAwareDeliveryProgressService(DeliveryProgressProperties deliveryProgressProperties, - LineItemService lineItemService, - DeliveryStatsService deliveryStatsService, - DeliveryProgressReportFactory deliveryProgressReportFactory, - long readyAtAdjustment, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - super( - deliveryProgressProperties, - lineItemService, - deliveryStatsService, - deliveryProgressReportFactory, - clock, - criteriaLogManager); - this.readyAtAdjustment = readyAtAdjustment; - this.firstReportUpdate = true; - } - - @Override - public void shutdown() { - // disable sending report during bean destroying process - } - - @Override - public void processAuctionEvent(AuctionContext auctionContext) { - final ZonedDateTime now = HttpUtil.getDateFromHeader(auctionContext.getHttpRequest().getHeaders(), - PG_SIM_TIMESTAMP); - if (firstReportUpdate) { - firstReportUpdate = false; - updateDeliveryProgressesStartTime(now); - } - super.processAuctionEvent(auctionContext.getTxnLog(), auctionContext.getAccount().getId(), now); - } - - protected void incrementTokens(LineItem lineItem, ZonedDateTime now, Map planIdToTokenPriority) { - final Integer classPriority = lineItem.incSpentToken(now, readyAtAdjustment); - if (classPriority != null) { - planIdToTokenPriority.put(lineItem.getActiveDeliveryPlan().getPlanId(), classPriority); - } - } - - private void updateDeliveryProgressesStartTime(ZonedDateTime now) { - overallDeliveryProgress.setStartTimeStamp(now); - currentDeliveryProgress.setStartTimeStamp(now); - } - - void createDeliveryProgressReport(ZonedDateTime now) { - createDeliveryProgressReports(now); - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java deleted file mode 100644 index 7debdb649ed..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareDeliveryStatsService.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.prebid.server.deals.simulation; - -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.Vertx; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressReportFactory; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.model.DeliveryStatsProperties; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; - -public class SimulationAwareDeliveryStatsService extends DeliveryStatsService { - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - - public SimulationAwareDeliveryStatsService(DeliveryStatsProperties deliveryStatsProperties, - DeliveryProgressReportFactory deliveryProgressReportFactory, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - Vertx vertx, - JacksonMapper mapper) { - super(deliveryStatsProperties, - deliveryProgressReportFactory, - alertHttpService, - httpClient, - metrics, - clock, - vertx, - mapper); - } - - @Override - protected Future sendReport(DeliveryProgressReport deliveryProgressReport, MultiMap headers, - ZonedDateTime now) { - return super.sendReport(deliveryProgressReport, - headers().add(PG_SIM_TIMESTAMP, UTC_MILLIS_FORMATTER.format(now)), now); - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java deleted file mode 100644 index 8c201ac081f..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequester.java +++ /dev/null @@ -1,177 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.response.Bid; -import io.vertx.core.Future; -import lombok.AllArgsConstructor; -import lombok.Value; -import org.apache.commons.collections4.CollectionUtils; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.BidRejectionReason; -import org.prebid.server.auction.model.BidRejectionTracker; -import org.prebid.server.auction.model.BidderRequest; -import org.prebid.server.bidder.Bidder; -import org.prebid.server.bidder.BidderErrorNotifier; -import org.prebid.server.bidder.BidderRequestCompletionTrackerFactory; -import org.prebid.server.bidder.HttpBidderRequestEnricher; -import org.prebid.server.bidder.HttpBidderRequester; -import org.prebid.server.bidder.model.BidderBid; -import org.prebid.server.bidder.model.BidderError; -import org.prebid.server.bidder.model.BidderSeatBid; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.execution.Timeout; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.model.CaseInsensitiveMultiMap; -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.response.BidType; -import org.prebid.server.vertx.http.HttpClient; - -import java.math.BigDecimal; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class SimulationAwareHttpBidderRequester extends HttpBidderRequester { - - private static final BigDecimal DEFAULT_CPM = BigDecimal.ONE; - private static final String DEFAULT_ADM = ""; - private static final String DEFAULT_CRID = "crid"; - private static final String DEFAULT_CURRENCY = "USD"; - private static final String BID_ID_FORMAT = "%s-%s"; - - private final Map bidRates; - private final LineItemService lineItemService; - private final JacksonMapper mapper; - - public SimulationAwareHttpBidderRequester( - HttpClient httpClient, - BidderRequestCompletionTrackerFactory bidderRequestCompletionTrackerFactory, - BidderErrorNotifier bidderErrorNotifier, - HttpBidderRequestEnricher requestEnricher, - LineItemService lineItemService, - JacksonMapper mapper) { - - super(httpClient, bidderRequestCompletionTrackerFactory, bidderErrorNotifier, requestEnricher, mapper); - - this.lineItemService = Objects.requireNonNull(lineItemService); - this.mapper = Objects.requireNonNull(mapper); - this.bidRates = new HashMap<>(); - } - - void setBidRates(Map bidRates) { - this.bidRates.putAll(bidRates); - } - - @Override - public Future requestBids(Bidder bidder, - BidderRequest bidderRequest, - BidRejectionTracker bidRejectionTracker, - Timeout timeout, - CaseInsensitiveMultiMap requestHeaders, - BidderAliases aliases, - boolean debugEnabled) { - - final List imps = bidderRequest.getBidRequest().getImp(); - final Map idToImps = imps.stream().collect(Collectors.toMap(Imp::getId, Function.identity())); - final Map> impsToDealInfo = imps.stream() - .filter(imp -> imp.getPmp() != null) - .collect(Collectors.toMap(Imp::getId, imp -> imp.getPmp().getDeals().stream() - .map(deal -> DealInfo.of(deal.getId(), getLineItemId(deal))) - .filter(dealInfo -> dealInfo.getLineItemId() != null) - .collect(Collectors.toSet()))); - - if (impsToDealInfo.values().stream().noneMatch(CollectionUtils::isNotEmpty)) { - bidRejectionTracker.rejectAll(BidRejectionReason.FAILED_TO_REQUEST_BIDS); - - return Future.succeededFuture(BidderSeatBid.builder() - .errors(Collections.singletonList(BidderError.failedToRequestBids( - "Matched or ready to serve line items were not found, but required in simulation mode"))) - .build()); - } - - final List bidderBids = impsToDealInfo.entrySet().stream() - .flatMap(impToDealInfo -> impToDealInfo.getValue() - .stream() - .map(dealInfo -> createBid(idToImps.get(impToDealInfo.getKey()), dealInfo.getDealId(), - dealInfo.getLineItemId())) - .filter(Objects::nonNull)) - .map(bid -> BidderBid.of(bid, BidType.banner, DEFAULT_CURRENCY)) - .toList(); - - return Future.succeededFuture(BidderSeatBid.of(bidderBids)); - } - - private String getLineItemId(Deal deal) { - final JsonNode extDealNode = deal.getExt(); - final ExtDeal extDeal = extDealNode != null ? getExtDeal(extDealNode) : null; - final ExtDealLine extDealLine = extDeal != null ? extDeal.getLine() : null; - return extDealLine != null ? extDealLine.getLineItemId() : null; - } - - private Bid createBid(Imp imp, String dealId, String lineItemId) { - final Double rate = bidRates.get(lineItemId); - if (rate == null) { - throw new PreBidException("Bid rate for line item with id %s was not found".formatted(lineItemId)); - } - final String impId = imp.getId(); - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - final List sizes = getLineItemSizes(imp); - return Math.random() < rate - ? Bid.builder() - .id(BID_ID_FORMAT.formatted(impId, lineItemId)) - .impid(impId) - .dealid(dealId) - .price(lineItem != null ? lineItem.getCpm() : DEFAULT_CPM) - .adm(DEFAULT_ADM) - .crid(DEFAULT_CRID) - .w(sizes.isEmpty() ? 0 : sizes.get(0).getW()) - .h(sizes.isEmpty() ? 0 : sizes.get(0).getH()) - .build() - : null; - } - - private List getLineItemSizes(Imp imp) { - return imp.getPmp().getDeals().stream() - .map(Deal::getExt) - .filter(Objects::nonNull) - .map(this::getExtDeal) - .filter(Objects::nonNull) - .map(ExtDeal::getLine) - .filter(Objects::nonNull) - .map(ExtDealLine::getSizes) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(Objects::nonNull) - .toList(); - } - - private ExtDeal getExtDeal(JsonNode extDeal) { - try { - return mapper.mapper().treeToValue(extDeal, ExtDeal.class); - } catch (JsonProcessingException e) { - throw new PreBidException("Error decoding bidRequest.imp.pmp.deal.ext: " + e.getMessage(), e); - } - } - - @Value - @AllArgsConstructor(staticName = "of") - private static class DealInfo { - - String dealId; - - String lineItemId; - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareLineItemService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareLineItemService.java deleted file mode 100644 index 1751ef8abd5..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareLineItemService.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Imp; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.TargetingService; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.model.MatchLineItemsResult; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.util.HttpUtil; -import org.springframework.beans.factory.annotation.Value; - -import java.time.Clock; - -public class SimulationAwareLineItemService extends LineItemService { - - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - - public SimulationAwareLineItemService(int maxDealsPerBidder, - TargetingService targetingService, - CurrencyConversionService conversionService, - ApplicationEventService applicationEventService, - @Value("${auction.ad-server-currency}}") String adServerCurrency, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - super( - maxDealsPerBidder, - targetingService, - conversionService, - applicationEventService, - adServerCurrency, - clock, - criteriaLogManager); - } - - @Override - public boolean accountHasDeals(AuctionContext auctionContext) { - return accountHasDeals( - auctionContext.getAccount().getId(), - HttpUtil.getDateFromHeader(auctionContext.getHttpRequest().getHeaders(), PG_SIM_TIMESTAMP)); - } - - @Override - public MatchLineItemsResult findMatchingLineItems(BidRequest bidRequest, - Imp imp, - String bidder, - BidderAliases aliases, - AuctionContext auctionContext) { - - return findMatchingLineItems( - bidRequest, - imp, - bidder, - aliases, - auctionContext, - HttpUtil.getDateFromHeader(auctionContext.getHttpRequest().getHeaders(), PG_SIM_TIMESTAMP)); - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java deleted file mode 100644 index 2009f94e63f..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwarePlannerService.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.prebid.server.deals.simulation; - -import io.vertx.core.AsyncResult; -import io.vertx.core.MultiMap; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.PlannerService; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; - -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - -public class SimulationAwarePlannerService extends PlannerService { - - private static final Logger logger = LoggerFactory.getLogger(SimulationAwarePlannerService.class); - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - private static final String PBS_PLANNER_CLIENT_ERROR = "pbs-planner-client-error"; - - private final SimulationAwareLineItemService lineItemService; - private final Metrics metrics; - private final AlertHttpService alertHttpService; - - private List lineItemMetaData; - - public SimulationAwarePlannerService(PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - SimulationAwareLineItemService lineItemService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - JacksonMapper mapper) { - super( - plannerProperties, - deploymentProperties, - lineItemService, - deliveryProgressService, - alertHttpService, - httpClient, - metrics, - clock, - mapper); - - this.lineItemService = Objects.requireNonNull(lineItemService); - this.alertHttpService = Objects.requireNonNull(alertHttpService); - this.metrics = Objects.requireNonNull(metrics); - this.lineItemMetaData = new ArrayList<>(); - } - - public void advancePlans(ZonedDateTime now) { - lineItemService.updateLineItems(lineItemMetaData, isPlannerResponsive.get(), now); - lineItemService.advanceToNextPlan(now); - } - - public void initiateLineItemsFetching(ZonedDateTime now) { - fetchLineItemMetaData(planEndpoint, headers(now)) - .onComplete(this::handleInitializationResult); - } - - /** - * Handles result of initialization process. Sets metadata if request was successful. - */ - @Override - protected void handleInitializationResult(AsyncResult> plannerResponse) { - if (plannerResponse.succeeded()) { - metrics.updatePlannerRequestMetric(true); - isPlannerResponsive.set(true); - lineItemService.updateIsPlannerResponsive(true); - lineItemMetaData = plannerResponse.result(); - } else { - alert(plannerResponse.cause().getMessage(), AlertPriority.HIGH, logger::warn); - logger.warn("Failed to retrieve line items from Planner after retry. Reason: {0}", - plannerResponse.cause().getMessage()); - isPlannerResponsive.set(false); - lineItemService.updateIsPlannerResponsive(false); - metrics.updatePlannerRequestMetric(false); - } - } - - private MultiMap headers(ZonedDateTime now) { - return headers().add(PG_SIM_TIMESTAMP, UTC_MILLIS_FORMATTER.format(now)); - } - - private void alert(String message, AlertPriority alertPriority, Consumer logger) { - alertHttpService.alert(PBS_PLANNER_CLIENT_ERROR, alertPriority, message); - logger.accept(message); - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java deleted file mode 100644 index d185285937e..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareRegisterService.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.prebid.server.deals.simulation; - -import io.vertx.core.MultiMap; -import io.vertx.core.Vertx; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.RegisterService; -import org.prebid.server.deals.events.AdminEventService; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.health.HealthMonitor; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.vertx.http.HttpClient; - -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; - -public class SimulationAwareRegisterService extends RegisterService { - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - private static final String PG_SIM_TIMESTAMP = "pg-sim-timestamp"; - - public SimulationAwareRegisterService(PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - AdminEventService adminEventService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HealthMonitor healthMonitor, - CurrencyConversionService currencyConversionService, - HttpClient httpClient, - Vertx vertx, - JacksonMapper mapper) { - super(plannerProperties, - deploymentProperties, - adminEventService, - deliveryProgressService, - alertHttpService, - healthMonitor, - currencyConversionService, - httpClient, - vertx, - mapper); - } - - @Override - public void initialize() { - // disable timer initialization for simulation mode - } - - public void performRegistration(ZonedDateTime now) { - register(headers(now)); - } - - private MultiMap headers(ZonedDateTime now) { - return headers().add(PG_SIM_TIMESTAMP, UTC_MILLIS_FORMATTER.format(now)); - } -} diff --git a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java b/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java deleted file mode 100644 index 78d9f8ae409..00000000000 --- a/src/main/java/org/prebid/server/deals/simulation/SimulationAwareUserService.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.prebid.server.deals.simulation; - -import io.vertx.core.Future; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.UserService; -import org.prebid.server.deals.model.SimulationProperties; -import org.prebid.server.deals.model.UserDetails; -import org.prebid.server.deals.model.UserDetailsProperties; -import org.prebid.server.execution.Timeout; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; - -import java.time.Clock; - -public class SimulationAwareUserService extends UserService { - - private final boolean winEventsEnabled; - private final boolean userDetailsEnabled; - - public SimulationAwareUserService(UserDetailsProperties userDetailsProperties, - SimulationProperties simulationProperties, - String dataCenterRegion, - LineItemService lineItemService, - HttpClient httpClient, - Clock clock, - Metrics metrics, - JacksonMapper mapper) { - super( - userDetailsProperties, - dataCenterRegion, - lineItemService, - httpClient, - clock, - metrics, - mapper); - - this.winEventsEnabled = simulationProperties.isWinEventsEnabled(); - this.userDetailsEnabled = simulationProperties.isUserDetailsEnabled(); - } - - @Override - public Future getUserDetails(AuctionContext context, Timeout timeout) { - return userDetailsEnabled - ? super.getUserDetails(context, timeout) - : Future.succeededFuture(UserDetails.empty()); - } - - @Override - public void processWinEvent(String lineItemId, String bidId, UidsCookie uids) { - if (winEventsEnabled) { - super.processWinEvent(lineItemId, bidId, uids); - } - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/RequestContext.java b/src/main/java/org/prebid/server/deals/targeting/RequestContext.java deleted file mode 100644 index 8aef7c152c0..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/RequestContext.java +++ /dev/null @@ -1,422 +0,0 @@ -package org.prebid.server.deals.targeting; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.iab.openrtb.request.App; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Data; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Publisher; -import com.iab.openrtb.request.Segment; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.User; -import com.iab.openrtb.request.Video; -import org.apache.commons.collections4.ListUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.targeting.model.GeoLocation; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; -import org.prebid.server.exception.TargetingSyntaxException; -import org.prebid.server.json.JacksonMapper; -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.ExtSite; -import org.prebid.server.proto.openrtb.ext.request.ExtUser; -import org.prebid.server.proto.openrtb.ext.request.ExtUserTime; -import org.prebid.server.util.StreamUtil; - -import java.beans.BeanInfo; -import java.beans.FeatureDescriptor; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class RequestContext { - - private static final String EXT_BIDDER = "bidder."; - private static final String EXT_CONTEXT_DATA = "context.data."; - private static final String EXT_DATA = "data."; - - private final BidRequest bidRequest; - private final Imp imp; - private final TxnLog txnLog; - - private final AttributeReader impReader; - private final AttributeReader geoReader; - private final AttributeReader deviceReader; - private final AttributeReader userReader; - private final AttributeReader siteReader; - private final AttributeReader appReader; - - public RequestContext(BidRequest bidRequest, - Imp imp, - TxnLog txnLog, - JacksonMapper mapper) { - - this.bidRequest = Objects.requireNonNull(bidRequest); - this.imp = Objects.requireNonNull(imp); - this.txnLog = Objects.requireNonNull(txnLog); - - impReader = AttributeReader.forImp(); - geoReader = AttributeReader.forGeo(getExtNode( - bidRequest.getDevice(), - device -> getIfNotNull(getIfNotNull(device, Device::getGeo), Geo::getExt), - mapper)); - deviceReader = AttributeReader.forDevice(getExtNode(bidRequest.getDevice(), Device::getExt, mapper)); - userReader = AttributeReader.forUser(); - siteReader = AttributeReader.forSite(); - appReader = AttributeReader.forApp(); - } - - private static ObjectNode getExtNode(T target, - Function extExtractor, - JacksonMapper mapper) { - - final FlexibleExtension ext = target != null ? extExtractor.apply(target) : null; - return ext != null ? (ObjectNode) mapper.mapper().valueToTree(ext) : null; - } - - public LookupResult lookupString(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - final String path = category.path(); - - return switch (type) { - case domain -> lookupResult( - getIfNotNull(bidRequest.getSite(), Site::getDomain), - getIfNotNull(getIfNotNull(bidRequest.getSite(), Site::getPublisher), Publisher::getDomain)); - case publisherDomain -> lookupResult(getIfNotNull( - getIfNotNull(bidRequest.getSite(), Site::getPublisher), Publisher::getDomain)); - case referrer -> lookupResult(getIfNotNull(bidRequest.getSite(), Site::getPage)); - case appBundle -> lookupResult(getIfNotNull(bidRequest.getApp(), App::getBundle)); - case adslot -> lookupResult( - imp.getTagid(), - impReader.readFromExt(imp, "gpid", RequestContext::nodeToString), - impReader.readFromExt(imp, "data.pbadslot", RequestContext::nodeToString), - impReader.readFromExt(imp, "data.adserver.adslot", RequestContext::nodeToString)); - case deviceGeoExt -> lookupResult(geoReader.readFromExt( - getIfNotNull(bidRequest.getDevice(), Device::getGeo), path, RequestContext::nodeToString)); - case deviceExt -> lookupResult( - deviceReader.readFromExt(bidRequest.getDevice(), path, RequestContext::nodeToString)); - case bidderParam -> lookupResult( - impReader.readFromExt(imp, EXT_BIDDER + path, RequestContext::nodeToString)); - case userFirstPartyData -> - userReader.read(bidRequest.getUser(), path, RequestContext::nodeToString, String.class); - case siteFirstPartyData -> getSiteFirstPartyData(path, RequestContext::nodeToString); - default -> LookupResult.empty(); - }; - } - - public LookupResult lookupInteger(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - final String path = category.path(); - - return switch (type) { - case pagePosition -> lookupResult(getIfNotNull(getIfNotNull(imp, Imp::getBanner), Banner::getPos)); - case dow -> lookupResult(getIfNotNull( - getIfNotNull(getIfNotNull(bidRequest.getUser(), User::getExt), ExtUser::getTime), - ExtUserTime::getUserdow)); - case hour -> lookupResult(getIfNotNull( - getIfNotNull(getIfNotNull(bidRequest.getUser(), User::getExt), ExtUser::getTime), - ExtUserTime::getUserhour)); - case deviceGeoExt -> lookupResult(geoReader.readFromExt( - getIfNotNull(bidRequest.getDevice(), Device::getGeo), path, RequestContext::nodeToInteger)); - case bidderParam -> lookupResult( - impReader.readFromExt(imp, EXT_BIDDER + path, RequestContext::nodeToInteger)); - case userFirstPartyData -> - userReader.read(bidRequest.getUser(), path, RequestContext::nodeToInteger, Integer.class); - case siteFirstPartyData -> getSiteFirstPartyData(path, RequestContext::nodeToInteger); - default -> LookupResult.empty(); - }; - } - - public LookupResult> lookupStrings(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - final String path = category.path(); - final User user = bidRequest.getUser(); - - return switch (type) { - case mediaType -> lookupResult(getMediaTypes()); - case bidderParam -> lookupResult( - impReader.readFromExt(imp, EXT_BIDDER + path, RequestContext::nodeToListOfStrings)); - case userSegment -> lookupResult(getSegments(category)); - case userFirstPartyData -> lookupResult( - listOfNonNulls(userReader.readFromObject(user, path, String.class)), - userReader.readFromExt(user, path, RequestContext::nodeToListOfStrings)); - case siteFirstPartyData -> getSiteFirstPartyData(path, RequestContext::nodeToListOfStrings); - default -> LookupResult.empty(); - }; - } - - public LookupResult> lookupIntegers(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - final String path = category.path(); - final User user = bidRequest.getUser(); - - return switch (type) { - case bidderParam -> lookupResult( - impReader.readFromExt(imp, EXT_BIDDER + path, RequestContext::nodeToListOfIntegers)); - case userFirstPartyData -> lookupResult( - listOfNonNulls(userReader.readFromObject(user, path, Integer.class)), - userReader.readFromExt(user, path, RequestContext::nodeToListOfIntegers)); - case siteFirstPartyData -> getSiteFirstPartyData(path, RequestContext::nodeToListOfIntegers); - default -> LookupResult.empty(); - }; - } - - public LookupResult> lookupSizes(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - if (type != TargetingCategory.Type.size) { - throw new TargetingSyntaxException("Unexpected category for fetching sizes for: " + type); - } - - final List sizes = ListUtils.union(sizesFromBanner(imp), sizesFromVideo(imp)); - - return !sizes.isEmpty() ? LookupResult.ofValue(sizes) : LookupResult.empty(); - } - - private static List sizesFromBanner(Imp imp) { - final List formats = getIfNotNull(imp.getBanner(), Banner::getFormat); - return ListUtils.emptyIfNull(formats).stream() - .map(format -> Size.of(format.getW(), format.getH())) - .toList(); - } - - private static List sizesFromVideo(Imp imp) { - final Video video = imp.getVideo(); - final Integer width = video != null ? video.getW() : null; - final Integer height = video != null ? video.getH() : null; - - return width != null && height != null - ? Collections.singletonList(Size.of(width, height)) - : Collections.emptyList(); - } - - public GeoLocation lookupGeoLocation(TargetingCategory category) { - final TargetingCategory.Type type = category.type(); - if (type != TargetingCategory.Type.location) { - throw new TargetingSyntaxException("Unexpected category for fetching geo location for: " + type); - } - - final Geo geo = getIfNotNull(getIfNotNull(bidRequest, BidRequest::getDevice), Device::getGeo); - final Float lat = getIfNotNull(geo, Geo::getLat); - final Float lon = getIfNotNull(geo, Geo::getLon); - - return lat != null && lon != null ? GeoLocation.of(lat, lon) : null; - } - - public TxnLog txnLog() { - return txnLog; - } - - @SafeVarargs - private static LookupResult lookupResult(T... candidates) { - return LookupResult.of(listOfNonNulls(candidates)); - } - - @SafeVarargs - private static List listOfNonNulls(T... candidates) { - return Stream.of(candidates) - .filter(Objects::nonNull) - .toList(); - } - - private static T getIfNotNull(S source, Function getter) { - return source != null ? getter.apply(source) : null; - } - - private List getMediaTypes() { - final List mediaTypes = new ArrayList<>(); - if (imp.getBanner() != null) { - mediaTypes.add("banner"); - } - if (imp.getVideo() != null) { - mediaTypes.add("video"); - } - if (imp.getXNative() != null) { - mediaTypes.add("native"); - } - return mediaTypes; - } - - private LookupResult getSiteFirstPartyData(String path, Function valueExtractor) { - return lookupResult( - impReader.readFromExt(imp, EXT_CONTEXT_DATA + path, valueExtractor), - impReader.readFromExt(imp, EXT_DATA + path, valueExtractor), - siteReader.readFromExt(bidRequest.getSite(), path, valueExtractor), - appReader.readFromExt(bidRequest.getApp(), path, valueExtractor)); - } - - private List getSegments(TargetingCategory category) { - final List userData = getIfNotNull(bidRequest.getUser(), User::getData); - - final List segments = ListUtils.emptyIfNull(userData) - .stream() - .filter(Objects::nonNull) - .filter(data -> Objects.equals(data.getId(), category.path())) - .flatMap(data -> ListUtils.emptyIfNull(data.getSegment()).stream()) - .map(Segment::getId) - .filter(Objects::nonNull) - .toList(); - - return !segments.isEmpty() ? segments : null; - } - - private static String toJsonPointer(String path) { - return Arrays.stream(path.split("\\.")) - .collect(Collectors.joining("/", "/", StringUtils.EMPTY)); - } - - private static String nodeToString(JsonNode node) { - return node.isTextual() ? node.asText() : null; - } - - private static Integer nodeToInteger(JsonNode node) { - return node.isInt() ? node.asInt() : null; - } - - private static List nodeToListOfStrings(JsonNode node) { - final Function valueExtractor = RequestContext::nodeToString; - return node.isTextual() - ? Collections.singletonList(valueExtractor.apply(node)) - : nodeToList(node, valueExtractor); - } - - private static List nodeToListOfIntegers(JsonNode node) { - final Function valueExtractor = RequestContext::nodeToInteger; - return node.isInt() - ? Collections.singletonList(valueExtractor.apply(node)) - : nodeToList(node, valueExtractor); - } - - private static List nodeToList(JsonNode node, Function valueExtractor) { - if (!node.isArray()) { - return null; - } - - return StreamUtil.asStream(node.spliterator()) - .map(valueExtractor) - .filter(Objects::nonNull) - .toList(); - } - - private static class AttributeReader { - - private static final Set> SUPPORTED_PROPERTY_TYPES = Set.of(String.class, Integer.class, int.class); - - private final Map properties; - private final Function extPathExtractor; - - private AttributeReader(Class type, Function extPathExtractor) { - this.properties = supportedBeanProperties(type); - this.extPathExtractor = extPathExtractor; - } - - public static AttributeReader forImp() { - return new AttributeReader<>( - Imp.class, - imp -> getIfNotNull(imp, Imp::getExt)); - } - - public static AttributeReader forGeo(ObjectNode geoExt) { - return new AttributeReader<>( - Geo.class, - ignored -> geoExt); - } - - public static AttributeReader forDevice(ObjectNode deviceExt) { - return new AttributeReader<>( - Device.class, - ignored -> deviceExt); - } - - public static AttributeReader forUser() { - return new AttributeReader<>( - User.class, - user -> getIfNotNull(getIfNotNull(user, User::getExt), ExtUser::getData)); - } - - public static AttributeReader forSite() { - return new AttributeReader<>( - Site.class, - site -> getIfNotNull(getIfNotNull(site, Site::getExt), ExtSite::getData)); - } - - public static AttributeReader forApp() { - return new AttributeReader<>( - App.class, - app -> getIfNotNull(getIfNotNull(app, App::getExt), ExtApp::getData)); - } - - public LookupResult read(T target, - String path, - Function valueExtractor, - Class attributeType) { - - return lookupResult( - // look in the object itself - readFromObject(target, path, attributeType), - // then examine ext if value not found on top level or if it is nested attribute - readFromExt(target, path, valueExtractor)); - } - - public A readFromObject(T target, String path, Class attributeType) { - return isTopLevelAttribute(path) - ? getIfNotNull(target, user -> readProperty(user, path, attributeType)) - : null; - } - - public A readFromExt(T target, String path, Function valueExtractor) { - final JsonNode extPath = getIfNotNull(target, extPathExtractor); - final JsonNode value = getIfNotNull(extPath, node -> node.at(toJsonPointer(path))); - return getIfNotNull(value, valueExtractor); - } - - private boolean isTopLevelAttribute(String path) { - return !path.contains("."); - } - - private static Map supportedBeanProperties(Class beanClass) { - try { - final BeanInfo beanInfo = Introspector.getBeanInfo(beanClass, Object.class); - return Arrays.stream(beanInfo.getPropertyDescriptors()) - .filter(descriptor -> SUPPORTED_PROPERTY_TYPES.contains(descriptor.getPropertyType())) - .collect(Collectors.toMap(FeatureDescriptor::getName, Function.identity())); - } catch (IntrospectionException e) { - return ExceptionUtils.rethrow(e); - } - } - - @SuppressWarnings("unchecked") - private A readProperty(T target, String path, Class attributeType) { - final PropertyDescriptor descriptor = properties.get(path); - - if (descriptor != null && descriptor.getPropertyType().equals(attributeType)) { - try { - return (A) descriptor.getReadMethod().invoke(target); - } catch (IllegalAccessException | InvocationTargetException e) { - // just ignore - } - } - - return null; - } - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/TargetingDefinition.java b/src/main/java/org/prebid/server/deals/targeting/TargetingDefinition.java deleted file mode 100644 index ec1cb8683af..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/TargetingDefinition.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.deals.targeting; - -import lombok.Value; -import org.prebid.server.deals.targeting.interpret.Expression; - -@Value(staticConstructor = "of") -public class TargetingDefinition { - - Expression rootExpression; -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/And.java b/src/main/java/org/prebid/server/deals/targeting/interpret/And.java deleted file mode 100644 index bfe69b2882a..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/And.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; - -import java.util.Collections; -import java.util.List; - -@EqualsAndHashCode -public class And implements NonTerminalExpression { - - private final List expressions; - - public And(List expressions) { - this.expressions = Collections.unmodifiableList(expressions); - } - - @Override - public boolean matches(RequestContext context) { - for (final Expression expression : expressions) { - if (!expression.matches(context)) { - return false; - } - } - return true; - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/DomainMetricAwareExpression.java b/src/main/java/org/prebid/server/deals/targeting/interpret/DomainMetricAwareExpression.java deleted file mode 100644 index 9d682256384..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/DomainMetricAwareExpression.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; - -@EqualsAndHashCode -public class DomainMetricAwareExpression implements Expression { - - private final Expression domainFunction; - private final String lineItemId; - - public DomainMetricAwareExpression(Expression domainFunction, String lineItemId) { - this.domainFunction = domainFunction; - this.lineItemId = lineItemId; - } - - @Override - public boolean matches(RequestContext requestContext) { - final boolean matches = domainFunction.matches(requestContext); - if (matches) { - requestContext.txnLog().lineItemsMatchedDomainTargeting().add(lineItemId); - } - return matches; - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Expression.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Expression.java deleted file mode 100644 index 332e6a2a2eb..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Expression.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.prebid.server.deals.targeting.RequestContext; - -public interface Expression { - - boolean matches(RequestContext context); -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/In.java b/src/main/java/org/prebid/server/deals/targeting/interpret/In.java deleted file mode 100644 index 299a74e254f..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/In.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -@EqualsAndHashCode -public abstract class In implements TerminalExpression { - - protected final TargetingCategory category; - - protected List values; - - public In(TargetingCategory category, List values) { - this.category = Objects.requireNonNull(category); - this.values = Collections.unmodifiableList(values); - } - - @Override - public boolean matches(RequestContext context) { - return lookupActualValue(context).anyMatch(values::contains); - } - - protected abstract LookupResult lookupActualValue(RequestContext context); -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/InIntegers.java b/src/main/java/org/prebid/server/deals/targeting/interpret/InIntegers.java deleted file mode 100644 index 99511bf484b..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/InIntegers.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.List; - -@EqualsAndHashCode(callSuper = true) -public class InIntegers extends In { - - public InIntegers(TargetingCategory category, List values) { - super(category, values); - } - - @Override - public LookupResult lookupActualValue(RequestContext context) { - return context.lookupInteger(category); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/InStrings.java b/src/main/java/org/prebid/server/deals/targeting/interpret/InStrings.java deleted file mode 100644 index 185d2069074..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/InStrings.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.apache.commons.collections4.CollectionUtils; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.List; -import java.util.function.Supplier; -import java.util.stream.Stream; - -@EqualsAndHashCode(callSuper = true) -public class InStrings extends In { - - public InStrings(TargetingCategory category, List values) { - super(category, toLowerCase(values)); - } - - @Override - public LookupResult lookupActualValue(RequestContext context) { - final List actualValue = firstNonEmpty( - () -> context.lookupString(category).getValues(), - () -> lookupIntegerAsString(context)); - - return actualValue != null - ? LookupResult.of(actualValue.stream().map(String::toLowerCase).toList()) - : LookupResult.empty(); - } - - private List lookupIntegerAsString(RequestContext context) { - final List actualValue = context.lookupInteger(category).getValues(); - return actualValue.stream().map(Object::toString).toList(); - } - - private static List toLowerCase(List values) { - return values.stream().map(String::toLowerCase).toList(); - } - - @SafeVarargs - private static List firstNonEmpty(Supplier>... suppliers) { - return Stream.of(suppliers) - .map(Supplier::get) - .filter(CollectionUtils::isNotEmpty) - .findFirst() - .orElse(null); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Intersects.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Intersects.java deleted file mode 100644 index e1113947683..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Intersects.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -@EqualsAndHashCode -public abstract class Intersects implements TerminalExpression { - - protected final TargetingCategory category; - - protected List values; - - public Intersects(TargetingCategory category, List values) { - this.category = Objects.requireNonNull(category); - this.values = Collections.unmodifiableList(values); - } - - @Override - public boolean matches(RequestContext context) { - return lookupActualValues(context) - .anyMatch(actualValues -> !Collections.disjoint(values, actualValues)); - } - - protected abstract LookupResult> lookupActualValues(RequestContext context); -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegers.java b/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegers.java deleted file mode 100644 index fd3b0f618cf..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegers.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.List; - -@EqualsAndHashCode(callSuper = true) -public class IntersectsIntegers extends Intersects { - - public IntersectsIntegers(TargetingCategory category, List values) { - super(category, values); - } - - @Override - public LookupResult> lookupActualValues(RequestContext context) { - return context.lookupIntegers(category); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsSizes.java b/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsSizes.java deleted file mode 100644 index 444bfdcc356..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsSizes.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.List; - -@EqualsAndHashCode(callSuper = true) -public class IntersectsSizes extends Intersects { - - public IntersectsSizes(TargetingCategory category, List values) { - super(category, values); - } - - @Override - public LookupResult> lookupActualValues(RequestContext context) { - return context.lookupSizes(category); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsStrings.java b/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsStrings.java deleted file mode 100644 index dd6d9dff2d8..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/IntersectsStrings.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.List; - -@EqualsAndHashCode(callSuper = true) -public class IntersectsStrings extends Intersects { - - public IntersectsStrings(TargetingCategory category, List values) { - super(category, toLowerCase(values)); - } - - @Override - public LookupResult> lookupActualValues(RequestContext context) { - return LookupResult.of( - context.lookupStrings(category).getValues().stream() - .map(IntersectsStrings::toLowerCase) - .toList()); - } - - private static List toLowerCase(List values) { - return values.stream().map(String::toLowerCase).toList(); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Matches.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Matches.java deleted file mode 100644 index 4d5394eeedf..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Matches.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.Objects; -import java.util.function.BiFunction; - -@EqualsAndHashCode -public class Matches implements TerminalExpression { - - private static final String WILDCARD = "*"; - - private final TargetingCategory category; - - private final BiFunction method; - - private final String value; - - public Matches(TargetingCategory category, String value) { - this.category = Objects.requireNonNull(category); - this.method = resolveMethod(Objects.requireNonNull(value)); - this.value = value.replaceAll("\\*", "").toLowerCase(); - } - - @Override - public boolean matches(RequestContext context) { - return context.lookupString(category) - .anyMatch(valueToMatch -> method.apply(valueToMatch.toLowerCase(), value)); - } - - private static BiFunction resolveMethod(String value) { - if (value.startsWith(WILDCARD) && value.endsWith(WILDCARD)) { - return String::contains; - } else if (value.startsWith(WILDCARD)) { - return String::endsWith; - } else if (value.endsWith(WILDCARD)) { - return String::startsWith; - } else { - return String::equals; - } - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/NonTerminalExpression.java b/src/main/java/org/prebid/server/deals/targeting/interpret/NonTerminalExpression.java deleted file mode 100644 index ee9f4235a3d..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/NonTerminalExpression.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -public interface NonTerminalExpression extends Expression { -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Not.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Not.java deleted file mode 100644 index ed8f1a35875..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Not.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; - -import java.util.Objects; - -@EqualsAndHashCode -public class Not implements NonTerminalExpression { - - private final Expression expression; - - public Not(Expression expression) { - this.expression = Objects.requireNonNull(expression); - } - - @Override - public boolean matches(RequestContext context) { - return !expression.matches(context); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Or.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Or.java deleted file mode 100644 index a4740f889ad..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Or.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; - -import java.util.Collections; -import java.util.List; - -@EqualsAndHashCode -public class Or implements NonTerminalExpression { - - private final List expressions; - - public Or(List expressions) { - this.expressions = Collections.unmodifiableList(expressions); - } - - @Override - public boolean matches(RequestContext context) { - for (final Expression expression : expressions) { - if (expression.matches(context)) { - return true; - } - } - return false; - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/TerminalExpression.java b/src/main/java/org/prebid/server/deals/targeting/interpret/TerminalExpression.java deleted file mode 100644 index 7c89885cc49..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/TerminalExpression.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -public interface TerminalExpression extends Expression { -} diff --git a/src/main/java/org/prebid/server/deals/targeting/interpret/Within.java b/src/main/java/org/prebid/server/deals/targeting/interpret/Within.java deleted file mode 100644 index 7a4da8f30c6..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/interpret/Within.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import lombok.EqualsAndHashCode; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.GeoLocation; -import org.prebid.server.deals.targeting.model.GeoRegion; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import java.util.Objects; - -@EqualsAndHashCode -public class Within implements TerminalExpression { - - private static final int EARTH_RADIUS_MI = 3959; - - private final TargetingCategory category; - - private final GeoRegion value; - - public Within(TargetingCategory category, GeoRegion value) { - this.category = Objects.requireNonNull(category); - this.value = Objects.requireNonNull(value); - } - - @Override - public boolean matches(RequestContext context) { - final GeoLocation location = context.lookupGeoLocation(category); - - return location != null && isLocationWithinRegion(location); - } - - private boolean isLocationWithinRegion(GeoLocation location) { - final double distance = calculateDistance(location.getLat(), location.getLon(), value.getLat(), value.getLon()); - - return value.getRadiusMiles() > distance; - } - - private static double calculateDistance(double startLat, double startLong, double endLat, double endLong) { - final double dLat = Math.toRadians(endLat - startLat); - final double dLong = Math.toRadians(endLong - startLong); - - final double a = Math.pow(Math.sin(dLat / 2), 2) - + Math.cos(Math.toRadians(startLat)) * Math.cos(Math.toRadians(endLat)) - * Math.pow(Math.sin(dLong / 2), 2); - final double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - - return EARTH_RADIUS_MI * c; - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/model/GeoLocation.java b/src/main/java/org/prebid/server/deals/targeting/model/GeoLocation.java deleted file mode 100644 index 4918d500e13..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/model/GeoLocation.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.targeting.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class GeoLocation { - - Float lat; - - Float lon; -} diff --git a/src/main/java/org/prebid/server/deals/targeting/model/GeoRegion.java b/src/main/java/org/prebid/server/deals/targeting/model/GeoRegion.java deleted file mode 100644 index f7ae09c5ffd..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/model/GeoRegion.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.deals.targeting.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class GeoRegion { - - Float lat; - - Float lon; - - @JsonProperty("radiusMiles") - Float radiusMiles; -} diff --git a/src/main/java/org/prebid/server/deals/targeting/model/LookupResult.java b/src/main/java/org/prebid/server/deals/targeting/model/LookupResult.java deleted file mode 100644 index 557fa98ec4a..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/model/LookupResult.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.prebid.server.deals.targeting.model; - -import lombok.Value; -import org.apache.commons.collections4.ListUtils; - -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; - -@Value(staticConstructor = "of") -public class LookupResult { - - private static final LookupResult EMPTY = LookupResult.of(Collections.emptyList()); - - List values; - - @SuppressWarnings("unchecked") - public static LookupResult empty() { - return (LookupResult) EMPTY; - } - - public static LookupResult ofValue(T value) { - return LookupResult.of(Collections.singletonList(value)); - } - - public boolean anyMatch(Predicate matcher) { - return values.stream().anyMatch(matcher); - } - - public LookupResult orElse(List orValues) { - return LookupResult.of(ListUtils.union(values, orValues)); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/model/Size.java b/src/main/java/org/prebid/server/deals/targeting/model/Size.java deleted file mode 100644 index 5b54b220596..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/model/Size.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.deals.targeting.model; - -import lombok.AllArgsConstructor; -import lombok.Value; - -@Value -@AllArgsConstructor(staticName = "of") -public class Size { - - Integer w; - - Integer h; -} diff --git a/src/main/java/org/prebid/server/deals/targeting/syntax/BooleanOperator.java b/src/main/java/org/prebid/server/deals/targeting/syntax/BooleanOperator.java deleted file mode 100644 index 534ed8f4fc8..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/syntax/BooleanOperator.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import java.util.Arrays; - -public enum BooleanOperator { - - AND("$and"), - OR("$or"), - NOT("$not"); - - private final String value; - - BooleanOperator(String value) { - this.value = value; - } - - public static boolean isBooleanOperator(String candidate) { - return Arrays.stream(BooleanOperator.values()).anyMatch(op -> op.value.equals(candidate)); - } - - public static BooleanOperator fromString(String candidate) { - for (final BooleanOperator op : values()) { - if (op.value.equals(candidate)) { - return op; - } - } - throw new IllegalArgumentException("Unrecognized boolean operator: " + candidate); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/syntax/MatchingFunction.java b/src/main/java/org/prebid/server/deals/targeting/syntax/MatchingFunction.java deleted file mode 100644 index 54bb4a78fb7..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/syntax/MatchingFunction.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import java.util.Arrays; - -public enum MatchingFunction { - - MATCHES("$matches"), - IN("$in"), - INTERSECTS("$intersects"), - WITHIN("$within"); - - private final String value; - - MatchingFunction(String value) { - this.value = value; - } - - public String value() { - return value; - } - - public static boolean isMatchingFunction(String candidate) { - return Arrays.stream(MatchingFunction.values()).anyMatch(op -> op.value.equals(candidate)); - } - - public static MatchingFunction fromString(String candidate) { - for (final MatchingFunction op : values()) { - if (op.value.equals(candidate)) { - return op; - } - } - throw new IllegalArgumentException("Unrecognized matching function: " + candidate); - } -} diff --git a/src/main/java/org/prebid/server/deals/targeting/syntax/TargetingCategory.java b/src/main/java/org/prebid/server/deals/targeting/syntax/TargetingCategory.java deleted file mode 100644 index b7461807420..00000000000 --- a/src/main/java/org/prebid/server/deals/targeting/syntax/TargetingCategory.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import lombok.EqualsAndHashCode; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.exception.TargetingSyntaxException; - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Objects; - -@EqualsAndHashCode -public class TargetingCategory { - - private static final String BIDDER_PARAM_PATH_PATTERN = "\\w+(\\.\\w+)+"; - - private static final EnumSet DYNAMIC_TYPES = EnumSet.of( - Type.deviceGeoExt, - Type.deviceExt, - Type.bidderParam, - Type.userSegment, - Type.userFirstPartyData, - Type.siteFirstPartyData); - - private static final EnumSet STATIC_TYPES = EnumSet.complementOf(DYNAMIC_TYPES); - - private final Type type; - private final String path; - - public TargetingCategory(Type type) { - this(type, null); - } - - public TargetingCategory(Type type, String path) { - this.type = Objects.requireNonNull(type); - this.path = path; - } - - public static boolean isTargetingCategory(String candidate) { - final boolean isSimpleCategory = STATIC_TYPES.stream().anyMatch(op -> op.attribute().equals(candidate)); - return isSimpleCategory || DYNAMIC_TYPES.stream().anyMatch(op -> candidate.startsWith(op.attribute())); - } - - public static TargetingCategory fromString(String candidate) { - for (final Type type : STATIC_TYPES) { - if (type.attribute().equals(candidate)) { - return new TargetingCategory(type); - } - } - - for (final Type type : DYNAMIC_TYPES) { - if (candidate.startsWith(type.attribute())) { - return parseDynamicCategory(candidate, type); - } - } - - throw new IllegalArgumentException("Unrecognized targeting category: " + candidate); - } - - private static TargetingCategory parseDynamicCategory(String candidate, Type type) { - return switch (type) { - case deviceGeoExt, deviceExt, userSegment, userFirstPartyData, siteFirstPartyData -> - parseByTypeAttribute(candidate, type); - case bidderParam -> parseBidderParam(candidate, type); - default -> throw new IllegalStateException("Unexpected dynamic targeting category type " + type); - }; - } - - private static TargetingCategory parseByTypeAttribute(String candidate, Type type) { - final String candidatePath = StringUtils.substringAfter(candidate, type.attribute()); - return new TargetingCategory(type, candidatePath); - } - - private static TargetingCategory parseBidderParam(String candidate, Type type) { - final String candidatePath = StringUtils.substringAfter(candidate, type.attribute()); - if (candidatePath.matches(BIDDER_PARAM_PATH_PATTERN)) { - return new TargetingCategory(type, dropBidderName(candidatePath)); - } else { - throw new TargetingSyntaxException("BidderParam path is incorrect: " + candidatePath); - } - } - - private static String dropBidderName(String path) { - final int index = path.indexOf('.'); - return path.substring(index + 1); - } - - public Type type() { - return type; - } - - public String path() { - return path; - } - - public enum Type { - size("adunit.size"), - mediaType("adunit.mediatype"), - adslot("adunit.adslot"), - domain("site.domain"), - publisherDomain("site.publisher.domain"), - referrer("site.referrer"), - appBundle("app.bundle"), - deviceGeoExt("device.geo.ext."), - deviceExt("device.ext."), - pagePosition("pos"), - location("geo.distance"), - bidderParam("bidp."), - userSegment("segment."), - userFirstPartyData("ufpd."), - siteFirstPartyData("sfpd."), - dow("user.ext.time.userdow"), - hour("user.ext.time.userhour"); - - private final String attribute; - - Type(String attribute) { - this.attribute = attribute; - } - - public String attribute() { - return attribute; - } - - public static Type fromString(String attribute) { - return Arrays.stream(values()) - .filter(value -> value.attribute.equals(attribute)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException( - "Unrecognized targeting category type: " + attribute)); - } - } -} diff --git a/src/main/java/org/prebid/server/events/EventRequest.java b/src/main/java/org/prebid/server/events/EventRequest.java index 59ee222c82b..64e430e3945 100644 --- a/src/main/java/org/prebid/server/events/EventRequest.java +++ b/src/main/java/org/prebid/server/events/EventRequest.java @@ -28,8 +28,6 @@ public class EventRequest { Analytics analytics; - String lineItemId; - public enum Type { win, imp diff --git a/src/main/java/org/prebid/server/events/EventUtil.java b/src/main/java/org/prebid/server/events/EventUtil.java index efb9f4137f9..864892e6725 100644 --- a/src/main/java/org/prebid/server/events/EventUtil.java +++ b/src/main/java/org/prebid/server/events/EventUtil.java @@ -37,8 +37,6 @@ public class EventUtil { private static final String ENABLED_ANALYTICS = "1"; // default private static final String DISABLED_ANALYTICS = "0"; - private static final String LINE_ITEM_ID_PARAMETER = "l"; - private EventUtil() { } @@ -142,7 +140,6 @@ public static EventRequest from(RoutingContext routingContext) { .format(format) .analytics(analytics) .integration(queryParams.get(INTEGRATION_PARAMETER)) - .lineItemId(queryParams.get(LINE_ITEM_ID_PARAMETER)) .build(); } @@ -192,10 +189,6 @@ private static String optionalParameters(EventRequest eventRequest) { result.append(nameValueAsQueryString(ANALYTICS_PARAMETER, DISABLED_ANALYTICS)); } - result.append(StringUtils.isNotEmpty(eventRequest.getLineItemId()) - ? nameValueAsQueryString(LINE_ITEM_ID_PARAMETER, eventRequest.getLineItemId()) - : StringUtils.EMPTY); // skip parameter - return result.toString(); } diff --git a/src/main/java/org/prebid/server/events/EventsService.java b/src/main/java/org/prebid/server/events/EventsService.java index 59accc7037e..72ec0472d96 100644 --- a/src/main/java/org/prebid/server/events/EventsService.java +++ b/src/main/java/org/prebid/server/events/EventsService.java @@ -19,8 +19,6 @@ public EventsService(String externalUrl) { public Events createEvent(String bidId, String bidder, String accountId, - String lineItemId, - boolean analyticsEnabled, EventsContext eventsContext) { return Events.of( eventUrl( @@ -28,8 +26,6 @@ public Events createEvent(String bidId, bidId, bidder, accountId, - lineItemId, - analytics(analyticsEnabled), EventRequest.Format.image, eventsContext), eventUrl( @@ -37,8 +33,6 @@ public Events createEvent(String bidId, bidId, bidder, accountId, - lineItemId, - analytics(analyticsEnabled), EventRequest.Format.image, eventsContext)); } @@ -46,15 +40,16 @@ public Events createEvent(String bidId, /** * Returns url for win tracking. */ - public String winUrl(String bidId, String bidder, String accountId, String lineItemId, - boolean analyticsEnabled, EventsContext eventsContext) { + public String winUrl(String bidId, + String bidder, + String accountId, + EventsContext eventsContext) { + return eventUrl( EventRequest.Type.win, bidId, bidder, accountId, - lineItemId, - analytics(analyticsEnabled), EventRequest.Format.image, eventsContext); } @@ -65,14 +60,12 @@ public String winUrl(String bidId, String bidder, String accountId, String lineI public String vastUrlTracking(String bidId, String bidder, String accountId, - String lineItemId, EventsContext eventsContext) { + return eventUrl(EventRequest.Type.imp, bidId, bidder, accountId, - lineItemId, - null, EventRequest.Format.blank, eventsContext); } @@ -81,8 +74,6 @@ private String eventUrl(EventRequest.Type type, String bidId, String bidder, String accountId, - String lineItemId, - EventRequest.Analytics analytics, EventRequest.Format format, EventsContext eventsContext) { @@ -95,14 +86,8 @@ private String eventUrl(EventRequest.Type type, .timestamp(eventsContext.getAuctionTimestamp()) .format(format) .integration(eventsContext.getIntegration()) - .lineItemId(lineItemId) - .analytics(analytics) .build(); return EventUtil.toUrl(externalUrl, eventRequest); } - - private static EventRequest.Analytics analytics(boolean analyticsEnabled) { - return analyticsEnabled ? null : EventRequest.Analytics.disabled; - } } diff --git a/src/main/java/org/prebid/server/exception/TargetingSyntaxException.java b/src/main/java/org/prebid/server/exception/TargetingSyntaxException.java deleted file mode 100644 index b5fbd75b47d..00000000000 --- a/src/main/java/org/prebid/server/exception/TargetingSyntaxException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.prebid.server.exception; - -public class TargetingSyntaxException extends RuntimeException { - - public TargetingSyntaxException(String message) { - super(message); - } - - public TargetingSyntaxException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/prebid/server/handler/DealsStatusHandler.java b/src/main/java/org/prebid/server/handler/DealsStatusHandler.java deleted file mode 100644 index 15a9dc066dd..00000000000 --- a/src/main/java/org/prebid/server/handler/DealsStatusHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.prebid.server.handler; - -import io.netty.handler.codec.http.HttpHeaderValues; -import io.vertx.core.Handler; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.ext.web.RoutingContext; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.HttpUtil; - -import java.util.Objects; - -public class DealsStatusHandler implements Handler { - - private static final Logger logger = LoggerFactory.getLogger(DealsStatusHandler.class); - - private final DeliveryProgressService deliveryProgressService; - private final JacksonMapper mapper; - - public DealsStatusHandler(DeliveryProgressService deliveryProgressService, JacksonMapper mapper) { - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.mapper = Objects.requireNonNull(mapper); - } - - @Override - public void handle(RoutingContext routingContext) { - final DeliveryProgressReport deliveryProgressReport = deliveryProgressService - .getOverallDeliveryProgressReport(); - final String body = mapper.encodeToString(deliveryProgressReport); - - // don't send the response if client has gone - if (routingContext.response().closed()) { - logger.warn("The client already closed connection, response will be skipped"); - return; - } - - routingContext.response() - .putHeader(HttpUtil.CONTENT_TYPE_HEADER, HttpHeaderValues.APPLICATION_JSON) - .exceptionHandler(this::handleResponseException) - .end(body); - } - - private void handleResponseException(Throwable throwable) { - logger.warn("Failed to send deals status response: {0}", throwable.getMessage()); - } -} diff --git a/src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java b/src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java deleted file mode 100644 index 942b4953147..00000000000 --- a/src/main/java/org/prebid/server/handler/ForceDealsUpdateHandler.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.prebid.server.handler; - -import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; -import io.vertx.ext.web.RoutingContext; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.PlannerService; -import org.prebid.server.deals.RegisterService; -import org.prebid.server.exception.InvalidRequestException; -import org.prebid.server.util.HttpUtil; - -import java.time.ZonedDateTime; -import java.util.Objects; - -public class ForceDealsUpdateHandler implements Handler { - - private static final String ACTION_NAME_PARAM = "action_name"; - - private final DeliveryStatsService deliveryStatsService; - private final PlannerService plannerService; - private final RegisterService registerService; - private final AlertHttpService alertHttpService; - private final DeliveryProgressService deliveryProgressService; - private final LineItemService lineItemService; - private final String endpoint; - - public ForceDealsUpdateHandler(DeliveryStatsService deliveryStatsService, - PlannerService plannerService, - RegisterService registerService, - AlertHttpService alertHttpService, - DeliveryProgressService deliveryProgressService, - LineItemService lineItemService, - String endpoint) { - - this.deliveryStatsService = Objects.requireNonNull(deliveryStatsService); - this.plannerService = Objects.requireNonNull(plannerService); - this.registerService = Objects.requireNonNull(registerService); - this.alertHttpService = Objects.requireNonNull(alertHttpService); - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.lineItemService = Objects.requireNonNull(lineItemService); - this.endpoint = Objects.requireNonNull(endpoint); - } - - @Override - public void handle(RoutingContext routingContext) { - try { - handleDealsAction(dealsActionFrom(routingContext)); - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.NO_CONTENT.code()) - .end()); - } catch (InvalidRequestException e) { - respondWithError(routingContext, HttpResponseStatus.BAD_REQUEST, e); - } catch (Exception e) { - respondWithError(routingContext, HttpResponseStatus.INTERNAL_SERVER_ERROR, e); - } - } - - private static DealsAction dealsActionFrom(RoutingContext routingContext) { - final String actionName = routingContext.request().getParam(ACTION_NAME_PARAM); - if (StringUtils.isEmpty(actionName)) { - throw new InvalidRequestException("Parameter '%s' is required and can't be empty" - .formatted(ACTION_NAME_PARAM)); - } - - try { - return DealsAction.valueOf(actionName.toUpperCase()); - } catch (IllegalArgumentException ignored) { - throw new InvalidRequestException("Given '%s' parameter value '%s' is not among possible actions" - .formatted(ACTION_NAME_PARAM, actionName)); - } - } - - private void handleDealsAction(DealsAction dealsAction) { - switch (dealsAction) { - case UPDATE_LINE_ITEMS -> plannerService.updateLineItemMetaData(); - case SEND_REPORT -> deliveryStatsService.sendDeliveryProgressReports(); - case REGISTER_INSTANCE -> registerService.performRegistration(); - case RESET_ALERT_COUNT -> { - alertHttpService.resetAlertCount("pbs-register-client-error"); - alertHttpService.resetAlertCount("pbs-planner-client-error"); - alertHttpService.resetAlertCount("pbs-planner-empty-response-error"); - alertHttpService.resetAlertCount("pbs-delivery-stats-client-error"); - } - case CREATE_REPORT -> deliveryProgressService.createDeliveryProgressReports(ZonedDateTime.now()); - case INVALIDATE_LINE_ITEMS -> lineItemService.invalidateLineItems(); - } - } - - private void respondWithError(RoutingContext routingContext, HttpResponseStatus statusCode, Exception exception) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(statusCode.code()) - .end(exception.getMessage())); - } - - enum DealsAction { - UPDATE_LINE_ITEMS, SEND_REPORT, REGISTER_INSTANCE, RESET_ALERT_COUNT, CREATE_REPORT, INVALIDATE_LINE_ITEMS - } -} diff --git a/src/main/java/org/prebid/server/handler/LineItemStatusHandler.java b/src/main/java/org/prebid/server/handler/LineItemStatusHandler.java deleted file mode 100644 index e43a543025a..00000000000 --- a/src/main/java/org/prebid/server/handler/LineItemStatusHandler.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.prebid.server.handler; - -import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.Handler; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import io.vertx.ext.web.RoutingContext; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.proto.report.LineItemStatusReport; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.util.HttpUtil; - -import java.util.Objects; - -public class LineItemStatusHandler implements Handler { - - private static final Logger logger = LoggerFactory.getLogger(LineItemStatusHandler.class); - - private static final String ID_PARAM = "id"; - - private final DeliveryProgressService deliveryProgressService; - private final JacksonMapper mapper; - private final String endpoint; - - public LineItemStatusHandler(DeliveryProgressService deliveryProgressService, JacksonMapper mapper, - String endpoint) { - this.deliveryProgressService = Objects.requireNonNull(deliveryProgressService); - this.mapper = Objects.requireNonNull(mapper); - this.endpoint = Objects.requireNonNull(endpoint); - } - - @Override - public void handle(RoutingContext routingContext) { - routingContext.response() - .exceptionHandler(LineItemStatusHandler::handleResponseException); - - final String lineItemId = lineItemIdFrom(routingContext); - if (StringUtils.isEmpty(lineItemId)) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) - .end(ID_PARAM + " parameter is required")); - return; - } - - try { - final LineItemStatusReport report = deliveryProgressService.getLineItemStatusReport(lineItemId); - - HttpUtil.headers().forEach(entry -> routingContext.response().putHeader(entry.getKey(), entry.getValue())); - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.OK.code()) - .end(mapper.encodeToString(report))); - } catch (PreBidException e) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) - .end(e.getMessage())); - } catch (Exception e) { - HttpUtil.executeSafely(routingContext, endpoint, - response -> response - .setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code()) - .end(e.getMessage())); - } - } - - private static String lineItemIdFrom(RoutingContext routingContext) { - return routingContext.request().getParam(ID_PARAM); - } - - private static void handleResponseException(Throwable exception) { - logger.warn("Failed to send line item status response: {0}", exception.getMessage()); - } -} diff --git a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java index 383b0cf7455..ef26b9d09da 100644 --- a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java +++ b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java @@ -10,7 +10,6 @@ import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; -import lombok.AllArgsConstructor; import lombok.Value; import org.prebid.server.activity.infrastructure.ActivityInfrastructure; import org.prebid.server.activity.infrastructure.creator.ActivityInfrastructureCreator; @@ -18,9 +17,6 @@ import org.prebid.server.analytics.model.NotificationEvent; import org.prebid.server.analytics.reporter.AnalyticsReporterDelegator; import org.prebid.server.auction.gpp.model.GppContextCreator; -import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.deals.UserService; -import org.prebid.server.deals.events.ApplicationEventService; import org.prebid.server.events.EventRequest; import org.prebid.server.events.EventUtil; import org.prebid.server.exception.PreBidException; @@ -48,36 +44,24 @@ public class NotificationEventHandler implements Handler { private static final String TRACKING_PIXEL_PNG = "static/tracking-pixel.png"; private static final String PNG_CONTENT_TYPE = "image/png"; - private final UidsCookieService uidsCookieService; - private final ApplicationEventService applicationEventService; - private final UserService userService; private final ActivityInfrastructureCreator activityInfrastructureCreator; private final AnalyticsReporterDelegator analyticsDelegator; private final TimeoutFactory timeoutFactory; private final ApplicationSettings applicationSettings; private final long defaultTimeoutMillis; - private final boolean dealsEnabled; private final TrackingPixel trackingPixel; - public NotificationEventHandler(UidsCookieService uidsCookieService, - ApplicationEventService applicationEventService, - UserService userService, - ActivityInfrastructureCreator activityInfrastructureCreator, + public NotificationEventHandler(ActivityInfrastructureCreator activityInfrastructureCreator, AnalyticsReporterDelegator analyticsDelegator, TimeoutFactory timeoutFactory, ApplicationSettings applicationSettings, - long defaultTimeoutMillis, - boolean dealsEnabled) { + long defaultTimeoutMillis) { - this.uidsCookieService = Objects.requireNonNull(uidsCookieService); - this.applicationEventService = applicationEventService; - this.userService = userService; this.activityInfrastructureCreator = Objects.requireNonNull(activityInfrastructureCreator); this.analyticsDelegator = Objects.requireNonNull(analyticsDelegator); this.timeoutFactory = Objects.requireNonNull(timeoutFactory); this.applicationSettings = Objects.requireNonNull(applicationSettings); this.defaultTimeoutMillis = defaultTimeoutMillis; - this.dealsEnabled = dealsEnabled; trackingPixel = createTrackingPixel(); } @@ -144,45 +128,35 @@ private static Future handleAccountExceptionOrFallback(Throwable except private void handleEvent(AsyncResult async, EventRequest eventRequest, RoutingContext routingContext) { if (async.failed()) { - respondWithServerError(routingContext, "Error occurred while fetching account", async.cause()); - } else { - final Account account = async.result(); - - final String lineItemId = eventRequest.getLineItemId(); - final String bidId = eventRequest.getBidId(); - if (dealsEnabled && lineItemId != null) { - applicationEventService.publishLineItemWinEvent(lineItemId); - userService.processWinEvent(lineItemId, bidId, uidsCookieService.parseFromRequest(routingContext)); - } - - final boolean eventsEnabledForAccount = Objects.equals(accountEventsEnabled(account), true); - final boolean eventsEnabledForRequest = eventRequest.getAnalytics() == EventRequest.Analytics.enabled; - - if (!eventsEnabledForAccount && eventsEnabledForRequest) { - respondWithUnauthorized(routingContext, - "Account '%s' doesn't support events".formatted(account.getId())); - return; - } - - final EventRequest.Type eventType = eventRequest.getType(); - if (eventsEnabledForRequest) { - final NotificationEvent notificationEvent = NotificationEvent.builder() - .type(eventType == EventRequest.Type.win - ? NotificationEvent.Type.win : NotificationEvent.Type.imp) - .bidId(eventRequest.getBidId()) - .account(account) - .bidder(eventRequest.getBidder()) - .timestamp(eventRequest.getTimestamp()) - .integration(eventRequest.getIntegration()) - .httpContext(HttpRequestContext.from(routingContext)) - .lineItemId(lineItemId) - .activityInfrastructure(activityInfrastructure(account)) - .build(); - - analyticsDelegator.processEvent(notificationEvent); - } - respondWithOk(routingContext, eventRequest.getFormat() == EventRequest.Format.image); + respondWithAccountError(routingContext, async.cause()); + return; + } + + final Account account = async.result(); + final boolean eventsEnabledForAccount = Objects.equals(accountEventsEnabled(account), true); + final boolean eventsEnabledForRequest = eventRequest.getAnalytics() == EventRequest.Analytics.enabled; + + if (!eventsEnabledForAccount && eventsEnabledForRequest) { + respondWithUnauthorized(routingContext, "Account '%s' doesn't support events".formatted(account.getId())); + return; + } + + final EventRequest.Type eventType = eventRequest.getType(); + if (eventsEnabledForRequest) { + final NotificationEvent notificationEvent = NotificationEvent.builder() + .type(eventType == EventRequest.Type.win ? NotificationEvent.Type.win : NotificationEvent.Type.imp) + .bidId(eventRequest.getBidId()) + .account(account) + .bidder(eventRequest.getBidder()) + .timestamp(eventRequest.getTimestamp()) + .integration(eventRequest.getIntegration()) + .httpContext(HttpRequestContext.from(routingContext)) + .activityInfrastructure(activityInfrastructure(account)) + .build(); + + analyticsDelegator.processEvent(notificationEvent); } + respondWithOk(routingContext, eventRequest.getFormat() == EventRequest.Format.image); } private static Boolean accountEventsEnabled(Account account) { @@ -202,13 +176,14 @@ private ActivityInfrastructure activityInfrastructure(Account account) { private void respondWithOk(RoutingContext routingContext, boolean respondWithPixel) { if (respondWithPixel) { - HttpUtil.executeSafely(routingContext, Endpoint.event, + HttpUtil.executeSafely( + routingContext, + Endpoint.event, response -> response .putHeader(HttpHeaders.CONTENT_TYPE, trackingPixel.getContentType()) .end(Buffer.buffer(trackingPixel.getContent()))); } else { - HttpUtil.executeSafely(routingContext, Endpoint.event, - HttpServerResponse::end); + HttpUtil.executeSafely(routingContext, Endpoint.event, HttpServerResponse::end); } } @@ -220,14 +195,16 @@ private static void respondWithUnauthorized(RoutingContext routingContext, Strin respondWith(routingContext, HttpResponseStatus.UNAUTHORIZED, message); } - private static void respondWithServerError(RoutingContext routingContext, String message, Throwable exception) { - logger.warn(message, exception); - final String body = "%s: %s".formatted(message, exception.getMessage()); + private static void respondWithAccountError(RoutingContext routingContext, Throwable exception) { + logger.warn("Error occurred while fetching account", exception); + final String body = "Error occurred while fetching account: " + exception.getMessage(); respondWith(routingContext, HttpResponseStatus.INTERNAL_SERVER_ERROR, body); } private static void respondWith(RoutingContext routingContext, HttpResponseStatus status, String body) { - HttpUtil.executeSafely(routingContext, Endpoint.event, + HttpUtil.executeSafely( + routingContext, + Endpoint.event, response -> response .setStatusCode(status.code()) .end(body)); @@ -236,8 +213,7 @@ private static void respondWith(RoutingContext routingContext, HttpResponseStatu /** * Internal class for holding pixels content type to its value. */ - @AllArgsConstructor(staticName = "of") - @Value + @Value(staticConstructor = "of") private static class TrackingPixel { String contentType; diff --git a/src/main/java/org/prebid/server/handler/TracerLogHandler.java b/src/main/java/org/prebid/server/handler/TracerLogHandler.java index ae0412860ae..53064a59264 100644 --- a/src/main/java/org/prebid/server/handler/TracerLogHandler.java +++ b/src/main/java/org/prebid/server/handler/TracerLogHandler.java @@ -13,7 +13,6 @@ public class TracerLogHandler implements Handler { private static final String ACCOUNT_PARAMETER = "account"; - private static final String LINE_ITEM_PARAMETER = "lineItemId"; private static final String BIDDER_CODE_PARAMETER = "bidderCode"; private static final String LOG_LEVEL_PARAMETER = "level"; private static final String DURATION_IN_SECONDS = "duration"; @@ -29,11 +28,11 @@ public void handle(RoutingContext routingContext) { final MultiMap parameters = routingContext.request().params(); final String accountId = parameters.get(ACCOUNT_PARAMETER); final String bidderCode = parameters.get(BIDDER_CODE_PARAMETER); - final String lineItemId = parameters.get(LINE_ITEM_PARAMETER); - if (StringUtils.isBlank(accountId) && StringUtils.isBlank(lineItemId) && StringUtils.isBlank(bidderCode)) { - routingContext.response().setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) - .end("At least one parameter should ne defined: account, bidderCode, lineItemId"); + if (StringUtils.isBlank(accountId) && StringUtils.isBlank(bidderCode)) { + routingContext.response() + .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) + .end("At least one parameter should be defined: account, bidderCode"); return; } @@ -42,14 +41,17 @@ public void handle(RoutingContext routingContext) { try { duration = parseDuration(parameters.get(DURATION_IN_SECONDS)); } catch (InvalidRequestException e) { - routingContext.response().setStatusCode(HttpResponseStatus.BAD_REQUEST.code()).end(e.getMessage()); + routingContext.response() + .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) + .end(e.getMessage()); return; } try { - criteriaManager.addCriteria(accountId, bidderCode, lineItemId, loggerLevel, duration); + criteriaManager.addCriteria(accountId, bidderCode, loggerLevel, duration); } catch (IllegalArgumentException e) { - routingContext.response().setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) + routingContext.response() + .setStatusCode(HttpResponseStatus.BAD_REQUEST.code()) .end("Invalid parameter: " + e.getMessage()); return; } @@ -67,6 +69,5 @@ private static int parseDuration(String rawDuration) { throw new InvalidRequestException( "duration parameter should be defined as integer, but was " + rawDuration); } - } } diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java index d2f94d27e67..55f61a554f7 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java @@ -370,8 +370,13 @@ private static String originFrom(RoutingContext routingContext) { return origin; } - private void respondWith(RoutingContext routingContext, HttpResponseStatus status, String body, long startTime, - MetricName metricRequestStatus, AmpEvent event, TcfContext tcfContext) { + private void respondWith(RoutingContext routingContext, + HttpResponseStatus status, + String body, + long startTime, + MetricName metricRequestStatus, + AmpEvent event, + TcfContext tcfContext) { final boolean responseSent = HttpUtil.executeSafely(routingContext, Endpoint.openrtb2_amp, response -> response diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java index 043890ae86b..a7c036a1f4c 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java @@ -127,6 +127,7 @@ private void handleResult(AsyncResult responseResult, AuctionEvent.AuctionEventBuilder auctionEventBuilder, RoutingContext routingContext, long startTime) { + final boolean responseSucceeded = responseResult.succeeded(); final AuctionContext auctionContext = responseSucceeded ? responseResult.result() : null; @@ -175,7 +176,8 @@ private void handleResult(AsyncResult responseResult, } else if (exception instanceof BlacklistedAppException || exception instanceof BlacklistedAccountException) { metricRequestStatus = exception instanceof BlacklistedAccountException - ? MetricName.blacklisted_account : MetricName.blacklisted_app; + ? MetricName.blacklisted_account + : MetricName.blacklisted_app; final String message = "Blacklisted: " + exception.getMessage(); logger.debug(message); @@ -205,17 +207,31 @@ private void handleResult(AsyncResult responseResult, final AuctionEvent auctionEvent = auctionEventBuilder.status(status.code()).errors(errorMessages).build(); final PrivacyContext privacyContext = auctionContext != null ? auctionContext.getPrivacyContext() : null; final TcfContext tcfContext = privacyContext != null ? privacyContext.getTcfContext() : TcfContext.empty(); - respondWith(routingContext, status, body, startTime, requestType, metricRequestStatus, auctionEvent, - tcfContext); + respondWith( + routingContext, + status, + body, + startTime, + requestType, + metricRequestStatus, + auctionEvent, + tcfContext); httpInteractionLogger.maybeLogOpenrtb2Auction(auctionContext, routingContext, status.code(), body); } - private void respondWith(RoutingContext routingContext, HttpResponseStatus status, String body, long startTime, - MetricName requestType, MetricName metricRequestStatus, AuctionEvent event, + private void respondWith(RoutingContext routingContext, + HttpResponseStatus status, + String body, + long startTime, + MetricName requestType, + MetricName metricRequestStatus, + AuctionEvent event, TcfContext tcfContext) { - final boolean responseSent = HttpUtil.executeSafely(routingContext, Endpoint.openrtb2_auction, + final boolean responseSent = HttpUtil.executeSafely( + routingContext, + Endpoint.openrtb2_auction, response -> response .exceptionHandler(throwable -> handleResponseException(throwable, requestType)) .setStatusCode(status.code()) diff --git a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java index 144338430ba..a68eb39eb45 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java @@ -66,6 +66,7 @@ public VideoHandler(VideoRequestFactory videoRequestFactory, Clock clock, PrebidVersionProvider prebidVersionProvider, JacksonMapper mapper) { + this.videoRequestFactory = Objects.requireNonNull(videoRequestFactory); this.videoResponseFactory = Objects.requireNonNull(videoResponseFactory); this.exchangeService = Objects.requireNonNull(exchangeService); diff --git a/src/main/java/org/prebid/server/log/Criteria.java b/src/main/java/org/prebid/server/log/Criteria.java index f98a45c2500..7ad5c3039fd 100644 --- a/src/main/java/org/prebid/server/log/Criteria.java +++ b/src/main/java/org/prebid/server/log/Criteria.java @@ -1,48 +1,32 @@ package org.prebid.server.log; import io.vertx.core.logging.Logger; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Value; +import org.apache.commons.lang3.StringUtils; import java.util.Objects; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; -@Value -@Builder -@AllArgsConstructor public class Criteria { private static final String TAG_SEPARATOR = "-"; - private static final String TAGGED_MESSAGE_PATTERN = "[%s]: %s"; private static final String TAGGED_RESPONSE_PATTERN = "[%s]: %s - %s"; public static final String BID_RESPONSE = "BidResponse"; public static final String RESOLVED_BID_REQUEST = "Resolved BidRequest"; - String account; + private final String account; + private final String bidder; + private final String tag; + private final BiConsumer loggerLevel; - String bidder; - - String lineItemId; - - String tag; - - BiConsumer loggerLevel; - - public static Criteria create(String account, String bidder, String lineItemId, - BiConsumer loggerLevel) { - return new Criteria(account, bidder, lineItemId, makeTag(account, bidder, lineItemId), loggerLevel); + private Criteria(String account, String bidder, BiConsumer loggerLevel) { + this.account = account; + this.bidder = bidder; + this.tag = makeTag(account, bidder); + this.loggerLevel = Objects.requireNonNull(loggerLevel); } - public void log(Criteria criteria, Logger logger, Object message, Consumer defaultLogger) { - if (isMatched(criteria)) { - loggerLevel.accept(logger, TAGGED_MESSAGE_PATTERN.formatted(tag, message)); - } else { - defaultLogger.accept(message); - } + public static Criteria create(String account, String bidder, BiConsumer loggerLevel) { + return new Criteria(account, bidder, loggerLevel); } public void logResponse(String bidResponse, Logger logger) { @@ -58,23 +42,19 @@ public void logResponseAndRequest(String bidResponse, String bidRequest, Logger } } - private boolean isMatched(Criteria criteria) { - return criteria != null - && (account == null || account.equals(criteria.account)) - && (bidder == null || bidder.equals(criteria.bidder)) - && (lineItemId == null || lineItemId.equals(criteria.lineItemId)); - } - private boolean isMatchedToString(String value) { return (account == null || value.contains(account)) - && (bidder == null || value.contains(bidder)) - && (lineItemId == null || value.contains(lineItemId)); + && (bidder == null || value.contains(bidder)); } - private static String makeTag(String account, String bidder, String lineItemId) { - return Stream.of(account, bidder, lineItemId) - .filter(Objects::nonNull) - .collect(Collectors.joining(TAG_SEPARATOR)); - } + private static String makeTag(String account, String bidder) { + if (account == null) { + return StringUtils.defaultString(bidder); + } + if (bidder == null) { + return account; + } + return account + TAG_SEPARATOR + bidder; + } } diff --git a/src/main/java/org/prebid/server/log/CriteriaLogManager.java b/src/main/java/org/prebid/server/log/CriteriaLogManager.java index b8e5801d436..20344901a31 100644 --- a/src/main/java/org/prebid/server/log/CriteriaLogManager.java +++ b/src/main/java/org/prebid/server/log/CriteriaLogManager.java @@ -10,7 +10,6 @@ import java.util.Objects; import java.util.Set; -import java.util.function.Consumer; public class CriteriaLogManager { @@ -24,25 +23,11 @@ public CriteriaLogManager(JacksonMapper mapper) { this.mapper = Objects.requireNonNull(mapper); } - public void log(Logger logger, Criteria criteria, Object message, Consumer defaultLogger) { - if (criterias.isEmpty()) { - defaultLogger.accept(message); - } - criterias.forEach(cr -> cr.log(criteria, logger, message, defaultLogger)); - } - - public void log(Logger logger, String account, Object message, Consumer defaultLogger) { - log(logger, Criteria.builder().account(account).build(), message, defaultLogger); - } - - public void log(Logger logger, String account, String bidder, String lineItemId, Object message, - Consumer defaultLogger) { - log(logger, Criteria.builder().account(account).bidder(bidder).lineItemId(lineItemId).build(), - message, defaultLogger); - } - - public BidResponse traceResponse(Logger logger, BidResponse bidResponse, BidRequest bidRequest, + public BidResponse traceResponse(Logger logger, + BidResponse bidResponse, + BidRequest bidRequest, boolean debugEnabled) { + if (criterias.isEmpty()) { return bidResponse; } diff --git a/src/main/java/org/prebid/server/log/CriteriaManager.java b/src/main/java/org/prebid/server/log/CriteriaManager.java index e5cde95a392..e55087ce50a 100644 --- a/src/main/java/org/prebid/server/log/CriteriaManager.java +++ b/src/main/java/org/prebid/server/log/CriteriaManager.java @@ -2,18 +2,13 @@ import io.vertx.core.Vertx; import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.prebid.server.deals.model.LogCriteriaFilter; -import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; public class CriteriaManager { private static final long MAX_CRITERIA_DURATION = 300000L; - private static final Logger logger = LoggerFactory.getLogger(CriteriaManager.class); - private final CriteriaLogManager criteriaLogManager; private final Vertx vertx; @@ -22,24 +17,16 @@ public CriteriaManager(CriteriaLogManager criteriaLogManager, Vertx vertx) { this.vertx = vertx; } - public void addCriteria(String accountId, String bidderCode, String lineItemId, String loggerLevel, + public void addCriteria(String accountId, + String bidderCode, + String loggerLevel, Integer durationMillis) { - final Criteria criteria = Criteria.create(accountId, bidderCode, lineItemId, resolveLogLevel(loggerLevel)); + + final Criteria criteria = Criteria.create(accountId, bidderCode, resolveLogLevel(loggerLevel)); criteriaLogManager.addCriteria(criteria); vertx.setTimer(limitDuration(durationMillis), ignored -> criteriaLogManager.removeCriteria(criteria)); } - public void addCriteria(LogCriteriaFilter filter, Long durationSeconds) { - if (filter != null) { - final Criteria criteria = Criteria.create(filter.getAccountId(), filter.getBidderCode(), - filter.getLineItemId(), Logger::error); - criteriaLogManager.addCriteria(criteria); - logger.info("Logger was updated with new criteria {0}", criteria); - vertx.setTimer(limitDuration(TimeUnit.SECONDS.toMillis(durationSeconds)), - ignored -> criteriaLogManager.removeCriteria(criteria)); - } - } - public void stop() { criteriaLogManager.removeAllCriteria(); } @@ -49,21 +36,18 @@ private long limitDuration(long durationMillis) { } private BiConsumer resolveLogLevel(String rawLogLevel) { - final LogLevel logLevel; try { - logLevel = LogLevel.valueOf(rawLogLevel.toLowerCase()); + return switch (LogLevel.valueOf(rawLogLevel.toLowerCase())) { + case info -> Logger::info; + case warn -> Logger::warn; + case trace -> Logger::trace; + case error -> Logger::error; + case fatal -> Logger::fatal; + case debug -> Logger::debug; + }; } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Invalid LoggingLevel: " + rawLogLevel); } - - return switch (logLevel) { - case info -> Logger::info; - case warn -> Logger::warn; - case trace -> Logger::trace; - case error -> Logger::error; - case fatal -> Logger::fatal; - case debug -> Logger::debug; - }; } private enum LogLevel { diff --git a/src/main/java/org/prebid/server/metric/MetricName.java b/src/main/java/org/prebid/server/metric/MetricName.java index ca51fe09b73..56bd07af58b 100644 --- a/src/main/java/org/prebid/server/metric/MetricName.java +++ b/src/main/java/org/prebid/server/metric/MetricName.java @@ -146,32 +146,6 @@ public enum MetricName { // price-floors price_floors("price-floors"), - // win notifications - win_notifications, - win_requests, - win_request_preparation_failed, - win_request_time, - win_request_failed, - win_request_successful, - - // user details - user_details_requests, - user_details_request_preparation_failed, - user_details_request_time, - user_details_request_failed, - user_details_request_successful, - - // pg - planner_lineitems_received, - planner_requests, - planner_request_failed, - planner_request_successful, - planner_request_time, - delivery_requests, - delivery_request_failed, - delivery_request_successful, - delivery_request_time, - // activity disallowed_count("disallowed.count"), processed_rules_count("processedrules.count"); diff --git a/src/main/java/org/prebid/server/metric/Metrics.java b/src/main/java/org/prebid/server/metric/Metrics.java index aa5316235b5..38f29307637 100644 --- a/src/main/java/org/prebid/server/metric/Metrics.java +++ b/src/main/java/org/prebid/server/metric/Metrics.java @@ -58,7 +58,6 @@ public class Metrics extends UpdatableMetrics { private final CurrencyRatesMetrics currencyRatesMetrics; private final Map settingsCacheMetrics; private final HooksMetrics hooksMetrics; - private final PgMetrics pgMetrics; public Metrics(MetricRegistry metricRegistry, CounterType counterType, @@ -97,7 +96,6 @@ public Metrics(MetricRegistry metricRegistry, currencyRatesMetrics = new CurrencyRatesMetrics(metricRegistry, counterType); settingsCacheMetrics = new HashMap<>(); hooksMetrics = new HooksMetrics(metricRegistry, counterType); - pgMetrics = new PgMetrics(metricRegistry, counterType); } RequestsMetrics requests() { @@ -140,10 +138,6 @@ UserSyncMetrics userSync() { return userSyncMetrics; } - PgMetrics pgMetrics() { - return pgMetrics; - } - CookieSyncMetrics cookieSync() { return cookieSyncMetrics; } @@ -505,58 +499,6 @@ public void createHttpClientCircuitBreakerNumberGauge(LongSupplier numberSupplie forCircuitBreakerType(MetricName.http).createGauge(MetricName.existing, numberSupplier); } - public void updatePlannerRequestMetric(boolean successful) { - pgMetrics().incCounter(MetricName.planner_requests); - if (successful) { - pgMetrics().incCounter(MetricName.planner_request_successful); - } else { - pgMetrics().incCounter(MetricName.planner_request_failed); - } - } - - public void updateDeliveryRequestMetric(boolean successful) { - pgMetrics().incCounter(MetricName.delivery_requests); - if (successful) { - pgMetrics().incCounter(MetricName.delivery_request_successful); - } else { - pgMetrics().incCounter(MetricName.delivery_request_failed); - } - } - - public void updateWinEventRequestMetric(boolean successful) { - incCounter(MetricName.win_requests); - if (successful) { - incCounter(MetricName.win_request_successful); - } else { - incCounter(MetricName.win_request_failed); - } - } - - public void updateUserDetailsRequestMetric(boolean successful) { - incCounter(MetricName.user_details_requests); - if (successful) { - incCounter(MetricName.user_details_request_successful); - } else { - incCounter(MetricName.user_details_request_failed); - } - } - - public void updateWinRequestTime(long millis) { - updateTimer(MetricName.win_request_time, millis); - } - - public void updateLineItemsNumberMetric(long count) { - pgMetrics().incCounter(MetricName.planner_lineitems_received, count); - } - - public void updatePlannerRequestTime(long millis) { - pgMetrics().updateTimer(MetricName.planner_request_time, millis); - } - - public void updateDeliveryRequestTime(long millis) { - pgMetrics().updateTimer(MetricName.delivery_request_time, millis); - } - public void updateGeoLocationMetric(boolean successful) { incCounter(MetricName.geolocation_requests); if (successful) { @@ -696,18 +638,6 @@ static MetricName fromAction(ExecutionAction action) { } } - public void updateWinNotificationMetric() { - incCounter(MetricName.win_notifications); - } - - public void updateWinRequestPreparationFailed() { - incCounter(MetricName.win_request_preparation_failed); - } - - public void updateUserDetailsRequestPreparationFailed() { - incCounter(MetricName.user_details_request_preparation_failed); - } - public void updateRequestsActivityDisallowedCount(Activity activity) { requests().activities().forActivity(activity).incCounter(MetricName.disallowed_count); } diff --git a/src/main/java/org/prebid/server/metric/PgMetrics.java b/src/main/java/org/prebid/server/metric/PgMetrics.java deleted file mode 100644 index a7aca3a35a4..00000000000 --- a/src/main/java/org/prebid/server/metric/PgMetrics.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.metric; - -import com.codahale.metrics.MetricRegistry; - -public class PgMetrics extends UpdatableMetrics { - - PgMetrics(MetricRegistry metricRegistry, CounterType counterType) { - super(metricRegistry, counterType, metricName -> "pg." + metricName); - } -} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugPgmetrics.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugPgmetrics.java deleted file mode 100644 index bf87b233962..00000000000 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugPgmetrics.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.prebid.server.proto.openrtb.ext.response; - -import lombok.Builder; -import lombok.Value; - -import java.util.Map; -import java.util.Set; - -/** - * Defines the contract for bidresponse.ext.debug.pgmetrics - */ -@Builder -@Value -public class ExtDebugPgmetrics { - - public static final ExtDebugPgmetrics EMPTY = ExtDebugPgmetrics.builder().build(); - - Set sentToClient; - - Set sentToClientAsTopMatch; - - Set matchedDomainTargeting; - - Set matchedWholeTargeting; - - Set matchedTargetingFcapped; - - Set matchedTargetingFcapLookupFailed; - - Set readyToServe; - - Set pacingDeferred; - - Map> sentToBidder; - - Map> sentToBidderAsTopMatch; - - Map> receivedFromBidder; - - Set responseInvalidated; -} diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugTrace.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugTrace.java index e1b047beac1..f17c2c9cf16 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugTrace.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtDebugTrace.java @@ -1,11 +1,9 @@ package org.prebid.server.proto.openrtb.ext.response; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Value; import java.util.List; -import java.util.Map; /** * Defines the contract for bidresponse.ext.debug.trace @@ -14,17 +12,5 @@ @Value public class ExtDebugTrace { - /** - * Defines the contract for bidresponse.ext.debug.trace.deals - */ - List deals; - - /** - * Defines the contract for bidresponse.ext.debug.trace.lineItems - */ - - @JsonProperty("lineitems") - Map> lineItems; - List activityInfrastructure; } diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtResponseDebug.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtResponseDebug.java index 253a6d9f7ea..7d1a5f4c499 100644 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtResponseDebug.java +++ b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtResponseDebug.java @@ -24,11 +24,6 @@ public class ExtResponseDebug { */ BidRequest resolvedrequest; - /** - * Defines the contract for bidresponse.ext.debug.pgmetrics - */ - ExtDebugPgmetrics pgmetrics; - /** * Defines the contract for bidresponse.ext.debug.trace */ diff --git a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtTraceDeal.java b/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtTraceDeal.java deleted file mode 100644 index 1187ef36757..00000000000 --- a/src/main/java/org/prebid/server/proto/openrtb/ext/response/ExtTraceDeal.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.prebid.server.proto.openrtb.ext.response; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Value; - -import java.time.ZonedDateTime; - -/** - * Defines the contract for bidresponse.ext.debug.trace.deals[] - */ -@AllArgsConstructor(staticName = "of") -@Value -public class ExtTraceDeal { - - /** - * Defines the contract for bidresponse.ext.debug.trace.deals[].lineitemid - */ - @JsonProperty("lineitemid") - String lineItemId; - - /** - * Defines the contract for bidresponse.ext.debug.trace.deals[].time - */ - ZonedDateTime time; - - /** - * Defines the contract for bidresponse.ext.debug.trace.deals[].category - */ - Category category; - - /** - * Defines the contract for bidresponse.ext.debug.trace.deals[].message - */ - String message; - - public enum Category { - targeting, pacing, cleanup, post_processing - } -} diff --git a/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java b/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java index 1bd29c31a3d..93c8b1f61b4 100644 --- a/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/AdminEndpointsConfiguration.java @@ -5,21 +5,11 @@ import lombok.NoArgsConstructor; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.PlannerService; -import org.prebid.server.deals.RegisterService; -import org.prebid.server.deals.simulation.DealsSimulationAdminHandler; import org.prebid.server.handler.AccountCacheInvalidationHandler; import org.prebid.server.handler.CollectedMetricsHandler; import org.prebid.server.handler.CurrencyRatesHandler; import org.prebid.server.handler.CustomizedAdminEndpoint; -import org.prebid.server.handler.DealsStatusHandler; -import org.prebid.server.handler.ForceDealsUpdateHandler; import org.prebid.server.handler.HttpInteractionLogHandler; -import org.prebid.server.handler.LineItemStatusHandler; import org.prebid.server.handler.LoggerControlKnobHandler; import org.prebid.server.handler.SettingsCacheNotificationHandler; import org.prebid.server.handler.TracerLogHandler; @@ -192,89 +182,6 @@ CustomizedAdminEndpoint tracerLogEndpoint( .withCredentials(adminEndpointCredentials); } - @Bean - @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.deals-status.enabled} == true") - CustomizedAdminEndpoint dealsStatusEndpoint( - DeliveryProgressService deliveryProgressService, - JacksonMapper mapper, - @Value("${admin-endpoints.deals-status.path}") String path, - @Value("${admin-endpoints.deals-status.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.deals-status.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { - - return new CustomizedAdminEndpoint( - path, - new DealsStatusHandler(deliveryProgressService, mapper), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); - } - - @Bean - @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.lineitem-status.enabled} == true") - CustomizedAdminEndpoint lineItemStatusEndpoint( - DeliveryProgressService deliveryProgressService, - JacksonMapper mapper, - @Value("${admin-endpoints.lineitem-status.path}") String path, - @Value("${admin-endpoints.lineitem-status.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.lineitem-status.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { - - return new CustomizedAdminEndpoint( - path, - new LineItemStatusHandler(deliveryProgressService, mapper, path), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); - } - - @Bean - @ConditionalOnExpression("${deals.enabled} == true and ${admin-endpoints.force-deals-update.enabled} == true") - CustomizedAdminEndpoint forceDealsUpdateEndpoint( - DeliveryStatsService deliveryStatsService, - PlannerService plannerService, - RegisterService registerService, - AlertHttpService alertHttpService, - DeliveryProgressService deliveryProgressService, - LineItemService lineItemService, - @Value("${admin-endpoints.force-deals-update.path}") String path, - @Value("${admin-endpoints.force-deals-update.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.force-deals-update.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { - - return new CustomizedAdminEndpoint( - path, - new ForceDealsUpdateHandler( - deliveryStatsService, - plannerService, - registerService, - alertHttpService, - deliveryProgressService, - lineItemService, - path), - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); - } - - @Bean - @ConditionalOnExpression("${deals.enabled} == true and ${deals.simulation.enabled} == true" - + " and ${admin-endpoints.e2eadmin.enabled} == true") - CustomizedAdminEndpoint dealsSimulationAdminEndpoint( - DealsSimulationAdminHandler dealsSimulationAdminHandler, - @Value("${admin-endpoints.e2eadmin.path}") String path, - @Value("${admin-endpoints.e2eadmin.on-application-port}") boolean isOnApplicationPort, - @Value("${admin-endpoints.e2eadmin.protected}") boolean isProtected, - @Autowired(required = false) Map adminEndpointCredentials) { - - return new CustomizedAdminEndpoint( - path, - dealsSimulationAdminHandler, - isOnApplicationPort, - isProtected) - .withCredentials(adminEndpointCredentials); - } - @Bean @ConditionalOnExpression("${admin-endpoints.collected-metrics.enabled} == true") CustomizedAdminEndpoint collectedMetricsAdminEndpoint( diff --git a/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java b/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java deleted file mode 100644 index 5b935ca1602..00000000000 --- a/src/main/java/org/prebid/server/spring/config/DealsConfiguration.java +++ /dev/null @@ -1,914 +0,0 @@ -package org.prebid.server.spring.config; - -import io.vertx.core.Vertx; -import io.vertx.core.eventbus.EventBus; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.ObjectUtils; -import org.prebid.server.bidder.BidderErrorNotifier; -import org.prebid.server.bidder.BidderRequestCompletionTrackerFactory; -import org.prebid.server.bidder.DealsBidderRequestCompletionTrackerFactory; -import org.prebid.server.bidder.HttpBidderRequestEnricher; -import org.prebid.server.bidder.HttpBidderRequester; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.AdminCentralService; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DealsService; -import org.prebid.server.deals.DeliveryProgressReportFactory; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.PlannerService; -import org.prebid.server.deals.RegisterService; -import org.prebid.server.deals.Suspendable; -import org.prebid.server.deals.TargetingService; -import org.prebid.server.deals.UserAdditionalInfoService; -import org.prebid.server.deals.UserService; -import org.prebid.server.deals.deviceinfo.DeviceInfoService; -import org.prebid.server.deals.events.AdminEventProcessor; -import org.prebid.server.deals.events.AdminEventService; -import org.prebid.server.deals.events.ApplicationEventProcessor; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.events.EventServiceInitializer; -import org.prebid.server.deals.simulation.DealsSimulationAdminHandler; -import org.prebid.server.deals.simulation.SimulationAwareDeliveryProgressService; -import org.prebid.server.deals.simulation.SimulationAwareDeliveryStatsService; -import org.prebid.server.deals.simulation.SimulationAwareHttpBidderRequester; -import org.prebid.server.deals.simulation.SimulationAwareLineItemService; -import org.prebid.server.deals.simulation.SimulationAwarePlannerService; -import org.prebid.server.deals.simulation.SimulationAwareRegisterService; -import org.prebid.server.deals.simulation.SimulationAwareUserService; -import org.prebid.server.geolocation.GeoLocationService; -import org.prebid.server.health.HealthMonitor; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.log.CriteriaManager; -import org.prebid.server.metric.Metrics; -import org.prebid.server.settings.CachingApplicationSettings; -import org.prebid.server.settings.SettingsCache; -import org.prebid.server.vertx.ContextRunner; -import org.prebid.server.vertx.http.HttpClient; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.validation.annotation.Validated; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.time.Clock; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Configuration -public class DealsConfiguration { - - @Configuration - @ConditionalOnExpression("${deals.enabled} == true and ${deals.simulation.enabled} == false") - public static class ProductionConfiguration { - - @Bean - PlannerService plannerService( - PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - DeliveryProgressService deliveryProgressService, - LineItemService lineItemService, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - JacksonMapper mapper) { - - return new PlannerService( - plannerProperties.toComponentProperties(), - deploymentProperties.toComponentProperties(), - lineItemService, - deliveryProgressService, - alertHttpService, - httpClient, - metrics, - clock, - mapper); - } - - @Bean - RegisterService registerService( - PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - AdminEventService adminEventService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HealthMonitor healthMonitor, - CurrencyConversionService currencyConversionService, - HttpClient httpClient, - Vertx vertx, - JacksonMapper mapper) { - - return new RegisterService( - plannerProperties.toComponentProperties(), - deploymentProperties.toComponentProperties(), - adminEventService, - deliveryProgressService, - alertHttpService, - healthMonitor, - currencyConversionService, - httpClient, - vertx, - mapper); - } - - @Bean - DeliveryStatsService deliveryStatsService( - DeliveryStatsProperties deliveryStatsProperties, - DeliveryProgressReportFactory deliveryProgressReportFactory, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - Vertx vertx, - JacksonMapper mapper) { - - return new DeliveryStatsService( - deliveryStatsProperties.toComponentProperties(), - deliveryProgressReportFactory, - alertHttpService, - httpClient, - metrics, - clock, - vertx, - mapper); - } - - @Bean - LineItemService lineItemService( - @Value("${deals.max-deals-per-bidder}") int maxDealsPerBidder, - TargetingService targetingService, - CurrencyConversionService conversionService, - ApplicationEventService applicationEventService, - @Value("${auction.ad-server-currency}") String adServerCurrency, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - return new LineItemService(maxDealsPerBidder, - targetingService, - conversionService, - applicationEventService, - adServerCurrency, - clock, - criteriaLogManager); - } - - @Bean - DeliveryProgressService deliveryProgressService( - DeliveryProgressProperties deliveryProgressProperties, - LineItemService lineItemService, - DeliveryStatsService deliveryStatsService, - DeliveryProgressReportFactory deliveryProgressReportFactory, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - return new DeliveryProgressService( - deliveryProgressProperties.toComponentProperties(), - lineItemService, - deliveryStatsService, - deliveryProgressReportFactory, - clock, - criteriaLogManager); - } - - @Bean - UserService userService( - UserDetailsProperties userDetailsProperties, - @Value("${datacenter-region}") String dataCenterRegion, - LineItemService lineItemService, - HttpClient httpClient, - Clock clock, - Metrics metrics, - JacksonMapper mapper) { - - return new UserService( - userDetailsProperties.toComponentProperties(), - dataCenterRegion, - lineItemService, - httpClient, - clock, - metrics, - mapper); - } - } - - @Configuration - @ConditionalOnExpression("${deals.enabled} == true and ${deals.simulation.enabled} == false") - @EnableScheduling - public static class SchedulerConfiguration { - - @Bean - GeneralPlannerScheduler generalPlannerScheduler(PlannerService plannerService, - ContextRunner contextRunner) { - return new GeneralPlannerScheduler(plannerService, contextRunner); - } - - @Bean - @ConditionalOnExpression( - "'${deals.delivery-stats.delivery-period}'" - + ".equals('${deals.delivery-progress.report-reset-period}')") - ImmediateDeliveryScheduler immediateDeliveryScheduler(DeliveryProgressService deliveryProgressService, - DeliveryStatsService deliveryStatsService, - Clock clock, - ContextRunner contextRunner) { - return new ImmediateDeliveryScheduler(deliveryProgressService, deliveryStatsService, clock, - contextRunner); - } - - @Bean - @ConditionalOnExpression( - "not '${deals.delivery-stats.delivery-period}'" - + ".equals('${deals.delivery-progress.report-reset-period}')") - DeliveryScheduler deliveryScheduler(DeliveryProgressService deliveryProgressService, - DeliveryStatsService deliveryStatsService, - Clock clock, - ContextRunner contextRunner) { - return new DeliveryScheduler(deliveryProgressService, deliveryStatsService, clock, - contextRunner); - } - - @Bean - AdvancePlansScheduler advancePlansScheduler(LineItemService lineItemService, - ContextRunner contextRunner, - Clock clock) { - return new AdvancePlansScheduler(lineItemService, contextRunner, clock); - } - - private static class GeneralPlannerScheduler { - - private final PlannerService plannerService; - private final ContextRunner contextRunner; - - GeneralPlannerScheduler(PlannerService plannerService, ContextRunner contextRunner) { - this.plannerService = plannerService; - this.contextRunner = contextRunner; - } - - @Scheduled(cron = "${deals.planner.update-period}") - public void fetchPlansFromGeneralPlanner() { - contextRunner.runOnServiceContext(future -> { - plannerService.updateLineItemMetaData(); - future.complete(); - }); - } - } - - private static class AdvancePlansScheduler { - private final LineItemService lineItemService; - private final ContextRunner contextRunner; - private final Clock clock; - - AdvancePlansScheduler(LineItemService lineItemService, ContextRunner contextRunner, Clock clock) { - this.lineItemService = lineItemService; - this.contextRunner = contextRunner; - this.clock = clock; - } - - @Scheduled(cron = "${deals.planner.plan-advance-period}") - public void advancePlans() { - contextRunner.runOnServiceContext(future -> { - lineItemService.advanceToNextPlan(ZonedDateTime.now(clock)); - future.complete(); - }); - } - } - - private static class ImmediateDeliveryScheduler { - - private final DeliveryProgressService deliveryProgressService; - private final DeliveryStatsService deliveryStatsService; - private final Clock clock; - private final ContextRunner contextRunner; - - ImmediateDeliveryScheduler(DeliveryProgressService deliveryProgressService, - DeliveryStatsService deliveryStatsService, - Clock clock, - ContextRunner contextRunner) { - this.deliveryProgressService = deliveryProgressService; - this.deliveryStatsService = deliveryStatsService; - this.clock = clock; - this.contextRunner = contextRunner; - } - - @Scheduled(cron = "${deals.delivery-stats.delivery-period}") - public void createAndSendDeliveryReport() { - contextRunner.runOnServiceContext(future -> { - final ZonedDateTime now = ZonedDateTime.now(clock); - deliveryProgressService.createDeliveryProgressReports(now); - deliveryStatsService.sendDeliveryProgressReports(now); - future.complete(); - }); - } - } - } - - private static class DeliveryScheduler { - - private final DeliveryProgressService deliveryProgressService; - private final DeliveryStatsService deliveryStatsService; - private final Clock clock; - private final ContextRunner contextRunner; - - DeliveryScheduler(DeliveryProgressService deliveryProgressService, - DeliveryStatsService deliveryStatsService, - Clock clock, - ContextRunner contextRunner) { - this.deliveryProgressService = deliveryProgressService; - this.deliveryStatsService = deliveryStatsService; - this.clock = clock; - this.contextRunner = contextRunner; - } - - @Scheduled(cron = "${deals.delivery-progress.report-reset-period}") - public void createDeliveryReport() { - contextRunner.runOnServiceContext(future -> { - deliveryProgressService.createDeliveryProgressReports(ZonedDateTime.now(clock)); - future.complete(); - }); - } - - @Scheduled(cron = "${deals.delivery-stats.delivery-period}") - public void sendDeliveryReport() { - contextRunner.runOnServiceContext(future -> { - deliveryStatsService.sendDeliveryProgressReports(ZonedDateTime.now(clock)); - future.complete(); - }); - } - } - - @Configuration - @ConditionalOnExpression("${deals.enabled} == true and ${deals.simulation.enabled} == true") - public static class SimulationConfiguration { - - @Bean - @ConditionalOnProperty(prefix = "deals", name = "call-real-bidders-in-simulation", havingValue = "false", - matchIfMissing = true) - SimulationAwareHttpBidderRequester simulationAwareHttpBidderRequester( - HttpClient httpClient, - BidderRequestCompletionTrackerFactory completionTrackerFactory, - BidderErrorNotifier bidderErrorNotifier, - HttpBidderRequestEnricher requestEnricher, - LineItemService lineItemService, - JacksonMapper mapper) { - - return new SimulationAwareHttpBidderRequester( - httpClient, completionTrackerFactory, bidderErrorNotifier, requestEnricher, lineItemService, - mapper); - } - - @Bean - SimulationAwarePlannerService plannerService( - PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - DeliveryProgressService deliveryProgressService, - SimulationAwareLineItemService lineItemService, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - JacksonMapper mapper) { - - return new SimulationAwarePlannerService( - plannerProperties.toComponentProperties(), - deploymentProperties.toComponentProperties(), - lineItemService, - deliveryProgressService, - alertHttpService, - httpClient, - metrics, - clock, - mapper); - } - - @Bean - SimulationAwareRegisterService registerService( - PlannerProperties plannerProperties, - DeploymentProperties deploymentProperties, - AdminEventService adminEventService, - DeliveryProgressService deliveryProgressService, - AlertHttpService alertHttpService, - HealthMonitor healthMonitor, - CurrencyConversionService currencyConversionService, - HttpClient httpClient, - Vertx vertx, - JacksonMapper mapper) { - - return new SimulationAwareRegisterService( - plannerProperties.toComponentProperties(), - deploymentProperties.toComponentProperties(), - adminEventService, - deliveryProgressService, - alertHttpService, - healthMonitor, - currencyConversionService, - httpClient, - vertx, - mapper); - } - - @Bean - SimulationAwareDeliveryStatsService deliveryStatsService( - DeliveryStatsProperties deliveryStatsProperties, - DeliveryProgressReportFactory deliveryProgressReportFactory, - AlertHttpService alertHttpService, - HttpClient httpClient, - Metrics metrics, - Clock clock, - Vertx vertx, - JacksonMapper mapper) { - - return new SimulationAwareDeliveryStatsService( - deliveryStatsProperties.toComponentProperties(), - deliveryProgressReportFactory, - alertHttpService, - httpClient, - metrics, - clock, - vertx, - mapper); - } - - @Bean - SimulationAwareLineItemService lineItemService( - @Value("${deals.max-deals-per-bidder}") int maxDealsPerBidder, - TargetingService targetingService, - CurrencyConversionService conversionService, - ApplicationEventService applicationEventService, - @Value("${auction.ad-server-currency}") String adServerCurrency, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - return new SimulationAwareLineItemService( - maxDealsPerBidder, - targetingService, - conversionService, - applicationEventService, - adServerCurrency, - clock, - criteriaLogManager); - } - - @Bean - SimulationAwareDeliveryProgressService deliveryProgressService( - DeliveryProgressProperties deliveryProgressProperties, - LineItemService lineItemService, - DeliveryStatsService deliveryStatsService, - DeliveryProgressReportFactory deliveryProgressReportFactory, - @Value("${deals.simulation.ready-at-adjustment-ms}") long readyAtAdjustment, - Clock clock, - CriteriaLogManager criteriaLogManager) { - - return new SimulationAwareDeliveryProgressService( - deliveryProgressProperties.toComponentProperties(), - lineItemService, - deliveryStatsService, - deliveryProgressReportFactory, - readyAtAdjustment, - clock, - criteriaLogManager); - } - - @Bean - SimulationAwareUserService userService( - UserDetailsProperties userDetailsProperties, - SimulationProperties simulationProperties, - @Value("${datacenter-region}") String dataCenterRegion, - LineItemService lineItemService, - HttpClient httpClient, - Clock clock, - Metrics metrics, - JacksonMapper mapper) { - - return new SimulationAwareUserService( - userDetailsProperties.toComponentProperties(), - simulationProperties.toComponentProperties(), - dataCenterRegion, - lineItemService, - httpClient, - clock, - metrics, - mapper); - } - - @Bean - DealsSimulationAdminHandler dealsSimulationAdminHandler( - SimulationAwareRegisterService registerService, - SimulationAwarePlannerService plannerService, - SimulationAwareDeliveryProgressService deliveryProgressService, - SimulationAwareDeliveryStatsService deliveryStatsService, - @Autowired(required = false) SimulationAwareHttpBidderRequester httpBidderRequester, - JacksonMapper mapper, - @Value("${admin-endpoints.e2eadmin.path}") String path) { - - return new DealsSimulationAdminHandler( - registerService, - plannerService, - deliveryProgressService, - deliveryStatsService, - httpBidderRequester, - mapper, - path); - } - - @Bean - BeanPostProcessor simulationCustomizationBeanPostProcessor( - @Autowired(required = false) SimulationAwareHttpBidderRequester httpBidderRequester) { - - return new BeanPostProcessor() { - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - // there are HttpBidderRequester and SimulationAwareHttpBidderRequester in context by now, we would - // like to replace former with latter everywhere - if (httpBidderRequester != null && bean.getClass().isAssignableFrom(HttpBidderRequester.class) - && !(bean instanceof SimulationAwareHttpBidderRequester)) { - return httpBidderRequester; - } - - return bean; - } - }; - } - } - - @Configuration - @ConditionalOnExpression("${deals.enabled} == true") - public static class DealsMainConfiguration { - - @Bean - @ConfigurationProperties - DeploymentProperties deploymentProperties() { - return new DeploymentProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.planner") - PlannerProperties plannerProperties() { - return new PlannerProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.delivery-stats") - DeliveryStatsProperties deliveryStatsProperties() { - return new DeliveryStatsProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.delivery-progress") - DeliveryProgressProperties deliveryProgressProperties() { - return new DeliveryProgressProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.user-data") - UserDetailsProperties userDetailsProperties() { - return new UserDetailsProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.alert-proxy") - AlertProxyProperties alertProxyProperties() { - return new AlertProxyProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "deals.simulation") - SimulationProperties simulationProperties() { - return new SimulationProperties(); - } - - @Bean - BidderRequestCompletionTrackerFactory bidderRequestCompletionTrackerFactory() { - return new DealsBidderRequestCompletionTrackerFactory(); - } - - @Bean - UserAdditionalInfoService userAdditionalInfoService( - LineItemService lineItemService, - @Autowired(required = false) DeviceInfoService deviceInfoService, - @Autowired(required = false) GeoLocationService geoLocationService, - UserService userService, - Clock clock, - JacksonMapper mapper, - CriteriaLogManager criteriaLogManager) { - - return new UserAdditionalInfoService( - lineItemService, - deviceInfoService, - geoLocationService, - userService, - clock, - mapper, - criteriaLogManager); - } - - @Bean - DealsService dealsService(LineItemService lineItemService, - JacksonMapper mapper, - CriteriaLogManager criteriaLogManager) { - - return new DealsService(lineItemService, mapper, criteriaLogManager); - } - - @Bean - DeliveryProgressReportFactory deliveryProgressReportFactory( - DeploymentProperties deploymentProperties, - @Value("${deals.delivery-progress-report.competitors-number}") int competitorsNumber, - LineItemService lineItemService) { - - return new DeliveryProgressReportFactory( - deploymentProperties.toComponentProperties(), competitorsNumber, lineItemService); - } - - @Bean - AlertHttpService alertHttpService(JacksonMapper mapper, - HttpClient httpClient, - Clock clock, - DeploymentProperties deploymentProperties, - AlertProxyProperties alertProxyProperties) { - - return new AlertHttpService( - mapper, - httpClient, - clock, - deploymentProperties.toComponentProperties(), - alertProxyProperties.toComponentProperties()); - } - - @Bean - TargetingService targetingService(JacksonMapper mapper) { - return new TargetingService(mapper); - } - - @Bean - AdminCentralService adminCentralService( - CriteriaManager criteriaManager, - LineItemService lineItemService, - DeliveryProgressService deliveryProgressService, - @Autowired(required = false) @Qualifier("settingsCache") SettingsCache settingsCache, - @Autowired(required = false) @Qualifier("ampSettingsCache") SettingsCache ampSettingsCache, - @Autowired(required = false) CachingApplicationSettings cachingApplicationSettings, - JacksonMapper mapper, - List suspendables) { - - return new AdminCentralService( - criteriaManager, - lineItemService, - deliveryProgressService, - settingsCache, - ampSettingsCache, - cachingApplicationSettings, - mapper, - suspendables); - } - - @Bean - ApplicationEventService applicationEventService(EventBus eventBus) { - return new ApplicationEventService(eventBus); - } - - @Bean - AdminEventService adminEventService(EventBus eventBus) { - return new AdminEventService(eventBus); - } - - @Bean - EventServiceInitializer eventServiceInitializer(List applicationEventProcessors, - List adminEventProcessors, - EventBus eventBus) { - - return new EventServiceInitializer(applicationEventProcessors, adminEventProcessors, eventBus); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class DeploymentProperties { - - @NotBlank - private String hostId; - - @NotBlank - private String datacenterRegion; - - @NotBlank - private String vendor; - - @NotBlank - private String profile; - - @NotBlank - private String infra; - - @NotBlank - private String dataCenter; - - @NotBlank - private String system; - - @NotBlank - private String subSystem; - - public org.prebid.server.deals.model.DeploymentProperties toComponentProperties() { - return org.prebid.server.deals.model.DeploymentProperties.builder() - .pbsHostId(getHostId()).pbsRegion(getDatacenterRegion()).pbsVendor(getVendor()) - .profile(getProfile()).infra(getInfra()).dataCenter(getDataCenter()).system(getSystem()) - .subSystem(getSubSystem()).build(); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class PlannerProperties { - - @NotBlank - private String planEndpoint; - @NotBlank - private String registerEndpoint; - @NotNull - private Long timeoutMs; - @NotNull - private Long registerPeriodSec; - @NotBlank - private String username; - @NotBlank - private String password; - - public org.prebid.server.deals.model.PlannerProperties toComponentProperties() { - return org.prebid.server.deals.model.PlannerProperties.builder() - .planEndpoint(getPlanEndpoint()) - .registerEndpoint(getRegisterEndpoint()) - .timeoutMs(getTimeoutMs()) - .registerPeriodSeconds(getRegisterPeriodSec()) - .username(getUsername()) - .password(getPassword()) - .build(); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class DeliveryStatsProperties { - - @NotBlank - private String endpoint; - @NotNull - private Integer cachedReportsNumber; - @NotNull - private Long timeoutMs; - @NotNull - private Integer lineItemsPerReport; - @NotNull - private Integer reportsIntervalMs; - @NotNull - private Integer batchesIntervalMs; - @NotNull - private Boolean requestCompressionEnabled; - @NotBlank - private String username; - @NotBlank - private String password; - - public org.prebid.server.deals.model.DeliveryStatsProperties toComponentProperties() { - return org.prebid.server.deals.model.DeliveryStatsProperties.builder() - .endpoint(getEndpoint()) - .cachedReportsNumber(getCachedReportsNumber()) - .timeoutMs(getTimeoutMs()) - .lineItemsPerReport(getLineItemsPerReport()) - .reportsIntervalMs(getReportsIntervalMs()) - .batchesIntervalMs(getBatchesIntervalMs()) - .requestCompressionEnabled(getRequestCompressionEnabled()) - .username(getUsername()) - .password(getPassword()) - .build(); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class DeliveryProgressProperties { - - @NotNull - private Long lineItemStatusTtlSec; - @NotNull - private Integer cachedPlansNumber; - - public org.prebid.server.deals.model.DeliveryProgressProperties toComponentProperties() { - return org.prebid.server.deals.model.DeliveryProgressProperties.of(getLineItemStatusTtlSec(), - getCachedPlansNumber()); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class UserDetailsProperties { - - @NotBlank - private String userDetailsEndpoint; - @NotBlank - private String winEventEndpoint; - @NotNull - private Long timeout; - @NotNull - private List userIds; - - public org.prebid.server.deals.model.UserDetailsProperties toComponentProperties() { - final List componentUserIds = getUserIds().stream() - .map(DealsConfiguration.UserIdRule::toComponentProperties) - .toList(); - - return org.prebid.server.deals.model.UserDetailsProperties.of( - getUserDetailsEndpoint(), getWinEventEndpoint(), getTimeout(), componentUserIds); - } - } - - @Validated - @Data - @NoArgsConstructor - private static class AlertProxyProperties { - - @NotNull - private boolean enabled; - - @NotBlank - private String url; - - @NotNull - private Integer timeoutSec; - - Map alertTypes; - - @NotBlank - private String username; - - @NotBlank - private String password; - - public org.prebid.server.deals.model.AlertProxyProperties toComponentProperties() { - return org.prebid.server.deals.model.AlertProxyProperties.builder() - .enabled(isEnabled()).url(getUrl()).timeoutSec(getTimeoutSec()) - .alertTypes(ObjectUtils.defaultIfNull(getAlertTypes(), new HashMap<>())) - .username(getUsername()) - .password(getPassword()).build(); - } - } - - @Validated - @NoArgsConstructor - @Data - private static class UserIdRule { - - @NotBlank - private String type; - - @NotBlank - private String source; - - @NotBlank - private String location; - - org.prebid.server.deals.model.UserIdRule toComponentProperties() { - return org.prebid.server.deals.model.UserIdRule.of(getType(), getSource(), getLocation()); - } - } - - @Validated - @NoArgsConstructor - @Data - private static class SimulationProperties { - - @NotNull - boolean enabled; - - Boolean winEventsEnabled; - - Boolean userDetailsEnabled; - - org.prebid.server.deals.model.SimulationProperties toComponentProperties() { - return org.prebid.server.deals.model.SimulationProperties.builder() - .enabled(isEnabled()) - .winEventsEnabled(getWinEventsEnabled() != null ? getWinEventsEnabled() : false) - .userDetailsEnabled(getUserDetailsEnabled() != null ? getUserDetailsEnabled() : false) - .build(); - } - } -} diff --git a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java index c5bbb261f03..19d10b342a0 100644 --- a/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/ServiceConfiguration.java @@ -70,9 +70,6 @@ import org.prebid.server.cookie.PrioritizedCoopSyncProvider; import org.prebid.server.cookie.UidsCookieService; import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.DealsService; -import org.prebid.server.deals.UserAdditionalInfoService; -import org.prebid.server.deals.events.ApplicationEventService; import org.prebid.server.events.EventsService; import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.floors.PriceFloorAdjuster; @@ -363,11 +360,9 @@ Ortb2RequestFactory openRtb2RequestFactory( ApplicationSettings applicationSettings, IpAddressHelper ipAddressHelper, HookStageExecutor hookStageExecutor, - @Autowired(required = false) UserAdditionalInfoService userAdditionalInfoService, CountryCodeMapper countryCodeMapper, PriceFloorProcessor priceFloorProcessor, - Metrics metrics, - Clock clock) { + Metrics metrics) { final List blacklistedAccounts = splitToList(blacklistedAccountsString); @@ -385,11 +380,9 @@ Ortb2RequestFactory openRtb2RequestFactory( applicationSettings, ipAddressHelper, hookStageExecutor, - userAdditionalInfoService, priceFloorProcessor, countryCodeMapper, - metrics, - clock); + metrics); } @Bean @@ -801,7 +794,6 @@ ExchangeService exchangeService( @Value("${logging.sampling-rate:0.01}") double logSamplingRate, BidderCatalog bidderCatalog, StoredResponseProcessor storedResponseProcessor, - @Autowired(required = false) DealsService dealsService, PrivacyEnforcementService privacyEnforcementService, FpdResolver fpdResolver, SupplyChainResolver supplyChainResolver, @@ -817,7 +809,6 @@ ExchangeService exchangeService( BidResponseCreator bidResponseCreator, BidResponsePostProcessor bidResponsePostProcessor, HookStageExecutor hookStageExecutor, - @Autowired(required = false) ApplicationEventService applicationEventService, HttpInteractionLogger httpInteractionLogger, PriceFloorAdjuster priceFloorAdjuster, PriceFloorEnforcer priceFloorEnforcer, @@ -833,7 +824,6 @@ ExchangeService exchangeService( logSamplingRate, bidderCatalog, storedResponseProcessor, - dealsService, privacyEnforcementService, fpdResolver, supplyChainResolver, @@ -849,7 +839,6 @@ ExchangeService exchangeService( bidResponseCreator, bidResponsePostProcessor, hookStageExecutor, - applicationEventService, httpInteractionLogger, priceFloorAdjuster, priceFloorEnforcer, @@ -977,16 +966,12 @@ BidderParamValidator bidderParamValidator(BidderCatalog bidderCatalog, JacksonMa ResponseBidValidator responseValidator( @Value("${auction.validations.banner-creative-max-size}") BidValidationEnforcement bannerMaxSizeEnforcement, @Value("${auction.validations.secure-markup}") BidValidationEnforcement secureMarkupEnforcement, - Metrics metrics, - JacksonMapper mapper, - @Value("${deals.enabled}") boolean dealsEnabled) { + Metrics metrics) { return new ResponseBidValidator( bannerMaxSizeEnforcement, secureMarkupEnforcement, metrics, - mapper, - dealsEnabled, logSamplingRate); } diff --git a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java b/src/main/java/org/prebid/server/spring/config/WebConfiguration.java index bcd8394d04e..4e958b3b7ce 100644 --- a/src/main/java/org/prebid/server/spring/config/WebConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/WebConfiguration.java @@ -26,8 +26,6 @@ import org.prebid.server.cookie.CookieDeprecationService; import org.prebid.server.cookie.CookieSyncService; import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.deals.UserService; -import org.prebid.server.deals.events.ApplicationEventService; import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.handler.BidderParamHandler; import org.prebid.server.handler.CookieSyncHandler; @@ -82,7 +80,8 @@ public class WebConfiguration { @Autowired private Vertx vertx; - @Bean // TODO: remove support for properties with http prefix after transition period + // TODO: remove support for properties with http prefix after transition period + @Bean HttpServerOptions httpServerOptions( @Value("#{'${http.max-headers-size:${server.max-headers-size:}}'}") int maxHeaderSize, @Value("#{'${http.max-initial-line-length:${server.max-initial-line-length:}}'}") int maxInitialLineLength, @@ -401,27 +400,18 @@ BidderDetailsHandler bidderDetailsHandler(BidderCatalog bidderCatalog, JacksonMa } @Bean - NotificationEventHandler notificationEventHandler( - UidsCookieService uidsCookieService, - @Autowired(required = false) ApplicationEventService applicationEventService, - @Autowired(required = false) UserService userService, - ActivityInfrastructureCreator activityInfrastructureCreator, - AnalyticsReporterDelegator analyticsReporterDelegator, - TimeoutFactory timeoutFactory, - ApplicationSettings applicationSettings, - @Value("${event.default-timeout-ms}") long defaultTimeoutMillis, - @Value("${deals.enabled}") boolean dealsEnabled) { + NotificationEventHandler notificationEventHandler(ActivityInfrastructureCreator activityInfrastructureCreator, + AnalyticsReporterDelegator analyticsReporterDelegator, + TimeoutFactory timeoutFactory, + ApplicationSettings applicationSettings, + @Value("${event.default-timeout-ms}") long defaultTimeoutMillis) { return new NotificationEventHandler( - uidsCookieService, - applicationEventService, - userService, activityInfrastructureCreator, analyticsReporterDelegator, timeoutFactory, applicationSettings, - defaultTimeoutMillis, - dealsEnabled); + defaultTimeoutMillis); } @Bean diff --git a/src/main/java/org/prebid/server/util/HttpUtil.java b/src/main/java/org/prebid/server/util/HttpUtil.java index 767d326b0a7..b848f1a4d41 100644 --- a/src/main/java/org/prebid/server/util/HttpUtil.java +++ b/src/main/java/org/prebid/server/util/HttpUtil.java @@ -10,9 +10,7 @@ import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.RoutingContext; import org.apache.commons.lang3.StringUtils; -import org.prebid.server.exception.PreBidException; import org.prebid.server.log.ConditionalLogger; -import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.model.Endpoint; import org.prebid.server.model.HttpRequestContext; @@ -21,15 +19,12 @@ import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.time.ZonedDateTime; import java.util.Arrays; -import java.util.Base64; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -47,7 +42,6 @@ public final class HttpUtil { public static final CharSequence X_FORWARDED_FOR_HEADER = HttpHeaders.createOptimized("X-Forwarded-For"); public static final CharSequence X_REAL_IP_HEADER = HttpHeaders.createOptimized("X-Real-Ip"); public static final CharSequence DNT_HEADER = HttpHeaders.createOptimized("DNT"); - public static final CharSequence X_REQUEST_AGENT_HEADER = HttpHeaders.createOptimized("X-Request-Agent"); public static final CharSequence ORIGIN_HEADER = HttpHeaders.createOptimized("Origin"); public static final CharSequence ACCEPT_HEADER = HttpHeaders.createOptimized("Accept"); public static final CharSequence SEC_GPC_HEADER = HttpHeaders.createOptimized("Sec-GPC"); @@ -65,19 +59,15 @@ public final class HttpUtil { public static final CharSequence ACCEPT_LANGUAGE_HEADER = HttpHeaders.createOptimized("Accept-Language"); public static final CharSequence SET_COOKIE_HEADER = HttpHeaders.createOptimized("Set-Cookie"); public static final CharSequence AUTHORIZATION_HEADER = HttpHeaders.createOptimized("Authorization"); - public static final CharSequence DATE_HEADER = HttpHeaders.createOptimized("Date"); public static final CharSequence CACHE_CONTROL_HEADER = HttpHeaders.createOptimized("Cache-Control"); public static final CharSequence EXPIRES_HEADER = HttpHeaders.createOptimized("Expires"); public static final CharSequence PRAGMA_HEADER = HttpHeaders.createOptimized("Pragma"); public static final CharSequence LOCATION_HEADER = HttpHeaders.createOptimized("Location"); public static final CharSequence CONNECTION_HEADER = HttpHeaders.createOptimized("Connection"); - public static final CharSequence ACCEPT_ENCODING_HEADER = HttpHeaders.createOptimized("Accept-Encoding"); public static final CharSequence CONTENT_ENCODING_HEADER = HttpHeaders.createOptimized("Content-Encoding"); public static final CharSequence X_OPENRTB_VERSION_HEADER = HttpHeaders.createOptimized("x-openrtb-version"); public static final CharSequence X_PREBID_HEADER = HttpHeaders.createOptimized("x-prebid"); private static final Set SENSITIVE_HEADERS = Set.of(AUTHORIZATION_HEADER.toString()); - public static final CharSequence PG_TRX_ID = HttpHeaders.createOptimized("pg-trx-id"); - public static final CharSequence PG_IGNORE_PACING = HttpHeaders.createOptimized("X-Prebid-PG-ignore-pacing"); //the low-entropy client hints public static final CharSequence SAVE_DATA = HttpHeaders.createOptimized("Save-Data"); @@ -85,8 +75,6 @@ public final class HttpUtil { public static final CharSequence SEC_CH_UA_MOBILE = HttpHeaders.createOptimized("Sec-CH-UA-Mobile"); public static final CharSequence SEC_CH_UA_PLATFORM = HttpHeaders.createOptimized("Sec-CH-UA-Platform"); - private static final String BASIC_AUTH_PATTERN = "Basic %s"; - private HttpUtil() { } @@ -138,28 +126,6 @@ public static void addHeaderIfValueIsNotEmpty(MultiMap headers, CharSequence hea } } - public static ZonedDateTime getDateFromHeader(MultiMap headers, String header) { - return getDateFromHeader(headers::get, header); - } - - public static ZonedDateTime getDateFromHeader(CaseInsensitiveMultiMap headers, String header) { - return getDateFromHeader(headers::get, header); - } - - private static ZonedDateTime getDateFromHeader(Function headerGetter, String header) { - final String isoTimeStamp = headerGetter.apply(header); - if (isoTimeStamp == null) { - return null; - } - - try { - return ZonedDateTime.parse(isoTimeStamp); - } catch (Exception e) { - throw new PreBidException( - "%s header is not compatible to ISO-8601 format: %s".formatted(header, isoTimeStamp)); - } - } - public static String getHostFromUrl(String url) { if (StringUtils.isBlank(url)) { return null; @@ -196,20 +162,22 @@ public static String createCookiesHeader(RoutingContext routingContext) { .collect(Collectors.joining("; ")); } - public static boolean executeSafely(RoutingContext routingContext, Endpoint endpoint, + public static boolean executeSafely(RoutingContext routingContext, + Endpoint endpoint, Consumer responseConsumer) { + return executeSafely(routingContext, endpoint.value(), responseConsumer); } - public static boolean executeSafely(RoutingContext routingContext, String endpoint, + public static boolean executeSafely(RoutingContext routingContext, + String endpoint, Consumer responseConsumer) { final HttpServerResponse response = routingContext.response(); if (response.closed()) { - conditionalLogger.warn( - "Client already closed connection, response to %s will be skipped".formatted(endpoint), - 0.01); + conditionalLogger + .warn("Client already closed connection, response to %s will be skipped".formatted(endpoint), 0.01); return false; } @@ -222,14 +190,6 @@ public static boolean executeSafely(RoutingContext routingContext, String endpoi } } - /** - * Creates standart basic auth header value - */ - public static String makeBasicAuthHeaderValue(String username, String password) { - return BASIC_AUTH_PATTERN - .formatted(Base64.getEncoder().encodeToString((username + ':' + password).getBytes())); - } - /** * Converts {@link MultiMap} headers format to Map, where keys are headers names and values are lists * of header's values diff --git a/src/main/java/org/prebid/server/util/LineItemUtil.java b/src/main/java/org/prebid/server/util/LineItemUtil.java deleted file mode 100644 index 37d89040e3c..00000000000 --- a/src/main/java/org/prebid/server/util/LineItemUtil.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.prebid.server.util; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; -import com.iab.openrtb.response.Bid; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.prebid.server.json.JacksonMapper; -import org.prebid.server.proto.openrtb.ext.request.ExtDeal; -import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; - -import java.util.List; -import java.util.Objects; - -public class LineItemUtil { - - private static final Logger logger = LoggerFactory.getLogger(LineItemUtil.class); - - private LineItemUtil() { - } - - /** - * Extracts line item ID from the given {@link Bid}. - */ - public static String lineItemIdFrom(Bid bid, List imps, JacksonMapper mapper) { - if (StringUtils.isEmpty(bid.getDealid())) { - return null; - } - final ExtDealLine extDealLine = extDealLineFrom(bid, imps, mapper); - return extDealLine != null ? extDealLine.getLineItemId() : null; - } - - private static ExtDealLine extDealLineFrom(Bid bid, List imps, JacksonMapper mapper) { - final Imp correspondingImp = imps.stream() - .filter(imp -> Objects.equals(imp.getId(), bid.getImpid())) - .findFirst() - .orElse(null); - return correspondingImp != null ? extDealLineFrom(bid, correspondingImp, mapper) : null; - } - - public static ExtDealLine extDealLineFrom(Bid bid, Imp imp, JacksonMapper mapper) { - if (StringUtils.isEmpty(bid.getDealid())) { - return null; - } - - final Pmp pmp = imp.getPmp(); - final List deals = pmp != null ? pmp.getDeals() : null; - return CollectionUtils.isEmpty(deals) - ? null - : deals.stream() - .filter(Objects::nonNull) - .filter(deal -> Objects.equals(deal.getId(), bid.getDealid())) // find deal by ID - .map(Deal::getExt) - .filter(Objects::nonNull) - .map((ObjectNode ext) -> dealExt(ext, mapper)) - .filter(Objects::nonNull) - .map(ExtDeal::getLine) - .findFirst() - .orElse(null); - } - - private static ExtDeal dealExt(JsonNode ext, JacksonMapper mapper) { - try { - return mapper.mapper().treeToValue(ext, ExtDeal.class); - } catch (JsonProcessingException e) { - logger.warn("Error decoding deal.ext: {0}", e, e.getMessage()); - return null; - } - } -} diff --git a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java index 353f4389a14..e3e405cb710 100644 --- a/src/main/java/org/prebid/server/validation/ResponseBidValidator.java +++ b/src/main/java/org/prebid/server/validation/ResponseBidValidator.java @@ -1,30 +1,22 @@ package org.prebid.server.validation; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; import com.iab.openrtb.request.Site; import com.iab.openrtb.response.Bid; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.prebid.server.auction.BidderAliases; import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.bidder.model.BidderBid; -import org.prebid.server.json.JacksonMapper; import org.prebid.server.log.ConditionalLogger; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; -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.response.BidType; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; @@ -33,15 +25,11 @@ import org.prebid.server.validation.model.ValidationResult; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Currency; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.stream.Stream; /** * Validator for response {@link Bid} object. @@ -58,31 +46,21 @@ public class ResponseBidValidator { private static final String[] INSECURE_MARKUP_MARKERS = {"http:", "http%3A"}; private static final String[] SECURE_MARKUP_MARKERS = {"https:", "https%3A"}; - private static final String PREBID_EXT = "prebid"; - private static final String BIDDER_EXT = "bidder"; - private static final String DEALS_ONLY = "dealsonly"; - private final BidValidationEnforcement bannerMaxSizeEnforcement; private final BidValidationEnforcement secureMarkupEnforcement; private final Metrics metrics; - private final JacksonMapper mapper; - private final boolean dealsEnabled; private final double logSamplingRate; public ResponseBidValidator(BidValidationEnforcement bannerMaxSizeEnforcement, BidValidationEnforcement secureMarkupEnforcement, Metrics metrics, - JacksonMapper mapper, - boolean dealsEnabled, double logSamplingRate) { this.bannerMaxSizeEnforcement = Objects.requireNonNull(bannerMaxSizeEnforcement); this.secureMarkupEnforcement = Objects.requireNonNull(secureMarkupEnforcement); this.metrics = Objects.requireNonNull(metrics); - this.mapper = Objects.requireNonNull(mapper); - this.dealsEnabled = dealsEnabled; this.logSamplingRate = logSamplingRate; } @@ -106,10 +84,6 @@ public ValidationResult validate(BidderBid bidderBid, warnings.addAll(validateBannerFields(bid, bidder, bidRequest, account, correspondingImp, aliases)); } - if (dealsEnabled) { - validateDealsFor(bidderBid, bidRequest, bidder, aliases, warnings); - } - warnings.addAll(validateSecureMarkup(bid, bidder, bidRequest, account, correspondingImp, aliases)); } catch (ValidationException e) { return ValidationResult.error(warnings, e.getMessage()); @@ -280,9 +254,9 @@ private static boolean markupIsNotSecure(String adm) { } private List singleWarningOrValidationException(BidValidationEnforcement enforcement, - Consumer metricsRecorder, - ConditionalLogger conditionalLogger, - String message) throws ValidationException { + Consumer metricsRecorder, + ConditionalLogger conditionalLogger, + String message) throws ValidationException { return switch (enforcement) { case enforce -> { metricsRecorder.accept(MetricName.err); @@ -302,165 +276,4 @@ private static String getReferer(BidRequest bidRequest) { final Site site = bidRequest.getSite(); return site != null ? site.getPage() : "unknown"; } - - private void validateDealsFor(BidderBid bidderBid, - BidRequest bidRequest, - String bidder, - BidderAliases aliases, - List warnings) throws ValidationException { - - final Bid bid = bidderBid.getBid(); - final String bidId = bid.getId(); - - final Imp imp = bidRequest.getImp().stream() - .filter(curImp -> Objects.equals(curImp.getId(), bid.getImpid())) - .findFirst() - .orElseThrow(() -> new ValidationException("Bid \"%s\" has no corresponding imp in request", bidId)); - - final String dealId = bid.getDealid(); - - if (isDealsOnlyImp(imp, bidder) && dealId == null) { - throw new ValidationException("Bid \"%s\" missing required field 'dealid'", bidId); - } - - if (dealId != null) { - final Set dealIdsFromImp = getDealIdsFromImp(imp, bidder, aliases); - if (CollectionUtils.isNotEmpty(dealIdsFromImp) && !dealIdsFromImp.contains(dealId)) { - warnings.add(""" - WARNING: Bid "%s" has 'dealid' not present in corresponding imp in request. \ - 'dealid' in bid: '%s', deal Ids in imp: '%s'""" - .formatted(bidId, dealId, String.join(",", dealIdsFromImp))); - } - if (bidderBid.getType() == BidType.banner) { - if (imp.getBanner() == null) { - throw new ValidationException(""" - Bid "%s" has banner media type but corresponding imp \ - in request is missing 'banner' object""", - bidId); - } - - final List bannerFormats = getBannerFormats(imp); - if (bidSizeNotInFormats(bid, bannerFormats)) { - throw new ValidationException(""" - Bid "%s" has 'w' and 'h' not supported by corresponding imp in \ - request. Bid dimensions: '%dx%d', formats in imp: '%s'""", - bidId, - bid.getW(), - bid.getH(), - formatSizes(bannerFormats)); - } - - if (isPgDeal(imp, dealId)) { - validateIsInLineItemSizes(bid, bidId, dealId, imp); - } - } - } - } - - private void validateIsInLineItemSizes(Bid bid, String bidId, String dealId, Imp imp) throws ValidationException { - final List lineItemSizes = getLineItemSizes(imp, dealId); - if (lineItemSizes.isEmpty()) { - throw new ValidationException( - "Line item sizes were not found for bidId %s and dealId %s", bid.getId(), dealId); - } - - if (bidSizeNotInFormats(bid, lineItemSizes)) { - throw new ValidationException( - """ - Bid "%s" has 'w' and 'h' not matched to Line Item. \ - Bid dimensions: '%dx%d', Line Item sizes: '%s'""", - bidId, bid.getW(), bid.getH(), formatSizes(lineItemSizes)); - } - } - - private static boolean isDealsOnlyImp(Imp imp, String bidder) { - final JsonNode dealsOnlyNode = bidderParamsFromImp(imp).path(bidder).path(DEALS_ONLY); - return dealsOnlyNode.isBoolean() && dealsOnlyNode.asBoolean(); - } - - private static JsonNode bidderParamsFromImp(Imp imp) { - return imp.getExt().path(PREBID_EXT).path(BIDDER_EXT); - } - - private Set getDealIdsFromImp(Imp imp, String bidder, BidderAliases aliases) { - return getDeals(imp) - .filter(Objects::nonNull) - .filter(deal -> isBidderHasDeal(bidder, dealExt(deal.getExt()), aliases)) - .map(Deal::getId) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); - } - - private static Stream getDeals(Imp imp) { - final Pmp pmp = imp.getPmp(); - return pmp != null ? pmp.getDeals().stream() : Stream.empty(); - } - - private static boolean isBidderHasDeal(String bidder, ExtDeal extDeal, BidderAliases aliases) { - final ExtDealLine extDealLine = extDeal != null ? extDeal.getLine() : null; - final String dealLineBidder = extDealLine != null ? extDealLine.getBidder() : null; - return dealLineBidder == null || aliases.isSame(bidder, dealLineBidder); - } - - private static boolean bidSizeNotInFormats(Bid bid, List formats) { - return formats.stream() - .noneMatch(format -> sizesEqual(bid, format)); - } - - private static boolean sizesEqual(Bid bid, Format format) { - return Objects.equals(format.getH(), bid.getH()) && Objects.equals(format.getW(), bid.getW()); - } - - private static List getBannerFormats(Imp imp) { - return ListUtils.emptyIfNull(imp.getBanner().getFormat()); - } - - private List getLineItemSizes(Imp imp, String dealId) { - return getDeals(imp) - .filter(deal -> dealId.equals(deal.getId())) - .map(Deal::getExt) - .filter(Objects::nonNull) - .map(this::dealExt) - .filter(Objects::nonNull) - .map(ExtDeal::getLine) - .filter(Objects::nonNull) - .map(ExtDealLine::getSizes) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(Objects::nonNull) - .toList(); - } - - private boolean isPgDeal(Imp imp, String dealId) { - return getDeals(imp) - .filter(Objects::nonNull) - .filter(deal -> Objects.equals(deal.getId(), dealId)) - .map(Deal::getExt) - .filter(Objects::nonNull) - .map(this::dealExt) - .filter(Objects::nonNull) - .map(ExtDeal::getLine) - .filter(Objects::nonNull) - .map(ExtDealLine::getLineItemId) - .anyMatch(Objects::nonNull); - } - - private ExtDeal dealExt(JsonNode ext) { - try { - return mapper.mapper().treeToValue(ext, ExtDeal.class); - } catch (JsonProcessingException e) { - logger.warn("Error decoding deal.ext: {0}", e, e.getMessage()); - return null; - } - } - - private static String formatSizes(List lineItemSizes) { - return lineItemSizes.stream() - .map(ResponseBidValidator::formatSize) - .collect(Collectors.joining(",")); - } - - private static String formatSize(Format lineItemSize) { - return "%dx%d".formatted(lineItemSize.getW(), lineItemSize.getH()); - } } diff --git a/src/main/java/org/prebid/server/vast/VastModifier.java b/src/main/java/org/prebid/server/vast/VastModifier.java index ce80078bfc1..eb87ab342ca 100644 --- a/src/main/java/org/prebid/server/vast/VastModifier.java +++ b/src/main/java/org/prebid/server/vast/VastModifier.java @@ -51,7 +51,6 @@ public JsonNode modifyVastXml(Boolean isEventsEnabled, putObject.getBidid(), bidder, accountId, - null, eventsContext); try { return new TextNode(appendTrackingUrlToVastXml(value.asText(), vastUrlTracking, bidder)); @@ -69,8 +68,8 @@ public String createBidVastXml(String bidder, String eventBidId, String accountId, EventsContext eventsContext, - List debugWarnings, - String lineItemId) { + List debugWarnings) { + if (!bidderCatalog.isModifyingVastXmlAllowed(bidder)) { return bidAdm; } @@ -80,8 +79,7 @@ public String createBidVastXml(String bidder, return vastXml; } - final String vastUrl = eventsService.vastUrlTracking(eventBidId, bidder, - accountId, lineItemId, eventsContext); + final String vastUrl = eventsService.vastUrlTracking(eventBidId, bidder, accountId, eventsContext); try { return appendTrackingUrlToVastXml(vastXml, vastUrl, bidder); } catch (PreBidException e) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 14b64b0cb1e..af936e77b8a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -67,21 +67,6 @@ admin-endpoints: path: /pbs-admin/tracelog on-application-port: false protected: true - deals-status: - enabled: false - path: /pbs-admin/deals-status - on-application-port: false - protected: true - lineitem-status: - enabled: false - path: /pbs-admin/lineitem-status - on-application-port: false - protected: true - force-deals-update: - enabled: false - path: /pbs-admin/force-deals-update - on-application-port: false - protected: true e2eadmin: enabled: false path: /pbs-admin/e2eAdmin/* From c9a87304e5f2fc6b3a195c07ab40920c219eee2d Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Mon, 4 Mar 2024 14:04:48 +0200 Subject: [PATCH 3/9] Verticles: Make deployment synchronous (#2313) --- .../spring/config/VertxConfiguration.java | 4 +- .../ApplicationServerConfiguration.java | 8 +-- .../verticles/InitializableVerticle.java | 30 ++++++++++ .../vertx/verticles/VerticleDefinition.java | 11 +--- .../vertx/verticles/VerticleDeployer.java | 58 +++++++++++-------- .../verticles/server/ServerVerticle.java | 17 ++++-- 6 files changed, 83 insertions(+), 45 deletions(-) create mode 100644 src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java diff --git a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java index fceca5d923c..f12cfdfcabb 100644 --- a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java @@ -70,7 +70,7 @@ ContextRunner contextRunner(Vertx vertx, @Value("${vertx.init-timeout-ms}") long } @Bean - VerticleDeployer verticleDeployer(Vertx vertx) { - return new VerticleDeployer(vertx); + VerticleDeployer verticleDeployer(Vertx vertx, @Value("${vertx.init-timeout-ms}") long initTimeoutMs) { + return new VerticleDeployer(vertx, initTimeoutMs); } } diff --git a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java index 62c5ab69a07..456fe5d3b07 100644 --- a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java @@ -1,6 +1,5 @@ package org.prebid.server.spring.config.server.application; -import io.vertx.core.Verticle; import io.vertx.core.Vertx; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerOptions; @@ -59,6 +58,7 @@ import org.prebid.server.util.HttpUtil; import org.prebid.server.validation.BidderParamValidator; import org.prebid.server.version.PrebidVersionProvider; +import org.prebid.server.vertx.verticles.InitializableVerticle; import org.prebid.server.vertx.verticles.VerticleDefinition; import org.prebid.server.vertx.verticles.server.ServerVerticle; import org.prebid.server.vertx.verticles.server.application.ApplicationResource; @@ -95,7 +95,7 @@ public class ApplicationServerConfiguration { VerticleDefinition httpApplicationServerVerticleDefinition( @Value("#{'${http.port:${server.http.port}}'}") Integer port, @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") Integer instances, - BiFunction applicationVerticleFactory) { + BiFunction applicationVerticleFactory) { return VerticleDefinition.ofMultiInstance( () -> applicationVerticleFactory.apply( @@ -108,7 +108,7 @@ VerticleDefinition httpApplicationServerVerticleDefinition( VerticleDefinition unixSocketApplicationServerVerticleDefinition( @Value("${server.unix-socket.path}") String path, @Value("${server.unix-socket.server-instances}") Integer instances, - BiFunction applicationVerticleFactory) { + BiFunction applicationVerticleFactory) { return VerticleDefinition.ofMultiInstance( () -> applicationVerticleFactory.apply( @@ -155,7 +155,7 @@ ExceptionHandler exceptionHandler(Metrics metrics) { } @Bean - BiFunction applicationVerticleFactory( + BiFunction applicationVerticleFactory( @Qualifier("applicationServerRouterFactory") Supplier routerFactory, HttpServerOptions httpServerOptions, ExceptionHandler exceptionHandler) { diff --git a/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java new file mode 100644 index 00000000000..f17d0328cea --- /dev/null +++ b/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java @@ -0,0 +1,30 @@ +package org.prebid.server.vertx.verticles; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Context; +import io.vertx.core.Future; +import io.vertx.core.Promise; +import io.vertx.core.Vertx; + +/** + * Base class for pbs Verticles, exists for making asynchronous verticles initialization synchronous, + * so that server bootstrap will crash if verticle can't init. Every child class should do initialization + * in {@link #initialize(Vertx, Context)} method + */ +public abstract class InitializableVerticle extends AbstractVerticle { + + private final Promise verticleInitialization = Promise.promise(); + + public Future getVerticleInitialization() { + return verticleInitialization.future(); + } + + public abstract Future initialize(Vertx vertx, Context context); + + @Override + public void init(Vertx vertx, Context context) { + initialize(vertx, context) + .onSuccess(verticleInitialization::tryComplete) + .onFailure(verticleInitialization::tryFail); + } +} diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java index f9b2703f318..7670e8ea77c 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java @@ -1,6 +1,5 @@ package org.prebid.server.vertx.verticles; -import io.vertx.core.Verticle; import lombok.Value; import java.util.function.Supplier; @@ -8,19 +7,15 @@ @Value(staticConstructor = "of") public class VerticleDefinition { - Supplier factory; + Supplier factory; int amount; - public static VerticleDefinition ofZeroInstances() { - return of(null, 0); - } - - public static VerticleDefinition ofSingleInstance(Supplier factory) { + public static VerticleDefinition ofSingleInstance(Supplier factory) { return of(factory, 1); } - public static VerticleDefinition ofMultiInstance(Supplier factory, int amount) { + public static VerticleDefinition ofMultiInstance(Supplier factory, int amount) { return of(factory, amount); } } diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java index 91beb6ef3a3..21559643257 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java @@ -1,21 +1,24 @@ package org.prebid.server.vertx.verticles; -import io.vertx.core.DeploymentOptions; +import io.vertx.core.CompositeFuture; +import io.vertx.core.Future; import io.vertx.core.Vertx; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import java.util.stream.IntStream; public class VerticleDeployer { - private static final int TIMEOUT_MILLIS = 5000; - + private final long timeoutMillis; private final Vertx vertx; - public VerticleDeployer(Vertx vertx) { + public VerticleDeployer(Vertx vertx, long timeoutMillis) { + this.timeoutMillis = timeoutMillis; this.vertx = Objects.requireNonNull(vertx); } @@ -26,38 +29,43 @@ public void deploy(VerticleDefinition definition) { } final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference failureThrowable = new AtomicReference<>(); - final AtomicBoolean failed = new AtomicBoolean(); - - final DeploymentOptions deploymentOptions = new DeploymentOptions(); - deploymentOptions.setInstances(amount); - - vertx.deployVerticle(definition.getFactory(), deploymentOptions, result -> { - if (result.failed()) { - failureThrowable.set(result.cause()); - failed.set(true); - } - - latch.countDown(); - }); + final List verticles = toVerticles(definition); + final CompositeFuture verticlesInitialization = toVerticlesInitialization(verticles) + .onComplete(result -> latch.countDown()); + verticles.forEach(vertx::deployVerticle); try { - if (!latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) { + if (!latch.await(timeoutMillis, TimeUnit.MILLISECONDS)) { throw new RuntimeException( - "Action has not completed within defined timeout %d ms".formatted(TIMEOUT_MILLIS)); + "Action has not completed within defined timeout %d ms".formatted(timeoutMillis)); } - if (failed.get()) { - final Throwable cause = failureThrowable.get(); + if (verticlesInitialization.failed()) { + final Throwable cause = verticlesInitialization.cause(); if (cause != null) { throw new RuntimeException(cause); } else { throw new RuntimeException("Action failed"); } } - } catch (InterruptedException e) { + } catch ( + InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for action to complete", e); } } + + private static List toVerticles(VerticleDefinition definition) { + return IntStream.range(0, definition.getAmount()) + .mapToObj(i -> definition.getFactory().get()) + .toList(); + } + + private static CompositeFuture toVerticlesInitialization(List verticles) { + final List verticlesInitializations = verticles.stream() + .map(InitializableVerticle::getVerticleInitialization) + .collect(Collectors.toCollection(ArrayList::new)); + + return CompositeFuture.all(verticlesInitializations); + } } diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java index adb120db7c5..95debd09e8f 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -1,8 +1,9 @@ package org.prebid.server.vertx.verticles.server; -import io.vertx.core.AbstractVerticle; import io.vertx.core.AsyncResult; import io.vertx.core.Context; +import io.vertx.core.Future; +import io.vertx.core.Promise; import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; @@ -12,11 +13,12 @@ import io.vertx.ext.web.Router; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.handler.ExceptionHandler; +import org.prebid.server.vertx.verticles.InitializableVerticle; import java.util.Objects; import java.util.function.Supplier; -public class ServerVerticle extends AbstractVerticle { +public class ServerVerticle extends InitializableVerticle { private static final Logger logger = LoggerFactory.getLogger(ServerVerticle.class); @@ -48,7 +50,8 @@ public ServerVerticle(String name, SocketAddress address, Supplier route } @Override - public void init(Vertx vertx, Context context) { + public Future initialize(Vertx vertx, Context context) { + final Promise completionPromise = Promise.promise(); final HttpServerOptions httpServerOptions = ObjectUtils.defaultIfNull(serverOptions, new HttpServerOptions()); final HttpServer server = vertx.createHttpServer(httpServerOptions) .requestHandler(router); @@ -57,18 +60,20 @@ public void init(Vertx vertx, Context context) { server.exceptionHandler(exceptionHandler); } - server.listen(address, this::onServerStarted); + server.listen(address, result -> onServerStarted(result, completionPromise)); + return completionPromise.future(); } - private void onServerStarted(AsyncResult result) { + private void onServerStarted(AsyncResult result, Promise completionPromise) { if (result.succeeded()) { + completionPromise.tryComplete(); logger.info( "Successfully started {0} instance on address: {1}, thread: {2}", name, address, Thread.currentThread().getName()); } else { - throw new RuntimeException(result.cause()); + completionPromise.tryFail(result.cause()); } } } From 14919938c5d6a076e32c2cec6fa01ead43901d7e Mon Sep 17 00:00:00 2001 From: Danylo Date: Mon, 4 Mar 2024 15:33:47 +0200 Subject: [PATCH 4/9] Delete tests. --- .../server/auction/BidResponseCreator.java | 1 + .../org/prebid/server/cache/CacheService.java | 1 + .../prebid/server/events/EventsService.java | 13 + .../model/deals/alert/Action.groovy | 6 - .../model/deals/alert/AlertEvent.groovy | 20 - .../model/deals/alert/AlertPriority.groovy | 6 - .../model/deals/alert/AlertSource.groovy | 17 - .../deals/lineitem/DeliverySchedule.groovy | 37 - .../model/deals/lineitem/FrequencyCap.groovy | 23 - .../model/deals/lineitem/LineItem.groovy | 74 - .../model/deals/lineitem/LineItemSize.groovy | 16 - .../deals/lineitem/LineItemStatus.groovy | 22 - .../model/deals/lineitem/MediaType.groovy | 20 - .../model/deals/lineitem/PeriodType.groovy | 24 - .../model/deals/lineitem/Price.groovy | 15 - .../deals/lineitem/RelativePriority.groovy | 24 - .../model/deals/lineitem/Token.groovy | 19 - .../lineitem/targeting/BooleanOperator.groovy | 20 - .../targeting/MatchingFunction.groovy | 18 - .../targeting/MatchingFunctionNode.groovy | 17 - .../deals/lineitem/targeting/Targeting.groovy | 92 - .../lineitem/targeting/TargetingNode.groovy | 13 - .../lineitem/targeting/TargetingType.groovy | 46 - .../register/CurrencyServiceState.groovy | 11 - .../deals/register/RegisterRequest.groovy | 13 - .../model/deals/register/Status.groovy | 11 - .../deals/report/DeliverySchedule.groovy | 15 - .../report/DeliveryStatisticsReport.groovy | 19 - .../model/deals/report/Event.groovy | 10 - .../model/deals/report/LineItemStatus.groovy | 30 - .../deals/report/LineItemStatusReport.groovy | 17 - .../model/deals/report/LostToLineItem.groovy | 11 - .../model/deals/report/Token.groovy | 17 - .../model/deals/userdata/Segment.groovy | 14 - .../model/deals/userdata/User.groovy | 16 - .../model/deals/userdata/UserData.groovy | 19 - .../model/deals/userdata/UserDetails.groovy | 10 - .../deals/userdata/UserDetailsRequest.groovy | 12 - .../deals/userdata/UserDetailsResponse.groovy | 14 - .../model/deals/userdata/UserExt.groovy | 14 - .../model/deals/userdata/UserId.groovy | 10 - .../userdata/WinEventNotification.groovy | 19 - .../generalplanner/PlansResponse.groovy | 19 - .../ForceDealsUpdateRequest.groovy | 48 - .../model/request/event/EventRequest.groovy | 2 - .../model/response/auction/BidResponse.groovy | 13 - .../service/PrebidServerService.groovy | 24 - .../testcontainers/PbsPgConfig.groovy | 135 -- .../scaffolding/pg/Alert.groovy | 50 - .../scaffolding/pg/DeliveryStatistics.groovy | 57 - .../scaffolding/pg/GeneralPlanner.groovy | 96 - .../scaffolding/pg/UserData.groovy | 77 - .../functional/tests/pg/AlertSpec.groovy | 281 --- .../functional/tests/pg/BasePgSpec.groovy | 60 - .../functional/tests/pg/CurrencySpec.groovy | 98 - .../tests/pg/LineItemStatusSpec.groovy | 193 -- .../functional/tests/pg/PgAuctionSpec.groovy | 520 ----- .../tests/pg/PgBidResponseSpec.groovy | 211 -- .../tests/pg/PgBidderRequestSpec.groovy | 167 -- .../tests/pg/PgDealsOnlySpec.groovy | 190 -- .../functional/tests/pg/PlansSpec.groovy | 57 - .../functional/tests/pg/RegisterSpec.groovy | 229 -- .../functional/tests/pg/ReportSpec.groovy | 559 ----- .../pg/TargetingFirstPartyDataSpec.groovy | 707 ------ .../functional/tests/pg/TargetingSpec.groovy | 560 ----- .../functional/tests/pg/TokenSpec.groovy | 317 --- .../tests/pg/UserDetailsSpec.groovy | 343 --- .../tests/privacy/PrivacyBaseSpec.groovy | 4 +- .../server/functional/util/HttpUtil.groovy | 11 - .../pubstack/PubstackEventHandlerTest.java | 4 - .../auction/BidResponseCreatorTest.java | 233 +- .../server/auction/ExchangeServiceTest.java | 197 +- .../WinningBidComparatorFactoryTest.java | 261 +-- .../requestfactory/AmpRequestFactoryTest.java | 9 +- .../AuctionRequestFactoryTest.java | 9 +- .../Ortb2RequestFactoryTest.java | 101 +- .../VideoRequestFactoryTest.java | 10 +- .../bidder/HttpBidderRequesterTest.java | 44 +- .../prebid/server/cache/CacheServiceTest.java | 36 +- .../server/deals/AdminCentralServiceTest.java | 437 ---- .../server/deals/AlertHttpServiceTest.java | 233 -- .../prebid/server/deals/DealsServiceTest.java | 403 ---- .../DeliveryProgressReportFactoryTest.java | 201 -- .../deals/DeliveryProgressServiceTest.java | 426 ---- .../deals/DeliveryStatsServiceTest.java | 428 ---- .../server/deals/LineItemServiceTest.java | 2076 ----------------- .../server/deals/PlannerServiceTest.java | 351 --- .../server/deals/RegisterServiceTest.java | 269 --- .../server/deals/TargetingServiceTest.java | 919 -------- .../deals/UserAdditionalInfoServiceTest.java | 507 ---- .../prebid/server/deals/UserServiceTest.java | 596 ----- .../deals/events/AdminEventServiceTest.java | 83 - .../events/ApplicationEventServiceTest.java | 156 -- .../deals/lineitem/DeliveryPlanTest.java | 30 - .../deals/lineitem/DeliveryProgressTest.java | 365 --- .../server/deals/model/DeepDebugLogTest.java | 51 - .../DealsSimulationAdminHandlerTest.java | 227 -- ...imulationAwareHttpBidderRequesterTest.java | 324 --- .../SimulationAwarePlannerServiceTest.java | 164 -- .../deals/targeting/RequestContextTest.java | 1262 ---------- .../deals/targeting/interpret/AndTest.java | 52 - .../targeting/interpret/InIntegersTest.java | 65 - .../targeting/interpret/InStringsTest.java | 85 - .../interpret/IntersectsIntegersTest.java | 74 - .../interpret/IntersectsSizesTest.java | 77 - .../interpret/IntersectsStringsTest.java | 83 - .../targeting/interpret/MatchesTest.java | 168 -- .../deals/targeting/interpret/NotTest.java | 42 - .../deals/targeting/interpret/OrTest.java | 52 - .../deals/targeting/interpret/WithinTest.java | 65 - .../targeting/syntax/BooleanOperatorTest.java | 51 - .../syntax/MatchingFunctionTest.java | 52 - .../syntax/TargetingCategoryTest.java | 121 - .../prebid/server/events/EventUtilTest.java | 10 +- .../server/events/EventsServiceTest.java | 47 +- .../handler/DealsStatusHandlerTest.java | 86 - .../handler/ForceDealsUpdateHandlerTest.java | 240 -- .../handler/LineItemStatusHandlerTest.java | 104 - .../handler/NotificationEventHandlerTest.java | 178 +- .../server/handler/TracerLogHandlerTest.java | 4 +- .../handler/openrtb2/AmpHandlerTest.java | 2 +- .../handler/openrtb2/AuctionHandlerTest.java | 3 +- .../org/prebid/server/it/ApplicationTest.java | 1 - .../prebid/server/it/DealsSimulationTest.java | 269 --- .../java/org/prebid/server/it/DealsTest.java | 333 --- .../org/prebid/server/it/IntegrationTest.java | 82 - .../prebid/server/it/PrematureReturnTest.java | 451 ---- .../server/log/CriteriaManagerTest.java | 25 +- .../org/prebid/server/log/CriteriaTest.java | 67 +- .../org/prebid/server/metric/MetricsTest.java | 143 -- .../org/prebid/server/util/HttpUtilTest.java | 52 - .../validation/ResponseBidValidatorTest.java | 211 +- .../prebid/server/vast/VastModifierTest.java | 88 +- .../targeting/test-device-targeting.json | 20 - ...rgeting-definition-and-with-non-array.json | 3 - ...nition-category-incompatible-function.json | 5 - ...on-category-incompatible-geo-function.json | 5 - ...ategory-incompatible-segment-function.json | 5 - ...category-incompatible-string-function.json | 5 - ...-category-incompatible-typed-function.json | 5 - ...geting-definition-category-non-object.json | 3 - ...ng-definition-in-integers-non-integer.json | 7 - ...eting-definition-intersects-non-array.json | 5 - ...efinition-intersects-sizes-empty-size.json | 8 - ...finition-intersects-sizes-non-objects.json | 8 - ...on-intersects-sizes-non-readable-size.json | 9 - ...g-definition-intersects-strings-empty.json | 7 - ...inition-intersects-strings-non-string.json | 7 - ...id-targeting-definition-matches-empty.json | 5 - ...rgeting-definition-matches-non-string.json | 5 - ...finition-multiple-fields-boolean-args.json | 8 - ...g-definition-multiple-fields-function.json | 6 - ...-targeting-definition-multiple-fields.json | 4 - ...valid-targeting-definition-non-object.json | 3 - ...geting-definition-not-with-non-object.json | 3 - ...tion-typed-function-incompatible-type.json | 7 - ...definition-typed-function-mixed-types.json | 8 - ...id-targeting-definition-unknown-field.json | 3 - ...targeting-definition-unknown-function.json | 5 - ...ng-definition-unknown-string-function.json | 5 - ...ing-definition-unknown-typed-function.json | 5 - ...ing-definition-within-empty-georegion.json | 6 - ...argeting-definition-within-non-object.json | 5 - ...inition-within-non-readable-georegion.json | 7 - .../targeting/test-not-and-definition.json | 28 - .../test-not-in-integers-definition.json | 10 - .../test-not-in-strings-definition.json | 10 - ...est-not-intersects-integer-definition.json | 10 - .../test-not-intersects-sizes-definition.json | 16 - .../test-not-matches-definition.json | 7 - .../targeting/test-not-or-definition.json | 28 - .../targeting/test-not-within-definition.json | 11 - .../test-valid-targeting-definition.json | 354 --- ...est-auction-first-and-second-response.json | 444 ---- .../test-auction-first-bid-only-response.json | 441 ---- .../test-auction-in-order-response.json | 441 ---- ...est-auction-in-reverse-order-response.json | 447 ---- ...test-auction-second-bid-only-response.json | 445 ---- ...est-auction-third-and-second-response.json | 446 ---- .../test-auction-third-bid-only-response.json | 445 ---- .../deals/premature/test-auction-request.json | 53 - .../premature/test-planner-plan-response.json | 209 -- .../test-rubicon-bid-response-1.json | 20 - .../test-rubicon-bid-response-2.json | 20 - .../test-rubicon-bid-response-3.json | 20 - .../test-rubicon-no-bid-response-1.json | 11 - .../test-rubicon-no-bid-response-2.json | 11 - .../test-rubicon-no-bid-response-3.json | 10 - .../simulation/test-auction-request.json | 53 - .../simulation/test-auction-response-1.json | 349 --- .../simulation/test-auction-response-2.json | 333 --- .../it/deals/simulation/test-bid-rates.json | 5 - ...est-delivery-stats-progress-request-1.json | 149 -- ...est-delivery-stats-progress-request-2.json | 98 - .../test-planner-plan-response-1.json | 257 -- .../test-planner-register-request-1.json | 6 - .../server/it/deals/test-auction-request.json | 133 -- .../it/deals/test-auction-response.json | 860 ------- .../it/deals/test-cache-deals-request.json | 79 - .../server/it/deals/test-cache-matcher.json | 5 - .../deals/test-deals-application.properties | 46 - ...st-deals-simulation-application.properties | 3 - .../test-delivery-stats-progress-request.json | 203 -- .../it/deals/test-generic-bid-request.json | 236 -- .../it/deals/test-generic-bid-response.json | 40 - .../it/deals/test-planner-plan-response.json | 347 --- .../deals/test-planner-register-request.json | 15 - .../deals/test-planner-register-response.json | 12 - ...st-user-data-details-generic-response.json | 35 - .../deals/test-user-data-details-request.json | 8 - ...st-user-data-details-rubicon-response.json | 35 - .../test-user-data-win-event-request.json | 20 - .../server/it/test-application.properties | 2 - 213 files changed, 244 insertions(+), 26858 deletions(-) delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/alert/Action.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertEvent.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertPriority.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertSource.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/DeliverySchedule.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/FrequencyCap.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItem.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemSize.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemStatus.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/MediaType.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/PeriodType.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Price.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/RelativePriority.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Token.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/BooleanOperator.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunction.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunctionNode.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/Targeting.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingNode.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingType.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/register/CurrencyServiceState.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/register/RegisterRequest.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/register/Status.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/DeliverySchedule.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/DeliveryStatisticsReport.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/Event.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatus.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatusReport.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/LostToLineItem.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/report/Token.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/Segment.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/User.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserData.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetails.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsRequest.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsResponse.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserExt.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserId.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/deals/userdata/WinEventNotification.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/mock/services/generalplanner/PlansResponse.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/model/request/dealsupdate/ForceDealsUpdateRequest.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/testcontainers/PbsPgConfig.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/Alert.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/DeliveryStatistics.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/GeneralPlanner.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/UserData.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/AlertSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/BasePgSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/CurrencySpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/LineItemStatusSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/PgAuctionSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/PgBidResponseSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/PgBidderRequestSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/PgDealsOnlySpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/PlansSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/RegisterSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/ReportSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/TargetingFirstPartyDataSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/TargetingSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/TokenSpec.groovy delete mode 100644 src/test/groovy/org/prebid/server/functional/tests/pg/UserDetailsSpec.groovy delete mode 100644 src/test/java/org/prebid/server/deals/AdminCentralServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/DealsServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/DeliveryProgressReportFactoryTest.java delete mode 100644 src/test/java/org/prebid/server/deals/DeliveryProgressServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/LineItemServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/PlannerServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/RegisterServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/TargetingServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/UserAdditionalInfoServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/UserServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/events/AdminEventServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/events/ApplicationEventServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/lineitem/DeliveryPlanTest.java delete mode 100644 src/test/java/org/prebid/server/deals/lineitem/DeliveryProgressTest.java delete mode 100644 src/test/java/org/prebid/server/deals/model/DeepDebugLogTest.java delete mode 100644 src/test/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandlerTest.java delete mode 100644 src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java delete mode 100644 src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/RequestContextTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/AndTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/InIntegersTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/InStringsTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegersTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsSizesTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsStringsTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/MatchesTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/NotTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/OrTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/interpret/WithinTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/syntax/BooleanOperatorTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/syntax/MatchingFunctionTest.java delete mode 100644 src/test/java/org/prebid/server/deals/targeting/syntax/TargetingCategoryTest.java delete mode 100644 src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java delete mode 100644 src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java delete mode 100644 src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java delete mode 100644 src/test/java/org/prebid/server/it/DealsSimulationTest.java delete mode 100644 src/test/java/org/prebid/server/it/DealsTest.java delete mode 100644 src/test/java/org/prebid/server/it/PrematureReturnTest.java delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-device-targeting.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-and-with-non-array.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-geo-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-segment-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-string-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-typed-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-non-object.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-in-integers-non-integer.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-non-array.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-empty-size.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-objects.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-readable-size.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-empty.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-non-string.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-empty.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-non-string.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-boolean-args.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-non-object.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-not-with-non-object.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-incompatible-type.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-mixed-types.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-field.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-string-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-typed-function.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-empty-georegion.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-object.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-readable-georegion.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-and-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-in-integers-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-in-strings-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-integer-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-sizes-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-matches-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-or-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-not-within-definition.json delete mode 100644 src/test/resources/org/prebid/server/deals/targeting/test-valid-targeting-definition.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-and-second-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-bid-only-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-order-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-reverse-order-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-second-bid-only-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-and-second-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-bid-only-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-auction-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-planner-plan-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-2.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-3.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-2.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-3.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-auction-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-2.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-bid-rates.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-2.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-planner-plan-response-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/simulation/test-planner-register-request-1.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-auction-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-auction-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-cache-deals-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-cache-matcher.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-deals-application.properties delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-deals-simulation-application.properties delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-delivery-stats-progress-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-generic-bid-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-generic-bid-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-planner-plan-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-planner-register-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-planner-register-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-user-data-details-generic-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-user-data-details-request.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-user-data-details-rubicon-response.json delete mode 100644 src/test/resources/org/prebid/server/it/deals/test-user-data-win-event-request.json diff --git a/src/main/java/org/prebid/server/auction/BidResponseCreator.java b/src/main/java/org/prebid/server/auction/BidResponseCreator.java index ee42b2982ed..c1ccc7922f9 100644 --- a/src/main/java/org/prebid/server/auction/BidResponseCreator.java +++ b/src/main/java/org/prebid/server/auction/BidResponseCreator.java @@ -1491,6 +1491,7 @@ private Events createEvents(String bidder, bidId, bidder, account.getId(), + true, eventsContext) : null; } diff --git a/src/main/java/org/prebid/server/cache/CacheService.java b/src/main/java/org/prebid/server/cache/CacheService.java index a19b9f9fd71..9656dd38501 100644 --- a/src/main/java/org/prebid/server/cache/CacheService.java +++ b/src/main/java/org/prebid/server/cache/CacheService.java @@ -527,6 +527,7 @@ private String generateWinUrl(String bidId, bidId, bidder, accountId, + true, eventsContext) : null; } diff --git a/src/main/java/org/prebid/server/events/EventsService.java b/src/main/java/org/prebid/server/events/EventsService.java index 72ec0472d96..819dfeb0e0a 100644 --- a/src/main/java/org/prebid/server/events/EventsService.java +++ b/src/main/java/org/prebid/server/events/EventsService.java @@ -19,13 +19,16 @@ public EventsService(String externalUrl) { public Events createEvent(String bidId, String bidder, String accountId, + boolean analyticsEnabled, EventsContext eventsContext) { + return Events.of( eventUrl( EventRequest.Type.win, bidId, bidder, accountId, + analytics(analyticsEnabled), EventRequest.Format.image, eventsContext), eventUrl( @@ -33,6 +36,7 @@ public Events createEvent(String bidId, bidId, bidder, accountId, + analytics(analyticsEnabled), EventRequest.Format.image, eventsContext)); } @@ -43,6 +47,7 @@ public Events createEvent(String bidId, public String winUrl(String bidId, String bidder, String accountId, + boolean analyticsEnabled, EventsContext eventsContext) { return eventUrl( @@ -50,6 +55,7 @@ public String winUrl(String bidId, bidId, bidder, accountId, + analytics(analyticsEnabled), EventRequest.Format.image, eventsContext); } @@ -66,6 +72,7 @@ public String vastUrlTracking(String bidId, bidId, bidder, accountId, + null, EventRequest.Format.blank, eventsContext); } @@ -74,6 +81,7 @@ private String eventUrl(EventRequest.Type type, String bidId, String bidder, String accountId, + EventRequest.Analytics analytics, EventRequest.Format format, EventsContext eventsContext) { @@ -86,8 +94,13 @@ private String eventUrl(EventRequest.Type type, .timestamp(eventsContext.getAuctionTimestamp()) .format(format) .integration(eventsContext.getIntegration()) + .analytics(analytics) .build(); return EventUtil.toUrl(externalUrl, eventRequest); } + + private static EventRequest.Analytics analytics(boolean analyticsEnabled) { + return analyticsEnabled ? null : EventRequest.Analytics.disabled; + } } diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/alert/Action.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/alert/Action.groovy deleted file mode 100644 index 8760760c00a..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/alert/Action.groovy +++ /dev/null @@ -1,6 +0,0 @@ -package org.prebid.server.functional.model.deals.alert - -enum Action { - - RAISE -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertEvent.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertEvent.groovy deleted file mode 100644 index 596b7221c46..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertEvent.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.prebid.server.functional.model.deals.alert - -import com.fasterxml.jackson.databind.PropertyNamingStrategies -import com.fasterxml.jackson.databind.annotation.JsonNaming -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy) -class AlertEvent { - - String id - Action action - AlertPriority priority - ZonedDateTime updatedAt - String name - String details - AlertSource source -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertPriority.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertPriority.groovy deleted file mode 100644 index 502b2d5eb25..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertPriority.groovy +++ /dev/null @@ -1,6 +0,0 @@ -package org.prebid.server.functional.model.deals.alert - -enum AlertPriority { - - HIGH, MEDIUM, LOW -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertSource.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertSource.groovy deleted file mode 100644 index 3175711c4be..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/alert/AlertSource.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.functional.model.deals.alert - -import com.fasterxml.jackson.databind.PropertyNamingStrategies -import com.fasterxml.jackson.databind.annotation.JsonNaming -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -@JsonNaming(PropertyNamingStrategies.KebabCaseStrategy) -class AlertSource { - - String env - String dataCenter - String region - String system - String subSystem - String hostId -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/DeliverySchedule.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/DeliverySchedule.groovy deleted file mode 100644 index 8b59632171b..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/DeliverySchedule.groovy +++ /dev/null @@ -1,37 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonFormat -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static org.prebid.server.functional.model.deals.lineitem.LineItem.TIME_PATTERN - -@ToString(includeNames = true, ignoreNulls = true) -class DeliverySchedule { - - String planId - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime startTimeStamp - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime endTimeStamp - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime updatedTimeStamp - - Set tokens - - static getDefaultDeliverySchedule() { - new DeliverySchedule(planId: PBSUtils.randomString, - startTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - endTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusDays(1), - updatedTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - tokens: [Token.defaultToken] - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/FrequencyCap.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/FrequencyCap.groovy deleted file mode 100644 index 995ae1b9309..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/FrequencyCap.groovy +++ /dev/null @@ -1,23 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -import static PeriodType.DAY - -@ToString(includeNames = true, ignoreNulls = true) -class FrequencyCap { - - String fcapId - Integer count - Integer periods - String periodType - - static getDefaultFrequencyCap() { - new FrequencyCap(count: 1, - fcapId: PBSUtils.randomString, - periods: 1, - periodType: DAY - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItem.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItem.groovy deleted file mode 100644 index 43051f0ab50..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItem.groovy +++ /dev/null @@ -1,74 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonFormat -import groovy.transform.ToString -import org.prebid.server.functional.model.deals.lineitem.targeting.Targeting -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static LineItemStatus.ACTIVE -import static java.time.ZoneOffset.UTC -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.VERY_HIGH - -@ToString(includeNames = true, ignoreNulls = true) -class LineItem { - - public static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'" - - String lineItemId - - String extLineItemId - - String dealId - - List sizes - - String accountId - - String source - - Price price - - RelativePriority relativePriority - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime startTimeStamp - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime endTimeStamp - - @JsonFormat(pattern = TIME_PATTERN) - ZonedDateTime updatedTimeStamp - - LineItemStatus status - - List frequencyCaps - - List deliverySchedules - - Targeting targeting - - static LineItem getDefaultLineItem(String accountId) { - int plannerAdapterLineItemId = PBSUtils.randomNumber - String plannerAdapterName = PBSUtils.randomString - new LineItem(lineItemId: "${plannerAdapterName}-$plannerAdapterLineItemId", - extLineItemId: plannerAdapterLineItemId, - dealId: PBSUtils.randomString, - sizes: [LineItemSize.defaultLineItemSize], - accountId: accountId, - source: GENERIC.name().toLowerCase(), - price: Price.defaultPrice, - relativePriority: VERY_HIGH, - startTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - endTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusMonths(1), - updatedTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - status: ACTIVE, - frequencyCaps: [], - deliverySchedules: [DeliverySchedule.defaultDeliverySchedule], - targeting: Targeting.defaultTargeting - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemSize.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemSize.groovy deleted file mode 100644 index 2ff7af18dec..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemSize.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import groovy.transform.ToString - -@ToString(includeNames = true) -class LineItemSize { - - Integer w - Integer h - - static getDefaultLineItemSize() { - new LineItemSize(w: 300, - h: 250 - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemStatus.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemStatus.groovy deleted file mode 100644 index c2dded2d3d2..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/LineItemStatus.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonValue - -enum LineItemStatus { - - ACTIVE("active"), - DELETED("deleted"), - PAUSED("paused") - - @JsonValue - final String value - - private LineItemStatus(String value) { - this.value = value - } - - @Override - String toString() { - value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/MediaType.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/MediaType.groovy deleted file mode 100644 index 949da3d9b53..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/MediaType.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonValue - -enum MediaType { - - BANNER("banner") - - @JsonValue - final String value - - private MediaType(String value) { - this.value = value - } - - @Override - String toString() { - value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/PeriodType.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/PeriodType.groovy deleted file mode 100644 index 10ca6f59d9c..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/PeriodType.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonValue - -enum PeriodType { - - HOUR("hour"), - DAY("day"), - WEEK("week"), - MONTH("month"), - CAMPAIGN("campaign") - - @JsonValue - final String value - - private PeriodType(String value) { - this.value = value - } - - @Override - String toString() { - value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Price.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Price.groovy deleted file mode 100644 index 5c0bb616ed6..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Price.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -@ToString(includeNames = true, ignoreNulls = true) -class Price { - - BigDecimal cpm - String currency - - static getDefaultPrice() { - new Price(cpm: PBSUtils.randomPrice, currency: "USD") - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/RelativePriority.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/RelativePriority.groovy deleted file mode 100644 index 911da0b365f..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/RelativePriority.groovy +++ /dev/null @@ -1,24 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonValue - -enum RelativePriority { - - VERY_HIGH(1), - HIGH(2), - MEDIUM(3), - LOW(4), - VERY_LOW(5) - - @JsonValue - final Integer value - - private RelativePriority(Integer value) { - this.value = value - } - - @Override - String toString() { - value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Token.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Token.groovy deleted file mode 100644 index e7dd3f2fc5d..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/Token.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem - -import com.fasterxml.jackson.annotation.JsonProperty -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class Token { - - @JsonProperty("class") - Integer priorityClass - - Integer total - - static getDefaultToken() { - new Token(priorityClass: 1, - total: 1000 - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/BooleanOperator.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/BooleanOperator.groovy deleted file mode 100644 index 0e4a4740e53..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/BooleanOperator.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue - -enum BooleanOperator { - - AND('$and'), - OR('$or'), - NOT('$not'), - - INVALID('$invalid'), - UPPERCASE_AND('$AND') - - @JsonValue - final String value - - private BooleanOperator(String value) { - this.value = value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunction.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunction.groovy deleted file mode 100644 index 54a1353808e..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunction.groovy +++ /dev/null @@ -1,18 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue - -enum MatchingFunction { - - MATCHES('$matches'), - IN('$in'), - INTERSECTS('$intersects'), - WITHIN('$within') - - @JsonValue - final String value - - private MatchingFunction(String value) { - this.value = value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunctionNode.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunctionNode.groovy deleted file mode 100644 index 6e639fe4383..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/MatchingFunctionNode.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue -import groovy.transform.PackageScope - -@PackageScope -class MatchingFunctionNode { - - Map> matchingFunctionMultipleValuesNode - - Map matchingFunctionSingleValueNode - - @JsonValue - def getMatchingFunctionNode() { - matchingFunctionMultipleValuesNode ?: matchingFunctionSingleValueNode - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/Targeting.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/Targeting.groovy deleted file mode 100644 index 12c9633cbaf..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/Targeting.groovy +++ /dev/null @@ -1,92 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue -import org.prebid.server.functional.model.deals.lineitem.LineItemSize - -import static BooleanOperator.AND -import static MatchingFunction.INTERSECTS -import static TargetingType.AD_UNIT_MEDIA_TYPE -import static TargetingType.AD_UNIT_SIZE -import static org.prebid.server.functional.model.deals.lineitem.MediaType.BANNER -import static org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator.NOT -import static org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator.OR - -class Targeting { - - private final Map> rootNode - - private final Map singleTargetingRootNode - - @JsonValue - def getSerializableRootNode() { - rootNode ?: singleTargetingRootNode - } - - private Targeting(Builder builder) { - rootNode = [(builder.rootOperator): builder.targetingNodes] - } - - private Targeting(Builder builder, TargetingNode targetingNode) { - singleTargetingRootNode = [(builder.rootOperator): targetingNode] - } - - Map> getTargetingRootNode() { - rootNode.asImmutable() - } - - static Targeting getDefaultTargeting() { - defaultTargetingBuilder.build() - } - - static Builder getDefaultTargetingBuilder() { - new Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [BANNER]) - } - - static Targeting getInvalidTwoRootNodesTargeting() { - defaultTargeting.tap { rootNode.put(OR, []) } - } - - static class Builder { - - private BooleanOperator rootOperator - private List targetingNodes = [] - - Builder(BooleanOperator rootOperator = AND) { - this.rootOperator = rootOperator - } - - Builder addTargeting(TargetingType targetingType, - MatchingFunction matchingFunction, - List targetingValues) { - MatchingFunctionNode matchingFunctionNode = new MatchingFunctionNode(matchingFunctionMultipleValuesNode: [(matchingFunction): targetingValues]) - addTargetingNode(targetingType, matchingFunctionNode) - this - } - - Builder addTargeting(TargetingType targetingType, - MatchingFunction matchingFunction, - Object targetingValue) { - MatchingFunctionNode matchingFunctionNode = new MatchingFunctionNode(matchingFunctionSingleValueNode: [(matchingFunction): targetingValue]) - addTargetingNode(targetingType, matchingFunctionNode) - this - } - - private void addTargetingNode(TargetingType targetingType, - MatchingFunctionNode matchingFunctionNode) { - targetingNodes << new TargetingNode([(targetingType): matchingFunctionNode]) - } - - Targeting build() { - new Targeting(this) - } - - Targeting buildNotBooleanOperatorTargeting(TargetingType targetingType, - MatchingFunction matchingFunction, - List targetingValues) { - rootOperator = NOT - MatchingFunctionNode matchingFunctionNode = new MatchingFunctionNode(matchingFunctionSingleValueNode: [(matchingFunction): targetingValues]) - new Targeting(this, new TargetingNode([(targetingType): matchingFunctionNode])) - } - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingNode.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingNode.groovy deleted file mode 100644 index 4e8ccecd318..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingNode.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue -import groovy.transform.PackageScope -import groovy.transform.TupleConstructor - -@PackageScope -@TupleConstructor -class TargetingNode { - - @JsonValue - Map targetingNode -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingType.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingType.groovy deleted file mode 100644 index 5434d38a59a..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/lineitem/targeting/TargetingType.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package org.prebid.server.functional.model.deals.lineitem.targeting - -import com.fasterxml.jackson.annotation.JsonValue - -enum TargetingType { - - AD_UNIT_SIZE("adunit.size"), - AD_UNIT_MEDIA_TYPE("adunit.mediatype"), - AD_UNIT_AD_SLOT("adunit.adslot"), - SITE_DOMAIN("site.domain"), - SITE_PUBLISHER_DOMAIN("site.publisher.domain"), - REFERRER("site.referrer"), - APP_BUNDLE("app.bundle"), - DEVICE_COUNTRY("device.geo.ext.geoprovider.country"), - DEVICE_TYPE("device.ext.deviceinfoprovider.type"), - DEVICE_OS("device.ext.deviceinfoprovider.osfamily"), - DEVICE_REGION("device.geo.ext.geoprovider.region"), - DEVICE_METRO("device.geo.ext.geoprovider.metro"), - PAGE_POSITION("pos"), - LOCATION("geo.distance"), - BIDP("bidp."), - BIDP_ACCOUNT_ID(BIDP.value + "rubicon.accountId"), - USER_SEGMENT("segment."), - USER_SEGMENT_NAME(USER_SEGMENT.value + "name"), - UFPD("ufpd."), - UFPD_KEYWORDS(UFPD.value + "keywords"), - UFPD_BUYER_UID(UFPD.value + "buyeruid"), - UFPD_BUYER_UIDS(UFPD.value + "buyeruids"), - UFPD_YOB(UFPD.value + "yob"), - SFPD("sfpd."), - SFPD_AMP(SFPD.value + "amp"), - SFPD_LANGUAGE(SFPD.value + "language"), - SFPD_KEYWORDS(SFPD.value + "keywords"), - SFPD_BUYER_ID(SFPD.value + "buyerid"), - SFPD_BUYER_IDS(SFPD.value + "buyerids"), - DOW("user.ext.time.userdow"), - HOUR("user.ext.time.userhour"), - INVALID("invalid.targeting.type") - - @JsonValue - final String value - - private TargetingType(String value) { - this.value = value - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/register/CurrencyServiceState.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/register/CurrencyServiceState.groovy deleted file mode 100644 index 4c0db24acd3..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/register/CurrencyServiceState.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.functional.model.deals.register - -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class CurrencyServiceState { - - ZonedDateTime lastUpdate -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/register/RegisterRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/register/RegisterRequest.groovy deleted file mode 100644 index 75daf33adc3..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/register/RegisterRequest.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package org.prebid.server.functional.model.deals.register - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class RegisterRequest { - - BigDecimal healthIndex - Status status - String hostInstanceId - String region - String vendor -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/register/Status.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/register/Status.groovy deleted file mode 100644 index ad065e9ac4a..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/register/Status.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.functional.model.deals.register - -import groovy.transform.ToString -import org.prebid.server.functional.model.deals.report.DeliveryStatisticsReport - -@ToString(includeNames = true, ignoreNulls = true) -class Status { - - CurrencyServiceState currencyRates - DeliveryStatisticsReport dealsStatus -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliverySchedule.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliverySchedule.groovy deleted file mode 100644 index 5701757e569..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliverySchedule.groovy +++ /dev/null @@ -1,15 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class DeliverySchedule { - - String planId - ZonedDateTime planStartTimeStamp - ZonedDateTime planExpirationTimeStamp - ZonedDateTime planUpdatedTimeStamp - Set tokens -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliveryStatisticsReport.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliveryStatisticsReport.groovy deleted file mode 100644 index 5ee7340c3dd..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/DeliveryStatisticsReport.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class DeliveryStatisticsReport { - - String reportId - String instanceId - String vendor - String region - Long clientAuctions - Set lineItemStatus - ZonedDateTime reportTimeStamp - ZonedDateTime dataWindowStartTimeStamp - ZonedDateTime dataWindowEndTimeStamp -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/Event.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/Event.groovy deleted file mode 100644 index 495bfaf673e..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/Event.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class Event { - - String type - Long count -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatus.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatus.groovy deleted file mode 100644 index a68029852c6..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatus.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class LineItemStatus { - - String lineItemSource - String lineItemId - String dealId - String extLineItemId - Long accountAuctions - Long domainMatched - Long targetMatched - Long targetMatchedButFcapped - Long targetMatchedButFcapLookupFailed - Long pacingDeferred - Long sentToBidder - Long sentToBidderAsTopMatch - Long receivedFromBidder - Long receivedFromBidderInvalidated - Long sentToClient - Long sentToClientAsTopMatch - Set lostToLineItems - Set events - Set deliverySchedule - String readyAt - Long spentTokens - Long pacingFrequency -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatusReport.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatusReport.groovy deleted file mode 100644 index 6fb1766c534..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/LineItemStatusReport.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class LineItemStatusReport { - - String lineItemId - DeliverySchedule deliverySchedule - Long spentTokens - ZonedDateTime readyToServeTimestamp - Long pacingFrequency - String accountId - Map target -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/LostToLineItem.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/LostToLineItem.groovy deleted file mode 100644 index 58567ffc974..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/LostToLineItem.groovy +++ /dev/null @@ -1,11 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class LostToLineItem { - - String lineItemSource - String lineItemId - Long count -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/report/Token.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/report/Token.groovy deleted file mode 100644 index 89310a5d73e..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/report/Token.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package org.prebid.server.functional.model.deals.report - -import com.fasterxml.jackson.annotation.JsonProperty -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class Token { - - @JsonProperty("class") - Integer priorityClass - - Integer total - - Long spent - - Long totalSpent -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/Segment.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/Segment.groovy deleted file mode 100644 index f11d8f32ff1..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/Segment.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -@ToString(includeNames = true, ignoreNulls = true) -class Segment { - - String id - - static getDefaultSegment() { - new Segment(id: PBSUtils.randomString) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/User.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/User.groovy deleted file mode 100644 index 6d2e527a0e6..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/User.groovy +++ /dev/null @@ -1,16 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class User { - - List data - UserExt ext - - static getDefaultUser() { - new User(data: [UserData.defaultUserData], - ext: UserExt.defaultUserExt - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserData.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserData.groovy deleted file mode 100644 index 5687d89285e..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserData.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -@ToString(includeNames = true, ignoreNulls = true) -class UserData { - - String id - String name - List segment - - static UserData getDefaultUserData() { - new UserData(id: PBSUtils.randomString, - name: PBSUtils.randomString, - segment: [Segment.defaultSegment] - ) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetails.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetails.groovy deleted file mode 100644 index 780ec674b24..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetails.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class UserDetails { - - List userData - List fcapIds -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsRequest.groovy deleted file mode 100644 index 74985c5808f..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsRequest.groovy +++ /dev/null @@ -1,12 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class UserDetailsRequest { - - ZonedDateTime time - List ids -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsResponse.groovy deleted file mode 100644 index 143aee234d9..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserDetailsResponse.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString -import org.prebid.server.functional.model.ResponseModel - -@ToString(includeNames = true, ignoreNulls = true) -class UserDetailsResponse implements ResponseModel { - - User user - - static UserDetailsResponse getDefaultUserResponse(User user = User.defaultUser) { - new UserDetailsResponse(user: user) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserExt.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserExt.groovy deleted file mode 100644 index 53a89aa97e2..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserExt.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString -import org.prebid.server.functional.util.PBSUtils - -@ToString(includeNames = true, ignoreNulls = true) -class UserExt { - - List fcapIds - - static getDefaultUserExt() { - new UserExt(fcapIds: [PBSUtils.randomString]) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserId.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserId.groovy deleted file mode 100644 index 8edeac5336d..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/UserId.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString - -@ToString(includeNames = true, ignoreNulls = true) -class UserId { - - String type - String id -} diff --git a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/WinEventNotification.groovy b/src/test/groovy/org/prebid/server/functional/model/deals/userdata/WinEventNotification.groovy deleted file mode 100644 index bea8f7c296b..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/deals/userdata/WinEventNotification.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.functional.model.deals.userdata - -import groovy.transform.ToString -import org.prebid.server.functional.model.deals.lineitem.FrequencyCap - -import java.time.ZonedDateTime - -@ToString(includeNames = true, ignoreNulls = true) -class WinEventNotification { - - String bidderCode - String bidId - String lineItemId - String region - List userIds - ZonedDateTime winEventDateTime - ZonedDateTime lineUpdatedDateTime - List frequencyCaps -} diff --git a/src/test/groovy/org/prebid/server/functional/model/mock/services/generalplanner/PlansResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/mock/services/generalplanner/PlansResponse.groovy deleted file mode 100644 index f9a9d4548e7..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/mock/services/generalplanner/PlansResponse.groovy +++ /dev/null @@ -1,19 +0,0 @@ -package org.prebid.server.functional.model.mock.services.generalplanner - -import com.fasterxml.jackson.annotation.JsonValue -import org.prebid.server.functional.model.ResponseModel -import org.prebid.server.functional.model.deals.lineitem.LineItem - -class PlansResponse implements ResponseModel { - - List lineItems - - static PlansResponse getDefaultPlansResponse(String accountId) { - new PlansResponse(lineItems: [LineItem.getDefaultLineItem(accountId)]) - } - - @JsonValue - List getLineItems() { - lineItems - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/dealsupdate/ForceDealsUpdateRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/request/dealsupdate/ForceDealsUpdateRequest.groovy deleted file mode 100644 index aaa1c0b2ece..00000000000 --- a/src/test/groovy/org/prebid/server/functional/model/request/dealsupdate/ForceDealsUpdateRequest.groovy +++ /dev/null @@ -1,48 +0,0 @@ -package org.prebid.server.functional.model.request.dealsupdate - -import com.fasterxml.jackson.databind.PropertyNamingStrategies -import com.fasterxml.jackson.databind.annotation.JsonNaming -import groovy.transform.ToString - -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.CREATE_REPORT -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.INVALIDATE_LINE_ITEMS -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.REGISTER_INSTANCE -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.RESET_ALERT_COUNT -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.SEND_REPORT -import static org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest.Action.UPDATE_LINE_ITEMS - -@ToString(includeNames = true, ignoreNulls = true) -@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy) -class ForceDealsUpdateRequest { - - String actionName - - static ForceDealsUpdateRequest getUpdateLineItemsRequest() { - new ForceDealsUpdateRequest(actionName: UPDATE_LINE_ITEMS.name()) - } - - static ForceDealsUpdateRequest getSendReportRequest() { - new ForceDealsUpdateRequest(actionName: SEND_REPORT.name()) - } - - static ForceDealsUpdateRequest getRegisterInstanceRequest() { - new ForceDealsUpdateRequest(actionName: REGISTER_INSTANCE.name()) - } - - static ForceDealsUpdateRequest getResetAlertCountRequest() { - new ForceDealsUpdateRequest(actionName: RESET_ALERT_COUNT.name()) - } - - static ForceDealsUpdateRequest getCreateReportRequest() { - new ForceDealsUpdateRequest(actionName: CREATE_REPORT.name()) - } - - static ForceDealsUpdateRequest getInvalidateLineItemsRequest() { - new ForceDealsUpdateRequest(actionName: INVALIDATE_LINE_ITEMS.name()) - } - - private enum Action { - - UPDATE_LINE_ITEMS, SEND_REPORT, REGISTER_INSTANCE, RESET_ALERT_COUNT, CREATE_REPORT, INVALIDATE_LINE_ITEMS - } -} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/event/EventRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/request/event/EventRequest.groovy index 9d7000cb7b3..6ed94f08161 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/event/EventRequest.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/event/EventRequest.groovy @@ -24,8 +24,6 @@ class EventRequest { Integer analytics @JsonProperty("ts") Long timestamp - @JsonProperty("l") - String lineItemId static EventRequest getDefaultEventRequest() { def request = new EventRequest() diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy index caae943a322..99e37de76ab 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/BidResponse.groovy @@ -5,7 +5,6 @@ import groovy.transform.ToString import org.prebid.server.functional.model.Currency import org.prebid.server.functional.model.ResponseModel import org.prebid.server.functional.model.bidder.BidderName -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse import org.prebid.server.functional.model.request.auction.BidRequest import static org.prebid.server.functional.model.bidder.BidderName.GENERIC @@ -29,16 +28,4 @@ class BidResponse implements ResponseModel { bidResponse.seatbid = [seatBid] bidResponse } - - static BidResponse getDefaultPgBidResponse(BidRequest bidRequest, PlansResponse plansResponse) { - def bidResponse = getDefaultBidResponse(bidRequest) - def bid = bidResponse.seatbid[0].bid[0] - def lineItem = plansResponse.lineItems[0] - bid.dealid = lineItem.dealId - if (lineItem.sizes) { - bid.w = lineItem.sizes[0].w - bid.h = lineItem.sizes[0].h - } - bidResponse - } } diff --git a/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy b/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy index a80cffe0c11..ade27a2fd6e 100644 --- a/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy +++ b/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy @@ -9,12 +9,10 @@ import io.restassured.response.Response import io.restassured.specification.RequestSpecification import org.prebid.server.functional.model.UidsCookie import org.prebid.server.functional.model.bidder.BidderName -import org.prebid.server.functional.model.deals.report.LineItemStatusReport import org.prebid.server.functional.model.mock.services.prebidcache.response.PrebidCacheResponse import org.prebid.server.functional.model.request.amp.AmpRequest import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.cookiesync.CookieSyncRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest import org.prebid.server.functional.model.request.event.EventRequest import org.prebid.server.functional.model.request.logging.httpinteraction.HttpInteractionRequest import org.prebid.server.functional.model.request.setuid.SetuidRequest @@ -59,8 +57,6 @@ class PrebidServerService implements ObjectMapperWrapper { static final String CURRENCY_RATES_ENDPOINT = "/currency/rates" static final String HTTP_INTERACTION_ENDPOINT = "/logging/httpinteraction" static final String COLLECTED_METRICS_ENDPOINT = "/collected-metrics" - static final String FORCE_DEALS_UPDATE_ENDPOINT = "/pbs-admin/force-deals-update" - static final String LINE_ITEM_STATUS_ENDPOINT = "/pbs-admin/lineitem-status" static final String PROMETHEUS_METRICS_ENDPOINT = "/metrics" static final String UIDS_COOKIE_NAME = "uids" @@ -290,26 +286,6 @@ class PrebidServerService implements ObjectMapperWrapper { decode(response.asString(), new TypeReference>() {}) } - @Step("[GET] /pbs-admin/force-deals-update") - void sendForceDealsUpdateRequest(ForceDealsUpdateRequest forceDealsUpdateRequest) { - def response = given(adminRequestSpecification).queryParams(toMap(forceDealsUpdateRequest)) - .get(FORCE_DEALS_UPDATE_ENDPOINT) - - checkResponseStatusCode(response, 204) - } - - @Step("[GET] /pbs-admin/lineitem-status") - LineItemStatusReport sendLineItemStatusRequest(String lineItemId) { - def request = given(adminRequestSpecification) - if (lineItemId != null) { - request.queryParam("id", lineItemId) - } - - def response = request.get(LINE_ITEM_STATUS_ENDPOINT) - - checkResponseStatusCode(response) - response.as(LineItemStatusReport) - } @Step("[GET] /metrics") String sendPrometheusMetricsRequest() { diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/PbsPgConfig.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/PbsPgConfig.groovy deleted file mode 100644 index 47de3679541..00000000000 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/PbsPgConfig.groovy +++ /dev/null @@ -1,135 +0,0 @@ -package org.prebid.server.functional.testcontainers - -import org.prebid.server.functional.model.Currency -import org.prebid.server.functional.testcontainers.container.NetworkServiceContainer -import org.prebid.server.functional.util.PBSUtils - -import java.time.LocalDate - -import static org.prebid.server.functional.testcontainers.scaffolding.pg.Alert.ALERT_ENDPOINT_PATH -import static org.prebid.server.functional.testcontainers.scaffolding.pg.DeliveryStatistics.REPORT_DELIVERY_ENDPOINT_PATH -import static org.prebid.server.functional.testcontainers.scaffolding.pg.GeneralPlanner.PLANS_ENDPOINT_PATH -import static org.prebid.server.functional.testcontainers.scaffolding.pg.GeneralPlanner.REGISTER_ENDPOINT_PATH -import static org.prebid.server.functional.testcontainers.scaffolding.pg.UserData.USER_DETAILS_ENDPOINT_PATH -import static org.prebid.server.functional.testcontainers.scaffolding.pg.UserData.WIN_EVENT_ENDPOINT_PATH - -class PbsPgConfig { - - public static final String PG_ENDPOINT_USERNAME = "pg" - public static final String PG_ENDPOINT_PASSWORD = "pg" - - private static final int NEXT_MONTH = LocalDate.now().plusMonths(1).monthValue - - final Map properties - final String env - final String dataCenter - final String region - final String system - final String subSystem - final String hostId - final String vendor - final Currency currency - final String userIdType - final int maxDealsPerBidder - final int lineItemsPerReport - - PbsPgConfig(NetworkServiceContainer networkServiceContainer) { - properties = getPgConfig(networkServiceContainer.rootUri).asImmutable() - env = properties.get("profile") - dataCenter = properties.get("data-center") - region = properties.get("datacenter-region") - system = properties.get("system") - subSystem = properties.get("sub-system") - hostId = properties.get("host-id") - vendor = properties.get("vendor") - currency = properties.get("auction.ad-server-currency") - userIdType = properties.get("deals.user-data.user-ids[0].type") - maxDealsPerBidder = getIntProperty(properties, "deals.max-deals-per-bidder") - lineItemsPerReport = getIntProperty(properties, "deals.delivery-stats.line-items-per-report") - } - - private static Map getPgConfig(String networkServiceContainerUri) { - pbsGeneralSettings() + adminDealsUpdateEndpoint() + deals() + deliveryProgress() + - planner(networkServiceContainerUri) + deliveryStatistics(networkServiceContainerUri) + - alert(networkServiceContainerUri) + userData(networkServiceContainerUri) + adminLineItemStatusEndpoint() - } - - private static Map pbsGeneralSettings() { - ["host-id" : PBSUtils.randomString, - "datacenter-region" : PBSUtils.randomString, - "vendor" : PBSUtils.randomString, - "profile" : PBSUtils.randomString, - "system" : PBSUtils.randomString, - "sub-system" : PBSUtils.randomString, - "data-center" : PBSUtils.randomString, - "auction.ad-server-currency": "USD", - ] - } - - private static Map adminDealsUpdateEndpoint() { - ["admin-endpoints.force-deals-update.enabled": "true"] - } - - private static Map adminLineItemStatusEndpoint() { - ["admin-endpoints.lineitem-status.enabled": "true"] - } - - private static Map deals() { - ["deals.enabled" : "true", - "deals.simulation.enabled" : "false", - "deals.max-deals-per-bidder": "3" - ] - } - - private static Map planner(String networkServiceContainerUri) { - ["deals.planner.plan-endpoint" : networkServiceContainerUri + PLANS_ENDPOINT_PATH, - "deals.planner.register-endpoint" : networkServiceContainerUri + REGISTER_ENDPOINT_PATH, - "deals.planner.update-period" : "0 15 10 15 $NEXT_MONTH ?" as String, - "deals.planner.plan-advance-period": "0 15 10 15 $NEXT_MONTH ?" as String, - "deals.planner.timeout-ms" : "5000", - "deals.planner.username" : PG_ENDPOINT_USERNAME, - "deals.planner.password" : PG_ENDPOINT_PASSWORD, - "deals.planner.register-period-sec": "3600" - ] - } - - private static Map deliveryStatistics(String networkServiceContainerUri) { - ["deals.delivery-stats.endpoint" : networkServiceContainerUri + - REPORT_DELIVERY_ENDPOINT_PATH, - "deals.delivery-stats.username" : PG_ENDPOINT_USERNAME, - "deals.delivery-stats.password" : PG_ENDPOINT_PASSWORD, - "deals.delivery-stats.delivery-period" : "0 15 10 15 $NEXT_MONTH ?" as String, - "deals.delivery-stats.timeout-ms" : "10000", - "deals.delivery-stats.request-compression-enabled": "false", - "deals.delivery-stats.line-items-per-report" : "5" - ] - } - - private static Map deliveryProgress() { - ["deals.delivery-progress.report-reset-period": "0 15 10 15 $NEXT_MONTH ?" as String] - } - - private static Map alert(String networkServiceContainerUri) { - ["deals.alert-proxy.enabled" : "true", - "deals.alert-proxy.url" : networkServiceContainerUri + ALERT_ENDPOINT_PATH, - "deals.alert-proxy.username" : PG_ENDPOINT_USERNAME, - "deals.alert-proxy.password" : PG_ENDPOINT_PASSWORD, - "deals.alert-proxy.timeout-sec": "10" - ] - } - - private static Map userData(String networkServiceContainerUri) { - ["deals.user-data.user-details-endpoint": networkServiceContainerUri + USER_DETAILS_ENDPOINT_PATH, - "deals.user-data.win-event-endpoint" : networkServiceContainerUri + WIN_EVENT_ENDPOINT_PATH, - "deals.user-data.timeout" : "1000", - "deals.user-data.user-ids[0].type" : "autotest", - "deals.user-data.user-ids[0].source" : "uid", - "deals.user-data.user-ids[0].location" : "generic" - ] - } - - private static getIntProperty(Map properties, String propertyName) { - def property = properties.get(propertyName) - property ? property as int : -1 - } -} diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/Alert.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/Alert.groovy deleted file mode 100644 index 49efd6b3441..00000000000 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/Alert.groovy +++ /dev/null @@ -1,50 +0,0 @@ -package org.prebid.server.functional.testcontainers.scaffolding.pg - -import com.fasterxml.jackson.core.type.TypeReference -import org.mockserver.model.HttpRequest -import org.prebid.server.functional.model.deals.alert.AlertEvent -import org.prebid.server.functional.testcontainers.scaffolding.NetworkScaffolding -import org.testcontainers.containers.MockServerContainer - -import static org.mockserver.model.HttpRequest.request -import static org.mockserver.model.HttpResponse.response -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.mockserver.model.JsonPathBody.jsonPath - -class Alert extends NetworkScaffolding { - - static final String ALERT_ENDPOINT_PATH = "/deals/alert" - - Alert(MockServerContainer mockServerContainer) { - super(mockServerContainer, ALERT_ENDPOINT_PATH) - } - - AlertEvent getRecordedAlertRequest() { - def body = getRecordedRequestsBody(request).last() - // 0 index element is returned after deserialization as PBS responses with SingletonList - decode(body, new TypeReference>() {})[0] - } - - Map> getLastRecordedAlertRequestHeaders() { - getLastRecordedRequestHeaders(request) - } - - @Override - void setResponse() { - mockServerClient.when(request().withPath(endpoint)) - .respond(response().withStatusCode(OK_200.code())) - } - - @Override - protected HttpRequest getRequest(String alertId) { - request().withMethod("POST") - .withPath(ALERT_ENDPOINT_PATH) - .withBody(jsonPath("\$[?(@.id == '$alertId')]")) - } - - @Override - protected HttpRequest getRequest() { - request().withMethod("POST") - .withPath(ALERT_ENDPOINT_PATH) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/DeliveryStatistics.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/DeliveryStatistics.groovy deleted file mode 100644 index 32f8f26b4d3..00000000000 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/DeliveryStatistics.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.prebid.server.functional.testcontainers.scaffolding.pg - -import org.mockserver.model.HttpRequest -import org.mockserver.model.HttpStatusCode -import org.prebid.server.functional.model.deals.report.DeliveryStatisticsReport -import org.prebid.server.functional.testcontainers.scaffolding.NetworkScaffolding -import org.testcontainers.containers.MockServerContainer - -import static org.mockserver.model.ClearType.ALL -import static org.mockserver.model.HttpRequest.request -import static org.mockserver.model.HttpResponse.response -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.mockserver.model.JsonPathBody.jsonPath - -class DeliveryStatistics extends NetworkScaffolding { - - static final String REPORT_DELIVERY_ENDPOINT_PATH = "/deals/report/delivery" - - DeliveryStatistics(MockServerContainer mockServerContainer) { - super(mockServerContainer, REPORT_DELIVERY_ENDPOINT_PATH) - } - - Map> getLastRecordedDeliveryRequestHeaders() { - getLastRecordedRequestHeaders(request) - } - - DeliveryStatisticsReport getLastRecordedDeliveryStatisticsReportRequest() { - recordedDeliveryStatisticsReportRequests.last() - } - - void resetRecordedRequests() { - reset(REPORT_DELIVERY_ENDPOINT_PATH, ALL) - } - - void setResponse(HttpStatusCode statusCode = OK_200) { - mockServerClient.when(request().withPath(endpoint)) - .respond(response().withStatusCode(statusCode.code())) - } - - List getRecordedDeliveryStatisticsReportRequests() { - def body = getRecordedRequestsBody(request) - body.collect { decode(it, DeliveryStatisticsReport) } - } - - @Override - protected HttpRequest getRequest(String reportId) { - request().withMethod("POST") - .withPath(REPORT_DELIVERY_ENDPOINT_PATH) - .withBody(jsonPath("\$[?(@.reportId == '$reportId')]")) - } - - @Override - protected HttpRequest getRequest() { - request().withMethod("POST") - .withPath(REPORT_DELIVERY_ENDPOINT_PATH) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/GeneralPlanner.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/GeneralPlanner.groovy deleted file mode 100644 index be27be483f6..00000000000 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/GeneralPlanner.groovy +++ /dev/null @@ -1,96 +0,0 @@ -package org.prebid.server.functional.testcontainers.scaffolding.pg - -import org.mockserver.matchers.Times -import org.mockserver.model.HttpRequest -import org.mockserver.model.HttpStatusCode -import org.prebid.server.functional.model.deals.register.RegisterRequest -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.testcontainers.scaffolding.NetworkScaffolding -import org.testcontainers.containers.MockServerContainer - -import static org.mockserver.model.HttpRequest.request -import static org.mockserver.model.HttpResponse.response -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.mockserver.model.JsonPathBody.jsonPath - -class GeneralPlanner extends NetworkScaffolding { - - static final String PLANS_ENDPOINT_PATH = "/deals/plans" - static final String REGISTER_ENDPOINT_PATH = "/deals/register" - - GeneralPlanner(MockServerContainer mockServerContainer) { - super(mockServerContainer, REGISTER_ENDPOINT_PATH) - } - - void initRegisterResponse(HttpStatusCode statusCode = OK_200) { - reset() - setResponse(statusCode) - } - - void initPlansResponse(PlansResponse plansResponse, - HttpStatusCode statusCode = OK_200, - Times times = Times.exactly(1)) { - resetPlansEndpoint() - setPlansResponse(plansResponse, statusCode, times) - } - - void resetPlansEndpoint() { - reset(PLANS_ENDPOINT_PATH) - } - - int getRecordedPlansRequestCount() { - getRequestCount(plansRequest) - } - - RegisterRequest getLastRecordedRegisterRequest() { - recordedRegisterRequests.last() - } - - List getRecordedRegisterRequests() { - def body = getRecordedRequestsBody(request) - body.collect { decode(it, RegisterRequest) } - } - - void setResponse(HttpStatusCode statusCode = OK_200) { - mockServerClient.when(request().withPath(endpoint)) - .respond(response().withStatusCode(statusCode.code())) - } - - Map> getLastRecordedRegisterRequestHeaders() { - getLastRecordedRequestHeaders(request) - } - - Map> getLastRecordedPlansRequestHeaders() { - getLastRecordedRequestHeaders(plansRequest) - } - - @Override - void reset() { - super.reset(PLANS_ENDPOINT_PATH) - super.reset(REGISTER_ENDPOINT_PATH) - } - - private void setPlansResponse(PlansResponse plansResponse, - HttpStatusCode statusCode, - Times times = Times.exactly(1)) { - setResponse(plansRequest, plansResponse, statusCode, times) - } - - @Override - protected HttpRequest getRequest(String hostInstanceId) { - request().withMethod("POST") - .withPath(REGISTER_ENDPOINT_PATH) - .withBody(jsonPath("\$[?(@.hostInstanceId == '$hostInstanceId')]")) - } - - @Override - protected HttpRequest getRequest() { - request().withMethod("POST") - .withPath(REGISTER_ENDPOINT_PATH) - } - - private static HttpRequest getPlansRequest() { - request().withMethod("GET") - .withPath(PLANS_ENDPOINT_PATH) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/UserData.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/UserData.groovy deleted file mode 100644 index 9a0caafa140..00000000000 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/pg/UserData.groovy +++ /dev/null @@ -1,77 +0,0 @@ -package org.prebid.server.functional.testcontainers.scaffolding.pg - -import org.mockserver.model.HttpRequest -import org.mockserver.model.HttpStatusCode -import org.prebid.server.functional.model.deals.userdata.UserDetailsRequest -import org.prebid.server.functional.model.deals.userdata.UserDetailsResponse -import org.prebid.server.functional.model.deals.userdata.WinEventNotification -import org.prebid.server.functional.testcontainers.scaffolding.NetworkScaffolding -import org.testcontainers.containers.MockServerContainer - -import static org.mockserver.model.HttpRequest.request -import static org.mockserver.model.HttpResponse.response -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.mockserver.model.JsonPathBody.jsonPath - -class UserData extends NetworkScaffolding { - - static final String USER_DETAILS_ENDPOINT_PATH = "/deals/user-details" - static final String WIN_EVENT_ENDPOINT_PATH = "/deals/win-event" - - UserData(MockServerContainer mockServerContainer) { - super(mockServerContainer, WIN_EVENT_ENDPOINT_PATH) - } - - UserDetailsRequest getRecordedUserDetailsRequest() { - def body = getRecordedRequestsBody(userDetailsRequest).last() - decode(body, UserDetailsRequest) - } - - WinEventNotification getRecordedWinEventRequest() { - def body = getRecordedRequestsBody(request).last() - decode(body, WinEventNotification) - } - - void setUserDataResponse(UserDetailsResponse userDataResponse, HttpStatusCode httpStatusCode = OK_200) { - resetUserDetailsEndpoint() - setResponse(userDetailsRequest, userDataResponse, httpStatusCode) - } - - int getRecordedUserDetailsRequestCount() { - getRequestCount(userDetailsRequest) - } - - void resetUserDetailsEndpoint() { - reset(USER_DETAILS_ENDPOINT_PATH) - } - - @Override - void reset() { - super.reset(USER_DETAILS_ENDPOINT_PATH) - super.reset(WIN_EVENT_ENDPOINT_PATH) - } - - @Override - void setResponse() { - mockServerClient.when(request().withPath(endpoint)) - .respond(response().withStatusCode(OK_200.code())) - } - - @Override - protected HttpRequest getRequest(String bidId) { - request().withMethod("POST") - .withPath(WIN_EVENT_ENDPOINT_PATH) - .withBody(jsonPath("\$[?(@.bidId == '$bidId')]")) - } - - @Override - protected HttpRequest getRequest() { - request().withMethod("POST") - .withPath(WIN_EVENT_ENDPOINT_PATH) - } - - private static HttpRequest getUserDetailsRequest() { - request().withMethod("POST") - .withPath(USER_DETAILS_ENDPOINT_PATH) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/AlertSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/AlertSpec.groovy deleted file mode 100644 index bae95e69d96..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/AlertSpec.groovy +++ /dev/null @@ -1,281 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.mockserver.matchers.Times -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Retry - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500 -import static org.mockserver.model.HttpStatusCode.NOT_FOUND_404 -import static org.mockserver.model.HttpStatusCode.NO_CONTENT_204 -import static org.prebid.server.functional.model.deals.alert.Action.RAISE -import static org.prebid.server.functional.model.deals.alert.AlertPriority.LOW -import static org.prebid.server.functional.model.deals.alert.AlertPriority.MEDIUM -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_PASSWORD -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_USERNAME -import static org.prebid.server.functional.util.HttpUtil.AUTHORIZATION_HEADER -import static org.prebid.server.functional.util.HttpUtil.CONTENT_TYPE_HEADER -import static org.prebid.server.functional.util.HttpUtil.CONTENT_TYPE_HEADER_VALUE -import static org.prebid.server.functional.util.HttpUtil.PG_TRX_ID_HEADER -import static org.prebid.server.functional.util.HttpUtil.UUID_REGEX - -class AlertSpec extends BasePgSpec { - - private static final String PBS_REGISTER_CLIENT_ERROR = "pbs-register-client-error" - private static final String PBS_PLANNER_CLIENT_ERROR = "pbs-planner-client-error" - private static final String PBS_PLANNER_EMPTY_RESPONSE = "pbs-planner-empty-response-error" - private static final String PBS_DELIVERY_CLIENT_ERROR = "pbs-delivery-stats-client-error" - private static final Integer DEFAULT_ALERT_PERIOD = 15 - - @Retry(exceptions = [IllegalStateException.class]) - def "PBS should send alert request when the threshold is reached"() { - given: "Changed Planner Register endpoint response to return bad status code" - generalPlanner.initRegisterResponse(NOT_FOUND_404) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - when: "Initiating PBS to register its instance through the bad Planner for the first time" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "PBS sends an alert request to the Alert Service for the first time" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - when: "Initiating PBS to register its instance through the bad Planner until the period threshold of alerts is reached" - (2..DEFAULT_ALERT_PERIOD).forEach { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - } - - then: "PBS sends an alert request to the Alert Service for the second time" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 2 } - - and: "Request has the right number of failed register attempts" - def alertRequest = alert.recordedAlertRequest - assert alertRequest.details.startsWith("Service register failed to send request $DEFAULT_ALERT_PERIOD " + - "time(s) with error message") - - cleanup: "Return initial Planner response status code" - generalPlanner.initRegisterResponse() - } - - def "PBS should send an alert request with appropriate headers"() { - given: "Changed Planner Register endpoint response to return bad status code" - generalPlanner.initRegisterResponse(NOT_FOUND_404) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - when: "Initiating PBS to register its instance through the bad Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - and: "PBS sends an alert request to the Alert Service" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - then: "Request headers correspond to the payload" - def alertRequestHeaders = alert.lastRecordedAlertRequestHeaders - assert alertRequestHeaders - - and: "Request has an authorization header with a basic auth token" - def basicAuthToken = HttpUtil.makeBasicAuthHeaderValue(PG_ENDPOINT_USERNAME, PG_ENDPOINT_PASSWORD) - assert alertRequestHeaders.get(AUTHORIZATION_HEADER) == [basicAuthToken] - - and: "Request has a header with uuid value" - def uuidHeaderValue = alertRequestHeaders.get(PG_TRX_ID_HEADER) - assert uuidHeaderValue?.size() == 1 - assert (uuidHeaderValue[0] =~ UUID_REGEX).matches() - - and: "Request has a content type header" - assert alertRequestHeaders.get(CONTENT_TYPE_HEADER) == [CONTENT_TYPE_HEADER_VALUE] - - cleanup: "Return initial Planner response status code" - generalPlanner.initRegisterResponse() - } - - def "PBS should send an alert when fetching line items response status wasn't OK ('#httpStatusCode')"() { - given: "Changed Planner line items endpoint response to return bad status code" - // PBS will make 2 requests to the planner: 1 normal, 2 - recovery request - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString), httpStatusCode, Times.exactly(2)) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - when: "Initiating PBS to fetch line items through the bad Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - - then: "PBS sends an alert request to the Alert Service" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - and: "Alert request should correspond to the payload" - verifyAll(alert.recordedAlertRequest) { alertRequest -> - (alertRequest.id =~ UUID_REGEX).matches() - alertRequest.action == RAISE - alertRequest.priority == MEDIUM - alertRequest.updatedAt.isBefore(ZonedDateTime.now(ZoneId.from(UTC))) - alertRequest.name == PBS_PLANNER_CLIENT_ERROR - alertRequest.details == "Service planner failed to send request 1 time(s) with error message :" + - " Failed to retrieve line items from GP. Reason: Failed to fetch data from Planner, HTTP status code ${httpStatusCode.code()}" - - alertRequest.source.env == pgConfig.env - alertRequest.source.dataCenter == pgConfig.dataCenter - alertRequest.source.region == pgConfig.region - alertRequest.source.system == pgConfig.system - alertRequest.source.subSystem == pgConfig.subSystem - alertRequest.source.hostId == pgConfig.hostId - } - - cleanup: "Return initial Planner response status code" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString)) - - where: "Bad status codes" - httpStatusCode << [NO_CONTENT_204, NOT_FOUND_404, INTERNAL_SERVER_ERROR_500] - } - - def "PBS should send an alert when register PBS instance response status wasn't OK ('#httpStatusCode')"() { - given: "Changed Planner register endpoint response to return bad status code" - generalPlanner.initRegisterResponse(httpStatusCode) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - when: "Initiating PBS to register its instance through the bad Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "PBS sends an alert request to the Alert Service" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - and: "Alert request should correspond to the payload" - verifyAll(alert.recordedAlertRequest) { alertRequest -> - (alertRequest.id =~ UUID_REGEX).matches() - alertRequest.action == RAISE - alertRequest.priority == MEDIUM - alertRequest.updatedAt.isBefore(ZonedDateTime.now(ZoneId.from(UTC))) - alertRequest.name == PBS_REGISTER_CLIENT_ERROR - alertRequest.details.startsWith("Service register failed to send request 1 time(s) with error message :" + - " Planner responded with non-successful code ${httpStatusCode.code()}") - - alertRequest.source.env == pgConfig.env - alertRequest.source.dataCenter == pgConfig.dataCenter - alertRequest.source.region == pgConfig.region - alertRequest.source.system == pgConfig.system - alertRequest.source.subSystem == pgConfig.subSystem - alertRequest.source.hostId == pgConfig.hostId - } - - cleanup: "Return initial Planner response status code" - generalPlanner.initRegisterResponse() - - where: "Bad status codes" - httpStatusCode << [NOT_FOUND_404, INTERNAL_SERVER_ERROR_500] - } - - def "PBS should send an alert when send delivery statistics report response status wasn't OK ('#httpStatusCode')"() { - given: "Changed Delivery Statistics endpoint response to return bad status code" - deliveryStatistics.reset() - deliveryStatistics.setResponse(httpStatusCode) - - and: "Set line items response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString)) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - and: "Report to send is generated by PBS" - updateLineItemsAndWait() - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - when: "Initiating PBS to send delivery statistics report through the bad Delivery Statistics Service" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends an alert request to the Alert Service" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - and: "Alert request should correspond to the payload" - verifyAll(alert.recordedAlertRequest) { alertRequest -> - (alertRequest.id =~ UUID_REGEX).matches() - alertRequest.action == RAISE - alertRequest.priority == MEDIUM - alertRequest.updatedAt.isBefore(ZonedDateTime.now(ZoneId.from(UTC))) - alertRequest.name == PBS_DELIVERY_CLIENT_ERROR - alertRequest.details.startsWith("Service deliveryStats failed to send request 1 time(s) with error message : " + - "Report was not send to delivery stats service with a reason: Delivery stats service responded with " + - "status code = ${httpStatusCode.code()} for report with id = ") - - alertRequest.source.env == pgConfig.env - alertRequest.source.dataCenter == pgConfig.dataCenter - alertRequest.source.region == pgConfig.region - alertRequest.source.system == pgConfig.system - alertRequest.source.subSystem == pgConfig.subSystem - alertRequest.source.hostId == pgConfig.hostId - } - - cleanup: "Return initial Delivery Statistics response status code" - deliveryStatistics.reset() - deliveryStatistics.setResponse() - - and: "Report to delivery statistics is sent" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - where: "Bad status codes" - httpStatusCode << [NOT_FOUND_404, INTERNAL_SERVER_ERROR_500] - } - - def "PBS should send an alert when Planner returns empty response"() { - given: "Changed Planner get plans response to return no plans" - generalPlanner.initPlansResponse(new PlansResponse(lineItems: [])) - - and: "PBS alert counter is reset" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.resetAlertCountRequest) - - and: "Initial Alert Service request count is taken" - def initialRequestCount = alert.requestCount - - when: "Initiating PBS to fetch line items through the Planner" - updateLineItemsAndWait() - - then: "PBS sends an alert request to the Alert Service" - PBSUtils.waitUntil { alert.requestCount == initialRequestCount + 1 } - - and: "Alert request should correspond to the payload" - verifyAll(alert.recordedAlertRequest) { alertRequest -> - (alertRequest.id =~ UUID_REGEX).matches() - alertRequest.action == RAISE - alertRequest.priority == LOW - alertRequest.updatedAt.isBefore(ZonedDateTime.now(ZoneId.from(UTC))) - alertRequest.name == PBS_PLANNER_EMPTY_RESPONSE - alertRequest.details.startsWith("Service planner failed to send request 1 time(s) with error message : " + - "Response without line items was received from planner") - - alertRequest.source.env == pgConfig.env - alertRequest.source.dataCenter == pgConfig.dataCenter - alertRequest.source.region == pgConfig.region - alertRequest.source.system == pgConfig.system - alertRequest.source.subSystem == pgConfig.subSystem - alertRequest.source.hostId == pgConfig.hostId - } - - cleanup: "Return initial Planner response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString)) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/BasePgSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/BasePgSpec.groovy deleted file mode 100644 index 9159bba8bb0..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/BasePgSpec.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.userdata.UserDetailsResponse -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.service.PrebidServerService -import org.prebid.server.functional.testcontainers.Dependencies -import org.prebid.server.functional.testcontainers.PbsPgConfig -import org.prebid.server.functional.testcontainers.PbsServiceFactory -import org.prebid.server.functional.testcontainers.scaffolding.Bidder -import org.prebid.server.functional.testcontainers.scaffolding.pg.Alert -import org.prebid.server.functional.testcontainers.scaffolding.pg.DeliveryStatistics -import org.prebid.server.functional.testcontainers.scaffolding.pg.GeneralPlanner -import org.prebid.server.functional.testcontainers.scaffolding.pg.UserData -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Retry -import spock.lang.Shared -import spock.lang.Specification - -@Retry(mode = Retry.Mode.SETUP_FEATURE_CLEANUP) -abstract class BasePgSpec extends Specification { - - protected static final PbsServiceFactory pbsServiceFactory = new PbsServiceFactory(Dependencies.networkServiceContainer) - - protected static final GeneralPlanner generalPlanner = new GeneralPlanner(Dependencies.networkServiceContainer) - protected static final DeliveryStatistics deliveryStatistics = new DeliveryStatistics(Dependencies.networkServiceContainer) - protected static final Alert alert = new Alert(Dependencies.networkServiceContainer) - protected static final UserData userData = new UserData(Dependencies.networkServiceContainer) - - protected static final PbsPgConfig pgConfig = new PbsPgConfig(Dependencies.networkServiceContainer) - protected static final Bidder bidder = new Bidder(Dependencies.networkServiceContainer) - - @Shared - protected final PrebidServerService pgPbsService = pbsServiceFactory.getService(pgConfig.properties) - - def setupSpec() { - bidder.setResponse() - generalPlanner.setResponse() - deliveryStatistics.setResponse() - alert.setResponse() - userData.setResponse() - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - } - - def cleanupSpec() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - generalPlanner.reset() - deliveryStatistics.reset() - alert.reset() - userData.reset() - bidder.reset() - } - - protected void updateLineItemsAndWait() { - def initialPlansRequestCount = generalPlanner.recordedPlansRequestCount - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == initialPlansRequestCount + 1 } - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/CurrencySpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/CurrencySpec.groovy deleted file mode 100644 index 9f2d6a3f540..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/CurrencySpec.groovy +++ /dev/null @@ -1,98 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.lineitem.Price -import org.prebid.server.functional.model.mock.services.currencyconversion.CurrencyConversionRatesResponse -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.service.PrebidServerService -import org.prebid.server.functional.testcontainers.scaffolding.CurrencyConversion -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Shared - -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.testcontainers.Dependencies.networkServiceContainer - -class CurrencySpec extends BasePgSpec { - - private static final CurrencyConversion currencyConversion = new CurrencyConversion(networkServiceContainer).tap { - setCurrencyConversionRatesResponse(CurrencyConversionRatesResponse.defaultCurrencyConversionRatesResponse) - } - - private static final Map pgCurrencyConverterPbsConfig = externalCurrencyConverterConfig + pgConfig.properties - private static final PrebidServerService pgCurrencyConverterPbsService = pbsServiceFactory.getService(pgCurrencyConverterPbsConfig) - - @Shared - BidRequest bidRequest - - def setup() { - bidRequest = BidRequest.defaultBidRequest - bidder.setResponse(bidRequest.id, BidResponse.getDefaultBidResponse(bidRequest)) - pgCurrencyConverterPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should convert non-default line item currency to the default one during the bidder auction"() { - given: "Planner Mock line items with the same CPM but different currencies" - def accountId = bidRequest.site.publisher.id - def defaultCurrency = Price.defaultPrice.currency - def nonDefaultCurrency = "EUR" - def defaultCurrencyLineItem = [LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 1, currency: defaultCurrency) }] - def nonDefaultCurrencyLineItems = [LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 1, currency: nonDefaultCurrency) }, - LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 1, currency: nonDefaultCurrency) }, - LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 1, currency: nonDefaultCurrency) }] - def lineItems = defaultCurrencyLineItem + nonDefaultCurrencyLineItems - def plansResponse = new PlansResponse(lineItems: lineItems) - generalPlanner.initPlansResponse(plansResponse) - def nonDefaultCurrencyLineItemIds = nonDefaultCurrencyLineItems.collect { it.lineItemId } - - and: "Line items are fetched by PBS" - def initialPlansRequestCount = generalPlanner.recordedPlansRequestCount - pgCurrencyConverterPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == initialPlansRequestCount + 1 } - - when: "Auction is requested" - def auctionResponse = pgCurrencyConverterPbsService.sendAuctionRequest(bidRequest) - - then: "All line items are ready to be served" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == plansResponse.lineItems.size() - - and: "Line Item with EUR defaultCurrency was sent to bidder as EUR defaultCurrency rate > than USD" - assert auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value)?.sort() == - nonDefaultCurrencyLineItemIds.sort() - } - - def "PBS should invalidate line item with an unknown for the conversion rate currency"() { - given: "Planner Mock line items with a default currency and unknown currency" - def defaultCurrency = Price.defaultPrice.currency - def unknownCurrency = "UAH" - def defaultCurrencyLineItem = [LineItem.getDefaultLineItem(bidRequest.site.publisher.id).tap { price = new Price(cpm: 1, currency: defaultCurrency) }] - def unknownCurrencyLineItem = [LineItem.getDefaultLineItem(bidRequest.site.publisher.id).tap { price = new Price(cpm: 1, currency: unknownCurrency) }] - def lineItems = defaultCurrencyLineItem + unknownCurrencyLineItem - def plansResponse = new PlansResponse(lineItems: lineItems) - generalPlanner.initPlansResponse(plansResponse) - def defaultCurrencyLineItemId = defaultCurrencyLineItem.collect { it.lineItemId } - - and: "Line items are fetched by PBS" - def initialPlansRequestCount = generalPlanner.recordedPlansRequestCount - pgCurrencyConverterPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == initialPlansRequestCount + 1 } - - when: "Auction is requested" - def auctionResponse = pgCurrencyConverterPbsService.sendAuctionRequest(bidRequest) - - then: "Only line item with the default currency is ready to be served and was sent to bidder" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe == defaultCurrencyLineItemId as Set - assert auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) == - defaultCurrencyLineItemId as Set - } - - private static Map getExternalCurrencyConverterConfig() { - ["currency-converter.external-rates.enabled" : "true", - "currency-converter.external-rates.url" : "$networkServiceContainer.rootUri/currency".toString(), - "currency-converter.external-rates.default-timeout-ms": "4000", - "currency-converter.external-rates.refresh-period-ms" : "900000" - ] - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/LineItemStatusSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/LineItemStatusSpec.groovy deleted file mode 100644 index 77f2c31f603..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/LineItemStatusSpec.groovy +++ /dev/null @@ -1,193 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.DeliverySchedule -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.lineitem.Token -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.service.PrebidServerException -import org.prebid.server.functional.util.ObjectMapperWrapper -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime -import java.time.temporal.ChronoUnit - -import static java.time.ZoneOffset.UTC - -class LineItemStatusSpec extends BasePgSpec implements ObjectMapperWrapper { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should return a bad request exception when no 'id' query parameter is provided"() { - when: "Requesting endpoint without 'id' parameter" - pgPbsService.sendLineItemStatusRequest(null) - - then: "PBS throws an exception" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody.contains("id parameter is required") - } - - def "PBS should return a bad request exception when endpoint is requested with not existing line item id"() { - given: "Not existing line item id" - def notExistingLineItemId = PBSUtils.randomString - - when: "Requesting endpoint" - pgPbsService.sendLineItemStatusRequest(notExistingLineItemId) - - then: "PBS throws an exception" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody.contains("LineItem not found: $notExistingLineItemId") - } - - def "PBS should return an empty line item status response when line item doesn't have a scheduled delivery"() { - given: "Line item with no delivery schedule" - def plansResponse = PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].deliverySchedules = null - } - def lineItemId = plansResponse.lineItems[0].lineItemId - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Requesting endpoint" - def lineItemStatusReport = pgPbsService.sendLineItemStatusRequest(lineItemId) - - then: "Empty line item status report is returned" - verifyAll(lineItemStatusReport) { - it.lineItemId == lineItemId - !it.deliverySchedule - !it.spentTokens - !it.readyToServeTimestamp - !it.pacingFrequency - !it.accountId - !it.target - } - } - - def "PBS should return filled line item status report when line item has a scheduled delivery"() { - given: "Line item with a scheduled delivery" - def plansResponse = new PlansResponse(lineItems: [LineItem.getDefaultLineItem(PBSUtils.randomString).tap { - deliverySchedules = [DeliverySchedule.defaultDeliverySchedule] - }]) - generalPlanner.initPlansResponse(plansResponse) - def lineItemId = plansResponse.lineItems[0].lineItemId - def lineItem = plansResponse.lineItems[0] - def deliverySchedule = lineItem.deliverySchedules[0] - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Requesting endpoint" - def lineItemStatusReport = pgPbsService.sendLineItemStatusRequest(lineItemId) - - then: "Line item status report is returned" - def reportTimeZone = lineItemStatusReport.deliverySchedule?.planStartTimeStamp?.zone - assert reportTimeZone - - verifyAll(lineItemStatusReport) { - it.lineItemId == lineItemId - it.deliverySchedule?.planId == deliverySchedule.planId - - it.deliverySchedule.planStartTimeStamp == - timeToReportFormat(deliverySchedule.startTimeStamp, reportTimeZone) - it.deliverySchedule?.planExpirationTimeStamp == - timeToReportFormat(deliverySchedule.endTimeStamp, reportTimeZone) - it.deliverySchedule?.planUpdatedTimeStamp == - timeToReportFormat(deliverySchedule.updatedTimeStamp, reportTimeZone) - - it.deliverySchedule?.tokens?.size() == deliverySchedule.tokens.size() - it.deliverySchedule?.tokens?.first()?.priorityClass == deliverySchedule.tokens[0].priorityClass - it.deliverySchedule?.tokens?.first()?.total == deliverySchedule.tokens[0].total - !it.deliverySchedule?.tokens?.first()?.spent - !it.deliverySchedule?.tokens?.first()?.totalSpent - - it.spentTokens == 0 - it.readyToServeTimestamp.isBefore(ZonedDateTime.now()) - it.pacingFrequency == getDeliveryRateMs(deliverySchedule) - it.accountId == lineItem.accountId - encode(it.target) == encode(lineItem.targeting) - } - } - - def "PBS should return line item status report with an active scheduled delivery"() { - given: "Line item with an active and expired scheduled deliveries" - def inactiveDeliverySchedule = DeliverySchedule.defaultDeliverySchedule.tap { - startTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusHours(12) - updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusHours(12) - endTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusHours(6) - } - def activeDeliverySchedule = DeliverySchedule.defaultDeliverySchedule.tap { - startTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)) - updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)) - endTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).plusHours(12) - } - def plansResponse = new PlansResponse(lineItems: [LineItem.getDefaultLineItem(PBSUtils.randomString).tap { - deliverySchedules = [inactiveDeliverySchedule, activeDeliverySchedule] - }]) - generalPlanner.initPlansResponse(plansResponse) - def lineItemId = plansResponse.lineItems[0].lineItemId - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Requesting endpoint" - def lineItemStatusReport = pgPbsService.sendLineItemStatusRequest(lineItemId) - - then: "Line item status report is returned with an active delivery" - assert lineItemStatusReport.lineItemId == lineItemId - assert lineItemStatusReport.deliverySchedule?.planId == activeDeliverySchedule.planId - } - - def "PBS should return line item status report with increased spent token number when PG auction has happened"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Line item with a scheduled delivery" - def plansResponse = new PlansResponse(lineItems: [LineItem.getDefaultLineItem(bidRequest.site.publisher.id).tap { - deliverySchedules = [DeliverySchedule.defaultDeliverySchedule.tap { - tokens = [Token.defaultToken] - }] - }]) - generalPlanner.initPlansResponse(plansResponse) - def lineItemId = plansResponse.lineItems[0].lineItemId - def spentTokensNumber = 1 - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "PG bid response is set" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "PBS PG auction is requested" - pgPbsService.sendAuctionRequest(bidRequest) - - when: "Requesting line item status endpoint" - def lineItemStatusReport = pgPbsService.sendLineItemStatusRequest(lineItemId) - - then: "Spent token number in line item status report is increased" - assert lineItemStatusReport.lineItemId == lineItemId - assert lineItemStatusReport.spentTokens == spentTokensNumber - assert lineItemStatusReport.deliverySchedule?.tokens?.first()?.spent == spentTokensNumber - } - - private ZonedDateTime timeToReportFormat(ZonedDateTime givenTime, ZoneId reportTimeZone) { - givenTime.truncatedTo(ChronoUnit.MILLIS).withZoneSameInstant(reportTimeZone) - } - - private Integer getDeliveryRateMs(DeliverySchedule deliverySchedule) { - deliverySchedule.tokens[0].total > 0 - ? (deliverySchedule.endTimeStamp.toInstant().toEpochMilli() - - deliverySchedule.startTimeStamp.toInstant().toEpochMilli()) / - deliverySchedule.tokens[0].total - : null - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/PgAuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/PgAuctionSpec.groovy deleted file mode 100644 index 4d7ffec88af..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/PgAuctionSpec.groovy +++ /dev/null @@ -1,520 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.UidsCookie -import org.prebid.server.functional.model.bidder.Generic -import org.prebid.server.functional.model.deals.lineitem.FrequencyCap -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.lineitem.LineItemSize -import org.prebid.server.functional.model.deals.lineitem.Price -import org.prebid.server.functional.model.deals.lineitem.RelativePriority -import org.prebid.server.functional.model.deals.lineitem.targeting.Targeting -import org.prebid.server.functional.model.deals.userdata.UserDetailsResponse -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.BidRequestExt -import org.prebid.server.functional.model.request.auction.Bidder -import org.prebid.server.functional.model.request.auction.Imp -import org.prebid.server.functional.model.request.auction.Prebid -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.deals.lineitem.LineItemStatus.DELETED -import static org.prebid.server.functional.model.deals.lineitem.LineItemStatus.PAUSED -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.HIGH -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.LOW -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.MEDIUM -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.VERY_HIGH -import static org.prebid.server.functional.model.deals.lineitem.RelativePriority.VERY_LOW -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.IN -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.INTERSECTS -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_MEDIA_TYPE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_SIZE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DEVICE_REGION -import static org.prebid.server.functional.model.response.auction.MediaType.BANNER -import static org.prebid.server.functional.util.HttpUtil.UUID_REGEX - -class PgAuctionSpec extends BasePgSpec { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should return base response after PG auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Auction response contains values according to the payload" - verifyAll(auctionResponse) { - auctionResponse.id == bidRequest.id - auctionResponse.cur == pgConfig.currency - !auctionResponse.bidid - !auctionResponse.customdata - !auctionResponse.nbr - } - - and: "Seat bid corresponds to the request seat bid" - assert auctionResponse.seatbid?.size() == bidRequest.imp.size() - def seatBid = auctionResponse.seatbid[0] - assert seatBid.seat == GENERIC - - assert seatBid.bid?.size() == 1 - - verifyAll(seatBid.bid[0]) { bid -> - (bid.id =~ UUID_REGEX).matches() - bid.impid == bidRequest.imp[0].id - bid.price == bidResponse.seatbid[0].bid[0].price - bid.crid == bidResponse.seatbid[0].bid[0].crid - bid.ext?.prebid?.type == BANNER - bid.ext?.origbidcpm == bidResponse.seatbid[0].bid[0].price - } - } - - def "PBS shouldn't process line item with #reason"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock non matched line item" - generalPlanner.initPlansResponse(plansResponse.tap { - it.lineItems[0].accountId = bidRequest.site.publisher.id - }) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start processing PG deals" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - reason | plansResponse - - "non matched targeting" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].targeting = new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [BANNER]) - .addTargeting(DEVICE_REGION, IN, [14]) - .build() - } - - "empty targeting" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].targeting = null - } - - "non matched bidder" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].source = PBSUtils.randomString - } - - "inactive status" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].status = DELETED - } - - "paused status" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].status = PAUSED - } - - "expired lifetime" | PlansResponse.getDefaultPlansResponse(PBSUtils.randomString).tap { - lineItems[0].startTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusMinutes(2) - lineItems[0].endTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusMinutes(1) - lineItems[0].updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusMinutes(2) - } - } - - def "PBS shouldn't process line item with non matched publisher account id"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock non matched publisher account id line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(PBSUtils.randomNumber as String) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start processing PG deals" - assert !auctionResponse.ext?.debug?.pgmetrics - } - - def "PBS shouldn't start processing PG deals when there is no any line item"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock no line items" - generalPlanner.initPlansResponse(new PlansResponse(lineItems: [])) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start processing PG deals" - assert !auctionResponse.ext?.debug?.pgmetrics - } - - def "PBS shouldn't allow line item with #reason delivery plan take part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line item with expired delivery schedule" - def plansResponse = plansResponseClosure(bidRequest) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't allow line item take part in auction" - assert auctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == - plansResponse.lineItems.collect { it.lineItemId } as Set - - where: - reason | plansResponseClosure - - "expired" | { BidRequest bidReq -> - PlansResponse.getDefaultPlansResponse(bidReq.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].startTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusDays(2) - lineItems[0].deliverySchedules[0].updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusDays(2) - lineItems[0].deliverySchedules[0].endTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).minusDays(1) - } - } - - "not set" | { BidRequest bidReq -> - PlansResponse.getDefaultPlansResponse(bidReq.site.publisher.id).tap { - lineItems[0].deliverySchedules = [] - } - } - } - - def "PBS should process only first #maxDealsPerBidder line items among the matched ones"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Publisher account id" - def accountId = bidRequest.site.publisher.id - - and: "Planner Mock line items to return #maxDealsPerBidder + 1 line items" - def maxLineItemsToProcess = pgConfig.maxDealsPerBidder - def plansResponse = new PlansResponse(lineItems: (1..maxLineItemsToProcess + 1).collect { - LineItem.getDefaultLineItem(accountId) - }) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "There are #maxLineItemsToProcess + 1 line items are matched and ready to serve" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == maxLineItemsToProcess + 1 - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == maxLineItemsToProcess + 1 - - and: "Only #maxLineItemsToProcess were sent to the bidder" - assert auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value)?.size() == maxLineItemsToProcess - } - - def "PBS should send to bidder only the first line item among line items with identical deal ids"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Deal id" - def dealId = PBSUtils.randomString - - and: "Planner Mock line items with identical deal ids" - def plansResponse = new PlansResponse(lineItems: (1..2).collect { - LineItem.getDefaultLineItem(bidRequest.site.publisher.id).tap { it.dealId = dealId } - }) - generalPlanner.initPlansResponse(plansResponse) - def lineItemsNumber = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "There are 2 matched and ready to serve line items" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemsNumber - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItemsNumber - - and: "Only 1 line item was sent to the bidder" - assert auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value)?.size() == lineItemsNumber - 1 - } - - def "PBS should allow line item with matched to the request bidder alias take part in auction"() { - given: "Bid request with set bidder alias" - def lineItemSource = PBSUtils.randomString - def bidRequest = BidRequest.defaultBidRequest.tap { - def prebid = new Prebid(aliases: [(lineItemSource): GENERIC], debug: 1) - ext = new BidRequestExt(prebid: prebid) - } - - and: "Planner Mock line items with changed line item source" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].source = lineItemSource - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemCount = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Line item was matched by alias bidder and took part in auction" - def pgMetrics = auctionResponse.ext?.debug?.pgmetrics - assert pgMetrics - assert pgMetrics.sentToBidder?.get(lineItemSource)?.size() == lineItemCount - assert pgMetrics.readyToServe?.size() == lineItemCount - assert pgMetrics.matchedWholeTargeting?.size() == lineItemCount - } - - def "PBS should abandon line items with matched user frequency capped ids take part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items with added frequency cap" - def fcapId = PBSUtils.randomNumber as String - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].frequencyCaps = [FrequencyCap.defaultFrequencyCap.tap { it.fcapId = fcapId }] - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "User Service Response is set to return frequency capped id identical to the line item fcapId" - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse.tap { - user.ext.fcapIds = [fcapId] - }) - - and: "Cookies header" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS hasn't started processing PG deals as line item was recognized as frequency capped" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedTargetingFcapped?.size() == plansResponse.lineItems.size() - - cleanup: - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - } - - def "PBS should allow line items with unmatched user frequency capped ids take part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items with added frequency cap" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].frequencyCaps = [FrequencyCap.defaultFrequencyCap.tap { fcapId = PBSUtils.randomNumber as String }] - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "User Service Response is set to return frequency capped id not identical to the line item fcapId" - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse.tap { - user.ext.fcapIds = [PBSUtils.randomNumber as String] - }) - - and: "Cookies header" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS hasn't started processing PG deals as line item was recognized as frequency capped" - assert !auctionResponse.ext?.debug?.pgmetrics?.matchedTargetingFcapped - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe - - cleanup: - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - } - - def "PBS shouldn't use already matched line items by the same bidder during one auction"() { - given: "Bid request with two impressions" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].ext.prebid.bidder = new Bidder(generic: new Generic()) - imp << Imp.defaultImpression - imp[1].ext.prebid.bidder = new Bidder(generic: new Generic()) - } - def accountId = bidRequest.site.publisher.id - - and: "Planner Mock with two line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(accountId).tap { - lineItems << LineItem.getDefaultLineItem(accountId) - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemCount = plansResponse.lineItems.size() - def lineItemIds = plansResponse.lineItems.collect { it.lineItemId } as Set - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Two line items are ready to be served" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItemCount - - and: "Two (as the number of imps) different line items were sent to the bidder" - def sentToBidder = auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == lineItemCount - assert sentToBidder.sort() == lineItemIds.sort() - - def sentToBidderAsTopMatch = auctionResponse.ext?.debug?.pgmetrics?.sentToBidderAsTopMatch?.get(GENERIC.value) - assert sentToBidderAsTopMatch?.size() == lineItemCount - assert sentToBidderAsTopMatch.sort() == lineItemIds.sort() - } - - def "PBS should send line items with the highest priority to the bidder during auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Planner Mock line items with different priorities" - def lowerPriorityLineItems = [LineItem.getDefaultLineItem(accountId).tap { relativePriority = VERY_LOW }, - LineItem.getDefaultLineItem(accountId).tap { relativePriority = LOW }] - def higherPriorityLineItems = [LineItem.getDefaultLineItem(accountId).tap { relativePriority = MEDIUM }, - LineItem.getDefaultLineItem(accountId).tap { relativePriority = HIGH }, - LineItem.getDefaultLineItem(accountId).tap { relativePriority = VERY_HIGH }] - def lineItems = lowerPriorityLineItems + higherPriorityLineItems - def plansResponse = new PlansResponse(lineItems: lineItems) - def higherPriorityLineItemIds = higherPriorityLineItems.collect { it.lineItemId } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "All line items are ready to be served" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItems.size() - - and: "#maxDealsPerBidder[3] line items were send to bidder" - def sentToBidder = auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == pgConfig.maxDealsPerBidder - - and: "Those line items with the highest priority were sent" - assert sentToBidder.sort() == higherPriorityLineItemIds.sort() - } - - def "PBS should send line items with the highest CPM to the bidder during auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Planner Mock line items with different CPMs" - def currency = Price.defaultPrice.currency - def lowerCpmLineItems = [LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 1, currency: currency) }, - LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 2, currency: currency) }] - def higherCpmLineItems = [LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 3, currency: currency) }, - LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 4, currency: currency) }, - LineItem.getDefaultLineItem(accountId).tap { price = new Price(cpm: 5, currency: currency) }] - def lineItems = lowerCpmLineItems + higherCpmLineItems - def plansResponse = new PlansResponse(lineItems: lineItems) - def higherCpmLineItemIds = higherCpmLineItems.collect { it.lineItemId } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "All line items are ready to be served" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItems.size() - - and: "#maxDealsPerBidder[3] line items were send to bidder" - def sentToBidder = auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == pgConfig.maxDealsPerBidder - - and: "Those line items with the highest CPM were sent" - assert sentToBidder.sort() == higherCpmLineItemIds.sort() - } - - def "PBS should send line items with the highest priority to the bidder during auction despite the price"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Planner Mock line items with different priorities and CPMs" - def lineItems = RelativePriority.values().collect { relativePriority -> - LineItem.getDefaultLineItem(accountId).tap { - it.relativePriority = relativePriority - it.price = Price.defaultPrice - } - } - - def plansResponse = new PlansResponse(lineItems: lineItems) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "All line items are ready to be served" - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItems.size() - - and: "#maxDealsPerBidder[3] line items were send to bidder" - def sentToBidder = auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - def dealsPerBidder = pgConfig.maxDealsPerBidder - assert sentToBidder?.size() == dealsPerBidder - - and: "Those line items with the highest priority were sent" - def prioritizedLineItems = lineItems.sort { it.relativePriority.value } - .take(dealsPerBidder) - assert sentToBidder.sort() == prioritizedLineItems.collect { it.lineItemId }.sort() - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidResponseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidResponseSpec.groovy deleted file mode 100644 index 2978fb91e0f..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidResponseSpec.groovy +++ /dev/null @@ -1,211 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.LineItemSize -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.Format -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.PBSUtils - -import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC - -class PgBidResponseSpec extends BasePgSpec { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should allow valid bidder response with deals info continue taking part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - def lineItemCount = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder returned valid response with deals info during auction" - assert auctionResponse.ext?.debug?.pgmetrics?.sentToClient?.size() == lineItemCount - assert auctionResponse.ext?.debug?.pgmetrics?.sentToClientAsTopMatch?.size() == lineItemCount - } - - def "PBS should invalidate bidder response when bid id doesn't match to the bid request bid id"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse).tap { - seatbid[0].bid[0].impid = PBSUtils.randomNumber as String - } - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder response is invalid" - def bidderErrors = auctionResponse.ext?.errors?.get(GENERIC) - def bidId = bidResponse.seatbid[0].bid[0].id - - assert bidderErrors?.size() == 1 - assert bidderErrors[0].message ==~ - /BidId `$bidId` validation messages:.* Error: Bid \"$bidId\" has no corresponding imp in request.*/ - } - - def "PBS should invalidate bidder response when deal id doesn't match to the bid request deal id"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse).tap { - seatbid[0].bid[0].dealid = PBSUtils.randomNumber as String - } - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder response is invalid" - def bidderErrors = auctionResponse.ext?.errors?.get(GENERIC) - def bidId = bidResponse.seatbid[0].bid[0].id - - assert bidderErrors?.size() == 1 - assert bidderErrors[0].message ==~ /BidId `$bidId` validation messages:.* Warning: / + - /WARNING: Bid "$bidId" has 'dealid' not present in corresponding imp in request.*/ - } - - def "PBS should invalidate bidder response when non-matched to the bid request size is returned"() { - given: "Bid request with set sizes" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = [Format.defaultFormat] - } - def impFormat = bidRequest.imp[0].banner.format[0] - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response with unmatched to the bid request size" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse).tap { - seatbid[0].bid[0].w = PBSUtils.randomNumber - } - def bid = bidResponse.seatbid[0].bid[0] - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder response is invalid" - assert auctionResponse.ext?.debug?.pgmetrics?.responseInvalidated?.size() == plansResponse.lineItems.size() - - and: "PBS invalidated response as unmatched by size" - def bidderErrors = auctionResponse.ext?.errors?.get(GENERIC) - - assert bidderErrors?.size() == 1 - assert bidderErrors[0].message ==~ /BidId `$bid.id` validation messages:.* Error: / + - /Bid "$bid.id" has 'w' and 'h' not supported by corresponding imp in request\. / + - /Bid dimensions: '${bid.w}x$bid.h', formats in imp: '${impFormat.w}x$impFormat.h'.*/ - } - - def "PBS should invalidate bidder response when non-matched to the PBS line item size response is returned"() { - given: "Bid request" - def newFormat = new Format(w: PBSUtils.randomNumber, h: PBSUtils.randomNumber) - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = [Format.defaultFormat, newFormat] - } - - and: "Planner Mock line items with a default size" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].sizes = [LineItemSize.defaultLineItemSize] - } - def lineItemSize = plansResponse.lineItems[0].sizes[0] - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response with non-matched to the line item size" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse).tap { - seatbid[0].bid[0].w = newFormat.w - seatbid[0].bid[0].h = newFormat.h - } - def bid = bidResponse.seatbid[0].bid[0] - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder response is invalid" - assert auctionResponse.ext?.debug?.pgmetrics?.responseInvalidated?.size() == plansResponse.lineItems.size() - - and: "PBS invalidated response as not matched by size" - def bidderErrors = auctionResponse.ext?.errors?.get(GENERIC) - - assert bidderErrors?.size() == 1 - assert bidderErrors[0].message ==~ /BidId `$bid.id` validation messages:.* Error: / + - /Bid "$bid.id" has 'w' and 'h' not matched to Line Item\. / + - /Bid dimensions: '${bid.w}x$bid.h', Line Item sizes: '${lineItemSize.w}x$lineItemSize.h'.*/ - } - - def "PBS should invalidate bidder response when line items sizes empty"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.format = [Format.defaultFormat] - } - - and: "Planner Mock line items with a empty sizes" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].sizes = [] - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Set bid response without line items sizes 'h' and 'w' " - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - def bid = bidResponse.seatbid[0].bid[0] - bidder.setResponse(bidRequest.id, bidResponse) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder response is invalid" - assert auctionResponse.ext?.debug?.pgmetrics?.responseInvalidated?.size() == plansResponse.lineItems.size() - - and: "PBS invalidated response as line items sizes empty" - def bidderErrors = auctionResponse.ext?.errors?.get(GENERIC) - - assert bidderErrors?.size() == 1 - assert bidderErrors[0].message == "BidId `${bid.id}` validation messages: " + - "Error: Line item sizes were not found for " + - "bidId ${bid.id} and dealId ${plansResponse.getLineItems()[0].dealId}" - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidderRequestSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidderRequestSpec.groovy deleted file mode 100644 index 0a0219d34ee..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/PgBidderRequestSpec.groovy +++ /dev/null @@ -1,167 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.UidsCookie -import org.prebid.server.functional.model.bidder.Generic -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.userdata.UserDetailsResponse -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.Bidder -import org.prebid.server.functional.model.request.auction.Device -import org.prebid.server.functional.model.request.auction.Imp -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Ignore - -class PgBidderRequestSpec extends BasePgSpec { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should be able to add given device info to the bidder request"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - device = new Device(ua: PBSUtils.randomString, - make: PBSUtils.randomString, - model: PBSUtils.randomString) - } - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "User Service response is set" - def userResponse = UserDetailsResponse.defaultUserResponse - userData.setUserDataResponse(userResponse) - - and: "Cookies with user ids" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS sent a request to the bidder with added device info" - verifyAll(bidder.getBidderRequest(bidRequest.id)) { bidderRequest -> - bidderRequest.user?.ext?.fcapids == userResponse.user.ext.fcapIds - bidderRequest.user.data?.size() == userResponse.user.data.size() - bidderRequest.user.data[0].id == userResponse.user.data[0].name - bidderRequest.user.data[0].segment?.size() == userResponse.user.data[0].segment.size() - bidderRequest.user.data[0].segment[0].id == userResponse.user.data[0].segment[0].id - } - } - - def "PBS should be able to add pmp deals part to the bidder request when PG is enabled"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def accountId = bidRequest.site.publisher.id - def plansResponse = new PlansResponse(lineItems: [LineItem.getDefaultLineItem(accountId), LineItem.getDefaultLineItem(accountId)]) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS sent a request to the bidder with added deals" - def bidderRequest = bidder.getBidderRequest(bidRequest.id) - - assert bidderRequest.imp?.size() == bidRequest.imp.size() - assert bidderRequest.imp[0].pmp?.deals?.size() == plansResponse.lineItems.size() - assert bidderRequest.imp[0].pmp?.deals - assert plansResponse.lineItems.each { lineItem -> - def deal = bidderRequest.imp[0]?.pmp?.deals?.find { it.id == lineItem.dealId } - - assert deal - verifyAll(deal) { - deal?.ext?.line?.lineItemId == lineItem.lineItemId - deal?.ext?.line?.extLineItemId == lineItem.extLineItemId - deal?.ext?.line?.sizes?.size() == lineItem.sizes.size() - deal?.ext?.line?.sizes[0].w == lineItem.sizes[0].w - deal?.ext?.line?.sizes[0].h == lineItem.sizes[0].h - } - } - } - - @Ignore - def "PBS shouldn't add already top matched line item by first impression to the second impression deals bidder request section"() { - given: "Bid request with two impressions" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].ext.prebid.bidder = new Bidder(generic: new Generic()) - imp << Imp.defaultImpression - imp[1].ext.prebid.bidder = new Bidder(generic: new Generic()) - } - - and: "Planner Mock line items" - def accountId = bidRequest.site.publisher.id - def plansResponse = new PlansResponse(lineItems: [LineItem.getDefaultLineItem(accountId), LineItem.getDefaultLineItem(accountId)]) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS sent a request to the bidder with two impressions" - def bidderRequest = bidder.getBidderRequest(bidRequest.id) - assert bidderRequest.imp?.size() == bidRequest.imp.size() - - and: "First impression contains 2 deals according to the line items" - def firstRequestImp = bidderRequest.imp.find { it.id == bidRequest.imp[0].id } - assert firstRequestImp?.pmp?.deals?.size() == plansResponse.lineItems.size() - assert plansResponse.lineItems.each { lineItem -> - def deal = firstRequestImp.pmp.deals.find { it.id == lineItem.dealId } - - assert deal - verifyAll(deal) { - deal?.ext?.line?.lineItemId == lineItem.lineItemId - deal?.ext?.line?.extLineItemId == lineItem.extLineItemId - deal?.ext?.line?.sizes?.size() == lineItem.sizes.size() - deal?.ext?.line?.sizes[0].w == lineItem.sizes[0].w - deal?.ext?.line?.sizes[0].h == lineItem.sizes[0].h - } - } - - def topMatchLineItemId = firstRequestImp.pmp.deals.first().ext.line.lineItemId - def secondRequestImp = bidderRequest.imp.find { it.id == bidRequest.imp[1].id } - - and: "Second impression contains only 1 deal excluding already top matched line items by the first impression" - assert secondRequestImp.pmp.deals.size() == plansResponse.lineItems.size() - 1 - assert !(secondRequestImp.pmp.deals.collect { it.ext.line.lineItemId } in topMatchLineItemId) - - assert plansResponse.lineItems.findAll { it.lineItemId != topMatchLineItemId }.each { lineItem -> - def deal = secondRequestImp.pmp.deals.find { it.id == lineItem.dealId } - - assert deal - verifyAll(deal) { - deal?.ext?.line?.lineItemId == lineItem.lineItemId - deal?.ext?.line?.extLineItemId == lineItem.extLineItemId - deal?.ext?.line?.sizes?.size() == lineItem.sizes.size() - deal?.ext?.line?.sizes[0].w == lineItem.sizes[0].w - deal?.ext?.line?.sizes[0].h == lineItem.sizes[0].h - } - } - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/PgDealsOnlySpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/PgDealsOnlySpec.groovy deleted file mode 100644 index d5677d963cf..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/PgDealsOnlySpec.groovy +++ /dev/null @@ -1,190 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.bidder.BidderName -import org.prebid.server.functional.model.bidder.Generic -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.BidRequestExt -import org.prebid.server.functional.model.request.auction.Prebid -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.PBSUtils - -import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC -import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID - -class PgDealsOnlySpec extends BasePgSpec { - - def "PBS shouldn't call bidder when bidder pgdealsonly flag is set to true and no available PG line items"() { - given: "Bid request with set pgdealsonly flag" - def bidRequest = BidRequest.defaultBidRequest - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(pgDealsOnly: true) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(new PlansResponse(lineItems: [])) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't called bidder during auction" - assert initialBidderRequestCount == bidder.requestCount - - and: "PBS returns a not calling bidder warning" - def auctionWarnings = auctionResponse.ext?.warnings?.get(PREBID) - assert auctionWarnings.size() == 1 - assert auctionWarnings[0].code == 999 - assert auctionWarnings[0].message == - "Not calling $GENERIC.value bidder for impressions ${bidRequest.imp[0].id}" + - " due to pgdealsonly flag and no available PG line items." - } - - def "PBS shouldn't call bidder when bidder alias is set, bidder pgdealsonly flag is set to true and no available PG line items"() { - given: "Bid request with set bidder alias and pgdealsonly flag" - def bidderAliasName = PBSUtils.randomString - def bidRequest = BidRequest.defaultBidRequest.tap { - def prebid = new Prebid(aliases: [(bidderAliasName): BidderName.GENERIC], debug: 1) - ext = new BidRequestExt(prebid: prebid) - } - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(pgDealsOnly: true) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(new PlansResponse(lineItems: [])) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't called bidder during auction" - assert initialBidderRequestCount == bidder.requestCount - - and: "PBS returns a not calling bidder warning" - def auctionWarnings = auctionResponse.ext?.warnings?.get(PREBID) - assert auctionWarnings.size() == 1 - assert auctionWarnings[0].code == 999 - assert auctionWarnings[0].message == - "Not calling $GENERIC.value bidder for impressions ${bidRequest.imp[0].id}" + - " due to pgdealsonly flag and no available PG line items." - } - - def "PBS should call bidder when bidder pgdealsonly flag is set to false and no available PG line items"() { - given: "Bid request with set pgdealsonly flag" - def bidRequest = BidRequest.defaultBidRequest - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(pgDealsOnly: false) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(new PlansResponse(lineItems: [])) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS has called bidder during auction" - assert initialBidderRequestCount + 1 == bidder.requestCount - assert !auctionResponse.ext?.warnings - } - - def "PBS should return an error when bidder dealsonly flag is set to true, no available PG line items and bid response misses 'dealid' field"() { - given: "Bid request with set dealsonly flag" - def bidRequest = BidRequest.defaultBidRequest - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(dealsOnly: true) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id)) - - and: "Bid response with missing 'dealid' field" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidResponse.seatbid[0].bid[0].dealid = null - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder was requested" - assert initialBidderRequestCount + 1 == bidder.requestCount - - and: "PBS returns an error of missing 'dealid' field in bid" - def bidErrors = auctionResponse.ext?.errors?.get(GENERIC) - def bidId = bidResponse.seatbid[0].bid[0].id - - assert bidErrors?.size() == 1 - assert bidErrors[0].code == 5 - assert bidErrors[0].message ==~ /BidId `$bidId` validation messages:.* Error: / + - /Bid "$bidId" missing required field 'dealid'.*/ - } - - def "PBS should add dealsonly flag when it is not specified and pgdealsonly flag is set to true"() { - given: "Bid request with set pgdealsonly flag, dealsonly is not specified" - def bidRequest = BidRequest.defaultBidRequest - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(pgDealsOnly: true) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id)) - - and: "Bid response with missing 'dealid' field to check dealsonly flag was added and worked" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidResponse.seatbid[0].bid[0].dealid = null - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder was requested" - assert initialBidderRequestCount + 1 == bidder.requestCount - - and: "PBS added dealsonly flag to the bidder request" - assert auctionResponse.ext?.debug?.resolvedRequest?.imp?.first()?.ext?.prebid?.bidder?.generic?.dealsOnly - - and: "PBS returns an error of missing 'dealid' field in bid" - def bidErrors = auctionResponse.ext?.errors?.get(GENERIC) - def bidId = bidResponse.seatbid[0].bid[0].id - - assert bidErrors?.size() == 1 - assert bidErrors[0].code == 5 - assert bidErrors[0].message ==~ /BidId `$bidId` validation messages:.* Error: / + - /Bid "$bidId" missing required field 'dealid'.*/ - } - - def "PBS shouldn't return an error when bidder dealsonly flag is set to true, no available PG line items and bid response misses 'dealid' field"() { - given: "Bid request with set dealsonly flag" - def bidRequest = BidRequest.defaultBidRequest - bidRequest.imp.first().ext.prebid.bidder.generic = new Generic(dealsOnly: false) - def initialBidderRequestCount = bidder.requestCount - - and: "No line items response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id)) - - and: "Bid response with missing 'dealid' field" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidResponse.seatbid[0].bid[0].dealid = null - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "Bidder was requested" - assert initialBidderRequestCount + 1 == bidder.requestCount - - and: "PBS hasn't returned an error" - !auctionResponse.ext?.errors - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/PlansSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/PlansSpec.groovy deleted file mode 100644 index 6d277034751..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/PlansSpec.groovy +++ /dev/null @@ -1,57 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils - -import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500 -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_PASSWORD -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_USERNAME -import static org.prebid.server.functional.util.HttpUtil.AUTHORIZATION_HEADER -import static org.prebid.server.functional.util.HttpUtil.PG_TRX_ID_HEADER -import static org.prebid.server.functional.util.HttpUtil.UUID_REGEX - -class PlansSpec extends BasePgSpec { - - def "PBS should be able to send a request to General Planner"() { - given: "General Planner response is set" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString), OK_200) - - when: "PBS sends request to General Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - - then: "Request is sent" - PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == 1 } - } - - def "PBS should retry request to General Planner when first request fails"() { - given: "Bad General Planner response" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString), INTERNAL_SERVER_ERROR_500) - - when: "PBS sends request to General Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - - then: "Request is sent two times" - PBSUtils.waitUntil { generalPlanner.recordedPlansRequestCount == 2 } - } - - def "PBS should send appropriate headers when requests plans from General Planner"() { - when: "PBS sends request to General Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - - then: "Request with headers is sent" - def plansRequestHeaders = generalPlanner.lastRecordedPlansRequestHeaders - assert plansRequestHeaders - - and: "Request has an authorization header with a basic auth token" - def basicAuthToken = HttpUtil.makeBasicAuthHeaderValue(PG_ENDPOINT_USERNAME, PG_ENDPOINT_PASSWORD) - assert plansRequestHeaders.get(AUTHORIZATION_HEADER) == [basicAuthToken] - - and: "Request has a header with uuid value" - def uuidHeader = plansRequestHeaders.get(PG_TRX_ID_HEADER) - assert uuidHeader?.size() == 1 - assert (uuidHeader[0] =~ UUID_REGEX).matches() - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/RegisterSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/RegisterSpec.groovy deleted file mode 100644 index a62a10cd594..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/RegisterSpec.groovy +++ /dev/null @@ -1,229 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_PASSWORD -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_USERNAME -import static org.prebid.server.functional.util.HttpUtil.AUTHORIZATION_HEADER -import static org.prebid.server.functional.util.HttpUtil.PG_TRX_ID_HEADER -import static org.prebid.server.functional.util.HttpUtil.UUID_REGEX - -class RegisterSpec extends BasePgSpec { - - def setupSpec() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should be able to register its instance in Planner on demand"() { - given: "Properties values from PBS config" - def host = pgConfig.hostId - def vendor = pgConfig.vendor - def region = pgConfig.region - - and: "Initial Planner request count" - def initialRequestCount = generalPlanner.requestCount - - when: "PBS sends request to Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "Request counter is increased" - PBSUtils.waitUntil { generalPlanner.requestCount == initialRequestCount + 1 } - - and: "PBS instance is healthy" - def registerRequest = generalPlanner.lastRecordedRegisterRequest - assert registerRequest.healthIndex >= 0 && registerRequest.healthIndex <= 1 - - and: "Host, vendor and region are appropriate to the config" - assert registerRequest.hostInstanceId == host - assert registerRequest.vendor == vendor - assert registerRequest.region == region - - and: "Delivery Statistics Report doesn't have delivery specific data" - verifyAll(registerRequest.status.dealsStatus) { delStatsReport -> - (delStatsReport.reportId =~ UUID_REGEX).matches() - delStatsReport.instanceId == host - delStatsReport.vendor == vendor - delStatsReport.region == region - !delStatsReport.lineItemStatus - !delStatsReport.dataWindowStartTimeStamp - !delStatsReport.dataWindowEndTimeStamp - delStatsReport.reportTimeStamp.isBefore(ZonedDateTime.now(ZoneId.from(UTC))) - } - } - - def "PBS should send a register request with appropriate headers"() { - when: "Initiating PBS to register its instance" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "Request with headers is sent" - def registerRequestHeaders = generalPlanner.lastRecordedRegisterRequestHeaders - assert registerRequestHeaders - - and: "Request has an authorization header with a basic auth token" - def basicAuthToken = HttpUtil.makeBasicAuthHeaderValue(PG_ENDPOINT_USERNAME, PG_ENDPOINT_PASSWORD) - assert registerRequestHeaders.get(AUTHORIZATION_HEADER) == [basicAuthToken] - - and: "Request has a header with uuid value" - def uuidHeader = registerRequestHeaders.get(PG_TRX_ID_HEADER) - assert uuidHeader?.size() == 1 - assert (uuidHeader[0] =~ UUID_REGEX).matches() - } - - def "PBS should be able to register its instance in Planner providing active PBS line items info"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - def lineItem = plansResponse.lineItems[0] - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial Planner request count" - def initialRequestCount = generalPlanner.requestCount - - when: "PBS sends request to Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "Request counter is increased" - PBSUtils.waitUntil { generalPlanner.requestCount == initialRequestCount + 1 } - - and: "Delivery Statistics Report has active line item data" - def registerRequest = generalPlanner.lastRecordedRegisterRequest - def delStatsReport = registerRequest.status?.dealsStatus - assert delStatsReport - def lineItemStatus = delStatsReport.lineItemStatus - - assert lineItemStatus?.size() == plansResponse.lineItems.size() - verifyAll(lineItemStatus) { - lineItemStatus[0].lineItemSource == lineItem.source - lineItemStatus[0].lineItemId == lineItem.lineItemId - lineItemStatus[0].dealId == lineItem.dealId - lineItemStatus[0].extLineItemId == lineItem.extLineItemId - } - - and: "Line item wasn't used in auction" - verifyAll(lineItemStatus) { - !lineItemStatus[0].accountAuctions - !lineItemStatus[0].targetMatched - !lineItemStatus[0].sentToBidder - !lineItemStatus[0].spentTokens - } - - cleanup: - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should be able to register its instance in Planner providing line items status after auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - def lineItem = plansResponse.lineItems[0] - def lineItemCount = plansResponse.lineItems.size() as Long - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial Planner request count" - def initialRequestCount = generalPlanner.requestCount - - and: "Auction is requested" - pgPbsService.sendAuctionRequest(bidRequest) - - when: "PBS sends request to Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "Request counter is increased" - PBSUtils.waitUntil { generalPlanner.requestCount == initialRequestCount + 1 } - - and: "Delivery Statistics Report has info about auction" - def registerRequest = generalPlanner.lastRecordedRegisterRequest - def delStatsReport = registerRequest.status.dealsStatus - assert delStatsReport - - and: "Delivery Statistics Report has correct line item status data" - def lineItemStatus = delStatsReport.lineItemStatus - - assert lineItemStatus?.size() as Long == lineItemCount - verifyAll(lineItemStatus) { - lineItemStatus[0].lineItemSource == lineItem.source - lineItemStatus[0].lineItemId == lineItem.lineItemId - lineItemStatus[0].dealId == lineItem.dealId - lineItemStatus[0].extLineItemId == lineItem.extLineItemId - } - - and: "Line item was used in auction" - verifyAll(lineItemStatus) { - lineItemStatus[0].accountAuctions == lineItemCount - lineItemStatus[0].targetMatched == lineItemCount - lineItemStatus[0].sentToBidder == lineItemCount - lineItemStatus[0].spentTokens == lineItemCount - } - - cleanup: - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should update auction count when register its instance in Planner after auction"() { - given: "Initial auction count" - def initialRequestCount = generalPlanner.requestCount - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - PBSUtils.waitUntil { generalPlanner.requestCount == initialRequestCount + 1 } - def initialAuctionCount = generalPlanner.lastRecordedRegisterRequest?.status?.dealsStatus?.clientAuctions - - and: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial Planner request count" - initialRequestCount = generalPlanner.requestCount - - and: "Auction is requested" - pgPbsService.sendAuctionRequest(bidRequest) - - when: "PBS sends request to Planner" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.registerInstanceRequest) - - then: "Request counter is increased" - PBSUtils.waitUntil { generalPlanner.requestCount == initialRequestCount + 1 } - - and: "Delivery Statistics Report has info about auction" - def registerRequest = generalPlanner.lastRecordedRegisterRequest - assert registerRequest.status?.dealsStatus?.clientAuctions == initialAuctionCount + 1 - - cleanup: - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/ReportSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/ReportSpec.groovy deleted file mode 100644 index 75c73d0f534..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/ReportSpec.groovy +++ /dev/null @@ -1,559 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.DeliverySchedule -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.lineitem.Token -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils - -import java.time.ZoneId -import java.time.ZonedDateTime -import java.time.format.DateTimeFormatter - -import static java.time.ZoneOffset.UTC -import static org.mockserver.model.HttpStatusCode.CONFLICT_409 -import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500 -import static org.mockserver.model.HttpStatusCode.OK_200 -import static org.prebid.server.functional.model.deals.lineitem.LineItem.TIME_PATTERN -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_PASSWORD -import static org.prebid.server.functional.testcontainers.PbsPgConfig.PG_ENDPOINT_USERNAME -import static org.prebid.server.functional.util.HttpUtil.AUTHORIZATION_HEADER -import static org.prebid.server.functional.util.HttpUtil.CHARSET_HEADER_VALUE -import static org.prebid.server.functional.util.HttpUtil.CONTENT_TYPE_HEADER -import static org.prebid.server.functional.util.HttpUtil.CONTENT_TYPE_HEADER_VALUE -import static org.prebid.server.functional.util.HttpUtil.PG_TRX_ID_HEADER -import static org.prebid.server.functional.util.HttpUtil.UUID_REGEX - -class ReportSpec extends BasePgSpec { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS shouldn't send delivery statistics when PBS doesn't have reports to send"() { - given: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "Delivery Statistics Service request count is not changed" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount } - } - - def "PBS shouldn't send delivery statistics when delivery report batch is created but doesn't have reports to send"() { - given: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "Delivery Statistics Service request count is not changed" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount } - } - - def "PBS should send a report request with appropriate headers"() { - given: "Initial report sent request count is taken" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Line items are fetched" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(PBSUtils.randomString)) - updateLineItemsAndWait() - - and: "Delivery report batch is created" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - and: "PBS sends a report request to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - then: "Request headers corresponds to the payload" - def deliveryRequestHeaders = deliveryStatistics.lastRecordedDeliveryRequestHeaders - assert deliveryRequestHeaders - - and: "Request has an authorization header with a basic auth token" - def basicAuthToken = HttpUtil.makeBasicAuthHeaderValue(PG_ENDPOINT_USERNAME, PG_ENDPOINT_PASSWORD) - assert deliveryRequestHeaders.get(AUTHORIZATION_HEADER) == [basicAuthToken] - - and: "Request has a header with uuid value" - def uuidHeader = deliveryRequestHeaders.get(PG_TRX_ID_HEADER) - assert uuidHeader?.size() == 1 - assert (uuidHeader[0] =~ UUID_REGEX).matches() - - and: "Request has a content type header" - assert deliveryRequestHeaders.get(CONTENT_TYPE_HEADER) == ["$CONTENT_TYPE_HEADER_VALUE;$CHARSET_HEADER_VALUE"] - } - - def "PBS should send delivery statistics report when delivery progress report with one line item is created"() { - given: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Time before report is sent" - def startTime = ZonedDateTime.now(UTC) - - and: "Set Planner response to return one line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(PBSUtils.randomString) - def lineItem = plansResponse.lineItems[0] - generalPlanner.initPlansResponse(plansResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report request to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "Report request should correspond to the payload" - def reportRequest = deliveryStatistics.lastRecordedDeliveryStatisticsReportRequest - def endTime = ZonedDateTime.now(ZoneId.from(UTC)) - - verifyAll(reportRequest) { - (reportRequest.reportId =~ UUID_REGEX).matches() - reportRequest.instanceId == pgConfig.hostId - reportRequest.vendor == pgConfig.vendor - reportRequest.region == pgConfig.region - !reportRequest.clientAuctions - - reportRequest.reportTimeStamp.isBefore(endTime) - reportRequest.dataWindowStartTimeStamp.isBefore(startTime) - reportRequest.dataWindowEndTimeStamp.isAfter(startTime) - reportRequest.dataWindowEndTimeStamp.isBefore(endTime) - reportRequest.reportTimeStamp.isAfter(reportRequest.dataWindowEndTimeStamp) - } - - and: "Report line items should have an appropriate to the initially set line items info" - assert reportRequest.lineItemStatus?.size() == 1 - def lineItemStatus = reportRequest.lineItemStatus[0] - - verifyAll(lineItemStatus) { - lineItemStatus.lineItemSource == lineItem.source - lineItemStatus.lineItemId == lineItem.lineItemId - lineItemStatus.dealId == lineItem.dealId - lineItemStatus.extLineItemId == lineItem.extLineItemId - !lineItemStatus.accountAuctions - !lineItemStatus.domainMatched - !lineItemStatus.targetMatched - !lineItemStatus.targetMatchedButFcapped - !lineItemStatus.targetMatchedButFcapLookupFailed - !lineItemStatus.pacingDeferred - !lineItemStatus.sentToBidder - !lineItemStatus.sentToBidderAsTopMatch - !lineItemStatus.receivedFromBidder - !lineItemStatus.receivedFromBidderInvalidated - !lineItemStatus.sentToClient - !lineItemStatus.sentToClientAsTopMatch - !lineItemStatus.lostToLineItems - !lineItemStatus.events - !lineItemStatus.readyAt - !lineItemStatus.spentTokens - !lineItemStatus.pacingFrequency - - lineItemStatus.deliverySchedule?.size() == 1 - } - - def timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN) - def deliverySchedule = lineItemStatus.deliverySchedule[0] - - verifyAll(deliverySchedule) { - deliverySchedule.planId == lineItem.deliverySchedules[0].planId - timeFormatter.format(deliverySchedule.planStartTimeStamp) == - timeFormatter.format(lineItem.deliverySchedules[0].startTimeStamp) - timeFormatter.format(deliverySchedule.planUpdatedTimeStamp) == - timeFormatter.format(lineItem.deliverySchedules[0].updatedTimeStamp) - timeFormatter.format(deliverySchedule.planExpirationTimeStamp) == - timeFormatter.format(lineItem.deliverySchedules[0].endTimeStamp) - - deliverySchedule.tokens?.size() == 1 - } - - verifyAll(deliverySchedule.tokens[0]) { tokens -> - tokens.priorityClass == lineItem.deliverySchedules[0].tokens[0].priorityClass - tokens.total == lineItem.deliverySchedules[0].tokens[0].total - tokens.spent == 0 - tokens.totalSpent == 0 - } - } - - def "PBS should send a correct delivery statistics report when auction with one line item is happened"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Time before report is sent" - def startTime = ZonedDateTime.now(UTC) - - and: "Set Planner response to return one line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - def lineItem = plansResponse.lineItems[0] - def lineItemCount = plansResponse.lineItems.size() as Long - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - when: "Auction request to PBS is sent" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report request to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "Report request should be sent after the test start" - def reportRequest = deliveryStatistics.lastRecordedDeliveryStatisticsReportRequest - assert reportRequest.reportTimeStamp.isAfter(startTime) - - and: "Request should contain correct number of client auctions made" - assert reportRequest.clientAuctions == 1 - - and: "Report line items should have an appropriate to the initially set line item info" - assert reportRequest.lineItemStatus?.size() == 1 - def lineItemStatus = reportRequest.lineItemStatus[0] - - verifyAll(lineItemStatus) { - lineItemStatus.lineItemSource == lineItem.source - lineItemStatus.lineItemId == lineItem.lineItemId - lineItemStatus.dealId == lineItem.dealId - lineItemStatus.extLineItemId == lineItem.extLineItemId - } - - and: "Report should have the right PG metrics info" - verifyAll(lineItemStatus) { - lineItemStatus?.accountAuctions == lineItemCount - lineItemStatus?.targetMatched == lineItemCount - lineItemStatus?.sentToBidder == lineItemCount - lineItemStatus?.sentToBidderAsTopMatch == lineItemCount - } - - and: "Report line item should have a delivery schedule" - assert lineItemStatus.deliverySchedule?.size() == 1 - assert lineItemStatus.deliverySchedule[0].planId == lineItem.deliverySchedules[0].planId - } - - def "PBS should use line item token with the highest priority"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Time before report is sent" - def startTime = ZonedDateTime.now(UTC) - - and: "Set Planner response to return one line item" - def highestPriorityToken = new Token(priorityClass: 1, total: 2) - def lowerPriorityToken = new Token(priorityClass: 3, total: 2) - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - def tokens = [highestPriorityToken, lowerPriorityToken] - lineItems[0].deliverySchedules[0].tokens = tokens - } - def tokens = plansResponse.lineItems[0].deliverySchedules[0].tokens - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - when: "Auction request to PBS is sent" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report request to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "Report request should be sent after the test start" - def reportRequest = deliveryStatistics.lastRecordedDeliveryStatisticsReportRequest - assert reportRequest.reportTimeStamp.isAfter(startTime) - - and: "Token with the highest priority was used" - def reportTokens = reportRequest.lineItemStatus?.first()?.deliverySchedule?.first()?.tokens - assert reportTokens - assert reportTokens.size() == tokens.size() - def usedToken = reportTokens.find { it.priorityClass == highestPriorityToken.priorityClass } - assert usedToken?.total == highestPriorityToken.total - assert usedToken?.spent == 1 - assert usedToken?.totalSpent == 1 - - and: "Token with a lower priority wasn't used" - def notUsedToken = reportTokens.find { it.priorityClass == lowerPriorityToken.priorityClass } - assert notUsedToken?.total == lowerPriorityToken.total - assert notUsedToken?.spent == 0 - assert notUsedToken?.totalSpent == 0 - } - - def "PBS shouldn't consider line item as used when bidder responds with non-deals specific info"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Time before report is sent" - def startTime = ZonedDateTime.now(UTC) - - and: "Set Planner response to return one line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Non-deals bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - when: "Auction request to PBS is sent" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report request to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "Report request should be sent after the test start" - def reportRequest = deliveryStatistics.lastRecordedDeliveryStatisticsReportRequest - assert reportRequest.reportTimeStamp.isAfter(startTime) - - and: "Line item token wasn't used" - def reportTokens = reportRequest.lineItemStatus?.first()?.deliverySchedule?.first()?.tokens - assert reportTokens?.size() == plansResponse.lineItems[0].deliverySchedules[0].tokens.size() - assert reportTokens[0].spent == 0 - assert reportTokens[0].totalSpent == 0 - } - - def "PBS should send additional report when line items number exceeds PBS 'line-items-per-report' property"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Already recorded request count is reset" - deliveryStatistics.resetRecordedRequests() - deliveryStatistics.setResponse() - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - and: "Set Planner response to return #lineItemsPerReport + 1 line items" - def lineItemsPerReport = pgConfig.lineItemsPerReport - def plansResponse = new PlansResponse(lineItems: (1..lineItemsPerReport + 1).collect { - LineItem.getDefaultLineItem(accountId) - }) - generalPlanner.initPlansResponse(plansResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - when: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends two report requests to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 2 } - - and: "Two reports are sent" - def reportRequests = deliveryStatistics.recordedDeliveryStatisticsReportRequests - assert reportRequests.size() == 2 - - and: "Two reports were sent with #lineItemsPerReport and 1 number of line items" - assert [reportRequests[-2].lineItemStatus.size(), reportRequests[-1].lineItemStatus.size()].sort() == - [lineItemsPerReport, 1].sort() - } - - def "PBS should save reports for later sending when response from Delivery Statistics was unsuccessful"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Set Planner response to return 1 line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(accountId) - generalPlanner.initPlansResponse(plansResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "Delivery Statistics Service response is set to return a bad status code" - deliveryStatistics.reset() - deliveryStatistics.setResponse(INTERNAL_SERVER_ERROR_500) - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report to Delivery Statistics" - PBSUtils.waitUntil { deliveryStatistics.requestCount == 1 } - - when: "Delivery Statistics Service response is set to return a success response" - deliveryStatistics.reset() - deliveryStatistics.setResponse(OK_200) - - and: "PBS is requested to send a report to Delivery Statistics for the second time" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS for the second time sends the same report to the Delivery Statistics Service" - PBSUtils.waitUntil { deliveryStatistics.requestCount == 1 } - } - - def "PBS shouldn't save reports for later sending when Delivery Statistics response is Conflict 409"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Set Planner response to return 1 line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(accountId) - generalPlanner.initPlansResponse(plansResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "Delivery Statistics Service response is set to return a Conflict status code" - deliveryStatistics.reset() - deliveryStatistics.setResponse(CONFLICT_409) - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - - when: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report to Delivery Statistics" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "PBS is requested to send a report to Delivery Statistics for the second time" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS doesn't request Delivery Statistics Service for the second time" - assert deliveryStatistics.requestCount == initialRequestCount + 1 - } - - def "PBS should change active delivery plan when the current plan lifetime expires"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - def accountId = bidRequest.site.publisher.id - - and: "Initial Delivery Statistics Service request count" - def initialRequestCount = deliveryStatistics.requestCount - def auctionCount = 2 - - and: "Current delivery plan which expires in 2 seconds" - def currentPlanTimeToLive = 2 - def currentDeliverySchedule = new DeliverySchedule(planId: PBSUtils.randomNumber as String, - startTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - updatedTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)), - endTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusSeconds(currentPlanTimeToLive), - tokens: [new Token(priorityClass: 1, total: 1000)]) - - and: "Next delivery plan" - def nextDeliverySchedule = new DeliverySchedule(planId: PBSUtils.randomNumber as String, - startTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusSeconds(currentPlanTimeToLive), - updatedTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusSeconds(currentPlanTimeToLive), - endTimeStamp: ZonedDateTime.now(ZoneId.from(UTC)).plusHours(1), - tokens: [new Token(priorityClass: 1, total: 500)]) - - and: "Set Planner response to return line item with two delivery plans" - def plansResponse = PlansResponse.getDefaultPlansResponse(accountId).tap { - lineItems[0].deliverySchedules = [currentDeliverySchedule, nextDeliverySchedule] - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "PBS requests Planner line items" - updateLineItemsAndWait() - - and: "Auction request to PBS is sent for the first time" - pgPbsService.sendAuctionRequest(bidRequest) - - when: "Current delivery plan lifetime is expired" - PBSUtils.waitUntil({ ZonedDateTime.now(ZoneId.from(UTC)).isAfter(currentDeliverySchedule.endTimeStamp) }, - (currentPlanTimeToLive * 1000) + 1000) - - and: "PBS requests Planner line items which also forces current PBS line items to be updated" - generalPlanner.initPlansResponse(plansResponse) - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.updateLineItemsRequest) - - and: "Auction request to PBS is sent for the second time" - bidder.setResponse(bidRequest.id, bidResponse) - pgPbsService.sendAuctionRequest(bidRequest) - - and: "PBS generates delivery report batch" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.createReportRequest) - - and: "PBS is requested to send a report to Delivery Statistics" - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.sendReportRequest) - - then: "PBS sends a report to Delivery Statistics" - PBSUtils.waitUntil { deliveryStatistics.requestCount == initialRequestCount + 1 } - - and: "Report has info about 2 happened auctions" - def reportRequest = deliveryStatistics.lastRecordedDeliveryStatisticsReportRequest - assert reportRequest.clientAuctions == auctionCount - assert reportRequest.lineItemStatus?.size() == plansResponse.lineItems.size() - assert reportRequest.lineItemStatus[0].accountAuctions == auctionCount - - and: "One line item during each auction was sent to the bidder" - assert reportRequest.lineItemStatus[0].sentToBidder == auctionCount - - and: "Report contains two delivery plans info" - def reportDeliverySchedules = reportRequest.lineItemStatus[0].deliverySchedule - assert reportDeliverySchedules?.size() == plansResponse.lineItems[0].deliverySchedules.size() - - and: "One token was used during the first auction by the first delivery plan" - assert reportDeliverySchedules.find { it.planId == currentDeliverySchedule.planId }?.tokens[0].spent == 1 - - and: "One token was used from another delivery plan during the second auction after first delivery plan lifetime expired" - assert reportDeliverySchedules.find { it.planId == nextDeliverySchedule.planId }?.tokens[0].spent == 1 - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingFirstPartyDataSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingFirstPartyDataSpec.groovy deleted file mode 100644 index a1552071a8d..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingFirstPartyDataSpec.groovy +++ /dev/null @@ -1,707 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.targeting.Targeting -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.AppExt -import org.prebid.server.functional.model.request.auction.AppExtData -import org.prebid.server.functional.model.request.auction.Banner -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.BidRequestExt -import org.prebid.server.functional.model.request.auction.BidderConfig -import org.prebid.server.functional.model.request.auction.BidderConfigOrtb -import org.prebid.server.functional.model.request.auction.DoohExt -import org.prebid.server.functional.model.request.auction.DoohExtData -import org.prebid.server.functional.model.request.auction.ExtPrebidBidderConfig -import org.prebid.server.functional.model.request.auction.Imp -import org.prebid.server.functional.model.request.auction.ImpExtContext -import org.prebid.server.functional.model.request.auction.ImpExtContextData -import org.prebid.server.functional.model.request.auction.Prebid -import org.prebid.server.functional.model.request.auction.Site -import org.prebid.server.functional.model.request.auction.SiteExt -import org.prebid.server.functional.model.request.auction.SiteExtData -import org.prebid.server.functional.model.request.auction.User -import org.prebid.server.functional.model.request.auction.UserExt -import org.prebid.server.functional.model.request.auction.UserExtData -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.service.PrebidServerException -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Shared - -import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.IN -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.INTERSECTS -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.MATCHES -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.SFPD_BUYER_ID -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.SFPD_BUYER_IDS -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.SFPD_KEYWORDS -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.SFPD_LANGUAGE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.UFPD_BUYER_UID -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.UFPD_BUYER_UIDS -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.UFPD_KEYWORDS -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.UFPD_YOB -import static org.prebid.server.functional.model.request.auction.DistributionChannel.APP -import static org.prebid.server.functional.model.request.auction.DistributionChannel.DOOH -import static org.prebid.server.functional.model.request.auction.DistributionChannel.SITE - -class TargetingFirstPartyDataSpec extends BasePgSpec { - - @Shared - String stringTargetingValue = PBSUtils.randomString - @Shared - Integer integerTargetingValue = PBSUtils.randomNumber - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should support both scalar and array String inputs by '#ufpdTargetingType' for INTERSECTS matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - ext = new UserExt(data: userExtData) - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(ufpdTargetingType, INTERSECTS, [stringTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - ufpdTargetingType | userExtData - UFPD_BUYER_UID | new UserExtData(buyeruid: stringTargetingValue) - UFPD_KEYWORDS | new UserExtData(keywords: [stringTargetingValue]) - } - - def "PBS should support both scalar and array Integer inputs by '#ufpdTargetingType' for INTERSECTS matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - ext = new UserExt(data: userExtData) - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(ufpdTargetingType, INTERSECTS, [stringTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - ufpdTargetingType | userExtData - UFPD_BUYER_UID | new UserExtData(buyeruid: stringTargetingValue) - UFPD_BUYER_UIDS | new UserExtData(buyeruids: [stringTargetingValue]) - } - - def "PBS should support taking Site First Party Data from #place source"() { - given: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.getAccountId()).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, INTERSECTS, [stringTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - place | bidRequest - "imp[].ext.context" | BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - ext.context = new ImpExtContext(data: new ImpExtContextData(language: stringTargetingValue)) - }] - } - "site" | BidRequest.defaultBidRequest.tap { - site = Site.defaultSite.tap { - ext = new SiteExt(data: new SiteExtData(language: stringTargetingValue)) - } - } - "imp[].ext.data" | BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - ext.data = new ImpExtContextData(language: stringTargetingValue) - }] - } - } - - def "PBS should support String array input for Site First Party Data to be matched by INTERSECTS matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - banner = Banner.defaultBanner - ext.context = new ImpExtContext(data: new ImpExtContextData(keywords: [stringTargetingValue])) - }] - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_KEYWORDS, INTERSECTS, [stringTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should support both scalar and array Integer inputs in Site First Party Data ('#targetingType') by INTERSECTS matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - banner = Banner.defaultBanner - ext.context = new ImpExtContext(data: impExtContextData) - }] - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(targetingType, INTERSECTS, [integerTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - targetingType | impExtContextData - SFPD_BUYER_ID | new ImpExtContextData(buyerId: integerTargetingValue) - SFPD_BUYER_IDS | new ImpExtContextData(buyerIds: [integerTargetingValue]) - } - - def "PBS shouldn't throw a NPE for Site First Party Data when its Ext is absent and targeting INTERSECTS matching type is selected"() { - given: "Bid request with set site first party data in bidRequest.site" - def bidRequest = BidRequest.defaultBidRequest.tap { - site = Site.defaultSite.tap { - keywords = stringTargetingValue - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_KEYWORDS, INTERSECTS, [stringTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS successfully processed request" - notThrown(PrebidServerException) - - and: "PBS hasn't had PG auction as request targeting is not specified in the right place" - assert !auctionResponse.ext?.debug?.pgmetrics - } - - def "PBS should support taking User FPD from bidRequest.user by #matchingFunction matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - updateUserFieldGeneric(it) - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(ufpdTargetingType, matchingFunction, [targetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - ufpdTargetingType | updateUserFieldGeneric | targetingValue | matchingFunction - UFPD_BUYER_UID | { it.buyeruid = stringTargetingValue } | stringTargetingValue | INTERSECTS - UFPD_BUYER_UID | { it.buyeruid = stringTargetingValue } | stringTargetingValue | IN - UFPD_YOB | { it.yob = integerTargetingValue } | integerTargetingValue | INTERSECTS - UFPD_YOB | { it.yob = integerTargetingValue } | integerTargetingValue | IN - } - - def "PBS should support taking User FPD from bidRequest.user by MATCHES matching function"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - it.buyeruid = stringTargetingValue - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should be able to match site FPD targeting taken from different sources by INTERSECTS matching function"() { - given: "Bid request with set site FPD in different request places" - def bidRequest = getSiteFpdBidRequest(siteLanguage, appLanguage, doohLanguage, impLanguage) - - and: "Planner response with INTERSECTS 1 of site FPD values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.getAccountId()).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, INTERSECTS, [stringTargetingValue, PBSUtils.randomString]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - siteLanguage | appLanguage | doohLanguage | impLanguage - stringTargetingValue | null | null | PBSUtils.randomString - null | stringTargetingValue | null | PBSUtils.randomString - null | null | stringTargetingValue | stringTargetingValue - } - - def "PBS should be able to match site FPD targeting taken from different sources by MATCHES matching function"() { - given: "Bid request with set site FPD in different request places" - def bidRequest = getSiteFpdBidRequest(siteLanguage, appLanguage, doohLanguage, impLanguage) - - and: "Planner response with MATCHES 1 of site FPD values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.getAccountId()).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - siteLanguage | appLanguage | doohLanguage | impLanguage - stringTargetingValue | null | null | PBSUtils.randomString - null | stringTargetingValue | null | PBSUtils.randomString - null | null | stringTargetingValue | stringTargetingValue - } - - def "PBS should be able to match site FPD targeting taken from different sources by IN matching function"() { - given: "Bid request with set site FPD in different request places" - def siteLanguage = PBSUtils.randomString - def appLanguage = PBSUtils.randomString - def doohLanguage = PBSUtils.randomString - def impLanguage = PBSUtils.randomString - def bidRequest = getSiteFpdBidRequest(siteLanguage, appLanguage, doohLanguage, impLanguage) - - and: "Planner response with IN all of site FPD values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, IN, [siteLanguage, appLanguage, impLanguage, PBSUtils.randomString]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should be able to match user FPD targeting taken from different sources by MATCHES matching function"() { - given: "Bid request with set user FPD in different request places" - def bidRequest = getUserFpdBidRequest(userBuyerUid, userExtDataBuyerUid) - - and: "Planner response with MATCHES 1 of user FPD values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - - where: - userBuyerUid | userExtDataBuyerUid - stringTargetingValue | PBSUtils.randomString - PBSUtils.randomString | stringTargetingValue - } - - def "PBS should be able to match user FPD targeting taken from different sources by IN matching function"() { - given: "Bid request with set user FPD in different request places" - def userBuyerUid = PBSUtils.randomString - def userExtDataBuyerUid = PBSUtils.randomString - def bidRequest = getUserFpdBidRequest(userBuyerUid, userExtDataBuyerUid) - - and: "Planner response with IN all of user FPD values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, IN, [userBuyerUid, userExtDataBuyerUid, PBSUtils.randomString]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - } - - def "PBS should support targeting by SITE First Party Data when request ext prebid bidder config is given"() { - given: "Bid request with set Site specific bidder config" - def bidRequest = BidRequest.defaultBidRequest.tap { - def site = new Site().tap { - ext = new SiteExt(data: new SiteExtData(language: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [GENERIC], - config: new BidderConfig(ortb2: new BidderConfigOrtb(site: site))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS should support targeting by USER First Party Data when request ext prebid bidder config is given"() { - given: "Bid request with set User specific bidder config" - def bidRequest = BidRequest.defaultBidRequest.tap { - def user = new User().tap { - ext = new UserExt(data: new UserExtData(buyeruid: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [GENERIC], - config: new BidderConfig(ortb2: new BidderConfigOrtb(user: user))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS shouldn't target by SITE First Party Data when request ext prebid bidder config with not matched bidder is given"() { - given: "Bid request with request not matched bidder" - def notMatchedBidder = APPNEXUS - def bidRequest = BidRequest.defaultBidRequest.tap { - def site = new Site().tap { - ext = new SiteExt(data: new SiteExtData(language: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [notMatchedBidder], - config: new BidderConfig(ortb2: new BidderConfigOrtb(site: site))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't had PG auction" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS shouldn't target by USER First Party Data when request ext prebid bidder config with not matched bidder is given"() { - given: "Bid request with request not matched bidder" - def notMatchedBidder = APPNEXUS - def bidRequest = BidRequest.defaultBidRequest.tap { - def user = new User().tap { - ext = new UserExt(data: new UserExtData(buyeruid: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [notMatchedBidder], - config: new BidderConfig(ortb2: new BidderConfigOrtb(user: user))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't had PG auction" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS should support targeting by SITE First Party Data when a couple of request ext prebid bidder configs are given"() { - given: "Bid request with 1 not matched Site specific bidder config and 1 matched" - def bidRequest = BidRequest.defaultBidRequest.tap { - def bidderConfigSite = new Site().tap { - ext = new SiteExt(data: new SiteExtData(language: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [GENERIC], - config: new BidderConfig(ortb2: new BidderConfigOrtb(site: bidderConfigSite))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SFPD_LANGUAGE, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS should support targeting by USER First Party Data when a couple of request ext prebid bidder configs are given"() { - given: "Bid request with 1 not matched User specific bidder config and 1 matched" - def bidRequest = BidRequest.defaultBidRequest.tap { - def bidderConfigUser = new User().tap { - ext = new UserExt(data: new UserExtData(buyeruid: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [GENERIC], - config: new BidderConfig(ortb2: new BidderConfigOrtb(user: bidderConfigUser))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, matchingFunction, matchingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - matchingFunction | matchingValue - INTERSECTS | [stringTargetingValue, PBSUtils.randomString] - MATCHES | stringTargetingValue - } - - def "PBS shouldn't rely on bidder name case strategy when bidder name in another case stately"() { - given: "Bid request with 1 not matched User specific bidder config and 1 matched" - def bidRequest = BidRequest.defaultBidRequest.tap { - def bidderConfigUser = new User().tap { - ext = new UserExt(data: new UserExtData(buyeruid: stringTargetingValue)) - } - def bidderConfig = new ExtPrebidBidderConfig(bidders: [bidders], - config: new BidderConfig(ortb2: new BidderConfigOrtb(user: bidderConfigUser))) - ext = new BidRequestExt(prebid: new Prebid(debug: 1, bidderConfig: [bidderConfig])) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(UFPD_BUYER_UID, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - bidders << [GENERIC, GENERIC_CAMEL_CASE] - } - - private BidRequest getSiteFpdBidRequest(String siteLanguage, String appLanguage, String doohLanguage, String impLanguage) { - def bidRequest - if (siteLanguage != null) { - bidRequest = BidRequest.getDefaultBidRequest(SITE).tap { - site.ext = new SiteExt(data: new SiteExtData(language: siteLanguage)) - } - } else if (appLanguage != null) { - bidRequest = BidRequest.getDefaultBidRequest(APP).tap { - app.ext = new AppExt(data: new AppExtData(language: appLanguage)) - } - } else { - bidRequest = BidRequest.getDefaultBidRequest(DOOH).tap { - dooh.ext = new DoohExt(data: new DoohExtData(language: doohLanguage)) - } - } - bidRequest.imp[0].tap { - ext.context = new ImpExtContext(data: new ImpExtContextData(language: impLanguage)) - } - bidRequest - } - - private BidRequest getUserFpdBidRequest(String userBuyerUid, String userExtDataBuyerUid) { - BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - buyeruid = userBuyerUid - ext = new UserExt(data: new UserExtData(buyeruid: userExtDataBuyerUid)) - } - } - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingSpec.groovy deleted file mode 100644 index 882860a9e5b..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/TargetingSpec.groovy +++ /dev/null @@ -1,560 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.bidder.Rubicon -import org.prebid.server.functional.model.deals.lineitem.LineItemSize -import org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator -import org.prebid.server.functional.model.deals.lineitem.targeting.Targeting -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.App -import org.prebid.server.functional.model.request.auction.Banner -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.auction.Bidder -import org.prebid.server.functional.model.request.auction.Device -import org.prebid.server.functional.model.request.auction.Geo -import org.prebid.server.functional.model.request.auction.GeoExt -import org.prebid.server.functional.model.request.auction.GeoExtGeoProvider -import org.prebid.server.functional.model.request.auction.Imp -import org.prebid.server.functional.model.request.auction.ImpExt -import org.prebid.server.functional.model.request.auction.ImpExtContext -import org.prebid.server.functional.model.request.auction.ImpExtContextData -import org.prebid.server.functional.model.request.auction.ImpExtContextDataAdServer -import org.prebid.server.functional.model.request.auction.Publisher -import org.prebid.server.functional.model.request.auction.User -import org.prebid.server.functional.model.request.auction.UserExt -import org.prebid.server.functional.model.request.auction.UserTime -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Shared - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static java.time.temporal.WeekFields.SUNDAY_START -import static org.prebid.server.functional.model.bidder.BidderName.RUBICON -import static org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator.NOT -import static org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator.OR -import static org.prebid.server.functional.model.deals.lineitem.targeting.BooleanOperator.UPPERCASE_AND -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.IN -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.INTERSECTS -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.MATCHES -import static org.prebid.server.functional.model.deals.lineitem.targeting.MatchingFunction.WITHIN -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_AD_SLOT -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_MEDIA_TYPE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.AD_UNIT_SIZE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.APP_BUNDLE -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.BIDP_ACCOUNT_ID -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DEVICE_METRO -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DEVICE_REGION -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.DOW -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.HOUR -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.INVALID -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.PAGE_POSITION -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.REFERRER -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.SITE_DOMAIN -import static org.prebid.server.functional.model.deals.lineitem.targeting.TargetingType.UFPD_BUYER_UID -import static org.prebid.server.functional.model.request.auction.DistributionChannel.APP -import static org.prebid.server.functional.model.response.auction.MediaType.BANNER -import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO - -class TargetingSpec extends BasePgSpec { - - @Shared - String stringTargetingValue = PBSUtils.randomString - @Shared - Integer integerTargetingValue = PBSUtils.randomNumber - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should invalidate line items when targeting has #reason"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = targeting - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't had PG deals auction as line item hasn't passed validation" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - reason | targeting - - "two root nodes" | Targeting.invalidTwoRootNodesTargeting - - "invalid boolean operator" | new Targeting.Builder(BooleanOperator.INVALID).addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [BANNER]) - .build() - - "uppercase boolean operator" | new Targeting.Builder(UPPERCASE_AND).addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [BANNER]) - .build() - - "invalid targeting type" | Targeting.defaultTargetingBuilder - .addTargeting(INVALID, INTERSECTS, [PBSUtils.randomString]) - .build() - - "'in' matching type value as not list" | new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, IN, BANNER) - .build() - - "'intersects' matching type value as not list" | new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, BANNER) - .build() - - "'within' matching type value as not list" | new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, WITHIN, BANNER) - .build() - - "'matches' matching type value as list" | new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, MATCHES, [BANNER]) - .build() - - "null targeting height and width" | new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [new LineItemSize(w: null, h: null)]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [BANNER]) - .build() - } - - def "PBS should invalidate line items with not supported '#matchingFunction' matching function by '#targetingType' targeting type"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(targetingType, matchingFunction, [PBSUtils.randomString]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't had PG deals auction as line item hasn't passed validation" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - matchingFunction | targetingType - INTERSECTS | SITE_DOMAIN - WITHIN | SITE_DOMAIN - INTERSECTS | REFERRER - WITHIN | REFERRER - INTERSECTS | APP_BUNDLE - WITHIN | APP_BUNDLE - INTERSECTS | AD_UNIT_AD_SLOT - WITHIN | AD_UNIT_AD_SLOT - } - - def "PBS should support line item targeting by string '#targetingType' targeting type"() { - given: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.getAccountId()).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(targetingType, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - targetingType | bidRequest - - REFERRER | BidRequest.defaultBidRequest.tap { - site.page = stringTargetingValue - } - - APP_BUNDLE | BidRequest.getDefaultBidRequest(APP).tap { - app = App.defaultApp.tap { - bundle = stringTargetingValue - } - } - - UFPD_BUYER_UID | BidRequest.defaultBidRequest.tap { - user = User.defaultUser.tap { - buyeruid = stringTargetingValue - } - } - } - - def "PBS should support targeting matching by bidder parameters"() { - given: "Bid request with specified bidder parameter" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - banner = Banner.defaultBanner - ext = ImpExt.defaultImpExt - ext.prebid.bidder = new Bidder(rubicon: Rubicon.defaultRubicon.tap { accountId = integerTargetingValue }) - }] - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].source = RUBICON.name().toLowerCase() - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(BIDP_ACCOUNT_ID, INTERSECTS, [integerTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should support line item targeting by page position targeting type"() { - given: "Bid request and bid response" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp[0].banner.pos = integerTargetingValue - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(PAGE_POSITION, IN, [integerTargetingValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should support line item targeting by userdow targeting type"() { - given: "Bid request and bid response" - def bidRequest = BidRequest.defaultBidRequest.tap { - def weekDay = ZonedDateTime.now(ZoneId.from(UTC)).dayOfWeek.get(SUNDAY_START.dayOfWeek()) - user = User.defaultUser.tap { - ext = new UserExt(time: new UserTime(userdow: weekDay)) - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(DOW, IN, [ZonedDateTime.now(ZoneId.from(UTC)).dayOfWeek.get(SUNDAY_START.dayOfWeek())]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should support line item targeting by userhour targeting type"() { - given: "Bid request and bid response" - def bidRequest = BidRequest.defaultBidRequest.tap { - def hour = ZonedDateTime.now(ZoneId.from(UTC)).hour - user = User.defaultUser.tap { - ext = new UserExt(time: new UserTime(userhour: hour)) - } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(HOUR, IN, [ZonedDateTime.now(ZoneId.from(UTC)).hour]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } - - def "PBS should support line item targeting by '#targetingType' targeting type"() { - given: "Bid request and bid response" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(HOUR, IN, [ZonedDateTime.now(ZoneId.from(UTC)).hour]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - - where: - targetingType | targetingValue - - "'\$or' root node with one match" | new Targeting.Builder(OR).addTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [VIDEO]) - .build() - - "'\$not' root node without matches" | new Targeting.Builder(NOT).buildNotBooleanOperatorTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [VIDEO]) - } - - def "PBS should support line item domain targeting by #domainTargetingType"() { - given: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SITE_DOMAIN, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - - and: "Targeting recorded as matched" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedDomainTargeting?.size() == lineItemSize - - where: - domainTargetingType | bidRequest - - "site domain" | BidRequest.defaultBidRequest.tap { - site.domain = stringTargetingValue - } - - "site publisher domain" | BidRequest.defaultBidRequest.tap { - site.publisher = Publisher.defaultPublisher.tap { domain = stringTargetingValue } - } - } - - def "PBS should support line item domain targeting"() { - given: "Bid response" - def bidRequest = BidRequest.defaultBidRequest.tap { - site.domain = siteDomain - site.publisher = Publisher.defaultPublisher.tap { domain = sitePublisherDomain } - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(SITE_DOMAIN, IN, [siteDomain]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - - and: "Targeting recorded as matched" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedDomainTargeting?.size() == lineItemSize - - where: - siteDomain | sitePublisherDomain - "www.example.com" | null - "https://www.example.com" | null - "www.example.com" | "example.com" - } - - def "PBS should appropriately match '\$or', '\$not' line items targeting root node rules"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = targeting - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't had PG deals auction as targeting differs" - assert !auctionResponse.ext?.debug?.pgmetrics - - where: - targeting << [new Targeting.Builder(OR).addTargeting(AD_UNIT_SIZE, INTERSECTS, [new LineItemSize(w: PBSUtils.randomNumber, h: PBSUtils.randomNumber)]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [VIDEO]) - .build(), - new Targeting.Builder(NOT).buildNotBooleanOperatorTargeting(AD_UNIT_SIZE, INTERSECTS, [LineItemSize.defaultLineItemSize])] - } - - def "PBS should support line item targeting by device geo region, metro when request region, metro as int or str value are given"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest.tap { - device = new Device(geo: new Geo(ext: new GeoExt(geoProvider: new GeoExtGeoProvider(region: requestValue, - metro: requestValue)))) - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(DEVICE_REGION, IN, [lineItemValue]) - .addTargeting(DEVICE_METRO, IN, [lineItemValue]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - assert auctionResponse.ext.debug.pgmetrics.matchedWholeTargeting.first() == plansResponse.lineItems.first().lineItemId - - where: - requestValue | lineItemValue - stringTargetingValue | stringTargetingValue - integerTargetingValue | integerTargetingValue as String - } - - def "PBS should be able to match Ad Slot targeting taken from different sources by MATCHES matching function"() { - given: "Bid request with set ad slot info in different request places" - def bidRequest = BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - tagId = impTagId - ext.gpid = impExtGpid - ext.data = new ImpExtContextData(pbAdSlot: adSlot, - adServer: new ImpExtContextDataAdServer(adSlot: adServerAdSlot)) - }] - } - - and: "Planner response with MATCHES one of Ad Slot values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(AD_UNIT_AD_SLOT, MATCHES, stringTargetingValue) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - - where: - impTagId | impExtGpid | adSlot | adServerAdSlot - stringTargetingValue | PBSUtils.randomString | PBSUtils.randomString | PBSUtils.randomString - PBSUtils.randomString | stringTargetingValue | PBSUtils.randomString | PBSUtils.randomString - null | null | stringTargetingValue | PBSUtils.randomString - null | null | PBSUtils.randomString | stringTargetingValue - } - - def "PBS should be able to match Ad Slot targeting taken from different sources by IN matching function"() { - given: "Bid request with set ad slot info in different request places" - def contextAdSlot = PBSUtils.randomString - def contextAdServerAdSlot = PBSUtils.randomString - def adSlot = PBSUtils.randomString - def adServerAdSlot = PBSUtils.randomString - def bidRequest = BidRequest.defaultBidRequest.tap { - imp = [Imp.defaultImpression.tap { - ext.context = new ImpExtContext(data: new ImpExtContextData(pbAdSlot: contextAdSlot, - adServer: new ImpExtContextDataAdServer(adSlot: contextAdServerAdSlot))) - ext.data = new ImpExtContextData(pbAdSlot: adSlot, - adServer: new ImpExtContextDataAdServer(adSlot: adServerAdSlot)) - }] - } - - and: "Planner response with IN all of Ad Slot values" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = Targeting.defaultTargetingBuilder - .addTargeting(AD_UNIT_AD_SLOT, IN, [contextAdSlot, contextAdServerAdSlot, adSlot, adServerAdSlot, PBSUtils.randomString]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - def lineItemSize = plansResponse.lineItems.size() - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == lineItemSize - } - - def "PBS should be able to match video size targeting taken from imp[].video sources by INTERSECTS matching function"() { - given: "Default video bid request" - def lineItemSize = LineItemSize.defaultLineItemSize - def bidRequest = BidRequest.defaultVideoRequest.tap { - imp[0].video.w = lineItemSize.w - imp[0].video.h = lineItemSize.h - } - - and: "Planner response" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].targeting = new Targeting.Builder().addTargeting(AD_UNIT_SIZE, INTERSECTS, [lineItemSize]) - .addTargeting(AD_UNIT_MEDIA_TYPE, INTERSECTS, [VIDEO]) - .build() - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS had PG auction" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedWholeTargeting?.size() == plansResponse.lineItems.size() - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/TokenSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/TokenSpec.groovy deleted file mode 100644 index 672db59e438..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/TokenSpec.groovy +++ /dev/null @@ -1,317 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.deals.lineitem.LineItem -import org.prebid.server.functional.model.deals.lineitem.Token -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.dealsupdate.ForceDealsUpdateRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.util.HttpUtil - -import java.time.ZoneId -import java.time.ZonedDateTime - -import static java.time.ZoneOffset.UTC -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC - -class TokenSpec extends BasePgSpec { - - def cleanup() { - pgPbsService.sendForceDealsUpdateRequest(ForceDealsUpdateRequest.invalidateLineItemsRequest) - } - - def "PBS should start using line item in auction when its expired tokens number is increased"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock zero tokens line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 0 - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested" - def firstAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start processing PG deals" - assert firstAuctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == - [plansResponse.lineItems[0].lineItemId] as Set - assert !firstAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder - - when: "Line item tokens are updated" - plansResponse.lineItems[0].deliverySchedules[0].tokens[0].total = 1 - plansResponse.lineItems[0].deliverySchedules[0].updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).plusSeconds(1) - generalPlanner.initPlansResponse(plansResponse) - - and: "Updated line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Auction is requested for the second time" - bidder.setResponse(bidRequest.id, bidResponse) - def secondAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS should process PG deals" - def sentToBidder = secondAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == plansResponse.lineItems.size() - assert sentToBidder[0] == plansResponse.lineItems[0].lineItemId - } - - def "PBS shouldn't allow line items with zero token number take part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock zero tokens line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 0 - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS should recognize line items with pacing deferred" - assert auctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == [plansResponse.lineItems[0].lineItemId] as Set - } - - def "PBS should allow line item take part in auction when it has at least one unspent token among all expired tokens"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line item with zero and 1 available tokens" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - def deliverySchedules = lineItems[0].deliverySchedules[0] - deliverySchedules.tokens[0].total = 0 - deliverySchedules.tokens << new Token(priorityClass: 2, total: 0) - deliverySchedules.tokens << new Token(priorityClass: 3, total: 1) - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - def lineItemCount = plansResponse.lineItems.size() - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS should process PG deals" - assert !auctionResponse.ext?.debug?.pgmetrics?.pacingDeferred - assert auctionResponse.ext?.debug?.pgmetrics?.readyToServe?.size() == lineItemCount - def sentToBidder = auctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == lineItemCount - assert sentToBidder[0] == plansResponse.lineItems[0].lineItemId - } - - def "PBS shouldn't allow line item take part in auction when all its tokens are spent"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock with 1 token to spend line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 1 - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Auction is happened for the first time" - pgPbsService.sendAuctionRequest(bidRequest) - - when: "Requesting auction for the second time" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start PG processing" - assert auctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == [plansResponse.lineItems[0].lineItemId] as Set - } - - def "PBS should take only the first token among tokens with the same priority class"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line item with 2 tokens of the same priority but the first has zero total number" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - def tokens = [new Token(priorityClass: 1, total: 0), new Token(priorityClass: 1, total: 1)] - lineItems[0].deliverySchedules[0].tokens = tokens - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is happened" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start PG processing as it was processed only the first token with 0 total number" - assert auctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == [plansResponse.lineItems[0].lineItemId] as Set - } - - def "PBS shouldn't allow line item take part in auction when its number of available impressions is ahead of the scheduled time"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line item to have max 2 impressions during one week" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 2 - lineItems[0].startTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)) - lineItems[0].updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)) - lineItems[0].endTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)).plusWeeks(1) - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested for the first time" - def firstAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS processed PG deals" - def sentToBidder = firstAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == plansResponse.lineItems.size() - assert sentToBidder[0] == plansResponse.lineItems[0].lineItemId - - when: "Auction is requested for the second time" - def secondAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS hasn't allowed line item take part in auction as it has only one impression left to be shown during the week" - assert secondAuctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == - [plansResponse.lineItems[0].lineItemId] as Set - assert !secondAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder - } - - def "PBS should abandon line item with updated zero available token number take part in auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock with not null tokens number line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 2 - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - when: "Auction is requested" - def firstAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS processed PG deals" - def sentToBidder = firstAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder?.get(GENERIC.value) - assert sentToBidder?.size() == plansResponse.lineItems.size() - assert sentToBidder[0] == plansResponse.lineItems[0].lineItemId - - when: "Line item tokens are updated to have no available tokens" - plansResponse.lineItems[0].deliverySchedules[0].tokens[0].total = 0 - plansResponse.lineItems[0].deliverySchedules[0].updatedTimeStamp = ZonedDateTime.now(ZoneId.from(UTC)) - - generalPlanner.initPlansResponse(plansResponse) - - and: "Updated line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Auction is requested for the second time" - def secondAuctionResponse = pgPbsService.sendAuctionRequest(bidRequest) - - then: "PBS shouldn't start processing PG deals" - assert secondAuctionResponse.ext?.debug?.pgmetrics?.pacingDeferred == - [plansResponse.lineItems[0].lineItemId] as Set - assert !secondAuctionResponse.ext?.debug?.pgmetrics?.sentToBidder - } - - def "PBS should ignore line item pacing when ignore pacing header is present in the request"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock zero tokens line item" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].deliverySchedules[0].tokens[0].total = 0 - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Pg ignore pacing header" - def pgIgnorePacingHeader = ["${HttpUtil.PG_IGNORE_PACING_HEADER}": "1"] - - when: "Auction is requested" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, pgIgnorePacingHeader) - - then: "PBS should process PG deals" - def pgMetrics = auctionResponse.ext?.debug?.pgmetrics - def sentToBidder = pgMetrics?.sentToBidder[GENERIC.value] - assert sentToBidder?.size() == plansResponse.lineItems.size() - assert sentToBidder[0] == plansResponse.lineItems[0].lineItemId - assert pgMetrics.readyToServe == [plansResponse.lineItems[0].lineItemId] as Set - } - - def "PBS should prioritize line item when pg ignore pacing and #reason"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock with additional lineItem" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems.add(updateLineItem(bidRequest.site.publisher.id)) - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Pg ignore pacing header" - def pgIgnorePacingHeader = ["${HttpUtil.PG_IGNORE_PACING_HEADER}": "1"] - - when: "Auction is requested" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, pgIgnorePacingHeader) - - then: "PBS should process PG deals" - def pgMetrics = auctionResponse.ext?.debug?.pgmetrics - assert pgMetrics?.readyToServe?.size() == plansResponse.lineItems.size() - assert pgMetrics.readyToServe.eachWithIndex { id, index -> - id == plansResponse.lineItems[index].lineItemId } - - where: - reason | updateLineItem - "cpm is null" | {siteId -> LineItem.getDefaultLineItem(siteId).tap { - price.cpm = null - }} - "relative priority is null" | {siteId -> LineItem.getDefaultLineItem(siteId).tap { - relativePriority = null - }} - "no tokens unspent" | {siteId -> LineItem.getDefaultLineItem(siteId).tap { - deliverySchedules[0].tokens[0].total = 0 - }} - "delivery plan is null" | {siteId -> LineItem.getDefaultLineItem(siteId).tap { - deliverySchedules = null - }} - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/pg/UserDetailsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pg/UserDetailsSpec.groovy deleted file mode 100644 index a61907af8ae..00000000000 --- a/src/test/groovy/org/prebid/server/functional/tests/pg/UserDetailsSpec.groovy +++ /dev/null @@ -1,343 +0,0 @@ -package org.prebid.server.functional.tests.pg - -import org.prebid.server.functional.model.UidsCookie -import org.prebid.server.functional.model.deals.lineitem.FrequencyCap -import org.prebid.server.functional.model.deals.userdata.UserDetailsResponse -import org.prebid.server.functional.model.mock.services.generalplanner.PlansResponse -import org.prebid.server.functional.model.mock.services.httpsettings.HttpAccountsResponse -import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.model.request.event.EventRequest -import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.testcontainers.Dependencies -import org.prebid.server.functional.testcontainers.scaffolding.HttpSettings -import org.prebid.server.functional.util.HttpUtil -import org.prebid.server.functional.util.PBSUtils -import spock.lang.Shared - -import java.time.format.DateTimeFormatter - -import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500 -import static org.mockserver.model.HttpStatusCode.NOT_FOUND_404 -import static org.mockserver.model.HttpStatusCode.NO_CONTENT_204 -import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.deals.lineitem.LineItem.TIME_PATTERN - -class UserDetailsSpec extends BasePgSpec { - - private static final String USER_SERVICE_NAME = "userservice" - - @Shared - HttpSettings httpSettings = new HttpSettings(Dependencies.networkServiceContainer) - - def "PBS should send user details request to the User Service during deals auction"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id)) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial user details request count is taken" - def initialRequestCount = userData.recordedUserDetailsRequestCount - - and: "Cookies with user ids" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS sends a request to the User Service" - def updatedRequestCount = userData.recordedUserDetailsRequestCount - assert updatedRequestCount == initialRequestCount + 1 - - and: "Request corresponds to the payload" - def userDetailsRequest = userData.recordedUserDetailsRequest - assert userDetailsRequest.ids?.size() == 1 - assert userDetailsRequest.ids[0].id == uidsCookie.tempUIDs.get(GENERIC).uid - assert userDetailsRequest.ids[0].type == pgConfig.userIdType - } - - def "PBS should validate bad user details response status code #statusCode"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "User Service response is set" - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse, statusCode) - - and: "Initial user details request count is taken" - def initialRequestCount = userData.recordedUserDetailsRequestCount - - and: "Cookies with user ids" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS sends a request to the User Service during auction" - assert userData.recordedUserDetailsRequestCount == initialRequestCount + 1 - def userServiceCall = auctionResponse.ext?.debug?.httpcalls?.get(USER_SERVICE_NAME) - assert userServiceCall?.size() == 1 - - assert !userServiceCall[0].status - assert !userServiceCall[0].responseBody - - cleanup: - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - - where: - statusCode << [NO_CONTENT_204, NOT_FOUND_404, INTERNAL_SERVER_ERROR_500] - } - - def "PBS should invalidate user details response body when response has absent #fieldName field"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial user details request count is taken" - def initialRequestCount = userData.recordedUserDetailsRequestCount - - and: "User Service response is set" - userData.setUserDataResponse(userDataResponse) - - and: "Cookies with user ids" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS sends a request to the User Service" - assert userData.recordedUserDetailsRequestCount == initialRequestCount + 1 - - and: "Call to the user service was made" - assert auctionResponse.ext?.debug?.httpcalls?.get(USER_SERVICE_NAME)?.size() == 1 - - and: "Data from the user service response wasn't added to the bid request by PBS" - assert !auctionResponse.ext?.debug?.resolvedRequest?.user?.data - assert !auctionResponse.ext?.debug?.resolvedRequest?.user?.ext?.fcapids - - cleanup: - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - - where: - fieldName | userDataResponse - "user" | new UserDetailsResponse(user: null) - "user.data" | UserDetailsResponse.defaultUserResponse.tap { user.data = null } - "user.ext" | UserDetailsResponse.defaultUserResponse.tap { user.ext = null } - } - - def "PBS should abandon line items with user fCap ids take part in auction when user details response failed"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Planner Mock line items with added frequency cap" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id).tap { - lineItems[0].frequencyCaps = [FrequencyCap.defaultFrequencyCap.tap { fcapId = PBSUtils.randomNumber as String }] - } - generalPlanner.initPlansResponse(plansResponse) - - and: "Bid response" - def bidResponse = BidResponse.getDefaultPgBidResponse(bidRequest, plansResponse) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Bad User Service Response is set" - userData.setUserDataResponse(new UserDetailsResponse(user: null)) - - and: "Cookies header" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS" - def auctionResponse = pgPbsService.sendAuctionRequest(bidRequest, cookieHeader) - - then: "PBS hasn't started processing PG deals as line item targeting frequency capped lookup failed" - assert auctionResponse.ext?.debug?.pgmetrics?.matchedTargetingFcapLookupFailed?.size() == - plansResponse.lineItems.size() - - cleanup: - userData.setUserDataResponse(UserDetailsResponse.defaultUserResponse) - } - - def "PBS should send win notification request to the User Service on bidder wins"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - def lineItemId = plansResponse.lineItems[0].lineItemId - def lineItemUpdateTime = plansResponse.lineItems[0].updatedTimeStamp - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial win notification request count" - def initialRequestCount = userData.requestCount - - and: "Enabled event request" - def winEventRequest = EventRequest.defaultEventRequest.tap { - it.lineItemId = lineItemId - analytics = 0 - } - - and: "Default account response" - def httpSettingsResponse = HttpAccountsResponse.getDefaultHttpAccountsResponse(winEventRequest.accountId.toString()) - httpSettings.setResponse(winEventRequest.accountId.toString(), httpSettingsResponse) - - and: "Cookies header" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS where the winner is instantiated" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "Sending event request to PBS" - pgPbsService.sendEventRequest(winEventRequest, cookieHeader) - - then: "PBS sends a win notification to the User Service" - PBSUtils.waitUntil { userData.requestCount == initialRequestCount + 1 } - - and: "Win request corresponds to the payload" - def timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN) - - verifyAll(userData.recordedWinEventRequest) { winNotificationRequest -> - winNotificationRequest.bidderCode == GENERIC.value - winNotificationRequest.bidId == winEventRequest.bidId - winNotificationRequest.lineItemId == lineItemId - winNotificationRequest.region == pgConfig.region - winNotificationRequest.userIds?.size() == 1 - winNotificationRequest.userIds[0].id == uidsCookie.tempUIDs.get(GENERIC).uid - winNotificationRequest.userIds[0].type == pgConfig.userIdType - timeFormatter.format(winNotificationRequest.lineUpdatedDateTime) == timeFormatter.format(lineItemUpdateTime) - winNotificationRequest.winEventDateTime.isAfter(winNotificationRequest.lineUpdatedDateTime) - !winNotificationRequest.frequencyCaps - } - } - - def "PBS shouldn't send win notification request to the User Service when #reason line item id is given"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - generalPlanner.initPlansResponse(PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id)) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial win notification request count" - def initialRequestCount = userData.requestCount - - and: "Enabled event request" - def eventRequest = EventRequest.defaultEventRequest.tap { - it.lineItemId = lineItemId - analytics = 0 - } - - and: "Default account response" - def httpSettingsResponse = HttpAccountsResponse.getDefaultHttpAccountsResponse(eventRequest.accountId.toString()) - httpSettings.setResponse(eventRequest.accountId.toString(), httpSettingsResponse) - - and: "Cookies header" - def uidsCookie = UidsCookie.defaultUidsCookie - def cookieHeader = HttpUtil.getCookieHeader(uidsCookie) - - when: "Sending auction request to PBS where the winner is instantiated" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "Sending event request to PBS" - pgPbsService.sendEventRequest(eventRequest, cookieHeader) - - then: "PBS hasn't sent a win notification to the User Service" - assert userData.requestCount == initialRequestCount - - where: - reason | lineItemId - "null" | null - "non-existent" | PBSUtils.randomNumber as String - } - - def "PBS shouldn't send win notification request to the User Service when #reason cookies header was given"() { - given: "Bid request" - def bidRequest = BidRequest.defaultBidRequest - - and: "Bid response" - def bidResponse = BidResponse.getDefaultBidResponse(bidRequest) - bidder.setResponse(bidRequest.id, bidResponse) - - and: "Planner Mock line items" - def plansResponse = PlansResponse.getDefaultPlansResponse(bidRequest.site.publisher.id) - def lineItemId = plansResponse.lineItems[0].lineItemId - generalPlanner.initPlansResponse(plansResponse) - - and: "Line items are fetched by PBS" - updateLineItemsAndWait() - - and: "Initial win notification request count" - def initialRequestCount = userData.requestCount - - and: "Enabled event request" - def eventRequest = EventRequest.defaultEventRequest.tap { - it.lineItemId = lineItemId - analytics = 0 - } - - and: "Default account response" - def httpSettingsResponse = HttpAccountsResponse.getDefaultHttpAccountsResponse(eventRequest.accountId.toString()) - httpSettings.setResponse(eventRequest.accountId.toString(), httpSettingsResponse) - - when: "Sending auction request to PBS where the winner is instantiated" - pgPbsService.sendAuctionRequest(bidRequest) - - and: "Sending event request to PBS" - pgPbsService.sendEventRequest(eventRequest, HttpUtil.getCookieHeader(uidsCookie)) - - then: "PBS hasn't sent a win notification to the User Service" - assert userData.requestCount == initialRequestCount - - where: - reason | uidsCookie - - "empty cookie" | new UidsCookie() - - "empty uids cookie" | UidsCookie.defaultUidsCookie.tap { - uids = null - tempUIDs = null - } - } -} diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy index 0b917c50055..6c274fb7ab4 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/PrivacyBaseSpec.groovy @@ -20,7 +20,6 @@ import org.prebid.server.functional.model.request.auction.RegsExt import org.prebid.server.functional.model.request.auction.User import org.prebid.server.functional.model.request.auction.UserExt import org.prebid.server.functional.service.PrebidServerService -import org.prebid.server.functional.testcontainers.PbsPgConfig import org.prebid.server.functional.testcontainers.scaffolding.VendorList import org.prebid.server.functional.tests.BaseSpec import org.prebid.server.functional.util.PBSUtils @@ -59,10 +58,9 @@ abstract class PrivacyBaseSpec extends BaseSpec { static final Map GDPR_VENDOR_LIST_CONFIG = ["gdpr.vendorlist.v2.http-endpoint-template": "$networkServiceContainer.rootUri/v2/vendor-list.json".toString(), "gdpr.vendorlist.v3.http-endpoint-template": "$networkServiceContainer.rootUri/v3/vendor-list.json".toString()] private static final Map SETTING_CONFIG = ["settings.enforce-valid-account": 'true'] - private static final PbsPgConfig pgConfig = new PbsPgConfig(networkServiceContainer) protected static final Map PBS_CONFIG = OPENX_CONFIG + OPENX_COOKIE_SYNC_CONFIG + - GENERIC_COOKIE_SYNC_CONFIG + pgConfig.properties + GDPR_VENDOR_LIST_CONFIG + SETTING_CONFIG + GENERIC_COOKIE_SYNC_CONFIG + GDPR_VENDOR_LIST_CONFIG + SETTING_CONFIG protected static final String VALID_VALUE_FOR_GPC_HEADER = "1" protected static final GppConsent SIMPLE_GPC_DISALLOW_LOGIC = new UspNatV1Consent.Builder().setGpc(true).build() protected static final VendorList vendorListResponse = new VendorList(networkServiceContainer) diff --git a/src/test/groovy/org/prebid/server/functional/util/HttpUtil.groovy b/src/test/groovy/org/prebid/server/functional/util/HttpUtil.groovy index 2e7d6a2d0a1..c1f60516abf 100644 --- a/src/test/groovy/org/prebid/server/functional/util/HttpUtil.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/HttpUtil.groovy @@ -7,11 +7,7 @@ import static java.nio.charset.StandardCharsets.UTF_8 class HttpUtil implements ObjectMapperWrapper { - public static final String UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/ - public static final String PG_TRX_ID_HEADER = "pg-trx-id" - public static final String PG_IGNORE_PACING_HEADER = "X-Prebid-PG-ignore-pacing" - public static final String AUTHORIZATION_HEADER = "Authorization" public static final String ACCEPT_HEADER = "Authorization" public static final String CONTENT_TYPE_HEADER = "Content-Type" public static final String COOKIE_HEADER = "cookie" @@ -21,13 +17,6 @@ class HttpUtil implements ObjectMapperWrapper { public static final String SET_COOKIE_HEADER = 'Set-Cookie' public static final String COOKIE_DEPRECATION_HEADER = 'Sec-Cookie-Deprecation' - public static final String CONTENT_TYPE_HEADER_VALUE = "application/json" - public static final String CHARSET_HEADER_VALUE = "charset=utf-8" - - static String makeBasicAuthHeaderValue(String username, String password) { - "Basic ${encodeWithBase64("$username:$password")}" - } - static HashMap getCookieHeader(UidsCookie uidsCookie) { [(COOKIE_HEADER): makeUidsCookieHeaderValue(encode(uidsCookie))] } diff --git a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java index 12ee628c670..98fd998571b 100644 --- a/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java +++ b/src/test/java/org/prebid/server/analytics/reporter/pubstack/PubstackEventHandlerTest.java @@ -17,8 +17,6 @@ import org.prebid.server.auction.model.AuctionContext; import org.prebid.server.auction.model.TimeoutContext; import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.execution.Timeout; import org.prebid.server.vertx.http.HttpClient; import org.prebid.server.vertx.http.model.HttpClientResponse; @@ -161,8 +159,6 @@ public void handleShouldBeAbleToEncodeAuctionEvent() { .auctionContext(AuctionContext.builder() .uidsCookie(mock(UidsCookie.class)) .timeoutContext(TimeoutContext.of(0, mock(Timeout.class), 0)) - .txnLog(mock(TxnLog.class)) - .deepDebugLog(mock(DeepDebugLog.class)) .build()) .build(); diff --git a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java index 67d7725c535..58a9386de55 100644 --- a/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java +++ b/src/test/java/org/prebid/server/auction/BidResponseCreatorTest.java @@ -58,8 +58,6 @@ import org.prebid.server.cache.model.CacheInfo; import org.prebid.server.cache.model.CacheServiceResult; import org.prebid.server.cache.model.DebugHttpCall; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.events.EventsContext; import org.prebid.server.events.EventsService; import org.prebid.server.exception.InvalidRequestException; @@ -95,7 +93,6 @@ import org.prebid.server.proto.openrtb.ext.response.ExtBidResponse; import org.prebid.server.proto.openrtb.ext.response.ExtBidResponsePrebid; import org.prebid.server.proto.openrtb.ext.response.ExtBidderError; -import org.prebid.server.proto.openrtb.ext.response.ExtDebugPgmetrics; import org.prebid.server.proto.openrtb.ext.response.ExtDebugTrace; import org.prebid.server.proto.openrtb.ext.response.ExtHttpCall; import org.prebid.server.proto.openrtb.ext.response.ExtResponseCache; @@ -105,7 +102,6 @@ import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInvocationDefaultResult; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityInvocationResult; import org.prebid.server.proto.openrtb.ext.response.ExtTraceActivityRule; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal; import org.prebid.server.proto.openrtb.ext.response.FledgeAuctionConfig; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.NonBid; import org.prebid.server.proto.openrtb.ext.response.seatnonbid.SeatNonBid; @@ -122,7 +118,6 @@ import java.time.Instant; import java.time.ZoneId; import java.time.ZoneOffset; -import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -136,7 +131,6 @@ import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; -import static java.util.Collections.singleton; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static java.util.function.UnaryOperator.identity; @@ -162,8 +156,6 @@ import static org.prebid.server.proto.openrtb.ext.response.BidType.banner; import static org.prebid.server.proto.openrtb.ext.response.BidType.video; import static org.prebid.server.proto.openrtb.ext.response.BidType.xNative; -import static org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category.pacing; -import static org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category.targeting; public class BidResponseCreatorTest extends VertxTest { @@ -551,7 +543,7 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { .with(toAuctionParticipant(bidderResponses)); final String modifiedAdm = "modifiedAdm"; - given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any(), any(), any())) + given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any(), any())) .willReturn(modifiedAdm); // just a stub to get through method call chain @@ -569,8 +561,14 @@ public void shouldRequestCacheServiceWithVideoBidsToModify() { .build(); verify(vastModifier) - .createBidVastXml(eq(bidder1), eq(null), eq(BID_NURL), eq(bidId1), - eq(accountId), eq(expectedEventContext), eq(emptyList()), eq(null)); + .createBidVastXml( + eq(bidder1), + eq(null), + eq(BID_NURL), + eq(bidId1), + eq(accountId), + eq(expectedEventContext), + eq(emptyList())); final ArgumentCaptor> bidInfoCaptor = ArgumentCaptor.forClass(List.class); verify(cacheService).cacheBidsOpenrtb( @@ -609,8 +607,7 @@ public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { final String modifiedVast = "modifiedVast"; given(vastModifier - .createBidVastXml(anyString(), anyString(), anyString(), - anyString(), anyString(), any(), any(), any())) + .createBidVastXml(anyString(), anyString(), anyString(), anyString(), anyString(), any(), any())) .willReturn(modifiedVast); // when @@ -623,8 +620,7 @@ public void shouldModifyBidAdmWhenBidVideoAndVastModifierReturnValue() { .containsOnly(modifiedVast); verify(vastModifier) - .createBidVastXml(eq(bidder), eq(BID_ADM), eq(BID_NURL), eq(bidId), eq("accountId"), any(), any(), - any()); + .createBidVastXml(eq(bidder), eq(BID_ADM), eq(BID_NURL), eq(bidId), eq("accountId"), any(), any()); } @SuppressWarnings("unchecked") @@ -840,14 +836,18 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); givenCacheServiceResult(singletonList(CacheInfo.of("id", null, null, null))); final Events events = Events.of("http://event-type-win", "http://event-type-view"); - given(eventsService.createEvent(anyString(), anyString(), anyString(), anyString(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(events); // when bidResponseCreator.create(auctionContext, cacheInfo, MULTI_BIDS).result(); // then - final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder().bidid(generatedBidId).type(banner).build(); + final ExtBidPrebid extBidPrebid = ExtBidPrebid.builder() + .bidid(generatedBidId) + .type(banner) + .events(events) + .build(); final Bid expectedBid = bid.toBuilder() .ext(mapper.createObjectNode().set("prebid", mapper.valueToTree(extBidPrebid))) .build(); @@ -855,7 +855,7 @@ public void shouldUseGeneratedBidIdForEventAndCacheWhenIdGeneratorIsUUIDAndEvent final BidInfo expectedBidInfo = toBidInfo(expectedBid, imp, bidder, banner, true); verify(cacheService).cacheBidsOpenrtb(eq(singletonList(expectedBidInfo)), any(), any(), any()); - verify(eventsService).createEvent(eq(generatedBidId), anyString(), anyString(), any(), anyBoolean(), any()); + verify(eventsService).createEvent(eq(generatedBidId), anyString(), anyString(), anyBoolean(), any()); } @SuppressWarnings("unchecked") @@ -1920,88 +1920,6 @@ public void shouldPopulateTargetingKeywordsForWinningBidsAndWinningBidsByBidder( verify(cacheService, never()).cacheBidsOpenrtb(anyList(), any(), any(), any()); } - @Test - public void shouldPopulateAuctionLostToMetricByWinningDealBid() { - // given - final String dealId1 = "dealId1"; - final String dealId2 = "dealId2"; - final String lineItemId1 = "lineItemId1"; - final String lineItemId2 = "lineItemId2"; - final BidRequest bidRequest = givenBidRequest( - identity(), - extBuilder -> extBuilder.targeting(givenTargeting()), - Imp.builder() - .id(IMP_ID) - .pmp(Pmp.builder() - // Order defines winning bid - .deals(asList( - Deal.builder().id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId1", null, null, null)))).build(), - Deal.builder().id("dealId2") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId2", null, null, null)))).build())) - .build()) - .build()); - - final Bid firstBid = Bid.builder().id("bidId1").impid(IMP_ID).price(BigDecimal.valueOf(5.67)) - .dealid(dealId1).build(); - final Bid secondBid = Bid.builder().id("bidId2").impid(IMP_ID).price(BigDecimal.valueOf(4.98)) - .dealid(dealId2).build(); - - final List bidderResponses = asList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(firstBid, banner, null)), 100), - BidderResponse.of("bidder2", givenSeatBid(BidderBid.of(secondBid, banner, null)), 100)); - - final AuctionContext auctionContext = givenAuctionContext( - bidRequest, - contextBuilder -> contextBuilder.auctionParticipations(toAuctionParticipant(bidderResponses))); - - // when - bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); - - // then - assertThat(auctionContext.getTxnLog().lostAuctionToLineItems().entrySet()) - .extracting(Map.Entry::getKey, Map.Entry::getValue) - .containsOnly(tuple(lineItemId2, singleton(lineItemId1))); - } - - @Test - public void shouldIncreaseLineItemSentToClientAsTopMatchMetricInTransactionLog() { - // given - final BidRequest bidRequest = givenBidRequest( - identity(), - extBuilder -> extBuilder.targeting(givenTargeting()), - givenImp(Collections.singletonMap("dealId", "lineItemId1"))); - - final Bid bid = Bid.builder() - .id("bidId1") - .impid(IMP_ID) - .price(BigDecimal.valueOf(5.67)) - .dealid("dealId") - .build(); - final List bidderResponses = singletonList( - BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, null)), 100)); - - final AuctionContext auctionContext = givenAuctionContext( - bidRequest, - context -> context - .debugContext(DebugContext.of(true, true, null)) - .auctionParticipations(toAuctionParticipant(bidderResponses))); - - // when - final BidResponse bidResponse = bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); - - // then - final ExtBidResponse responseExt = bidResponse.getExt(); - - assertThat(responseExt.getDebug()).isNotNull(); - assertThat(responseExt.getDebug().getPgmetrics()).isNotNull(); - assertThat(singletonList(responseExt.getDebug().getPgmetrics())) - .flatExtracting(ExtDebugPgmetrics::getSentToClientAsTopMatch) - .containsOnly("lineItemId1"); - } - @Test public void shouldPopulateTargetingKeywordsFromMediaTypePriceGranularities() { // given @@ -2159,43 +2077,6 @@ public void shouldPopulateTargetingKeywordsIfBidWasCachedAndAdmWasRemoved() { .doesNotContainNull(); } - @Test - public void shouldCallEventsServiceWhenEventsDisabledByRequestButBidWithLineItem() { - // given - final Account account = Account.builder() - .id("accountId") - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build(); - final BidRequest bidRequest = givenBidRequest( - identity(), - extBuilder -> extBuilder.targeting(givenTargeting()), - givenImp(Collections.singletonMap("dealId", "lineItemId"))); - - final Bid bid = Bid.builder() - .id("bidId") - .price(BigDecimal.valueOf(5.67)) - .impid(IMP_ID) - .dealid("dealId") - .build(); - final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); - - final AuctionContext auctionContext = givenAuctionContext( - bidRequest, - contextBuilder -> contextBuilder - .account(account) - .auctionParticipations(toAuctionParticipant(bidderResponses))); - - // when - bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); - - // then - verify(eventsService).createEvent( - anyString(), anyString(), anyString(), eq("lineItemId"), eq(false), any()); - } - @Test public void shouldAddExtPrebidEventsIfEventsAreEnabledAndExtRequestPrebidEventPresent() { // given @@ -2227,7 +2108,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndExtRequestPrebidEventPr .auctionParticipations(toAuctionParticipant(bidderResponses))); final Events events = Events.of("http://event-type-win", "http://event-type-view"); - given(eventsService.createEvent(anyString(), anyString(), anyString(), any(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(events); final BidRequestCacheInfo cacheInfo = BidRequestCacheInfo.builder().doCaching(true).build(); @@ -2284,7 +2165,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndAccountSupportEventsFor .auctionParticipations(toAuctionParticipant(bidderResponses))); final Events events = Events.of("http://event-type-win", "http://event-type-view"); - given(eventsService.createEvent(anyString(), anyString(), anyString(), any(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(events); // when @@ -2331,7 +2212,7 @@ public void shouldAddExtPrebidEventsIfEventsAreEnabledAndDefaultAccountAnalytics .auctionParticipations(toAuctionParticipant(bidderResponses))); final Events events = Events.of("http://event-type-win", "http://event-type-view"); - given(eventsService.createEvent(anyString(), anyString(), anyString(), any(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(events); // when @@ -3089,7 +2970,7 @@ public void shouldPassIntegrationToCacheServiceAndBidEvents() { givenCacheServiceResult(singletonList(CacheInfo.empty())); - given(eventsService.createEvent(anyString(), anyString(), anyString(), any(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(Events.of( "http://win-url?param=value&int=integration", "http://imp-url?param=value&int=integration")); @@ -3109,41 +2990,6 @@ public void shouldPassIntegrationToCacheServiceAndBidEvents() { "http://imp-url?param=value&int=integration")); } - @Test - public void shouldPopulateExtensionResponseDebugAndDeepDebugLogIfEnabled() { - // given - final DeepDebugLog deepDebugLog = DeepDebugLog.create(true, clock); - deepDebugLog.add("line-item-id-1", pacing, () -> "test-1"); - deepDebugLog.add("line-item-id-2", targeting, () -> "test-2"); - deepDebugLog.add("", targeting, () -> "test-3"); - - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); - final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); - - final AuctionContext auctionContext = givenAuctionContext( - givenBidRequest(givenImp()), - builder -> builder - .deepDebugLog(deepDebugLog) - .auctionParticipations(toAuctionParticipant(bidderResponses))); - - // when - final BidResponse bidResponse = bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); - - // then - final ExtDebugTrace extDebugTrace = bidResponse.getExt().getDebug().getTrace(); - - assertThat(extDebugTrace.getDeals()) - .containsExactly(ExtTraceDeal.of("", ZonedDateTime.now(clock), targeting, "test-3")); - - assertThat(extDebugTrace.getLineItems()) - .containsExactly( - entry("line-item-id-1", List.of(ExtTraceDeal.of("line-item-id-1", - ZonedDateTime.now(clock), pacing, "test-1"))), - entry("line-item-id-2", List.of(ExtTraceDeal.of("line-item-id-2", - ZonedDateTime.now(clock), targeting, "test-2")))); - } - @Test public void shouldPopulateActivityInfrastructureTraceLogOnSpecifiedTraceLevel() { // given @@ -3184,26 +3030,6 @@ public void shouldPopulateActivityInfrastructureTraceLogOnSpecifiedTraceLevel() .isEqualTo(traceLog); } - @Test - public void shouldBidResponseDebugReturnNullIfDeepDebugLogIsEnabledAndNotPopulated() { - // given - final Bid bid = Bid.builder().id("bidId1").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); - final List bidderResponses = singletonList(BidderResponse.of("bidder1", - givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); - - final AuctionContext auctionContext = givenAuctionContext( - givenBidRequest(givenImp()), - builder -> builder - .deepDebugLog(DeepDebugLog.create(true, clock)) - .auctionParticipations(toAuctionParticipant(bidderResponses))); - - // when - final BidResponse bidResponse = bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); - - // then - assertThat(bidResponse.getExt().getDebug()).isNull(); - } - @Test public void shouldPopulateBidResponseExtErrorIfImpExtIsInvalid() { // given @@ -3398,7 +3224,7 @@ public void shouldPopulateEventsContextForRequestIfEventsEnabledForRequest() { final Events givenEvents = Events.of( "http://win-url?auctionId=123×tamp=1000", "http://imp-url?auctionId=123×tamp=1000"); - given(eventsService.createEvent(anyString(), anyString(), anyString(), any(), anyBoolean(), any())) + given(eventsService.createEvent(anyString(), anyString(), anyString(), anyBoolean(), any())) .willReturn(givenEvents); // when @@ -3767,18 +3593,13 @@ public void shouldPopulateBidExtWhenExtMediaTypePriceGranularityHasValidxNativeE .includebidderkeys(true) .build(); - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemsSentToBidder(); - final Bid bid = Bid.builder().id("bidId").price(BigDecimal.valueOf(5.67)).impid(IMP_ID).build(); final List bidderResponses = singletonList(BidderResponse.of("bidder1", givenSeatBid(BidderBid.of(bid, banner, "USD")), 100)); - final AuctionContext auctionContext = givenAuctionContext(givenBidRequest( - identity(), extBuilder -> extBuilder.targeting(targeting), givenImp()), - auctionContextBuilder -> auctionContextBuilder - .txnLog(txnLog) - .auctionParticipations(toAuctionParticipant(bidderResponses))); + final AuctionContext auctionContext = givenAuctionContext( + givenBidRequest(identity(), extBuilder -> extBuilder.targeting(targeting), givenImp()), + context -> context.auctionParticipations(toAuctionParticipant(bidderResponses))); // when final BidResponse bidResponse = bidResponseCreator.create(auctionContext, CACHE_INFO, MULTI_BIDS).result(); @@ -3880,10 +3701,8 @@ private AuctionContext givenAuctionContext(BidRequest bidRequest, final AuctionContext.AuctionContextBuilder auctionContextBuilder = AuctionContext.builder() .account(Account.empty("accountId")) .bidRequest(bidRequest) - .txnLog(TxnLog.create()) .timeoutContext(TimeoutContext.of(0, timeout, 0)) .debugContext(DebugContext.empty()) - .deepDebugLog(DeepDebugLog.create(false, clock)) .debugHttpCalls(new HashMap<>()) .debugWarnings(emptyList()) .auctionParticipations(emptyList()) diff --git a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java index e0aa389eb79..913dbee4256 100644 --- a/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java +++ b/src/test/java/org/prebid/server/auction/ExchangeServiceTest.java @@ -1,7 +1,6 @@ package org.prebid.server.auction; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.BooleanNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import com.iab.openrtb.request.App; @@ -32,7 +31,6 @@ import com.iab.openrtb.response.SeatBid; import io.vertx.core.Future; import org.apache.commons.collections4.MapUtils; -import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -69,10 +67,6 @@ import org.prebid.server.bidder.model.BidderSeatBid; import org.prebid.server.cookie.UidsCookie; import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.DealsService; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.Timeout; @@ -109,8 +103,6 @@ import org.prebid.server.proto.openrtb.ext.request.ExtAppPrebid; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfig; import org.prebid.server.proto.openrtb.ext.request.ExtBidderConfigOrtb; -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.ExtDooh; import org.prebid.server.proto.openrtb.ext.request.ExtGranularityRange; import org.prebid.server.proto.openrtb.ext.request.ExtImpAuctionEnvironment; @@ -197,7 +189,6 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willReturn; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyList; import static org.mockito.Mockito.doAnswer; @@ -224,9 +215,6 @@ public class ExchangeServiceTest extends VertxTest { @Mock private StoredResponseProcessor storedResponseProcessor; - @Mock - private DealsService dealsService; - @Mock private PrivacyEnforcementService privacyEnforcementService; @@ -272,9 +260,6 @@ public class ExchangeServiceTest extends VertxTest { @Mock private HookStageExecutor hookStageExecutor; - @Mock - private ApplicationEventService applicationEventService; - @Mock private HttpInteractionLogger httpInteractionLogger; @@ -394,9 +379,6 @@ public void setUp() { given(storedResponseProcessor.updateStoredBidResponse(any())) .willAnswer(inv -> inv.getArgument(0)); - given(dealsService.matchAndPopulateDeals(any(), any(), any())) - .willAnswer(inv -> inv.getArgument(0)); - given(priceFloorEnforcer.enforce(any(), any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); given(dsaEnforcer.enforce(any(), any(), any())).willAnswer(inv -> inv.getArgument(1)); given(priceFloorAdjuster.adjustForImp(any(), any(), any(), any())) @@ -697,88 +679,6 @@ public void shouldPassRequestModifiedByRawBidderResponseHooks() { .containsOnly(hookChangedBid); } - @Test - public void shouldFilterPgDealsOnlyBiddersWithoutDeals() { - // given - final Bidder bidder1 = mock(Bidder.class); - final Bidder bidder2 = mock(Bidder.class); - givenBidder("bidder1", bidder1, givenEmptySeatBid()); - givenBidder("bidder2", bidder2, givenEmptySeatBid()); - - final BidRequest bidRequest = givenBidRequest(asList( - givenImp( - Map.of( - "bidder1", mapper.valueToTree("traceToken"), - "bidder2", mapper.createObjectNode().set("pgdealsonly", BooleanNode.getTrue())), - imp -> imp.id("imp1")), - givenImp( - singletonMap("bidder2", mapper.createObjectNode().set("pgdealsonly", BooleanNode.getTrue())), - imp -> imp.id("imp2")))); - - // when - final Future result = target.holdAuction(givenRequestContext(bidRequest)); - - // then - final ArgumentCaptor bidRequestCaptor = ArgumentCaptor.forClass(BidderRequest.class); - verify(httpBidderRequester, times(1)) - .requestBids(any(), bidRequestCaptor.capture(), any(), any(), any(), any(), anyBoolean()); - - assertThat(bidRequestCaptor.getValue().getBidRequest().getImp()).hasSize(1) - .extracting(imp -> imp.getExt().get("bidder").asText()) - .containsExactly("traceToken"); - - assertThat(result.result().getDebugWarnings()).containsExactly(""" - Not calling bidder2 bidder for impressions imp1, imp2 \ - due to pgdealsonly flag and no available PG line items."""); - } - - @Test - public void shouldFillAuctionContextWithMatchedDeals() { - // given - final Bidder bidder1 = mock(Bidder.class); - final Bidder bidder2 = mock(Bidder.class); - givenBidder("bidder1", bidder1, givenEmptySeatBid()); - givenBidder("bidder2", bidder2, givenEmptySeatBid()); - - final BidRequest bidRequest = givenBidRequest(asList( - givenImp(singletonMap("bidder1", mapper.createObjectNode()), imp -> imp.id("imp1")), - givenImp(singletonMap("bidder2", mapper.createObjectNode()), imp -> imp.id("imp2")))); - - given(dealsService.matchAndPopulateDeals(any(), any(), any())) - .willAnswer(arguments -> { - final BidderRequest bidderRequest = arguments.getArgument(0); - final Map> impIdToDeals = switch (bidderRequest.getBidder()) { - case "bidder1" -> singletonMap("imp1", singletonList(Deal.builder().id("deal1").build())); - case "bidder2" -> singletonMap("imp2", singletonList(Deal.builder().id("deal2").build())); - default -> null; - }; - - return bidderRequest.toBuilder().impIdToDeals(impIdToDeals).build(); - }); - - // when - final Future result = target.holdAuction(givenRequestContext(bidRequest)); - - // then - assertThat(result.result()) - .extracting(AuctionContext::getBidRequest) - .extracting(BidRequest::getImp) - .satisfies(imps -> { - assertThat(imps.get(0)) - .extracting(Imp::getPmp) - .extracting(Pmp::getDeals) - .asInstanceOf(InstanceOfAssertFactories.list(Deal.class)) - .containsExactly(Deal.builder().id("deal1").build()); - - assertThat(imps.get(1)) - .extracting(Imp::getPmp) - .extracting(Pmp::getDeals) - .asInstanceOf(InstanceOfAssertFactories.list(Deal.class)) - .containsExactly(Deal.builder().id("deal2").build()); - }); - - } - @Test public void shouldPassRequestWithExtPrebidToDefinedBidder() { // given @@ -1382,7 +1282,7 @@ public void shouldOverrideDebugEnabledFlag() { .willReturn(Future.succeededFuture( BidResponse.builder() .ext(ExtBidResponse.builder() - .debug(ExtResponseDebug.of(null, null, null, null)) + .debug(ExtResponseDebug.of(null, null, null)) .build()) .build())); @@ -1412,7 +1312,7 @@ public void shouldAddDebugInfoIfDebugEnabledAndPublisherAndBidderAllowedDebug() .willReturn(Future.succeededFuture( BidResponse.builder() .ext(ExtBidResponse.builder() - .debug(ExtResponseDebug.of(null, null, null, null)) + .debug(ExtResponseDebug.of(null, null, null)) .build()) .build())); @@ -4466,74 +4366,6 @@ public void shouldIncrementHooksGlobalAndAccountMetrics() { verify(metrics).updateAccountModuleDurationMetric(any(), eq("module3"), eq(8L)); } - @Test - public void shouldTolerateBidWithDealThatHasNoLineItemAssociated() { - // given - givenBidder(givenSingleSeatBid(givenBidderBid( - Bid.builder().impid("impId").dealid("dealId").price(BigDecimal.ONE).build()))); - - final BidRequest bidRequest = givenBidRequest(givenSingleImp(singletonMap("someBidder", 1)), identity()); - final AuctionContext auctionContext = givenRequestContext(bidRequest); - - // when - target.holdAuction(auctionContext); - - // then - final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); - verify(applicationEventService).publishAuctionEvent(argumentCaptor.capture()); - final TxnLog txnLog = argumentCaptor.getValue().getTxnLog(); - - assertThat(txnLog).isEqualTo(TxnLog.create()); - } - - @Test - public void shouldRecordLineItemMetricsInTransactionLog() { - // given - givenBidder(givenSeatBid(asList( - givenBidderBid(Bid.builder().impid("impId").dealid("dealId1").price(BigDecimal.ONE).build()), - givenBidderBid(Bid.builder().impid("impId").dealid("dealId2").price(BigDecimal.ONE).build())))); - - willReturn(ValidationResult.success()).given(responseBidValidator) - .validate(argThat(bid -> bid.getBid().getDealid().equals("dealId1")), any(), any(), any()); - willReturn(ValidationResult.error("validation error")).given(responseBidValidator) - .validate(argThat(bid -> bid.getBid().getDealid().equals("dealId2")), any(), any(), any()); - - final List deals = asList( - Deal.builder() - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of( - ExtDealLine.of("lineItemId1", null, null, "someBidder")))) - .build(), - Deal.builder() - .id("dealId2") - .ext(mapper.valueToTree(ExtDeal.of( - ExtDealLine.of("lineItemId2", null, null, "someBidder")))) - .build()); - final Imp imp = givenImp( - singletonMap("someBidder", 1), - builder -> builder - .id("impId") - .pmp(Pmp.builder() - .deals(deals) - .build())); - final BidRequest bidRequest = givenBidRequest(singletonList(imp), identity()); - final AuctionContext auctionContext = givenRequestContext(bidRequest); - - // when - target.holdAuction(auctionContext); - - // then - final ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(AuctionContext.class); - verify(applicationEventService).publishAuctionEvent(argumentCaptor.capture()); - final TxnLog txnLog = argumentCaptor.getValue().getTxnLog(); - - final TxnLog expectedTxnLog = TxnLog.create(); - expectedTxnLog.lineItemsReceivedFromBidder().get("someBidder").addAll(asList("lineItemId1", "lineItemId2")); - expectedTxnLog.lineItemsResponseInvalidated().add("lineItemId2"); - - assertThat(txnLog).isEqualTo(expectedTxnLog); - } - @Test public void shouldProperPopulateImpExtPrebidEvenIfInExtImpPrebidContainNotCorrectField() { // given @@ -4621,27 +4453,6 @@ public void shouldReturnsSourceWithCorrespondingRequestExtPrebidSchainsIfSchainI .isEqualTo(givenSourceSchain); } - @Test - public void shouldNotModifyOriginalDealsIfDealsFromLineItemServiceAreMissing() { - // given - final Pmp pmp = Pmp.builder() - .deals(singletonList(Deal.builder().id("dealId1").build())) // deal from prebid request (not from PG) - .build(); - final BidRequest bidRequest = givenBidRequest(singletonList(givenImp(singletonMap("someBidder", 1), - builder -> builder.pmp(pmp))), identity()); - final AuctionContext auctionContext = givenRequestContext(bidRequest).toBuilder() - .build(); - - // when - target.holdAuction(auctionContext); - - // then - final BidRequest capturedBidRequest = captureBidRequest(); - assertThat(capturedBidRequest.getImp()) - .extracting(Imp::getPmp) - .containsExactly(pmp); - } - @Test public void shouldReduceBidsHavingDealIdWithSameImpIdByBidderWithToleratingNotObtainedBidWithTopDeal() { // given @@ -4807,7 +4618,6 @@ private void givenTarget(boolean enabledStrictAppSiteDoohValidation) { 0, bidderCatalog, storedResponseProcessor, - dealsService, privacyEnforcementService, fpdResolver, supplyChainResolver, @@ -4823,7 +4633,6 @@ private void givenTarget(boolean enabledStrictAppSiteDoohValidation) { bidResponseCreator, bidResponsePostProcessor, hookStageExecutor, - applicationEventService, httpInteractionLogger, priceFloorAdjuster, priceFloorEnforcer, @@ -4858,8 +4667,6 @@ private AuctionContext givenRequestContext(BidRequest bidRequest, Account accoun .timeoutContext(TimeoutContext.of(clock.millis(), timeout, 90)) .hookExecutionContext(HookExecutionContext.of(Endpoint.openrtb2_auction)) .debugContext(DebugContext.empty()) - .txnLog(TxnLog.create()) - .deepDebugLog(DeepDebugLog.create(false, clock)) .bidRejectionTrackers(new HashMap<>()) .activityInfrastructure(activityInfrastructure) .build(); diff --git a/src/test/java/org/prebid/server/auction/WinningBidComparatorFactoryTest.java b/src/test/java/org/prebid/server/auction/WinningBidComparatorFactoryTest.java index 57d5ecbea2a..3716bc7b92e 100644 --- a/src/test/java/org/prebid/server/auction/WinningBidComparatorFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/WinningBidComparatorFactoryTest.java @@ -1,18 +1,14 @@ package org.prebid.server.auction; -import com.iab.openrtb.request.Deal; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; import com.iab.openrtb.response.Bid; import org.junit.Test; import org.prebid.server.auction.model.BidInfo; import java.math.BigDecimal; -import java.util.Arrays; import java.util.List; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; public class WinningBidComparatorFactoryTest { @@ -60,10 +56,10 @@ public void preferDealsComparatorCompareShouldReturnZeroWhenPriceAreEqualForNonD } @Test - public void preferDealsComparatorCompareShouldReturnMoreThanZeroWhenFirstHasNonPgDeal() { + public void preferDealsComparatorCompareShouldReturnMoreThanZeroWhenFirstHasDeal() { // given - final BidInfo dealPriceBidInfo = givenBidInfo(5.0f, "dealId", emptyList()); - final BidInfo higherPriceBidInfo = givenBidInfo(10.0f, null, emptyList()); + final BidInfo dealPriceBidInfo = givenBidInfo(1.0f, "dealId"); + final BidInfo higherPriceBidInfo = givenBidInfo(5.0f); // when final int result = winningBidComparatorFactory.create(true).compare(dealPriceBidInfo, higherPriceBidInfo); @@ -73,10 +69,10 @@ public void preferDealsComparatorCompareShouldReturnMoreThanZeroWhenFirstHasNonP } @Test - public void preferDealsComparatorCompareShouldReturnLessThanZeroWhenFirstHasNoDeal() { + public void preferDealsComparatorCompareShouldReturnLessThanZeroWhenSecondHasDeal() { // given - final BidInfo higherPriceBidInfo = givenBidInfo(10.0f, null, emptyList()); - final BidInfo dealPriceBidInfo = givenBidInfo(5.0f, "dealId", emptyList()); + final BidInfo higherPriceBidInfo = givenBidInfo(5.0f); + final BidInfo dealPriceBidInfo = givenBidInfo(1.0f, "dealId"); // when final int result = winningBidComparatorFactory.create(true).compare(higherPriceBidInfo, dealPriceBidInfo); @@ -86,117 +82,64 @@ public void preferDealsComparatorCompareShouldReturnLessThanZeroWhenFirstHasNoDe } @Test - public void preferDealsComparatorCompareShouldReturnZeroWhenBothHaveNonPgDeals() { - // given - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId", emptyList()); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", emptyList()); - - // when - final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isEqualTo(0); - } - - @Test - public void preferDealsComparatorCompareShouldReturnZeroWhenBothHaveSamePgDealIdAndHasSamePrice() { + public void preferDealsComparatorCompareShouldReturnMoreThanZeroWhenBothHaveDealsAndFirstHasHigherPrice() { // given - final List impDeals = singletonList("dealId"); - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", impDeals); + final BidInfo higherPriceBidInfo = givenBidInfo(5.0f, "dealId1"); + final BidInfo lowerPriceBidInfo = givenBidInfo(1.0f, "dealId2"); // when - final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isEqualTo(0); - } - - @Test - public void preferDealsComparatorCompareShouldReturnMoreThanZeroWhenBothHaveSamePgDealIdAndFirstHasHigherPrice() { - // given - final List impDeals = singletonList("dealId"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", impDeals); - - // when - final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); + final int result = winningBidComparatorFactory.create(true).compare(higherPriceBidInfo, lowerPriceBidInfo); // then assertThat(result).isGreaterThan(0); } @Test - public void preferDealsComparatorShouldReturnLessThanZeroWhenFirstHasHigherPriceAndSecondHasLessImpPgDealIndex() { - // given - final List impDeals = Arrays.asList("dealId1", "dealId2"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId1", impDeals); - - // when - final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isLessThan(0); - } - - @Test - public void preferDealsComparatorShouldReturnLessThanZeroWhenFirstIsNonPgDealWithHigherPriceAndSecondPgDeal() { + public void preferDealsComparatorCompareShouldReturnLessThanZeroWhenBothHaveDealsAndFirstHasLowerPrice() { // given - final List impDeals = singletonList("dealId1"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId1", impDeals); + final BidInfo lowerPriceBidInfo = givenBidInfo(1.0f, "dealId1"); + final BidInfo higherPriceBidInfo = givenBidInfo(5.0f, "dealId2"); // when - final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); + final int result = winningBidComparatorFactory.create(true).compare(lowerPriceBidInfo, higherPriceBidInfo); // then assertThat(result).isLessThan(0); } @Test - public void preferDealsComparatorShouldReturnGreaterThanZeroWhenFirstPgDealAndSecondMonPgDeal() { + public void preferDealsComparatorCompareShouldReturnZeroWhenBothHaveDealsAndPriceAreEqual() { // given - final List impDeals = singletonList("dealId2"); - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(10.0f, "dealId1", impDeals); + final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId1"); + final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId2"); // when final int result = winningBidComparatorFactory.create(true).compare(bidInfo1, bidInfo2); // then - assertThat(result).isGreaterThan(0); + assertThat(result).isEqualTo(0); } @Test public void preferDealsComparatorSortShouldReturnExpectedSortedResultWithDeals() { // given - final String dealId1 = "pgDealId1"; - final String dealId2 = "pgDealId2"; - final List impDeals = Arrays.asList(dealId1, dealId2); - - final BidInfo bidInfo1 = givenBidInfo(1.0f, dealId1, impDeals); // pg deal with lower price - final BidInfo bidInfo2 = givenBidInfo(2.0f, dealId1, impDeals); // pg deal with middle price - final BidInfo bidInfo3 = givenBidInfo(4.1f, dealId2, impDeals); // pg deal with higher price - final BidInfo bidInfo4 = givenBidInfo(5.0f, null, impDeals); // non deal with lower price - final BidInfo bidInfo5 = givenBidInfo(100.1f, null, impDeals); // non deal with higher price - final BidInfo bidInfo6 = givenBidInfo(0.5f, "dealId1", impDeals); // non pg deal with lower price - final BidInfo bidInfo7 = givenBidInfo(1f, "dealId2", impDeals); // non pg deal with middle price - final BidInfo bidInfo8 = givenBidInfo(4.4f, "dealId3", impDeals); // non pg deal with higher price - - final List bidInfos = Arrays.asList(bidInfo5, bidInfo3, bidInfo1, bidInfo2, bidInfo1, bidInfo4, - bidInfo6, bidInfo7, bidInfo8); + final BidInfo bidInfo1 = givenBidInfo(5.0f); // non deal with lower price + final BidInfo bidInfo2 = givenBidInfo(100.1f); // non deal with higher price + final BidInfo bidInfo3 = givenBidInfo(0.5f, "dealId1"); // deal with lower price + final BidInfo bidInfo4 = givenBidInfo(1f, "dealId2"); // deal with middle price + final BidInfo bidInfo5 = givenBidInfo(6f, "dealId3"); // deal with higher price + + final List bidInfos = asList(bidInfo5, bidInfo4, bidInfo2, bidInfo3, bidInfo1, bidInfo2); // when bidInfos.sort(winningBidComparatorFactory.create(true)); // then - assertThat(bidInfos).containsOnly(bidInfo4, bidInfo5, bidInfo6, bidInfo7, bidInfo8, bidInfo3, bidInfo2, - bidInfo1, bidInfo1); + assertThat(bidInfos).containsExactly(bidInfo1, bidInfo2, bidInfo2, bidInfo3, bidInfo4, bidInfo5); } @Test - public void priceComparatorCompareShouldReturnMoreThatZeroWhenFirstHasHigherPriceForNonDealsBids() { + public void priceComparatorCompareShouldReturnMoreThatZeroWhenFirstHasHigherPrice() { // given final BidInfo higherPriceBidInfo = givenBidInfo(5.0f); final BidInfo lowerPriceBidInfo = givenBidInfo(1.0f); @@ -209,7 +152,7 @@ public void priceComparatorCompareShouldReturnMoreThatZeroWhenFirstHasHigherPric } @Test - public void priceComparatorCompareShouldReturnLessThatZeroWhenFirstHasLowerPriceForNonDealsBids() { + public void priceComparatorCompareShouldReturnLessThatZeroWhenFirstHasLowerPrice() { // given final BidInfo lowerPriceBidInfo = givenBidInfo(1.0f); final BidInfo higherPriceBidInfo = givenBidInfo(5.0f); @@ -234,140 +177,22 @@ public void priceComparatorCompareShouldReturnZeroWhenPriceAreEqualForNonDealsBi assertThat(result).isEqualTo(0); } - @Test - public void preferPriceComparatorCompareShouldReturnLessThanZeroWhenFirstHasNonPgDeal() { - // given - final BidInfo dealPriceBidInfo = givenBidInfo(5.0f, "dealId", emptyList()); - final BidInfo higherPriceBidInfo = givenBidInfo(10.0f, null, emptyList()); - - // when - final int result = winningBidComparatorFactory.create(false).compare(dealPriceBidInfo, higherPriceBidInfo); - - // then - assertThat(result).isLessThan(0); - } - - @Test - public void preferPriceComparatorCompareShouldReturnGreaterThanZeroWhenFirstHasNoDeal() { - // given - final BidInfo higherPriceBidInfo = givenBidInfo(10.0f, null, emptyList()); - final BidInfo dealPriceBidInfo = givenBidInfo(5.0f, "dealId", emptyList()); - - // when - final int result = winningBidComparatorFactory.create(false).compare(higherPriceBidInfo, dealPriceBidInfo); - - // then - assertThat(result).isGreaterThan(0); - } - - @Test - public void preferPriceComparatorCompareShouldReturnZeroWhenBothHaveNonPgDeals() { - // given - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId", emptyList()); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", emptyList()); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isEqualTo(0); - } - - @Test - public void preferPriceComparatorCompareShouldReturnZeroWhenBothHaveSamePgDealIdAndHasSamePrice() { - // given - final List impDeals = singletonList("dealId"); - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", impDeals); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isEqualTo(0); - } - - @Test - public void preferPriceComparatorCompareShouldReturnMoreThanZeroWhenBothHaveSamePgDealIdAndFirstHasHigherPrice() { - // given - final List impDeals = singletonList("dealId"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId", impDeals); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isGreaterThan(0); - } - - @Test - public void preferPriceComparatorShouldReturnLessThanZeroWhenFirstHasHigherPriceAndSecondHasLessImpPgDealIndex() { - // given - final List impDeals = Arrays.asList("dealId1", "dealId2"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId1", impDeals); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isLessThan(0); - } - - @Test - public void preferPriceComparatorShouldReturnLessThanZeroWhenFirstIsNonPgDealWithHigherPriceAndSecondPgDeal() { - // given - final List impDeals = singletonList("dealId1"); - final BidInfo bidInfo1 = givenBidInfo(10.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(5.0f, "dealId1", impDeals); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isLessThan(0); - } - - @Test - public void preferPriceComparatorShouldReturnGreaterThanZeroWhenFirstPgDealAndSecondMonPgDeal() { - // given - final List impDeals = singletonList("dealId2"); - final BidInfo bidInfo1 = givenBidInfo(5.0f, "dealId2", impDeals); - final BidInfo bidInfo2 = givenBidInfo(10.0f, "dealId1", impDeals); - - // when - final int result = winningBidComparatorFactory.create(false).compare(bidInfo1, bidInfo2); - - // then - assertThat(result).isGreaterThan(0); - } - @Test public void preferPriceComparatorSortShouldReturnExpectedSortedResultWithDeals() { // given - final String dealId1 = "pgDealId1"; - final String dealId2 = "pgDealId2"; - final List impDeals = Arrays.asList(dealId1, dealId2); - - final BidInfo bidInfo1 = givenBidInfo(1.0f, dealId1, impDeals); // pg deal with lower price - final BidInfo bidInfo2 = givenBidInfo(2.0f, dealId1, impDeals); // pg deal with middle price - final BidInfo bidInfo3 = givenBidInfo(4.1f, dealId2, impDeals); // pg deal with higher price - final BidInfo bidInfo4 = givenBidInfo(5.0f, null, impDeals); // non deal with lower price - final BidInfo bidInfo5 = givenBidInfo(100.1f, null, impDeals); // non deal with higher price - final BidInfo bidInfo6 = givenBidInfo(0.5f, "dealId1", impDeals); // non pg deal with lower price - final BidInfo bidInfo7 = givenBidInfo(1f, "dealId2", impDeals); // non pg deal with middle price - final BidInfo bidInfo8 = givenBidInfo(4.4f, "dealId3", impDeals); // non pg deal with higher price - - final List bidInfos = Arrays.asList(bidInfo5, bidInfo3, bidInfo1, bidInfo2, bidInfo1, bidInfo4, - bidInfo6, bidInfo7, bidInfo8); + final BidInfo bidInfo1 = givenBidInfo(5.0f, null); // non deal with lower price + final BidInfo bidInfo2 = givenBidInfo(100.1f, null); // non deal with higher price + final BidInfo bidInfo3 = givenBidInfo(0.5f, "dealId1"); // deal with lower price + final BidInfo bidInfo4 = givenBidInfo(1f, "dealId2"); // deal with middle price + final BidInfo bidInfo5 = givenBidInfo(6f, "dealId3"); // deal with higher price + + final List bidInfos = asList(bidInfo5, bidInfo4, bidInfo2, bidInfo3, bidInfo1, bidInfo2); // when bidInfos.sort(winningBidComparatorFactory.create(false)); // then - assertThat(bidInfos).containsOnly(bidInfo6, bidInfo7, bidInfo8, bidInfo4, bidInfo5, bidInfo1, - bidInfo1, bidInfo2, bidInfo3); + assertThat(bidInfos).containsExactly(bidInfo3, bidInfo4, bidInfo1, bidInfo5, bidInfo2, bidInfo2); } private static BidInfo givenBidInfo(float price) { @@ -381,16 +206,4 @@ private static BidInfo givenBidInfo(float price, String dealId) { .correspondingImp(Imp.builder().id(IMP_ID).build()) .build(); } - - private static BidInfo givenBidInfo(float price, String dealId, List impDealIds) { - final List impDeals = impDealIds.stream() - .map(impDealId -> Deal.builder().id(impDealId).build()) - .toList(); - final Pmp pmp = Pmp.builder().deals(impDeals).build(); - - return BidInfo.builder() - .bid(Bid.builder().impid(IMP_ID).price(BigDecimal.valueOf(price)).dealid(dealId).build()) - .correspondingImp(Imp.builder().id(IMP_ID).pmp(pmp).build()) - .build(); - } } diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java index a81e971a019..26ba2d77e5e 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AmpRequestFactoryTest.java @@ -152,7 +152,7 @@ public void setUp() { given(ortb2RequestFactory.restoreResultFromRejection(any())) .willAnswer(invocation -> Future.failedFuture((Throwable) invocation.getArgument(0))); given(ortb2RequestFactory.enrichWithPriceFloors(any())).willAnswer(invocation -> invocation.getArgument(0)); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())).willAnswer(invocation -> invocation.getArgument(0)); + given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); given(fpdResolver.resolveApp(any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); @@ -161,8 +161,6 @@ public void setUp() { given(fpdResolver.resolveUser(any(), any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); given(fpdResolver.resolveImpExt(any(), any())).willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); - given(ortb2RequestFactory.populateUserAdditionalInfo(any())) - .willAnswer(invocationOnMock -> Future.succeededFuture(invocationOnMock.getArgument(0))); given(ortb2RequestFactory.activityInfrastructureFrom(any())) .willReturn(Future.succeededFuture()); @@ -1665,7 +1663,7 @@ public void shouldUpdateTimeout() { // given givenBidRequest(); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())) + given(ortb2RequestFactory.updateTimeout(any())) .willAnswer(invocation -> { final AuctionContext auctionContext = invocation.getArgument(0); return auctionContext.with(auctionContext.getBidRequest().toBuilder().tmax(10000L).build()); @@ -1707,7 +1705,8 @@ private void givenBidRequest( .willAnswer(invocation -> Future.succeededFuture((BidRequest) invocation.getArgument(0))); given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any())) - .willAnswer(invocation -> ((AuctionContext) invocation.getArgument(0)).getBidRequest()); + .willAnswer(invocation -> Future.succeededFuture( + ((AuctionContext) invocation.getArgument(0)).getBidRequest())); given(ortb2RequestFactory.executeProcessedAuctionRequestHooks(any())) .willAnswer(invocation -> Future.succeededFuture( ((AuctionContext) invocation.getArgument(0)).getBidRequest())); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java index 60dc83c3438..0f9f2da493d 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/AuctionRequestFactoryTest.java @@ -159,7 +159,7 @@ public void setUp() { given(ortb2RequestFactory.validateRequest(any(), any(), any())) .willAnswer(invocationOnMock -> Future.succeededFuture((BidRequest) invocationOnMock.getArgument(0))); given(ortb2RequestFactory.enrichWithPriceFloors(any())).willAnswer(invocation -> invocation.getArgument(0)); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())).willAnswer(invocation -> invocation.getArgument(0)); + given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); given(paramsResolver.resolve(any(), any(), any(), anyBoolean())) .will(invocationOnMock -> invocationOnMock.getArgument(0)); @@ -171,12 +171,11 @@ public void setUp() { .willReturn(Future.succeededFuture(defaultPrivacyContext)); given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any())) - .willAnswer(invocation -> ((AuctionContext) invocation.getArgument(0)).getBidRequest()); + .willAnswer(invocation -> Future.succeededFuture( + ((AuctionContext) invocation.getArgument(0)).getBidRequest())); given(ortb2RequestFactory.executeProcessedAuctionRequestHooks(any())) .willAnswer(invocation -> Future.succeededFuture( ((AuctionContext) invocation.getArgument(0)).getBidRequest())); - given(ortb2RequestFactory.populateUserAdditionalInfo(any())) - .willAnswer(invocationOnMock -> Future.succeededFuture(invocationOnMock.getArgument(0))); given(ortb2RequestFactory.restoreResultFromRejection(any())) .willAnswer(invocation -> Future.failedFuture((Throwable) invocation.getArgument(0))); given(ortb2RequestFactory.activityInfrastructureFrom(any())) @@ -734,7 +733,7 @@ public void shouldUpdateTimeout() { // given givenValidBidRequest(); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())) + given(ortb2RequestFactory.updateTimeout(any())) .willAnswer(invocation -> { final AuctionContext auctionContext = invocation.getArgument(0); return auctionContext.with(auctionContext.getBidRequest().toBuilder().tmax(10000L).build()); diff --git a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java index c57edaf4d02..0c6374e3218 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/Ortb2RequestFactoryTest.java @@ -33,9 +33,6 @@ import org.prebid.server.cookie.UidsCookie; import org.prebid.server.cookie.UidsCookieService; import org.prebid.server.cookie.proto.Uids; -import org.prebid.server.deals.UserAdditionalInfoService; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.TxnLog; import org.prebid.server.exception.BlacklistedAccountException; import org.prebid.server.exception.InvalidRequestException; import org.prebid.server.exception.PreBidException; @@ -80,7 +77,6 @@ import org.prebid.server.validation.RequestValidator; import org.prebid.server.validation.model.ValidationResult; -import java.time.Clock; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -131,16 +127,12 @@ public class Ortb2RequestFactoryTest extends VertxTest { @Mock private HookStageExecutor hookStageExecutor; @Mock - private UserAdditionalInfoService userAdditionalInfoService; - @Mock private PriceFloorProcessor priceFloorProcessor; @Mock private CountryCodeMapper countryCodeMapper; @Mock private Metrics metrics; - private final Clock clock = Clock.systemDefaultZone(); - private Ortb2RequestFactory target; @Mock @@ -179,9 +171,6 @@ public void setUp() { false, AuctionRequestPayloadImpl.of(invocation.getArgument(0))))); - given(userAdditionalInfoService.populate(any())) - .willAnswer(invocationOnMock -> Future.succeededFuture(invocationOnMock.getArgument(0))); - givenTarget(false, 90); } @@ -703,7 +692,6 @@ public void createAuctionContextShouldReturnExpectedAuctionContext() { .hookExecutionContext(hookExecutionContext) .debugContext(DebugContext.empty()) .requestRejected(false) - .txnLog(TxnLog.create()) .debugHttpCalls(emptyMap()) .bidRejectionTrackers(new HashMap<>()) .build()); @@ -734,7 +722,6 @@ public void enrichAuctionContextShouldReturnExpectedAuctionContext() { .prebidErrors(new ArrayList<>()) .debugWarnings(new ArrayList<>()) .hookExecutionContext(hookExecutionContext) - .txnLog(TxnLog.create()) .debugHttpCalls(emptyMap()) .build(), httpRequest, @@ -756,8 +743,6 @@ public void enrichAuctionContextShouldReturnExpectedAuctionContext() { .prebidErrors(new ArrayList<>()) .debugWarnings(new ArrayList<>()) .hookExecutionContext(hookExecutionContext) - .txnLog(TxnLog.create()) - .deepDebugLog(DeepDebugLog.create(false, clock)) .debugHttpCalls(new HashMap<>()) .build()); } @@ -777,38 +762,6 @@ public void enrichAuctionContextShouldSetDebugOff() { assertThat(result.getDebugContext()).isEqualTo(DebugContext.empty()); } - @Test - public void enrichAuctionContextShouldReturnAuctionContextWithDeepDebugLogWhenDeepDebugIsOff() { - // when - final AuctionContext auctionContext = target.enrichAuctionContext( - AuctionContext.builder().build(), - httpRequest, - BidRequest.builder().build(), - 100); - - // then - assertThat(auctionContext.getDeepDebugLog()).isNotNull().returns(false, DeepDebugLog::isDeepDebugEnabled); - } - - @Test - public void enrichAuctionContextShouldReturnAuctionContextWithDeepDebugLogWhenDeepDebugIsOn() { - // given - final BidRequest bidRequest = BidRequest.builder() - .ext(ExtRequest.of( - ExtRequestPrebid.builder().trace(TraceLevel.verbose).build())) - .build(); - - // when - final AuctionContext auctionContext = target.enrichAuctionContext( - AuctionContext.builder().build(), - httpRequest, - bidRequest, - 100); - - // then - assertThat(auctionContext.getDeepDebugLog()).isNotNull().returns(true, DeepDebugLog::isDeepDebugEnabled); - } - @Test public void validateRequestShouldThrowInvalidRequestExceptionIfRequestIsInvalid() { // given @@ -902,7 +855,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldReturnSameBidRequest( .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -956,7 +909,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldReturnBidRequestWithA .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1001,7 +954,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddCountryFromPrivacy .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(List.of(result)) @@ -1041,7 +994,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddRegionFromPrivacy( .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1074,7 +1027,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldMakeRegionUpperCasedW .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1104,11 +1057,12 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV4FromPri // when final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData( - AuctionContext.builder() - .bidRequest(bidRequest) - .account(account) - .privacyContext(privacyContext) - .build()); + AuctionContext.builder() + .bidRequest(bidRequest) + .account(account) + .privacyContext(privacyContext) + .build()) + .result(); // then assertThat(Collections.singleton(result)) @@ -1137,11 +1091,12 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldAddIpAddressV6FromPri // when final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData( - AuctionContext.builder() - .bidRequest(bidRequest) - .account(account) - .privacyContext(privacyContext) - .build()); + AuctionContext.builder() + .bidRequest(bidRequest) + .account(account) + .privacyContext(privacyContext) + .build()) + .result(); // then assertThat(Collections.singleton(result)) @@ -1348,7 +1303,7 @@ public void updateTimeoutShouldReturnSameContextIfNoNeedUpdates() { .build(); // when - final AuctionContext result = target.updateTimeout(auctionContext, 0L); + final AuctionContext result = target.updateTimeout(auctionContext); // then assertThat(result).isSameAs(auctionContext); @@ -1371,7 +1326,7 @@ public void updateTimeoutShouldReturnContextWithUpdatedTimeout() { .build(); // when - final AuctionContext result = target.updateTimeout(auctionContext, 0L); + final AuctionContext result = target.updateTimeout(auctionContext); // then assertThat(result.getBidRequest()).isSameAs(auctionContext.getBidRequest()); @@ -1392,7 +1347,7 @@ public void updateTimeoutShouldReturnContextWithUpdatedBidRequestTmax() { .build(); // when - final AuctionContext result = target.updateTimeout(auctionContext, 0L); + final AuctionContext result = target.updateTimeout(auctionContext); // then assertThat(result.getBidRequest()).isEqualTo(givenBidRequest(request -> request.tmax(500L))); @@ -1416,7 +1371,7 @@ public void updateTimeoutShouldReturnContextWithUpdatedTimeoutAndBidRequestTmax( .build(); // when - final AuctionContext result = target.updateTimeout(auctionContext, 0L); + final AuctionContext result = target.updateTimeout(auctionContext); // then assertThat(result.getBidRequest()).isEqualTo(givenBidRequest(request -> request.tmax(500L))); @@ -1465,7 +1420,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldSetDsaFromAccountWhen .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1522,7 +1477,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldNotSetDsaFromAccountW .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1585,7 +1540,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldNotSetDsaFromAccountW .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1644,7 +1599,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldSetDsaFromAccountWhen .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1705,7 +1660,7 @@ public void enrichBidRequestWithAccountAndPrivacyDataShouldNotSetDsaFromAccountW .build(); // when - final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext); + final BidRequest result = target.enrichBidRequestWithAccountAndPrivacyData(auctionContext).result(); // then assertThat(result) @@ -1732,11 +1687,9 @@ private void givenTarget(boolean enforceValidAccount, int timeoutAdjustmentFacto applicationSettings, ipAddressHelper, hookStageExecutor, - userAdditionalInfoService, priceFloorProcessor, countryCodeMapper, - metrics, - clock); + metrics); } private static String bidRequestToString(BidRequest bidRequest) { diff --git a/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java index 71eb233b2f4..4e1f9ff20c9 100644 --- a/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java +++ b/src/test/java/org/prebid/server/auction/requestfactory/VideoRequestFactoryTest.java @@ -101,7 +101,7 @@ public void setUp() { given(ortb2RequestFactory.restoreResultFromRejection(any())) .willAnswer(invocation -> Future.failedFuture((Throwable) invocation.getArgument(0))); given(ortb2RequestFactory.enrichWithPriceFloors(any())).willAnswer(invocation -> invocation.getArgument(0)); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())).willAnswer(invocation -> invocation.getArgument(0)); + given(ortb2RequestFactory.updateTimeout(any())).willAnswer(invocation -> invocation.getArgument(0)); given(ortb2RequestFactory.activityInfrastructureFrom(any())) .willReturn(Future.succeededFuture()); @@ -127,9 +127,6 @@ public void setUp() { given(privacyEnforcementService.contextFromBidRequest(any())) .willReturn(Future.succeededFuture(defaultPrivacyContext)); - given(ortb2RequestFactory.populateUserAdditionalInfo(any())) - .willAnswer(invocationOnMock -> Future.succeededFuture(invocationOnMock.getArgument(0))); - target = new VideoRequestFactory( Integer.MAX_VALUE, false, @@ -406,7 +403,8 @@ private void givenBidRequest(BidRequest bidRequest, List podErrors) { .willAnswer(answerWithFirstArgument()); given(ortb2RequestFactory.enrichBidRequestWithAccountAndPrivacyData(any())) - .willAnswer(invocation -> ((AuctionContext) invocation.getArgument(0)).getBidRequest()); + .willAnswer(invocation -> Future.succeededFuture( + ((AuctionContext) invocation.getArgument(0)).getBidRequest())); given(ortb2RequestFactory.executeProcessedAuctionRequestHooks(any())) .willAnswer(invocation -> Future.succeededFuture( ((AuctionContext) invocation.getArgument(0)).getBidRequest())); @@ -489,7 +487,7 @@ public void shouldUpdateTimeout() throws JsonProcessingException { // given prepareMinimumSuccessfulConditions(); - given(ortb2RequestFactory.updateTimeout(any(), anyLong())) + given(ortb2RequestFactory.updateTimeout(any())) .willAnswer(invocation -> { final AuctionContext auctionContext = invocation.getArgument(0); return auctionContext.with(auctionContext.getBidRequest().toBuilder().tmax(10000L).build()); diff --git a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java index 88a99caf1bb..222fe74882d 100644 --- a/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java +++ b/src/test/java/org/prebid/server/bidder/HttpBidderRequesterTest.java @@ -50,6 +50,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.UnaryOperator; import static java.util.Arrays.asList; @@ -459,8 +460,28 @@ public void shouldCompressRequestBodyIfContentEncodingHeaderIsGzip() { @Test public void shouldNotWaitForResponsesWhenAllDealsIsGathered() throws JsonProcessingException { // given - target = new HttpBidderRequester(httpClient, new DealsBidderRequestCompletionTrackerFactory(), - bidderErrorNotifier, requestEnricher, jacksonMapper); + target = new HttpBidderRequester( + httpClient, + bidRequest -> new BidderRequestCompletionTracker() { + + private final AtomicInteger waitAllDeals = new AtomicInteger(2); + private final Promise promise = Promise.promise(); + + @Override + public Future future() { + return promise.future(); + } + + @Override + public void processBids(List bids) { + if (waitAllDeals.decrementAndGet() <= 0) { + promise.complete(); + } + } + }, + bidderErrorNotifier, + requestEnricher, + jacksonMapper); final BidRequest bidRequest = bidRequestWithDeals("deal1", "deal2"); final BidderRequest bidderRequest = BidderRequest.builder() @@ -512,16 +533,15 @@ public void shouldNotWaitForResponsesWhenAllDealsIsGathered() throws JsonProcess CompositeBidderResponse.withBids(singletonList(bidderBidDeal2), emptyList())); // when - final BidderSeatBid bidderSeatBid = - target.requestBids( - bidder, - bidderRequest, - bidRejectionTracker, - timeout, - CaseInsensitiveMultiMap.empty(), - bidderAliases, - false) - .result(); + final BidderSeatBid bidderSeatBid = target.requestBids( + bidder, + bidderRequest, + bidRejectionTracker, + timeout, + CaseInsensitiveMultiMap.empty(), + bidderAliases, + false) + .result(); // then verify(bidder).makeHttpRequests(any()); diff --git a/src/test/java/org/prebid/server/cache/CacheServiceTest.java b/src/test/java/org/prebid/server/cache/CacheServiceTest.java index 74feaf189af..4e4410b7b1c 100644 --- a/src/test/java/org/prebid/server/cache/CacheServiceTest.java +++ b/src/test/java/org/prebid/server/cache/CacheServiceTest.java @@ -232,8 +232,7 @@ public void cacheBidsOpenrtbShouldStoreWinUrl() { .build(); // when cacheService.cacheBidsOpenrtb( - singletonList(givenBidInfo(builder -> builder.id("bidId1"), BidType.banner, "bidder", - "lineItemId")), + singletonList(givenBidInfo(builder -> builder.id("bidId1"), BidType.banner, "bidder")), givenAuctionContext(), CacheContext.builder() .shouldCacheBids(true) @@ -241,9 +240,16 @@ public void cacheBidsOpenrtbShouldStoreWinUrl() { eventsContext); // then - verify(eventsService).winUrl(eq("bidId1"), eq("bidder"), eq("accountId"), eq("lineItemId"), eq(true), - eq(EventsContext.builder().enabledForAccount(true).enabledForRequest(true) - .auctionId("auctionId").build())); + verify(eventsService).winUrl( + eq("bidId1"), + eq("bidder"), + eq("accountId"), + eq(true), + eq(EventsContext.builder() + .enabledForAccount(true) + .enabledForRequest(true) + .auctionId("auctionId") + .build())); } @Test @@ -790,8 +796,8 @@ public void cacheBidsOpenrtbShouldUpdateVastXmlPutObjectWithKeyWhenBidHasCategor // given final Imp imp1 = givenImp(builder -> builder.id("impId1").video(Video.builder().build())); - final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id("bid1").adm("adm"), - BidType.video, "bidder", null) + final BidInfo bidInfo1 = givenBidInfo( + builder -> builder.id("bid1").adm("adm"), BidType.video, "bidder") .toBuilder().category("bid1Category").build(); given(idGenerator.generateId()).willReturn("randomId"); @@ -820,10 +826,10 @@ public void cacheBidsOpenrtbShouldUpdateVastXmlPutObjectWithKeyWhenBidHasCategor public void cacheBidsOpenrtbShouldNotUpdateVastXmlPutObjectWithKeyWhenDoesNotHaveCatDur() throws IOException { // given final Imp imp1 = givenImp(builder -> builder.id("impId1").video(Video.builder().build())); - final BidInfo bidInfo1 = givenBidInfo(builder -> builder.id("bid1").impid("impId1").adm("adm"), - BidType.video, "bidder", null); + final BidInfo bidInfo1 = givenBidInfo( + builder -> builder.id("bid1").impid("impId1").adm("adm"), BidType.video, "bidder"); - given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any(), any(), any())).willReturn("adm"); + given(vastModifier.createBidVastXml(any(), any(), any(), any(), any(), any(), any())).willReturn("adm"); // when cacheService.cacheBidsOpenrtb( @@ -1015,16 +1021,6 @@ private static BidInfo givenBidInfo(UnaryOperator bidCustomizer, .build(); } - private static BidInfo givenBidInfo(UnaryOperator bidCustomizer, - BidType bidType, - String bidder, - String lineItemId) { - - return givenBidInfo(bidCustomizer, bidType, bidder).toBuilder() - .lineItemId(lineItemId) - .build(); - } - private static Imp givenImp(UnaryOperator impCustomizer) { return impCustomizer.apply(Imp.builder()).build(); } diff --git a/src/test/java/org/prebid/server/deals/AdminCentralServiceTest.java b/src/test/java/org/prebid/server/deals/AdminCentralServiceTest.java deleted file mode 100644 index 7ff33ff7cd6..00000000000 --- a/src/test/java/org/prebid/server/deals/AdminCentralServiceTest.java +++ /dev/null @@ -1,437 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Imp; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.model.AdminAccounts; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.deals.model.AdminLineItems; -import org.prebid.server.deals.model.Command; -import org.prebid.server.deals.model.LogCriteriaFilter; -import org.prebid.server.deals.model.LogTracer; -import org.prebid.server.deals.model.ServicesCommand; -import org.prebid.server.log.CriteriaManager; -import org.prebid.server.settings.CachingApplicationSettings; -import org.prebid.server.settings.SettingsCache; -import org.prebid.server.settings.proto.request.InvalidateSettingsCacheRequest; -import org.prebid.server.settings.proto.request.UpdateSettingsCacheRequest; - -import java.util.Collections; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; - -public class AdminCentralServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private AdminCentralService adminCentralService; - - @Mock - private LineItemService lineItemService; - - @Mock - private DeliveryProgressService deliveryProgressService; - - @Mock - private CriteriaManager criteriaManager; - - @Mock - private SettingsCache settingsCache; - - @Mock - private SettingsCache ampSettingsCache; - - @Mock - private CachingApplicationSettings cachingApplicationSettings; - - @Mock - private Suspendable suspendable; - - @Before - public void setUp() { - adminCentralService = new AdminCentralService(criteriaManager, lineItemService, deliveryProgressService, - settingsCache, ampSettingsCache, cachingApplicationSettings, - jacksonMapper, singletonList(suspendable)); - } - - @Test - public void processAdminCentralEventShouldAddCriteriaWhenTraceLogAndCriteriaFilterArePresentAndCmdIsStart() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of( - LogTracer.of("start", false, 800L, LogCriteriaFilter.of(null, null, null)), null, null, null, null, - null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(criteriaManager).addCriteria(any(), anyLong()); - } - - @Test - public void processAdminCentralEventShouldAddCriteriaWhenTraceLogAndCriteriaFilterArePresentAndCmdIsStop() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(LogTracer.of("stop", false, 0L, null), - null, null, null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(criteriaManager).stop(); - } - - @Test - public void processAdminCentralEventShouldStopServicesWhenServicesStopCommandIsPresent() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, null, null, null, - ServicesCommand.of("stop")); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(suspendable).suspend(); - } - - @Test - public void processAdminCentralEventShouldNotStopServicesWhenServicesCommandIsNotStop() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, null, null, null, - ServicesCommand.of("invalid")); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(suspendable); - } - - @Test - public void processAdminCentralEventShouldAddCriteriaAndStopServices() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of( - LogTracer.of("start", false, 800L, LogCriteriaFilter.of(null, null, null)), null, null, null, null, - ServicesCommand.of("stop")); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(suspendable).suspend(); - verify(criteriaManager).addCriteria(any(), anyLong()); - } - - @Test - public void processAdminCentralEventShouldNotCallCriteriaManagerWhenCommandIsNull() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of( - LogTracer.of(null, false, 800L, LogCriteriaFilter.of(null, null, null)), null, null, null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(criteriaManager); - } - - @Test - public void processAdminCentralEventShouldNotCallCriteriaManagerWhenItIsNotStartOrStop() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of( - LogTracer.of("invalid", false, 800L, LogCriteriaFilter.of(null, null, null)), null, null, - null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(criteriaManager); - } - - @Test - public void processAdminCentralEventShouldNotCallSettingsCacheWhenCommandWasNotDefined() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, Command.of(null, null), - Command.of(null, null), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(settingsCache); - verifyNoInteractions(ampSettingsCache); - } - - @Test - public void processAdminCentralEventShouldNotCallSettingsCacheWhenBodyWasNotDefined() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, Command.of("save", null), - Command.of("save", null), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(settingsCache); - verifyNoInteractions(ampSettingsCache); - } - - @Test - public void processAdminCentralEventShouldCallSettings() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, Command.of("save", null), - Command.of("save", null), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(settingsCache); - verifyNoInteractions(ampSettingsCache); - } - - @Test - public void processAdminCentralEventShouldCallSaveAmpSettingsCache() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, - Command.of("save", jacksonMapper.mapper().valueToTree(UpdateSettingsCacheRequest - .of(Collections.emptyMap(), Collections.emptyMap()))), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(ampSettingsCache).save(any(), any()); - } - - @Test - public void processAdminCentralEventShouldCallInvalidateAmpSettingsCache() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, - Command.of("invalidate", jacksonMapper.mapper().valueToTree(InvalidateSettingsCacheRequest - .of(Collections.emptyList(), Collections.emptyList()))), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(ampSettingsCache).invalidate(any(), any()); - } - - @Test - public void processAdminCentralEventShouldNotCallAmpSettingsCacheWhenCantParseBody() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, - Command.of("save", jacksonMapper.mapper().createObjectNode().put("requests", 1)), null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(ampSettingsCache); - } - - @Test - public void processAdminCentralEventShouldCallSaveSettingsCache() throws JsonProcessingException { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - Command.of("save", jacksonMapper.mapper().valueToTree(UpdateSettingsCacheRequest - .of(Collections.singletonMap("requestId", - jacksonMapper.mapper().writeValueAsString(BidRequest.builder().id("requestId") - .build())), - Collections.singletonMap("impId", - jacksonMapper.mapper().writeValueAsString(Imp.builder().id("impId") - .build()))))), - null, null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(settingsCache).save(any(), any()); - } - - @Test - public void processAdminCentralEventShouldCallInvalidateSettingsCache() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - Command.of("invalidate", jacksonMapper.mapper().valueToTree(InvalidateSettingsCacheRequest - .of(Collections.emptyList(), Collections.emptyList()))), null, null, null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(settingsCache).invalidate(any(), any()); - } - - @Test - public void processAdminCentralEventShouldNotCallSettingsCacheWhenCantParseBody() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - Command.of("save", jacksonMapper.mapper().createObjectNode().put("requests", 1)), null, null, null, - null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(settingsCache); - } - - @Test - public void processAdminCentralEventShouldCallInvalidateLineItemsById() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, Command.of("invalidate", jacksonMapper.mapper() - .valueToTree(AdminLineItems.of(singletonList("lineItemId")))), null, null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(lineItemService).invalidateLineItemsByIds(eq(singletonList("lineItemId"))); - verify(deliveryProgressService).invalidateLineItemsByIds(eq(singletonList("lineItemId"))); - } - - @Test - public void processAdminCentralEventShouldCallInvalidateAllLineItems() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, Command.of("invalidate", null), null, null); - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(lineItemService).invalidateLineItems(); - verify(deliveryProgressService).invalidateLineItems(); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateWhenCmdNotDefined() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, Command.of(null, null), null, null); - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoMoreInteractions(lineItemService); - verifyNoMoreInteractions(deliveryProgressService); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateWhenCmdHasValueOtherToInvalidate() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, Command.of("save", null), null, null); - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoMoreInteractions(lineItemService); - verifyNoMoreInteractions(deliveryProgressService); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateWhenCantParseBody() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, Command.of("invalidate", mapper.createObjectNode() - .set("ids", mapper.valueToTree(AdminLineItems.of(singletonList("5"))))), null, - null); - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoMoreInteractions(lineItemService); - verifyNoMoreInteractions(deliveryProgressService); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateAccountsWhenCommandIsNotDefined() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, null, Command.of(null, mapper.createObjectNode() - .set("ids", mapper.valueToTree(AdminAccounts.of(singletonList("1001"))))), null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(cachingApplicationSettings); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateAccountsWhenInvalidCommandValue() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, null, Command.of("invalid", mapper.valueToTree(AdminAccounts.of(singletonList("1001")))), - null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(cachingApplicationSettings); - } - - @Test - public void processAdminCentralEventShouldNotCallInvalidateAccountsCantParseBody() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, null, Command.of("invalidate", mapper.createObjectNode() - .set("accounts", mapper.valueToTree(AdminAccounts.of(singletonList("5"))))), null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verifyNoInteractions(cachingApplicationSettings); - } - - @Test - public void processAdminCentralEventShouldInvalidateAccounts() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, null, Command.of("invalidate", - mapper.valueToTree(AdminAccounts.of(asList("1001", "1002")))), null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(cachingApplicationSettings).invalidateAccountCache(eq("1001")); - verify(cachingApplicationSettings).invalidateAccountCache(eq("1002")); - } - - @Test - public void processAdminCentralEventShouldInvalidateAllAccounts() { - // given - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, - null, null, null, Command.of("invalidate", mapper.createObjectNode() - .set("ids", mapper.valueToTree(AdminAccounts.of(null)))), null); - - // when - adminCentralService.processAdminCentralEvent(adminCentralResponse); - - // then - verify(cachingApplicationSettings).invalidateAllAccountCache(); - } -} diff --git a/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java b/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java deleted file mode 100644 index 3dd501bed23..00000000000 --- a/src/test/java/org/prebid/server/deals/AlertHttpServiceTest.java +++ /dev/null @@ -1,233 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.model.AlertEvent; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.AlertProxyProperties; -import org.prebid.server.deals.model.AlertSource; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.vertx.http.HttpClient; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.List; -import java.util.stream.IntStream; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class AlertHttpServiceTest extends VertxTest { - - @Rule - public final MockitoRule rule = MockitoJUnit.rule(); - - @Mock - private HttpClient httpClient; - - private ZonedDateTime now; - - private Clock clock; - - private AlertHttpService alertHttpService; - - @Before - public void setUp() { - clock = Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC); - now = ZonedDateTime.now(clock); - final HashMap servicesAlertPeriod = new HashMap<>(); - servicesAlertPeriod.put("pbs-error", 3L); - alertHttpService = new AlertHttpService(jacksonMapper, httpClient, clock, DeploymentProperties.builder() - .pbsVendor("pbsVendor") - .pbsRegion("pbsRegion").pbsHostId("pbsHostId").subSystem("pbsSubSystem").system("pbsSystem") - .dataCenter("pbsDataCenter").infra("pbsInfra").profile("pbsProfile").build(), - AlertProxyProperties.builder().password("password").username("username").timeoutSec(5) - .url("http://localhost") - .alertTypes(servicesAlertPeriod).enabled(true).build()); - } - - @Test - public void alertShouldNotSendAlertWhenServiceIsNotEnabled() { - // given - alertHttpService = new AlertHttpService(jacksonMapper, httpClient, clock, DeploymentProperties.builder() - .pbsVendor("pbsVendor").pbsRegion("pbsRegion").pbsHostId("pbsHostId").subSystem("pbsSubSystem") - .system("pbsSystem").dataCenter("pbsDataCenter").infra("pbsInfra").profile("pbsProfile").build(), - AlertProxyProperties.builder().password("password").username("username").timeoutSec(5) - .alertTypes(emptyMap()) - .url("http://localhost").enabled(false).build()); - - // when - alertHttpService.alert("pbs", AlertPriority.HIGH, "errorMessage"); - - // then - verifyNoInteractions(httpClient); - } - - @Test - public void alertShouldSendAlertWhenServiceIsEnabled() throws JsonProcessingException { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture()); - - // when - alertHttpService.alert("pbs", AlertPriority.HIGH, "errorMessage"); - - // then - final List requestPayloadObject = getRequestPayload(); - final String id = requestPayloadObject.get(0).getId(); - assertThat(requestPayloadObject) - .isEqualTo(singletonList(AlertEvent.builder().id(id).action("RAISE").priority(AlertPriority.HIGH) - .updatedAt(now).name("pbs").details("errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - } - - @Test - public void alertWithPeriodShouldSendAlertFirstTimeWithPassedAlertPriority() throws JsonProcessingException { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture()); - - // when - alertHttpService.alertWithPeriod("pbs", "pbs-error", AlertPriority.MEDIUM, "errorMessage"); - - // then - final List requestPayloadObject = getRequestPayload(); - final String id = requestPayloadObject.get(0).getId(); - assertThat(requestPayloadObject) - .isEqualTo(singletonList(AlertEvent.builder().id(id).action("RAISE").priority(AlertPriority.MEDIUM) - .updatedAt(now).name("pbs-error").details("Service pbs failed to send request 1 time(s) " - + "with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - } - - @Test - public void alertWithPeriodShouldSendAlertWithPassedPriorityAndWithHighPriorityAfterPeriodLimitReached() - throws JsonProcessingException { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture()); - - // when - IntStream.range(0, 3).forEach(ignored -> - alertHttpService.alertWithPeriod("pbs", "pbs-error", AlertPriority.MEDIUM, "errorMessage")); - - // then - final ArgumentCaptor requestBodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClient, times(2)).post(anyString(), any(), requestBodyCaptor.capture(), anyLong()); - - final List requests = requestBodyCaptor.getAllValues(); - final List alertEvents1 = parseAlertEvents(requests.get(0)); - - final String id = alertEvents1.get(0).getId(); - - assertThat(alertEvents1) - .isEqualTo(singletonList(AlertEvent.builder().id(id).action("RAISE").priority(AlertPriority.MEDIUM) - .updatedAt(now).name("pbs-error").details("Service pbs failed to send request 1 time(s) " - + "with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - - final List alertEvents2 = parseAlertEvents(requests.get(1)); - final String id2 = alertEvents2.get(0).getId(); - - assertThat(alertEvents2) - .isEqualTo(singletonList(AlertEvent.builder().id(id2).action("RAISE").priority(AlertPriority.HIGH) - .updatedAt(now).name("pbs-error").details("Service pbs failed to send request 3 time(s) " - + "with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - } - - @Test - public void alertWithPeriodShouldSendAlertTwoTimesForUnknownServiceWithDefaultPeriod() - throws JsonProcessingException { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture()); - - // when - IntStream.range(0, 15).forEach(ignored -> - alertHttpService.alertWithPeriod("unknown", "unknown-error", AlertPriority.MEDIUM, "errorMessage")); - - // then - final ArgumentCaptor requestBodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClient, times(2)).post(anyString(), any(), requestBodyCaptor.capture(), anyLong()); - - final List requests = requestBodyCaptor.getAllValues(); - final List alertEvents1 = parseAlertEvents(requests.get(0)); - - final String id = alertEvents1.get(0).getId(); - - assertThat(alertEvents1) - .isEqualTo(singletonList(AlertEvent.builder().id(id).action("RAISE").priority(AlertPriority.MEDIUM) - .updatedAt(now).name("unknown-error").details("Service unknown failed to send request" - + " 1 time(s) with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - - final List alertEvents2 = parseAlertEvents(requests.get(1)); - final String id2 = alertEvents2.get(0).getId(); - - assertThat(alertEvents2) - .isEqualTo(singletonList(AlertEvent.builder().id(id2).action("RAISE").priority(AlertPriority.HIGH) - .updatedAt(now).name("unknown-error").details("Service unknown failed to send request" - + " 15 time(s) with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - } - - @Test - public void alertWithPeriodShouldSendAlertFirstTimeWithPassedAlertPriorityForUnknownService() - throws JsonProcessingException { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture()); - - // when - alertHttpService.alertWithPeriod("unknown", "unknown-error", AlertPriority.MEDIUM, "errorMessage"); - - // then - final List requestPayloadObject = getRequestPayload(); - final String id = requestPayloadObject.get(0).getId(); - assertThat(requestPayloadObject) - .isEqualTo(singletonList(AlertEvent.builder().id(id).action("RAISE").priority(AlertPriority.MEDIUM) - .updatedAt(now).name("unknown-error").details("Service unknown failed to send request " - + "1 time(s) with error message : errorMessage") - .source(AlertSource.builder().env("pbsProfile").dataCenter("pbsDataCenter").region("pbsRegion") - .system("pbsSystem").subSystem("pbsSubSystem").hostId("pbsHostId").build()).build())); - } - - private List getRequestPayload() throws JsonProcessingException { - final ArgumentCaptor requestBodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClient).post(anyString(), any(), requestBodyCaptor.capture(), anyLong()); - return parseAlertEvents(requestBodyCaptor.getValue()); - } - - private List parseAlertEvents(String row) throws JsonProcessingException { - return mapper.readValue(row, - new TypeReference<>() { - }); - } -} diff --git a/src/test/java/org/prebid/server/deals/DealsServiceTest.java b/src/test/java/org/prebid/server/deals/DealsServiceTest.java deleted file mode 100644 index 4bbd4d8a008..00000000000 --- a/src/test/java/org/prebid/server/deals/DealsServiceTest.java +++ /dev/null @@ -1,403 +0,0 @@ -package org.prebid.server.deals; - -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; -import org.assertj.core.api.InstanceOfAssertFactories; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.auction.model.AuctionParticipation; -import org.prebid.server.auction.model.BidderRequest; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.MatchLineItemsResult; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.LineItemSize; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.proto.openrtb.ext.request.ExtDeal; -import org.prebid.server.proto.openrtb.ext.request.ExtDealLine; -import org.prebid.server.settings.model.Account; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.UnaryOperator; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static java.util.function.UnaryOperator.identity; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; - -public class DealsServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock - private LineItemService lineItemService; - @Mock - private CriteriaLogManager criteriaLogManager; - @Mock - private BidderCatalog bidderCatalog; - - private BidderAliases bidderAliases; - private DealsService dealsService; - - private static final Clock CLOCK = Clock.fixed(Instant.parse("2019-10-10T00:01:00Z"), ZoneOffset.UTC); - - @Before - public void setUp() { - given(lineItemService.accountHasDeals(any())).willReturn(true); - given(lineItemService.findMatchingLineItems(any(), any(), anyString(), any(), any())) - .willReturn(MatchLineItemsResult.of(emptyList())); - - bidderAliases = BidderAliases.of(emptyMap(), emptyMap(), bidderCatalog); - dealsService = new DealsService(lineItemService, jacksonMapper, criteriaLogManager); - } - - @Test - public void matchAndPopulateDealsShouldReturnOriginalBidderRequestIfAccountHasNoDeals() { - // given - given(lineItemService.accountHasDeals(any())).willReturn(false); - - final BidderRequest bidderRequest = givenBidderRequest(request -> request - .imp(singletonList(givenImp(identity())))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final BidderRequest result = dealsService.matchAndPopulateDeals(bidderRequest, bidderAliases, auctionContext); - - // then - assertThat(result).isEqualTo(bidderRequest.toBuilder().impIdToDeals(emptyMap()).build()); - } - - @Test - public void matchAndPopulateDealsShouldEnrichImpWithDeals() { - // given - given(lineItemService.findMatchingLineItems(any(), any(), anyString(), any(), any())) - .willReturn(MatchLineItemsResult.of(singletonList(LineItem.of( - LineItemMetaData.builder() - .lineItemId("lineItemId") - .extLineItemId("extLineItemId") - .source("bidder") - .dealId("dealId") - .build(), - null, - null, - ZonedDateTime.now(CLOCK))))); - - final BidderRequest bidderRequest = givenBidderRequest(request -> request - .device(Device.builder().ip("ip").ua("ua").build()) - .imp(singletonList(givenImp(imp -> imp - .id("impId") - .pmp(Pmp.builder() - .deals(singletonList(Deal.builder().id("existingDealId").build())) - .build()))))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final BidderRequest result = dealsService.matchAndPopulateDeals(bidderRequest, bidderAliases, auctionContext); - - // then - assertThat(result).satisfies(request -> { - assertThat(request.getImpIdToDeals()) - .containsExactlyEntriesOf(Map.of("impId", singletonList(Deal.builder() - .id("dealId") - .ext(mapper.valueToTree( - ExtDeal.of(ExtDealLine.of("lineItemId", "extLineItemId", null, "bidder")))) - .build()))); - - assertThat(request.getBidRequest()) - .extracting(BidRequest::getImp) - .asInstanceOf(InstanceOfAssertFactories.list(Imp.class)) - .extracting(Imp::getPmp) - .flatExtracting(Pmp::getDeals) - .containsExactly( - Deal.builder().id("existingDealId").build(), - Deal.builder() - .id("dealId") - .ext(mapper.valueToTree( - ExtDeal.of(ExtDealLine.of("lineItemId", "extLineItemId", null, null)))) - .build()); - }); - } - - @Test - public void matchAndPopulateDealsShouldEnrichImpWithDealsAndAddLineItemSizesIfSizesIntersectionMatched() { - // given - given(lineItemService.findMatchingLineItems(any(), any(), anyString(), any(), any())) - .willReturn(MatchLineItemsResult.of(singletonList(LineItem.of( - LineItemMetaData.builder() - .lineItemId("lineItemId") - .extLineItemId("extLineItemId") - .sizes(singletonList(LineItemSize.of(200, 20))) - .source("bidder") - .dealId("dealId") - .build(), - null, - null, - ZonedDateTime.now(CLOCK))))); - - final BidderRequest bidderRequest = givenBidderRequest(request -> request - .device(Device.builder().ip("ip").ua("ua").build()) - .imp(singletonList(givenImp(imp -> imp - .id("impId") - .banner(Banner.builder() - .format(asList( - Format.builder().w(100).h(10).build(), - Format.builder().w(200).h(20).build())) - .build()))))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final BidderRequest result = dealsService.matchAndPopulateDeals(bidderRequest, bidderAliases, auctionContext); - - // then - assertThat(result).satisfies(request -> { - assertThat(request.getImpIdToDeals()) - .containsExactlyEntriesOf(Map.of("impId", singletonList(Deal.builder() - .id("dealId") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId", - "extLineItemId", - singletonList(Format.builder().w(200).h(20).build()), - "bidder")))) - .build()))); - - assertThat(request.getBidRequest()) - .extracting(BidRequest::getImp) - .asInstanceOf(InstanceOfAssertFactories.list(Imp.class)) - .extracting(Imp::getPmp) - .flatExtracting(Pmp::getDeals) - .containsExactly( - Deal.builder() - .id("dealId") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId", - "extLineItemId", - singletonList(Format.builder().w(200).h(20).build()), - null)))) - .build()); - }); - } - - @Test - public void matchAndPopulateDealsShouldEnrichImpWithDealsAndNotAddLineItemSizesIfSizesIntersectionNotMatched() { - // given - given(lineItemService.findMatchingLineItems(any(), any(), anyString(), any(), any())) - .willReturn(MatchLineItemsResult.of(singletonList(LineItem.of( - LineItemMetaData.builder() - .lineItemId("lineItemId") - .extLineItemId("extLineItemId") - .sizes(singletonList(LineItemSize.of(200, 20))) - .source("bidder") - .dealId("dealId") - .build(), - null, - null, - ZonedDateTime.now(CLOCK))))); - - final BidderRequest bidderRequest = givenBidderRequest(request -> request - .device(Device.builder().ip("ip").ua("ua").build()) - .imp(singletonList(givenImp(imp -> imp - .id("impId") - .banner(Banner.builder() - .format(singletonList(Format.builder().w(100).h(10).build())) - .build()))))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final BidderRequest result = dealsService.matchAndPopulateDeals(bidderRequest, bidderAliases, auctionContext); - - // then - assertThat(result).satisfies(request -> { - assertThat(request.getImpIdToDeals()) - .containsExactlyEntriesOf(Map.of("impId", singletonList(Deal.builder() - .id("dealId") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId", - "extLineItemId", - null, - "bidder")))) - .build()))); - - assertThat(request.getBidRequest()) - .extracting(BidRequest::getImp) - .asInstanceOf(InstanceOfAssertFactories.list(Imp.class)) - .extracting(Imp::getPmp) - .flatExtracting(Pmp::getDeals) - .containsExactly( - Deal.builder() - .id("dealId") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - "lineItemId", - "extLineItemId", - null, - null)))) - .build()); - }); - } - - @Test - public void matchAndPopulateDealsShouldFilterExistingDeals() { - // given - given(lineItemService.findMatchingLineItems(any(), any(), anyString(), any(), any())) - .willReturn(MatchLineItemsResult.of(emptyList())); - - final BidderRequest bidderRequest = givenBidderRequest(request -> request - .device(Device.builder().ip("ip").ua("ua").build()) - .imp(singletonList(givenImp(imp -> imp - .id("impId") - .pmp(Pmp.builder() - .deals(asList( - Deal.builder().id("deal1").build(), - Deal.builder() - .id("deal2") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - null, - null, - null, - "anotherBidder")))) - .build(), - Deal.builder() - .id("deal3") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of( - null, - null, - null, - "bidder")))) - .build())) - .build()))))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final BidderRequest result = dealsService.matchAndPopulateDeals(bidderRequest, bidderAliases, auctionContext); - - // then - assertThat(result).satisfies(request -> { - assertThat(request.getImpIdToDeals()).isEmpty(); - - assertThat(request.getBidRequest()) - .extracting(BidRequest::getImp) - .asInstanceOf(InstanceOfAssertFactories.list(Imp.class)) - .extracting(Imp::getPmp) - .flatExtracting(Pmp::getDeals) - .containsExactly( - Deal.builder().id("deal1").build(), - Deal.builder().id("deal3").build()); - }); - } - - @Test - public void removePgDealsOnlyImpsWithoutDealsShouldRemovePgDealsOnlyImpsWithoutMatchedDeals() { - // given - final List auctionParticipations = asList( - givenAuctionParticipation(givenBidderRequest( - "bidder1", - request -> request.imp(asList( - givenImp(imp -> imp.id("imp1").ext(mapper.createObjectNode())), - givenImp(imp -> imp.id("imp2").ext(mapper.createObjectNode())))), - null)), - givenAuctionParticipation(givenBidderRequest( - "bidder2", - request -> request.imp(asList( - givenImp(imp -> imp - .id("imp1") - .ext(mapper.valueToTree(Map.of("bidder", Map.of("pgdealsonly", true))))), - givenImp(imp -> imp - .id("imp2") - .ext(mapper.valueToTree(Map.of("bidder", Map.of("pgdealsonly", true))))))), - emptyMap())), - givenAuctionParticipation(givenBidderRequest( - "bidder3", - request -> request.imp(asList( - givenImp(imp -> imp - .id("imp1") - .ext(mapper.valueToTree(Map.of("bidder", Map.of("pgdealsonly", true))))), - givenImp(imp -> imp - .id("imp2") - .ext(mapper.valueToTree(Map.of("bidder", Map.of("pgdealsonly", true))))))), - singletonMap("imp2", singletonList(Deal.builder().build()))))); - final AuctionContext auctionContext = givenAuctionContext(identity()); - - // when - final List result = DealsService.removePgDealsOnlyImpsWithoutDeals( - auctionParticipations, auctionContext); - - // then - assertThat(result).containsExactly( - givenAuctionParticipation(givenBidderRequest( - "bidder1", - request -> request.imp(asList( - givenImp(imp -> imp.id("imp1").ext(mapper.createObjectNode())), - givenImp(imp -> imp.id("imp2").ext(mapper.createObjectNode())))), - null)), - givenAuctionParticipation(givenBidderRequest( - "bidder3", - request -> request.imp(singletonList( - givenImp(imp -> imp - .id("imp2") - .ext(mapper.valueToTree(Map.of("bidder", Map.of("pgdealsonly", true))))))), - singletonMap("imp2", singletonList(Deal.builder().build()))))); - assertThat(auctionContext.getDebugWarnings()).containsExactly( - """ - Not calling bidder2 bidder for impressions imp1, imp2 \ - due to pgdealsonly flag and no available PG line items.""", - """ - Not calling bidder3 bidder for impressions imp1 \ - due to pgdealsonly flag and no available PG line items."""); - } - - private static Imp givenImp(UnaryOperator customizer) { - return customizer.apply(Imp.builder()).build(); - } - - private static BidderRequest givenBidderRequest(UnaryOperator customizer) { - return BidderRequest.builder() - .bidder("bidder") - .bidRequest(customizer.apply(BidRequest.builder()).build()) - .build(); - } - - private static BidderRequest givenBidderRequest(String bidder, - UnaryOperator customizer, - Map> impIdToDeals) { - - return BidderRequest.builder() - .bidder(bidder) - .bidRequest(customizer.apply(BidRequest.builder()).build()) - .impIdToDeals(impIdToDeals) - .build(); - } - - private static AuctionParticipation givenAuctionParticipation(BidderRequest bidderRequest) { - return AuctionParticipation.builder().bidderRequest(bidderRequest).build(); - } - - private static AuctionContext givenAuctionContext(UnaryOperator customizer) { - return AuctionContext.builder() - .account(customizer.apply(Account.builder().id("accountId")).build()) - .debugWarnings(new ArrayList<>()) - .build(); - } -} diff --git a/src/test/java/org/prebid/server/deals/DeliveryProgressReportFactoryTest.java b/src/test/java/org/prebid/server/deals/DeliveryProgressReportFactoryTest.java deleted file mode 100644 index ef9daed10eb..00000000000 --- a/src/test/java/org/prebid/server/deals/DeliveryProgressReportFactoryTest.java +++ /dev/null @@ -1,201 +0,0 @@ -package org.prebid.server.deals; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.lineitem.LineItemStatus; -import org.prebid.server.deals.lineitem.LostToLineItem; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Token; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.DeliveryProgressReportBatch; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.LongAdder; - -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -public class DeliveryProgressReportFactoryTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private LineItemService lineItemService; - - private DeliveryProgressReportFactory deliveryProgressReportFactory; - - private ZonedDateTime now; - - @Before - public void setUp() { - deliveryProgressReportFactory = new DeliveryProgressReportFactory( - DeploymentProperties.builder().pbsHostId("pbsHost").pbsRegion("pbsRegion") - .pbsVendor("pbsVendor").build(), 2, lineItemService); - - now = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC)); - } - - @Test - public void fromDeliveryProgressShouldCreateReportWithTop2Competitors() { - // given - given(lineItemService.getLineItemById(anyString())) - .willReturn(LineItem.of( - LineItemMetaData.builder() - .accountId("accountId") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now.minusHours(1)) - .build())) - .source("rubicon") - .build(), - null, null, now)); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - deliveryProgress.setEndTimeStamp(now.minusHours(2)); - - final Map lostTo = new ConcurrentHashMap<>(); - lostTo.put("lineItemId1", LostToLineItem.of("lineItemId1", makeLongAdderWithValue(100L))); - lostTo.put("lineItemId2", LostToLineItem.of("lineItemId2", makeLongAdderWithValue(50L))); - lostTo.put("lineItemId3", LostToLineItem.of("lineItemId3", makeLongAdderWithValue(80L))); - lostTo.put("lineItemId4", LostToLineItem.of("lineItemId4", makeLongAdderWithValue(120L))); - deliveryProgress.getLineItemIdToLost().put("lineItemId5", lostTo); - deliveryProgress.getLineItemStatuses().put("lineItemId5", LineItemStatus.of("lineItemId5")); - - // when - final DeliveryProgressReport deliveryProgressReport = deliveryProgressReportFactory - .fromDeliveryProgress(deliveryProgress, now, false); - - // then - assertThat(deliveryProgressReport.getLineItemStatus()) - .flatExtracting(org.prebid.server.deals.proto.report.LineItemStatus::getLostToLineItems) - .extracting(org.prebid.server.deals.proto.report.LostToLineItem::getLineItemSource, - org.prebid.server.deals.proto.report.LostToLineItem::getLineItemId, - org.prebid.server.deals.proto.report.LostToLineItem::getCount) - .containsOnly( - tuple("rubicon", "lineItemId4", 120L), - tuple("rubicon", "lineItemId1", 100L)); - } - - @Test - public void fromDeliveryProgressShouldCreateOverallReport() { - // given - given(lineItemService.getLineItemById(anyString())) - .willReturn(LineItem.of( - LineItemMetaData.builder() - .accountId("accountId") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now.minusHours(1)) - .tokens(singleton(Token.of(1, 100))) - .build())) - .source("rubicon") - .build(), - null, null, now)); - - final DeliveryProgress deliveryProgress = mock(DeliveryProgress.class); - given(deliveryProgress.getRequests()).willReturn(new LongAdder()); - given(deliveryProgress.getLineItemStatuses()).willReturn(singletonMap("lineItemId1", - LineItemStatus.of("lineItemId1"))); - deliveryProgress.setEndTimeStamp(now.minusHours(2)); - - // when - final DeliveryProgressReport deliveryProgressReport = deliveryProgressReportFactory - .fromDeliveryProgress(deliveryProgress, now, true); - - // then - assertThat(deliveryProgressReport.getLineItemStatus()) - .extracting(org.prebid.server.deals.proto.report.LineItemStatus::getReadyAt, - org.prebid.server.deals.proto.report.LineItemStatus::getPacingFrequency, - org.prebid.server.deals.proto.report.LineItemStatus::getSpentTokens) - .containsOnly(tuple("2019-07-26T10:00:00.000Z", 72000L, 0L)); - } - - @Test - public void fromDeliveryProgressShouldDropLineItemsWithoutDeliverySchedule() { - // given - given(lineItemService.getLineItemById(anyString())) - .willReturn(LineItem.of( - LineItemMetaData.builder() - .accountId("accountId") - .source("rubicon") - .build(), - null, null, now)); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - deliveryProgress.setEndTimeStamp(now.minusHours(2)); - - // when - final DeliveryProgressReport deliveryProgressReport = deliveryProgressReportFactory - .fromDeliveryProgress(deliveryProgress, now, false); - - // then - assertThat(deliveryProgressReport.getLineItemStatus()).isEmpty(); - } - - @Test - public void batchFromDeliveryProgressShouldCreateTwoReportsInBatchWithSameId() { - // given - given(lineItemService.getLineItemById(anyString())) - .willReturn(LineItem.of( - LineItemMetaData.builder() - .accountId("accountId") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now.minusHours(1)) - .build())) - .source("rubicon") - .build(), - null, null, now)); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - deliveryProgress.setEndTimeStamp(now.minusHours(2)); - - deliveryProgress.getLineItemStatuses().put("lineItemId1", LineItemStatus.of("lineItemId1")); - deliveryProgress.getLineItemStatuses().put("lineItemId2", LineItemStatus.of("lineItemId2")); - deliveryProgress.getLineItemStatuses().put("lineItemId3", LineItemStatus.of("lineItemId3")); - - // when - final DeliveryProgressReportBatch deliveryProgressReportBatch = deliveryProgressReportFactory - .batchFromDeliveryProgress(deliveryProgress, null, now, 2, false); - - // then - final Set reports = deliveryProgressReportBatch.getReports(); - assertThat(reports).hasSize(2) - .extracting(DeliveryProgressReport::getReportId) - .containsOnly(deliveryProgressReportBatch.getReportId()); - assertThat(reports) - .extracting(deliveryProgressReport -> deliveryProgressReport.getLineItemStatus().size()) - .containsOnly(1, 2); - } - - private static LongAdder makeLongAdderWithValue(Long value) { - final LongAdder longAdder = new LongAdder(); - longAdder.add(value); - return longAdder; - } -} diff --git a/src/test/java/org/prebid/server/deals/DeliveryProgressServiceTest.java b/src/test/java/org/prebid/server/deals/DeliveryProgressServiceTest.java deleted file mode 100644 index 2981b1bc179..00000000000 --- a/src/test/java/org/prebid/server/deals/DeliveryProgressServiceTest.java +++ /dev/null @@ -1,426 +0,0 @@ -package org.prebid.server.deals; - -import org.assertj.core.api.iterable.ThrowingExtractor; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.lineitem.DeliveryPlan; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.lineitem.DeliveryToken; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.lineitem.LineItemStatus; -import org.prebid.server.deals.lineitem.LostToLineItem; -import org.prebid.server.deals.model.DeliveryProgressProperties; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.deals.proto.Token; -import org.prebid.server.deals.proto.report.Event; -import org.prebid.server.deals.proto.report.LineItemStatusReport; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.settings.model.Account; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.LongAdder; -import java.util.function.UnaryOperator; -import java.util.stream.IntStream; - -import static java.util.Arrays.asList; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -public class DeliveryProgressServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private LineItemService lineItemService; - @Mock - private DeliveryStatsService deliveryStatsService; - @Mock - private DeliveryProgressReportFactory deliveryProgressReportFactory; - @Mock - private CriteriaLogManager criteriaLogManager; - - private DeliveryProgressService deliveryProgressService; - - private final Clock clock = Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC); - private ZonedDateTime now; - - @Before - public void setUp() { - now = ZonedDateTime.now(clock); - - deliveryProgressService = new DeliveryProgressService( - DeliveryProgressProperties.of(200L, 20), - lineItemService, - deliveryStatsService, - deliveryProgressReportFactory, - clock, - criteriaLogManager); - } - - @Test - public void updateLineItemsShouldUpdateCurrentDeliveryReportIfUpdatedPlanUpdateTimeStampIsInFuture() { - // given - final LineItemMetaData firstPlanResponse = givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId("lineItem1") - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "planId1", - now.minusHours(1), - now.plusHours(1), - now, - singleton(Token.of(1, 100)))))); - final LineItemMetaData secondPlanResponse = givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId("lineItem1") - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "planId1", - now.minusHours(1), - now.plusHours(1), - now.plusMinutes(1), - singleton(Token.of(1, 200)))))); - - final LineItem lineItem1 = LineItem.of(firstPlanResponse, null, null, now); - final LineItem lineItem12 = LineItem.of(secondPlanResponse, null, null, now); - - given(lineItemService.getLineItems()).willReturn( - singletonList(lineItem1), - singletonList(lineItem12)); - - given(lineItemService.getLineItemById(anyString())).willReturn( - lineItem12); - - // when - deliveryProgressService.processDeliveryProgressUpdateEvent(); - recordLineItemsServed(40, "lineItem1"); - deliveryProgressService.processDeliveryProgressUpdateEvent(); - - // then - // trigger overall progress passing to report factory - deliveryProgressService.getOverallDeliveryProgressReport(); - - final ArgumentCaptor overallProgressCaptor = ArgumentCaptor.forClass(DeliveryProgress.class); - verify(deliveryProgressReportFactory).fromDeliveryProgress(overallProgressCaptor.capture(), any(), - anyBoolean()); - - final DeliveryProgress overallProgress = overallProgressCaptor.getValue(); - assertThat(overallProgress).isNotNull(); - assertThat(overallProgress.getLineItemStatuses()).isNotNull(); - assertThat(overallProgress.getLineItemStatuses().keySet()) - .containsOnly("lineItem1"); - final LineItemStatus overallLineItemStatus = overallProgress.getLineItemStatuses().get("lineItem1"); - assertThat(overallLineItemStatus).isNotNull(); - assertThat(overallLineItemStatus.getDeliveryPlans()) - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getStartTimeStamp, DeliveryPlan::getEndTimeStamp, - DeliveryPlan::getUpdatedTimeStamp) - .containsOnly(tuple("planId1", now.minusHours(1), now.plusHours(1), now.plusMinutes(1))); - assertThat(overallLineItemStatus.getDeliveryPlans()) - .flatExtracting(DeliveryPlan::getDeliveryTokens) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsOnly(tuple(1, 200, 40L)); - - // trigger current progress passing to delivery stats - deliveryProgressService.shutdown(); - - final ArgumentCaptor currentProgressCaptor = ArgumentCaptor.forClass(DeliveryProgress - .class); - verify(deliveryStatsService).addDeliveryProgress(currentProgressCaptor.capture(), any()); - - final DeliveryProgress currentProgress = currentProgressCaptor.getValue(); - assertThat(currentProgress).isNotNull(); - assertThat(currentProgress.getLineItemStatuses()).isNotNull(); - final LineItemStatus currentLineItemStatus = currentProgress.getLineItemStatuses().get("lineItem1"); - assertThat(currentLineItemStatus).isNotNull(); - assertThat(currentLineItemStatus.getDeliveryPlans()) - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getStartTimeStamp, DeliveryPlan::getEndTimeStamp, - DeliveryPlan::getUpdatedTimeStamp) - .containsOnly(tuple("planId1", now.minusHours(1), now.plusHours(1), now.plusMinutes(1))); - assertThat(currentLineItemStatus.getDeliveryPlans()) - .flatExtracting(DeliveryPlan::getDeliveryTokens) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsOnly(tuple(1, 200, 40L)); - } - - @Test - public void processAuctionEventShouldUpdateCurrentPlan() { - // given - final String lineItemId1 = "lineItemId1"; - final String lineItemId2 = "lineItemId2"; - - final LineItem lineItem1 = LineItem.of( - givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId(lineItemId1) - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "plan1", - now.minusHours(1), - now.plusHours(1), - Set.of(Token.of(1, 100), Token.of(2, 100)))))), - null, - null, - now); - final LineItem lineItem2 = LineItem.of( - givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId(lineItemId2) - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "plan2", - now.minusHours(1), - now.plusHours(1), - Set.of(Token.of(1, 100), Token.of(2, 100)))))), - null, - null, - now); - - given(lineItemService.getLineItemById(eq(lineItemId1))).willReturn(lineItem1); - given(lineItemService.getLineItemById(eq(lineItemId2))).willReturn(lineItem2); - - recordLineItemsServed(150, lineItemId1); - - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemSentToClientAsTopMatch().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsSentToClient().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsMatchedDomainTargeting().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsMatchedWholeTargeting().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsMatchedTargetingFcapped().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsMatchedTargetingFcapLookupFailed().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lineItemsSentToBidder().put("rubicon", new HashSet<>(asList(lineItemId1, lineItemId2))); - txnLog.lineItemsSentToBidderAsTopMatch().put("rubicon", singleton(lineItemId1)); - txnLog.lineItemsSentToBidderAsTopMatch().put("appnexus", singleton(lineItemId2)); - txnLog.lineItemsReceivedFromBidder().put("rubicon", new HashSet<>(asList(lineItemId1, lineItemId2))); - txnLog.lineItemsResponseInvalidated().addAll(asList(lineItemId1, lineItemId2)); - txnLog.lostMatchingToLineItems().put(lineItemId1, singleton(lineItemId2)); - - // when and then - deliveryProgressService.processAuctionEvent(AuctionContext.builder() - .account(Account.empty("1001")) - .txnLog(txnLog) - .build()); - deliveryProgressService.createDeliveryProgressReports(now); - - final ArgumentCaptor deliveryProgressReportCaptor = - ArgumentCaptor.forClass(DeliveryProgress.class); - verify(deliveryStatsService).addDeliveryProgress(deliveryProgressReportCaptor.capture(), any()); - final DeliveryProgress deliveryProgress = deliveryProgressReportCaptor.getValue(); - assertThat(deliveryProgress.getRequests().sum()).isEqualTo(151); - - final Set lineItemStatuses = new HashSet<>(deliveryProgress.getLineItemStatuses().values()); - - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getDomainMatched, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getTargetMatched, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getTargetMatchedButFcapped, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getTargetMatchedButFcapLookupFailed, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getSentToBidder, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getReceivedFromBidder, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getReceivedFromBidderInvalidated, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getSentToClientAsTopMatch, 151L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getSentToBidderAsTopMatch, 1L, 1L); - checkLineItemStatusStats(lineItemStatuses, LineItemStatus::getSentToClient, 1L, 1L); - - assertThat(deliveryProgress.getLineItemIdToLost()) - .extracting(lineItemId1) - .extracting(lineItemId2) - .extracting(lostToLineItem -> ((LostToLineItem) lostToLineItem).getCount().sum()) - .isEqualTo(1L); - - assertThat(lineItemStatuses) - .flatExtracting(LineItemStatus::getDeliveryPlans) - .flatExtracting(DeliveryPlan::getDeliveryTokens) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, - deliveryToken -> deliveryToken.getSpent().sum()) - .containsOnly( - tuple(1, 100, 100L), - tuple(2, 100, 51L), - tuple(1, 100, 1L), - tuple(2, 100, 0L)); - - assertThat(lineItem1.getActiveDeliveryPlan().getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsExactly( - tuple(1, 100, 100L), - tuple(2, 100, 51L)); - - assertThat(lineItem2.getActiveDeliveryPlan().getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsExactly( - tuple(1, 100, 1L), - tuple(2, 100, 0L)); - } - - @Test - public void trackWinEventShouldCreateLineItemStatusAndUpdateWinEventsMetric() { - // given - final LineItem lineItem = LineItem.of( - givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId("lineItemId1") - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "plan1", - now.minusHours(1), - now.plusHours(1), - Set.of(Token.of(1, 100), Token.of(2, 100)))))), - null, - null, - now); - - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(lineItem); - - // when - deliveryProgressService.processLineItemWinEvent("lineItemId1"); - - // then - // trigger current progress passing to delivery stats - deliveryProgressService.shutdown(); - - final ArgumentCaptor currentProgressCaptor = ArgumentCaptor.forClass(DeliveryProgress.class); - verify(deliveryStatsService).addDeliveryProgress(currentProgressCaptor.capture(), any()); - - final DeliveryProgress currentProgress = currentProgressCaptor.getValue(); - assertThat(currentProgress).isNotNull(); - assertThat(currentProgress.getLineItemStatuses().entrySet()).hasSize(1) - .extracting(Map.Entry::getValue) - .flatExtracting(LineItemStatus::getEvents) - .extracting(Event::getType, event -> event.getCount().sum()) - .containsOnly(tuple("win", 1L)); - } - - @Test - public void getLineItemStatusReportShouldReturnExpectedResult() { - // given - final LineItem lineItem = LineItem.of( - givenLineItemMetaData( - now, - lineItemMetaData -> lineItemMetaData - .lineItemId("lineItemId1") - .accountId("1001") - .source("rubicon") - .deliverySchedules(singletonList( - givenDeliverySchedule( - "plan1", - now.minusHours(1), - now.plusHours(1), - singleton(Token.of(1, 100))))) - .targeting(mapper.createObjectNode().put("targetingField", "targetingValue"))), - null, - null, - now); - given(lineItemService.getLineItemById(anyString())).willReturn(lineItem); - - // when - final LineItemStatusReport report = deliveryProgressService.getLineItemStatusReport("lineItemId1"); - - // then - assertThat(report).isEqualTo(LineItemStatusReport.builder() - .lineItemId("lineItemId1") - .deliverySchedule(org.prebid.server.deals.proto.report.DeliverySchedule.builder() - .planId("plan1") - .planStartTimeStamp("2019-07-26T09:00:00.000Z") - .planExpirationTimeStamp("2019-07-26T11:00:00.000Z") - .planUpdatedTimeStamp("2019-07-26T09:00:00.000Z") - .tokens(singleton(org.prebid.server.deals.proto.report.Token.of(1, 100, 0L, null))) - .build()) - .readyToServeTimestamp(now) - .spentTokens(0L) - .pacingFrequency(72000L) - .accountId("1001") - .target(mapper.createObjectNode().put("targetingField", "targetingValue")) - .build()); - } - - private static LineItemMetaData givenLineItemMetaData( - ZonedDateTime now, - UnaryOperator lineItemMetaDataCustomizer) { - - return lineItemMetaDataCustomizer - .apply(LineItemMetaData.builder() - .dealId("dealId") - .status("active") - .price(Price.of(BigDecimal.ONE, "USD")) - .relativePriority(5) - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now)) - .build(); - } - - private static DeliverySchedule givenDeliverySchedule(String planId, ZonedDateTime start, ZonedDateTime end, - ZonedDateTime updated, Set tokens) { - return DeliverySchedule.builder() - .planId(planId) - .startTimeStamp(start) - .endTimeStamp(end) - .updatedTimeStamp(updated) - .tokens(tokens) - .build(); - } - - private static DeliverySchedule givenDeliverySchedule(String planId, ZonedDateTime start, ZonedDateTime end, - Set tokens) { - return givenDeliverySchedule(planId, start, end, start, tokens); - } - - private static void checkLineItemStatusStats(Set lineItemStatuses, - ThrowingExtractor stat, - Long... values) { - assertThat(lineItemStatuses) - .extracting(stat) - .extracting(LongAdder::sum) - .containsOnly(values); - } - - private void recordLineItemsServed(int times, String... lineItemIds) { - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder() - .account(Account.empty("1001")) - .txnLog(txnLog) - .build(); - txnLog.lineItemSentToClientAsTopMatch().addAll(asList(lineItemIds)); - IntStream.range(0, times).forEach(i -> deliveryProgressService.processAuctionEvent(auctionContext)); - - } -} diff --git a/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java b/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java deleted file mode 100644 index 07badbbc5c3..00000000000 --- a/src/test/java/org/prebid/server/deals/DeliveryStatsServiceTest.java +++ /dev/null @@ -1,428 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.Vertx; -import org.apache.http.HttpHeaders; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.lineitem.DeliveryProgress; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeliveryStatsProperties; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.DeliveryProgressReportBatch; -import org.prebid.server.deals.proto.report.LineItemStatus; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; -import org.springframework.test.util.ReflectionTestUtils; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashSet; -import java.util.NavigableSet; -import java.util.concurrent.TimeoutException; -import java.util.zip.GZIPInputStream; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class DeliveryStatsServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private DeliveryProgressReportFactory deliveryProgressReportFactory; - @Mock - private AlertHttpService alertHttpService; - @Mock - private HttpClient httpClient; - @Mock - private Clock clock; - @Mock - private Metrics metrics; - - @Mock - private Vertx vertx; - - private DeliveryStatsService deliveryStatsService; - - private ZonedDateTime now; - - @Mock - private LineItemService lineItemService; - - @Before - public void setUp() { - now = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC)); - given(clock.instant()).willReturn(now.toInstant()); - given(clock.getZone()).willReturn(ZoneOffset.UTC); - - deliveryStatsService = new DeliveryStatsService( - DeliveryStatsProperties.builder() - .endpoint("localhost/delivery") - .cachedReportsNumber(3) - .timeoutMs(500L) - .reportsIntervalMs(0) - .batchesIntervalMs(0) - .username("username") - .password("password") - .build(), - deliveryProgressReportFactory, - alertHttpService, - httpClient, - metrics, - clock, - vertx, - jacksonMapper); - } - - @SuppressWarnings("unchecked") - @Test - public void sendDeliveryProgressReportShouldSendBothBatches() { - // given - givenDeliveryProgressHttpResponse(httpClient, 200, null); - - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn( - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "1", - now.minusHours(2).toString()), - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("2") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(1).toString()).build()), "2", - now.minusHours(1).toString())); - - final DeliveryProgress deliveryProgress1 = DeliveryProgress.of(now.minusHours(3), lineItemService); - final DeliveryProgress deliveryProgress2 = DeliveryProgress.of(now.minusHours(2), lineItemService); - - // when - deliveryStatsService.addDeliveryProgress(deliveryProgress1, emptyMap()); - deliveryStatsService.addDeliveryProgress(deliveryProgress2, emptyMap()); - deliveryStatsService.sendDeliveryProgressReports(); - - // then - verify(httpClient, times(2)).post(anyString(), any(), anyString(), anyLong()); - final NavigableSet reports = (NavigableSet) - ReflectionTestUtils.getField(deliveryStatsService, "requiredBatches"); - assertThat(reports).isEmpty(); - verify(metrics, times(2)).updateDeliveryRequestMetric(eq(true)); - } - - @SuppressWarnings("unchecked") - @Test - public void sendDeliveryProgressReportShouldSendOneBatchAndCacheFailedBatch() { - // given - final DeliveryProgress deliveryProgress1 = DeliveryProgress.of(now.minusHours(3), lineItemService); - final DeliveryProgress deliveryProgress2 = DeliveryProgress.of(now.minusHours(2), lineItemService); - - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn( - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "1", - now.minusHours(2).toString()), - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("2") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(1).toString()).build()), "2", - now.minusHours(1).toString())); - - deliveryStatsService.addDeliveryProgress(deliveryProgress1, null); - deliveryStatsService.addDeliveryProgress(deliveryProgress2, null); - - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, null)), - Future.failedFuture(new TimeoutException())); - - deliveryStatsService.sendDeliveryProgressReports(); - - // when and then - verify(httpClient, times(2)).post(anyString(), any(), anyString(), anyLong()); - final NavigableSet reports = (NavigableSet) - ReflectionTestUtils.getField(deliveryStatsService, "requiredBatches"); - assertThat(reports).hasSize(1); - verify(metrics).updateDeliveryRequestMetric(eq(true)); - verify(metrics).updateDeliveryRequestMetric(eq(false)); - } - - @Test - public void sendDeliveryProgressReportShouldSendFirstReportFromFirstBatchFailOnSecondsAndCacheOther() { - // given - final DeliveryProgress deliveryProgress1 = DeliveryProgress.of(now.minusHours(3), lineItemService); - final DeliveryProgress deliveryProgress2 = DeliveryProgress.of(now.minusHours(2), lineItemService); - - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn( - DeliveryProgressReportBatch.of( - new HashSet<>(asList(DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(singleton(LineItemStatus.builder().lineItemId("1") - .build())) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build(), - DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(singleton(LineItemStatus.builder().lineItemId("2") - .build())) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build())), - "1", now.minusHours(2).toString()), - DeliveryProgressReportBatch.of( - new HashSet<>(asList(DeliveryProgressReport.builder().reportId("2") - .lineItemStatus(singleton(LineItemStatus.builder().lineItemId("1") - .build())) - .dataWindowEndTimeStamp(now.minusHours(3).toString()).build(), - DeliveryProgressReport.builder().reportId("2") - .lineItemStatus(singleton(LineItemStatus.builder().lineItemId("2") - .build())) - .dataWindowEndTimeStamp(now.minusHours(3).toString()).build())), - "2", now.minusHours(3).toString())); - - deliveryStatsService.addDeliveryProgress(deliveryProgress1, null); - deliveryStatsService.addDeliveryProgress(deliveryProgress2, null); - - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, null)), - Future.failedFuture(new TimeoutException())); - - deliveryStatsService.sendDeliveryProgressReports(); - - // when and then - verify(httpClient, times(2)).post(anyString(), any(), anyString(), anyLong()); - final NavigableSet reports = (NavigableSet) - ReflectionTestUtils.getField(deliveryStatsService, "requiredBatches"); - assertThat(reports).hasSize(2) - .flatExtracting(DeliveryProgressReportBatch::getReports) - .hasSize(3); - verify(metrics).updateDeliveryRequestMetric(eq(true)); - verify(metrics).updateDeliveryRequestMetric(eq(false)); - } - - @Test - public void sendDeliveryProgressReportShouldHandleFailedBatchesCacheLimitWhenResponseStatusIsBadRequest() { - // given - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn( - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .dataWindowEndTimeStamp(now.minusHours(4).toString()).build()), "1", - now.minusHours(4).toString()), - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("2") - .dataWindowEndTimeStamp(now.minusHours(3).toString()).build()), "2", - now.minusHours(3).toString()), - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("3") - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "3", - now.minusHours(2).toString()), - DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("4") - .dataWindowEndTimeStamp(now.minusHours(1).toString()).build()), "4", - now.minusHours(1).toString())); - - final DeliveryProgress deliveryProgress1 = DeliveryProgress.of(now.minusHours(5), lineItemService); - final DeliveryProgress deliveryProgress2 = DeliveryProgress.of(now.minusHours(4), lineItemService); - final DeliveryProgress deliveryProgress3 = DeliveryProgress.of(now.minusHours(3), lineItemService); - final DeliveryProgress deliveryProgress4 = DeliveryProgress.of(now.minusHours(2), lineItemService); - - deliveryStatsService.addDeliveryProgress(deliveryProgress1, null); - deliveryStatsService.addDeliveryProgress(deliveryProgress2, null); - deliveryStatsService.addDeliveryProgress(deliveryProgress3, null); - deliveryStatsService.addDeliveryProgress(deliveryProgress4, null); - - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(400, null, null))); - - deliveryStatsService.sendDeliveryProgressReports(); - - // when and then - verify(httpClient).post(anyString(), any(), anyString(), anyLong()); - @SuppressWarnings("unchecked") final NavigableSet reports = (NavigableSet) - ReflectionTestUtils.getField(deliveryStatsService, "requiredBatches"); - assertThat(reports).hasSize(3); - } - - @Test - public void sendDeliveryProgressReportShouldShouldRemoveReportFromQueueWhenDelStatsRespondWith409Conflict() { - // given - givenDeliveryProgressHttpResponse(httpClient, 409, null); - - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn(DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "1", - now.minusHours(2).toString())); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - - // when - deliveryStatsService.addDeliveryProgress(deliveryProgress, emptyMap()); - deliveryStatsService.sendDeliveryProgressReports(); - - // then - final NavigableSet reports = - (NavigableSet) ReflectionTestUtils.getField(deliveryStatsService, "requiredBatches"); - assertThat(reports).isEmpty(); - } - - @Test - public void sendDeliveryProgressReportShouldCallAlertServiceWhenRequestFailed() { - // given - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn(DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "1", - now.minusHours(2).toString())); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - - deliveryStatsService.addDeliveryProgress(deliveryProgress, emptyMap()); - - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("Timeout"))); - - // when - deliveryStatsService.sendDeliveryProgressReports(); - - // then - verify(alertHttpService).alertWithPeriod(eq("deliveryStats"), eq("pbs-delivery-stats-client-error"), - eq(AlertPriority.MEDIUM), - eq("Report was not send to delivery stats service with a reason: Sending report with id = 1 failed" - + " in a reason: Timeout")); - } - - @Test - public void sendDeliveryProgressReportShouldCallAlertServiceResetWhenRequestWasSuccessful() { - // given - givenDeliveryProgressHttpResponse(httpClient, 200, null); - - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn(DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build()), "1", - now.minusHours(2).toString())); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - - // when - deliveryStatsService.addDeliveryProgress(deliveryProgress, emptyMap()); - deliveryStatsService.sendDeliveryProgressReports(); - - // then - verify(alertHttpService).resetAlertCount(eq("pbs-delivery-stats-client-error")); - } - - @Test - public void suspendShouldSetSuspendFlagAndReportShouldNotBeSent() { - // given - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn(DeliveryProgressReportBatch.of(singleton(DeliveryProgressReport.builder().reportId("1") - .dataWindowEndTimeStamp(now.minusHours(4).toString()).build()), "1", - now.minusHours(4).toString())); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(5), lineItemService); - - deliveryStatsService.addDeliveryProgress(deliveryProgress, null); - - // when - deliveryStatsService.suspend(); - deliveryStatsService.sendDeliveryProgressReports(); - - // then - verifyNoInteractions(httpClient); - } - - @Test - public void sendDeliveryProgressReportShouldSendGzippedBody() throws JsonProcessingException { - // given - final DeliveryStatsService deliveryStatsService = new DeliveryStatsService( - DeliveryStatsProperties.builder() - .endpoint("localhost/delivery") - .cachedReportsNumber(3) - .timeoutMs(500L) - .reportsIntervalMs(0) - .requestCompressionEnabled(true) - .username("username") - .password("password") - .build(), - deliveryProgressReportFactory, - alertHttpService, - httpClient, - metrics, - clock, - vertx, - jacksonMapper); - - givenDeliveryProgressHttpResponse(httpClient, 200, null); - - final DeliveryProgressReport deliveryProgressReport = DeliveryProgressReport.builder().reportId("1") - .lineItemStatus(emptySet()) - .dataWindowEndTimeStamp(now.minusHours(2).toString()).build(); - given(deliveryProgressReportFactory.updateReportTimeStamp(any(), any())).willReturn(deliveryProgressReport); - given(deliveryProgressReportFactory.batchFromDeliveryProgress(any(), any(), any(), anyInt(), anyBoolean())) - .willReturn( - DeliveryProgressReportBatch.of(singleton(deliveryProgressReport), "1", - now.minusHours(2).toString())); - - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now.minusHours(3), lineItemService); - - // when - deliveryStatsService.addDeliveryProgress(deliveryProgress, emptyMap()); - deliveryStatsService.sendDeliveryProgressReports(); - - // then - final ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(byte[].class); - final ArgumentCaptor headerCaptor = ArgumentCaptor.forClass(MultiMap.class); - verify(httpClient).request(any(), anyString(), headerCaptor.capture(), bodyCaptor.capture(), anyLong()); - // verify body was compressed well - final byte[] compressedRequestBody = bodyCaptor.getValue(); - final String decompressedRequestBody = decompress(compressedRequestBody); - assertThat(mapper.readValue(decompressedRequestBody, DeliveryProgressReport.class)) - .isEqualTo(deliveryProgressReport); - // verify Content-encoding header was added - final MultiMap headers = headerCaptor.getValue(); - assertThat(headers.get(HttpHeaders.CONTENT_ENCODING)).isEqualTo("gzip"); - } - - private static String decompress(byte[] byteArray) { - final StringBuilder body = new StringBuilder(); - try ( - GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(byteArray)); - BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - body.append(line); - } - return body.toString(); - } catch (IOException e) { - throw new RuntimeException("Error occurred while decompressing gzipped body"); - } - } - - private static void givenDeliveryProgressHttpResponse(HttpClient httpClient, int statusCode, String response) { - final HttpClientResponse httpClientResponse = HttpClientResponse.of(statusCode, null, response); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(httpClientResponse)); - } -} diff --git a/src/test/java/org/prebid/server/deals/LineItemServiceTest.java b/src/test/java/org/prebid/server/deals/LineItemServiceTest.java deleted file mode 100644 index 07fade4e37e..00000000000 --- a/src/test/java/org/prebid/server/deals/LineItemServiceTest.java +++ /dev/null @@ -1,2076 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.databind.node.TextNode; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.User; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.mockito.stubbing.Answer; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.bidder.BidderCatalog; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.events.ApplicationEventService; -import org.prebid.server.deals.lineitem.DeliveryPlan; -import org.prebid.server.deals.lineitem.DeliveryToken; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.DeepDebugLog; -import org.prebid.server.deals.model.MatchLineItemsResult; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.FrequencyCap; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.deals.proto.Token; -import org.prebid.server.deals.targeting.TargetingDefinition; -import org.prebid.server.log.CriteriaLogManager; -import org.prebid.server.model.CaseInsensitiveMultiMap; -import org.prebid.server.model.HttpRequestContext; -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.ExtUser; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category; -import org.prebid.server.settings.model.Account; -import org.prebid.server.util.HttpUtil; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.IntStream; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyMap; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -public class LineItemServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private TargetingService targetingService; - @Mock - private BidderCatalog bidderCatalog; - @Mock - private CurrencyConversionService conversionService; - @Mock - private ApplicationEventService applicationEventService; - @Mock - private Clock clock; - @Mock - private CriteriaLogManager criteriaLogManager; - - private BidderAliases bidderAliases; - - private LineItemService lineItemService; - - private ZonedDateTime now; - - @Before - public void setUp() { - now = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC)); - - given(clock.instant()).willReturn(now.toInstant()); - given(clock.getZone()).willReturn(ZoneOffset.UTC); - - given(conversionService.convertCurrency(any(), anyMap(), anyString(), anyString(), any())) - .willReturn(BigDecimal.ONE); - - bidderAliases = BidderAliases.of(Map.of("rubiAlias", "rubicon"), emptyMap(), bidderCatalog); - - lineItemService = new LineItemService( - 2, - targetingService, - conversionService, - applicationEventService, - "USD", - clock, - criteriaLogManager); - } - - @Test - public void updateLineItemsShouldRemoveLineItemIfItIsNotActiveFromPlannerResponse() { - // given - final List firstPlanResponse = asList( - givenLineItemMetaData("lineItem1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity()), - givenLineItemMetaData("lineItem2", now, "2", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - final List secondPlanResponse = asList( - givenLineItemMetaData("lineItem1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), - builder -> builder.status("inactive")), - givenLineItemMetaData("lineItem2", now, "2", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - lineItemService.updateLineItems(secondPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - } - - @Test - public void updateLineItemsShouldRemoveLineItemIfItHasEndTimeInPastInPlannerResponse() { - // given - final List firstPlanResponse = asList( - givenLineItemMetaData("lineItem1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity()), - givenLineItemMetaData("lineItem2", now, "2", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - final List secondPlanResponse = asList( - givenLineItemMetaData("lineItem1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), - builder -> builder.endTimeStamp(now.minusHours(1))), - givenLineItemMetaData("lineItem2", now, "2", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - lineItemService.updateLineItems(secondPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - } - - @Test - public void updateLineItemsShouldRemoveLineItemIfItHasEndTimeInPastInMemory() { - // given - final List firstPlanResponse = asList( - givenLineItemMetaData("lineItem1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), - builder -> builder.endTimeStamp(now.plusSeconds(1))), - givenLineItemMetaData("lineItem2", now, "2", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true, now); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - lineItemService.updateLineItems(emptyList(), true, now.plusSeconds(2)); - assertThat(lineItemService.getLineItemById("lineItem1")).isNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - } - - @Test - public void updateLineItemsShouldNotRemoveLineItemIfItWasMissedInPlannerResponse() { - // given - final List firstPlanResponse = asList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), now), - givenLineItemMetaData("lineItem2", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), now)); - - final List secondPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), now)); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - lineItemService.updateLineItems(secondPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - assertThat(lineItemService.getLineItemById("lineItem2")).isNotNull(); - } - - @Test - public void updateLineItemShouldSaveLineItemIfItHasEmptyDeliverySchedules() { - // given - final List firstPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", emptyList(), now)); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - } - - @Test - public void updateLineItemShouldSaveLineItemIfItDoesNotHaveDeliverySchedules() { - // given - final List firstPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", null, now)); - - // when and then - lineItemService.updateLineItems(firstPlanResponse, true); - assertThat(lineItemService.getLineItemById("lineItem1")).isNotNull(); - } - - @Test - public void updateLineItemsShouldUpdateCurrentPlanIfUpdatedPlanUpdateTimeStampIsInFuture() { - // given - final List firstPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), now)); - - final List secondPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now.plusMinutes(1), singleton(Token.of(1, 200)))), now)); - - // when - lineItemService.updateLineItems(firstPlanResponse, true); - incSpentTokens(10, "lineItem1"); - lineItemService.updateLineItems(secondPlanResponse, true); - - // then - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem).isNotNull(); - - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - - assertThat(activeDeliveryPlan).isNotNull() - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getStartTimeStamp, DeliveryPlan::getEndTimeStamp, - DeliveryPlan::getUpdatedTimeStamp) - .containsOnly("planId1", now.minusHours(1), now.plusHours(1), now.plusMinutes(1)); - assertThat(activeDeliveryPlan.getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsOnly(tuple(1, 200, 10L)); - - // 6 minutes after plan started - assertThat(lineItem.getReadyAt()).isEqualTo(now.minusHours(1).plusMinutes(6)); - } - - @Test - public void updateLineItemsShouldUpdateReadyAtBasedOnPlanStartTime() { - // given - final List firstPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), now, singleton(Token.of(1, 100)))), now)); - - // when - lineItemService.updateLineItems(firstPlanResponse, true); - incSpentTokens(1, "lineItem1"); - - // then - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem).isNotNull(); - - // 1 * (120 * 60 * 1000) \ 100 tokens = 72,000 millis = 1 minute 12 seconds shift from plan startTime - assertThat(lineItem.getReadyAt()).isEqualTo(now.minusHours(1).plusMinutes(1).plusSeconds(12)); - } - - @Test - public void updateLineItemsShouldConvertPriceWhenLineItemMetaDataCurrencyIsDifferent() { - // given - final String defaultCurrency = "RUB"; - lineItemService = new LineItemService( - 2, - targetingService, - conversionService, - applicationEventService, - defaultCurrency, - clock, - criteriaLogManager); - - final List planResponse = asList( - givenLineItemMetaData("lineItem1", null, null, - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusHours(1), - emptySet())), now), - givenLineItemMetaData("lineItem2", null, null, - singletonList(givenDeliverySchedule("planId2", now.minusHours(1), now.plusHours(1), - emptySet())), now)); - - final BigDecimal updatedCmp = BigDecimal.TEN; - given(conversionService.convertCurrency(any(), anyMap(), anyString(), anyString(), any())) - .willReturn(updatedCmp); - - // when - lineItemService.updateLineItems(planResponse, true); - - // then - final LineItem lineItem1 = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem1.getCpm()).isEqualTo(updatedCmp); - assertThat(lineItem1.getCurrency()).isEqualTo(defaultCurrency); - - final LineItem lineItem2 = lineItemService.getLineItemById("lineItem2"); - assertThat(lineItem2.getCpm()).isEqualTo(updatedCmp); - assertThat(lineItem2.getCurrency()).isEqualTo(defaultCurrency); - } - - @Test - public void updateLineItemsShouldCreateLineItemsWhenPlannerIsResponsive() { - // given - final List planResponse = asList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), singleton(Token.of(1, 100)))), now), - givenLineItemMetaData("lineItem2", "1002", "rubicon", - singletonList(givenDeliverySchedule("planId2", now.plusHours(1), - now.plusHours(2), singleton(Token.of(1, 100)))), now)); - - // when - lineItemService.updateLineItems(planResponse, true); - - // then - final LineItem lineItem1 = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem1).isNotNull(); - - final DeliveryPlan activeDeliveryPlan = lineItem1.getActiveDeliveryPlan(); - assertThat(activeDeliveryPlan).isNotNull() - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getStartTimeStamp, DeliveryPlan::getEndTimeStamp) - .containsOnly("planId1", now.minusHours(1), now.plusHours(1)); - assertThat(activeDeliveryPlan.getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal) - .containsOnly(tuple(1, 100)); - - assertThat(lineItem1.getReadyAt()).isEqualTo(now); - - final LineItem lineItem2 = lineItemService.getLineItemById("lineItem2"); - assertThat(lineItem2).isNotNull(); - assertThat(lineItem2.getActiveDeliveryPlan()).isNull(); - assertThat(lineItem2.getReadyAt()).isNull(); - } - - @Test - public void updateLineItemsShouldCreateLineItemsWithNullTargetingIfCantParse() { - // given - final List planResponse = singletonList( - LineItemMetaData.builder() - .lineItemId("lineItem1") - .status("active") - .dealId("dealId") - .accountId("1001") - .source("rubicon") - .price(Price.of(BigDecimal.ONE, "USD")) - .relativePriority(5) - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .targeting(mapper.createObjectNode().set("$invalid", new TextNode("invalid"))) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), singleton(Token.of(1, 100))))) - .build()); - - // when - lineItemService.updateLineItems(planResponse, true); - - // then - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem).isNotNull(); - assertThat(lineItem.getTargetingDefinition()).isNull(); - } - - @Test - public void updateLineItemsShouldNotUpdateCurrentPlanIfUpdatedPlanUpdateTimeStampIsNotInFuture() { - // given - final List firstPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), singleton(Token.of(1, 100)))), now)); - - final List secondPlanResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusHours(1), singleton(Token.of(1, 200)))), now)); - - // when - lineItemService.updateLineItems(firstPlanResponse, true); - incSpentTokens(10, "lineItem1"); - lineItemService.updateLineItems(secondPlanResponse, true); - - // then - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - assertThat(lineItem).isNotNull(); - - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - assertThat(activeDeliveryPlan).isNotNull() - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getStartTimeStamp, DeliveryPlan::getEndTimeStamp) - .containsOnly("planId1", now.minusHours(1), now.plusHours(1)); - assertThat(activeDeliveryPlan.getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, token -> token.getSpent().sum()) - .containsOnly(tuple(1, 100, 10L)); - - // should be ready at 12 minutes after plan start - assertThat(lineItem.getReadyAt()).isEqualTo(now.minusHours(1).plusMinutes(12)); - } - - @Test - public void updateLineItemsShouldMergeLineItemsWhenPlannerIsNotResponsive() { - // given - given(clock.instant()).willReturn(now.toInstant(), now.toInstant(), now.plusSeconds(2).toInstant()); - given(clock.getZone()).willReturn(ZoneOffset.UTC); - - final Set expiredTokens = new HashSet<>(); - expiredTokens.add(Token.of(1, 100)); - expiredTokens.add(Token.of(3, 300)); - expiredTokens.add(Token.of(4, 400)); - expiredTokens.add(Token.of(5, 500)); - - final Set newActiveTokens = new HashSet<>(); - newActiveTokens.add(Token.of(1, 100)); - newActiveTokens.add(Token.of(2, 200)); - newActiveTokens.add(Token.of(3, 300)); - newActiveTokens.add(Token.of(4, 400)); - - final List planResponse = singletonList(givenLineItemMetaData( - "lineItem1", "1001", "rubicon", - asList( - givenDeliverySchedule("planId1", now.minusHours(1), now.plusSeconds(1), expiredTokens), - givenDeliverySchedule("planId2", now.plusSeconds(1), now.plusHours(1), newActiveTokens)), - now)); - - // when and then - lineItemService.updateLineItems(planResponse, true); - incSpentTokens(240, "lineItem1"); - lineItemService.updateLineItems(null, false); - lineItemService.advanceToNextPlan(now.plusSeconds(1)); - - verify(clock, times(2)).instant(); - - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - assertThat(activeDeliveryPlan).isNotNull(); - assertThat(activeDeliveryPlan.getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, - deliveryToken -> deliveryToken.getSpent().sum()) - .containsExactly( - tuple(1, 200, 100L), - tuple(2, 200, 0L), - tuple(3, 600, 140L), - tuple(4, 800, 0L), - tuple(5, 500, 0L)); - } - - @Test - public void updateLineItemShouldUpdatePlanWithoutActiveCurrentDeliveryPlan() { - // given - given(clock.instant()).willReturn(now.toInstant(), now.toInstant(), now.plusSeconds(3).toInstant()); - given(clock.getZone()).willReturn(ZoneOffset.UTC); - - final List planResponse = singletonList(givenLineItemMetaData( - "lineItem1", "1001", "rubicon", - asList( - givenDeliverySchedule("planId1", now.minusHours(2), - now.minusHours(1), singleton(Token.of(1, 100))), - givenDeliverySchedule("planId2", now.plusSeconds(2), - now.plusHours(1), singleton(Token.of(1, 100)))), - now)); - - // when and then - lineItemService.updateLineItems(planResponse, true); - lineItemService.updateLineItems(null, false); - lineItemService.advanceToNextPlan(now.plusSeconds(2)); - - verify(clock, times(2)).instant(); - - final LineItem lineItem = lineItemService.getLineItemById("lineItem1"); - - final DeliveryPlan activeDeliveryPlan = lineItem.getActiveDeliveryPlan(); - assertThat(activeDeliveryPlan).isNotNull(); - assertThat(activeDeliveryPlan.getDeliveryTokens()) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, - deliveryToken -> deliveryToken.getSpent().sum()) - .containsExactly(tuple(1, 100, 0L)); - } - - @Test - public void accountHasDealsShouldReturnTrue() { - // given - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusHours(1), - emptySet())), now)); - lineItemService.updateLineItems(planResponse, true); - - // when and then - assertThat(lineItemService.accountHasDeals(AuctionContext.builder() - .account(Account.builder().id("1001").build()).build())) - .isTrue(); - } - - @Test - public void accountHasDealsShouldReturnFalseWhenAccountIsEmptyString() { - // given - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusHours(1), - emptySet())), now)); - lineItemService.updateLineItems(planResponse, true); - - // when and then - assertThat(lineItemService.accountHasDeals(AuctionContext.builder().account(Account.builder().id("").build()) - .build())).isFalse(); - } - - @Test - public void accountHasDealsShouldReturnFalseWhenNoMatchingLineItemWereFound() { - // given - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "3003", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusHours(1), - emptySet())), now)); - lineItemService.updateLineItems(planResponse, true); - - // when and then - assertThat(lineItemService.accountHasDeals(AuctionContext.builder().account(Account.builder().id("1001") - .build()).build())).isFalse(); - } - - @Test - public void accountHasDealsShouldReturnFalseWhenMatchedLineItemIsNotActive() { - // given - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusHours(1), - emptySet())), now)); - lineItemService.updateLineItems(planResponse, true); - given(clock.instant()).willReturn(now.plusHours(2).toInstant()); - - // when and then - assertThat(lineItemService.accountHasDeals(AuctionContext.builder().account(Account.builder().id("1001") - .build()).build())).isFalse(); - } - - @Test - public void findMatchingLineItemsShouldReturnEmptyListWhenLineItemsIsEmpty() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldReturnEmptyListWhenNoLineItemsForAccount() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountIdUnknown", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldReturnEmptyListWhenNoBiddersMatched() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountId", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusMinutes(1), - singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "pubmatic", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldReturnLineItemsForMatchingBidder() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountId", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusMinutes(1), - singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("lineItem1"); - } - - @Test - public void findMatchingLineItemsShouldReturnLineItemsWhenLineItemsBidderIsAlias() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountId", "rubiAlias", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusMinutes(1), - singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("lineItem1"); - } - - @Test - public void findMatchingLineItemsShouldReturnLineItemsWhenBidderFromInputBiddersIsAlias() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountId", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusMinutes(1), - singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubiAlias", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("lineItem1"); - } - - @Test - public void findMatchingLineItemsShouldReturnEmptyListWhenAccountIsEmptyString() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder().account(Account.builder().id("").build()).build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = singletonList( - givenLineItemMetaData("lineItem1", "accountId", "rubicon", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), now.plusMinutes(1), - singleton(Token.of(1, 100)))), now)); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldFilterNotMatchingTargeting() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - given(targetingService.parseTargetingDefinition(any(), eq("id1"))) - .willReturn(TargetingDefinition.of(context -> false)); - given(targetingService.parseTargetingDefinition(any(), eq("id2"))) - .willReturn(TargetingDefinition.of(context -> true)); - given(targetingService.matchesTargeting(any(), any(), any(), any())) - .willAnswer(withEvaluatedTargeting()); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).isEmpty(); - - assertThat(auctionContext.getDeepDebugLog().entries()).containsOnly( - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.targeting, - "Line Item id1 targeting did not match imp with id imp1")); - } - - @Test - public void findMatchingLineItemsShouldReturnLineItemsThatMatchedTargeting() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - given(targetingService.parseTargetingDefinition(any(), eq("id1"))) - .willReturn(TargetingDefinition.of(context -> false)); - given(targetingService.parseTargetingDefinition(any(), eq("id2"))) - .willReturn(TargetingDefinition.of(context -> true)); - given(targetingService.matchesTargeting(any(), any(), any(), any())) - .willAnswer(withEvaluatedTargeting()); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "appnexus", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - - assertThat(auctionContext.getDeepDebugLog().entries()).containsOnly( - ExtTraceDeal.of("id2", ZonedDateTime.now(clock), Category.targeting, - "Line Item id2 targeting matched imp with id imp1"), - ExtTraceDeal.of("id2", ZonedDateTime.now(clock), Category.pacing, - "Matched Line Item id2 for bidder appnexus ready to serve. relPriority null")); - } - - @Test - public void findMatchingLineItemsShouldFilterNullTargeting() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - given(targetingService.parseTargetingDefinition(any(), eq("id1"))) - .willReturn(null); - given(targetingService.parseTargetingDefinition(any(), eq("id2"))) - .willReturn(TargetingDefinition.of(context -> true)); - given(targetingService.matchesTargeting(any(), any(), any(), any())) - .willAnswer(withEvaluatedTargeting()); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).isEmpty(); - - assertThat(auctionContext.getDeepDebugLog().entries()).containsOnly( - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.targeting, - "Line Item id1 targeting was not defined or has incorrect format")); - } - - @Test - public void findMatchingLineItemsShouldFilterNotReadyLineItems() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusMinutes(1), - now.plusDays(1), singleton(Token.of(1, 1))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - lineItemService.getLineItemById("id1").incSpentToken(now.plusSeconds(1)); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldFilterLineItemsWithFcapIdsWhenUserDetailsFcapIsNull() { - // given - final AuctionContext auctionContext = givenAuctionContext(null); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .frequencyCaps(singletonList(FrequencyCap.builder().fcapId("123").build())) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).isEmpty(); - } - - @Test - public void findMatchingLineItemsShouldFilterFcappedLineItems() { - // given - final AuctionContext auctionContext = givenAuctionContext(asList("fcap2", "fcap3")); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .frequencyCaps(singletonList(FrequencyCap.builder().fcapId("fcap2").build())) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).isEmpty(); - assertThat(auctionContext.getTxnLog().lineItemsMatchedTargetingFcapped()).containsOnly("id1"); - assertThat(auctionContext.getDeepDebugLog().entries()).contains( - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.pacing, - "Matched Line Item id1 for bidder rubicon is frequency capped by fcap id fcap2.")); - } - - @Test - public void findMatchingLineItemsShouldFilterSameSentToBidderAsTopMatchLineItemsPerBidder() { - // given - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemsSentToBidderAsTopMatch().put("rubicon", new HashSet<>(singleton("id1"))); - final AuctionContext auctionContext = givenAuctionContext(emptyList()).toBuilder().txnLog(txnLog).build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("rubicon") - .accountId("accountId") - .relativePriority(2) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - } - - @Test - public void findMatchingLineItemsShouldFilterSameSentToBidderAsTopMatchLineItemsPerAllBidders() { - // given - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemsSentToBidderAsTopMatch().put("appnexus", new HashSet<>(singleton("id1"))); - final AuctionContext auctionContext = givenAuctionContext(emptyList()).toBuilder().txnLog(txnLog).build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("appnexus") - .accountId("accountId") - .relativePriority(1) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("rubicon") - .accountId("accountId") - .relativePriority(2) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - } - - @Test - public void findMatchingLineItemsShouldFilterLineItemsWithSameDealAndLowestPriorityTokenClassWithinBidder() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(3, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - } - - @Test - public void findMatchingLineItemsShouldFilterLineItemsWithSameDealIdAndLowestLineItemPriority() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(3) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - } - - @Test - public void findMatchingLineItemsShouldFilterLineItemsWithSameDealIdAndLowestCpm() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - } - - @Test - public void findMatchingLineItemsShouldFilterLineItemsWithoutUnspentTokensAndIncrementDeferred() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 0))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(auctionContext.getTxnLog().lineItemsPacingDeferred()).contains("id1"); - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2"); - assertThat(auctionContext.getDeepDebugLog().entries()).contains( - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.pacing, - "Matched Line Item id1 for bidder rubicon does not have unspent tokens to be served")); - } - - @Test - public void findMatchingLineItemsShouldLimitLineItemsPerBidder() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id3") - .status("active") - .dealId("3") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id2", "id3"); - } - - @Test - public void findMatchingLineItemsShouldReturnLineItemWithReadyToServeEqualToNow() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - givenClock(now, now.plusSeconds((now.plusMinutes(5).toEpochSecond() - now.toEpochSecond()) / 100)); - - final List planResponse = singletonList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("futurePlanId", now.minusMinutes(1), - now.plusMinutes(5), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsOnly("id1"); - } - - @Test - public void findMatchingLineItemsShouldRecordLineItemsInTxnLog() { - // given - final AuctionContext auctionContext = givenAuctionContext(asList("fcap2", "fcap3")); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .frequencyCaps(singletonList(FrequencyCap.builder().fcapId("fcap3").build())) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id3") - .status("active") - .dealId("3") - .source("appnexus") - .accountId("accountId") - .relativePriority(2) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id4") - .status("active") - .dealId("4") - .source("appnexus") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "appnexus", bidderAliases, auctionContext); - - // then - final TxnLog expectedTxnLog = TxnLog.create(); - expectedTxnLog.lineItemsMatchedWholeTargeting().addAll(asList("id1", "id2", "id3", "id4")); - expectedTxnLog.lineItemsMatchedTargetingFcapped().add("id2"); - expectedTxnLog.lineItemsReadyToServe().addAll(asList("id1", "id3", "id4")); - expectedTxnLog.lineItemsSentToBidderAsTopMatch().put("rubicon", singleton("id1")); - expectedTxnLog.lineItemsSentToBidderAsTopMatch().put("appnexus", singleton("id4")); - expectedTxnLog.lineItemsSentToBidder().get("rubicon").add("id1"); - expectedTxnLog.lineItemsSentToBidder().get("appnexus").addAll(asList("id3", "id4")); - expectedTxnLog.lostMatchingToLineItems().put("id3", singleton("id4")); - assertThat(auctionContext.getTxnLog()).isEqualTo(expectedTxnLog); - } - - @Test - public void findMatchingLineItemsShouldRecordLineItemsInTxnLogWhenPacingDeferred() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - givenTargetingService(); - - final List planResponse = singletonList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id5") - .status("active") - .dealId("5") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(2), singleton(Token.of(1, 2))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - lineItemService.getLineItemById("id5").incSpentToken(now.plusSeconds(1)); - lineItemService.getLineItemById("id5").incSpentToken(now.plusSeconds(1)); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - final TxnLog expectedTxnLog = TxnLog.create(); - expectedTxnLog.lineItemsMatchedWholeTargeting().add("id5"); - expectedTxnLog.lineItemsPacingDeferred().add("id5"); - assertThat(auctionContext.getTxnLog()).isEqualTo(expectedTxnLog); - } - - @Test - public void findMatchingLineItemsShouldRecordLineItemsInTxnLogWhenFcapLookupFailed() { - // given - final AuctionContext auctionContext = givenAuctionContext(null); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .dealId("1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .dealId("2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .frequencyCaps(singletonList(FrequencyCap.builder().fcapId("fcap3").build())) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(auctionContext.getTxnLog().lineItemsMatchedTargetingFcapLookupFailed()).containsOnly("id2"); - assertThat(auctionContext.getDeepDebugLog().entries()).contains( - ExtTraceDeal.of("id2", ZonedDateTime.now(clock), Category.pacing, - "Failed to match fcap for Line Item id2 bidder rubicon in a reason of bad response" - + " from user data service")); - } - - @Test - public void findMatchingLineItemsShouldHasCorrectRandomDistribution() { - // given - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - lineItemService = new LineItemService( - 3, - targetingService, - conversionService, - applicationEventService, - "USD", - clock, - criteriaLogManager); - - final List planResponse = asList( - givenLineItemMetaData("id1", now, "1", - singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), now, singleton(Token.of(1, 100)))), Function.identity()), - givenLineItemMetaData("id2", now, "2", - singletonList(givenDeliverySchedule("planId2", now.minusHours(1), - now.plusMinutes(1), now, singleton(Token.of(1, 100)))), Function.identity()), - givenLineItemMetaData("id3", now, "3", - singletonList(givenDeliverySchedule("planId3", now.minusHours(1), - now.plusMinutes(1), now, singleton(Token.of(1, 100)))), Function.identity())); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final Map count = new HashMap<>(); - for (int i = 0; i < 1000; i++) { - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - final MatchLineItemsResult matchLineItemsResult = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - count.compute(matchLineItemsResult.getLineItems().get(0).getLineItemId(), - (s, integer) -> integer != null ? ++integer : 1); - } - - // then - assertThat(count.get("id1")).isBetween(290, 390); - assertThat(count.get("id2")).isBetween(290, 390); - assertThat(count.get("id3")).isBetween(290, 390); - } - - @Test - public void findMatchingLineItemsShouldAddDebugMessages() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id1") - .status("active") - .source("rubicon") - .accountId("accountId") - .relativePriority(2) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(1), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId("id2") - .status("active") - .source("appnexus") - .accountId("accountId") - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusMinutes(1), - now.plusDays(1), singleton(Token.of(1, 2))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - lineItemService.getLineItemById("id2").incSpentToken(now.plusSeconds(1)); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "appnexus", bidderAliases, auctionContext); - - // then - assertThat(auctionContext.getDeepDebugLog().entries()).containsOnly( - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.targeting, - "Line Item id1 targeting matched imp with id imp1"), - ExtTraceDeal.of("id2", ZonedDateTime.now(clock), Category.targeting, - "Line Item id2 targeting matched imp with id imp1"), - ExtTraceDeal.of("id1", ZonedDateTime.now(clock), Category.pacing, - "Matched Line Item id1 for bidder rubicon ready to serve. relPriority 2"), - ExtTraceDeal.of("id2", ZonedDateTime.now(clock), Category.pacing, - "Matched Line Item id2 for bidder appnexus not ready to serve. Will be ready" - + " at 2019-07-26T21:59:30.000Z, current time is 2019-07-26T10:01:00.000Z")); - } - - @Test - public void findMatchingLineItemsShouldReturnWithoutUnspentTokensOrOnCoolDownIfIgnorePacingHeaderProvided() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder() - .httpRequest(HttpRequestContext.builder() - .headers(CaseInsensitiveMultiMap.builder().add(HttpUtil.PG_IGNORE_PACING, "1").build()) - .build()) - .build(); - - givenTargetingService(); - - givenClock(now.plusMinutes(5), now); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 0))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsExactly("id2", "id1"); - } - - @Test - public void findMatchingLineItemsShouldLowerPriorityIfDeliveryPlanIsNullAndPgIgnorePacing() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder() - .httpRequest(HttpRequestContext.builder() - .headers(CaseInsensitiveMultiMap.builder().add(HttpUtil.PG_IGNORE_PACING, "1").build()) - .build()) - .build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(null) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsExactly("id1", "id2"); - } - - @Test - public void findMatchingLineItemsShouldLowerPriorityIfNoTokensUnspentAndPgIgnorePacing() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder() - .httpRequest(HttpRequestContext.builder() - .headers(CaseInsensitiveMultiMap.builder().add(HttpUtil.PG_IGNORE_PACING, "1").build()) - .build()) - .build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 0))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsExactly("id1", "id2"); - } - - @Test - public void findMatchingLineItemsShouldLowerPriorityIfRelativePriorityIsNullAndPgIgnorePacing() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder() - .httpRequest(HttpRequestContext.builder() - .headers(CaseInsensitiveMultiMap.builder().add(HttpUtil.PG_IGNORE_PACING, "1").build()) - .build()) - .build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ONE, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(null) - .price(Price.of(BigDecimal.TEN, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsExactly("id1", "id2"); - } - - @Test - public void findMatchingLineItemsShouldLowerPriorityIfCpmIsNullAndPgIgnorePacing() { - // given - final AuctionContext auctionContext = givenAuctionContext(emptyList()) - .toBuilder() - .httpRequest(HttpRequestContext.builder() - .headers(CaseInsensitiveMultiMap.builder().add(HttpUtil.PG_IGNORE_PACING, "1").build()) - .build()) - .build(); - - givenTargetingService(); - - givenClock(now, now.plusMinutes(1)); - - final List planResponse = asList( - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id1") - .status("active") - .dealId("dealId1") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(BigDecimal.ZERO, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build(), - LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(10)) - .lineItemId("id2") - .status("active") - .dealId("dealId2") - .source("rubicon") - .accountId("accountId") - .relativePriority(1) - .price(Price.of(null, "USD")) - .deliverySchedules(singletonList(givenDeliverySchedule("planId1", now.minusHours(1), - now.plusMinutes(10), singleton(Token.of(1, 100))))) - .build()); - - lineItemService.updateLineItems(planResponse, true); - - final Imp imp = Imp.builder().id("imp1").build(); - - // when - final MatchLineItemsResult result = lineItemService.findMatchingLineItems( - auctionContext.getBidRequest(), imp, "rubicon", bidderAliases, auctionContext); - - // then - assertThat(result.getLineItems()).extracting(LineItem::getLineItemId).containsExactly("id1", "id2"); - } - - private static LineItemMetaData givenLineItemMetaData( - String lineItemId, - ZonedDateTime now, - String dealId, - List deliverySchedules, - Function lineItemMetaDataCustomizer) { - return lineItemMetaDataCustomizer.apply(LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId(lineItemId) - .dealId(dealId) - .status("active") - .accountId("accountId") - .source("rubicon") - .price(Price.of(BigDecimal.ONE, "USD")) - .relativePriority(5) - .updatedTimeStamp(now) - .deliverySchedules(deliverySchedules)) - .build(); - } - - private static LineItemMetaData givenLineItemMetaData( - String lineItemId, String account, String bidderCode, List deliverySchedules, - ZonedDateTime now) { - - return LineItemMetaData.builder() - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .lineItemId(lineItemId) - .dealId("dealId") - .status("active") - .accountId(account) - .source(bidderCode) - .price(Price.of(BigDecimal.ONE, "USD")) - .relativePriority(5) - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .deliverySchedules(deliverySchedules) - .build(); - } - - private static DeliverySchedule givenDeliverySchedule(String planId, ZonedDateTime start, ZonedDateTime end, - ZonedDateTime updated, Set tokens) { - return DeliverySchedule.builder() - .planId(planId) - .startTimeStamp(start) - .endTimeStamp(end) - .updatedTimeStamp(updated) - .tokens(tokens) - .build(); - } - - private static DeliverySchedule givenDeliverySchedule(String planId, ZonedDateTime start, ZonedDateTime end, - Set tokens) { - return givenDeliverySchedule(planId, start, end, start, tokens); - } - - private void incSpentTokens(int times, String... lineItemIds) { - for (final String lineItemId : lineItemIds) { - final LineItem lineItem = lineItemService.getLineItemById(lineItemId); - IntStream.range(0, times).forEach(i -> lineItem.incSpentToken(now)); - } - } - - private AuctionContext givenAuctionContext(List fcaps) { - return AuctionContext.builder() - .httpRequest(HttpRequestContext.builder().headers(CaseInsensitiveMultiMap.empty()).build()) - .account(Account.builder().id("accountId").build()) - .deepDebugLog(DeepDebugLog.create(true, clock)) - .txnLog(TxnLog.create()) - .bidRequest(BidRequest.builder() - .user(User.builder().ext( - ExtUser.builder().fcapIds(fcaps).build()).build()) - .ext(ExtRequest.of(ExtRequestPrebid.builder() - .aliases(singletonMap("rubiAlias", "rubicon")) - .build())) - .build()) - .build(); - } - - private void givenTargetingService() { - given(targetingService.parseTargetingDefinition(any(), any())) - .willReturn(TargetingDefinition.of(context -> true)); - given(targetingService.matchesTargeting(any(), any(), any(), any())) - .willAnswer(withEvaluatedTargeting()); - } - - private Answer withEvaluatedTargeting() { - return invocation -> ((TargetingDefinition) invocation.getArgument(2)).getRootExpression().matches(null); - } - - private void givenClock(ZonedDateTime... dateTimes) { - given(clock.instant()).willReturn( - dateTimes[0].toInstant(), - Arrays.stream(dateTimes).skip(1).map(ZonedDateTime::toInstant).toArray(Instant[]::new)); - given(clock.getZone()).willReturn(dateTimes[0].getZone()); - } -} diff --git a/src/test/java/org/prebid/server/deals/PlannerServiceTest.java b/src/test/java/org/prebid/server/deals/PlannerServiceTest.java deleted file mode 100644 index 940f6c3628c..00000000000 --- a/src/test/java/org/prebid/server/deals/PlannerServiceTest.java +++ /dev/null @@ -1,351 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.BDDMockito; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.FrequencyCap; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.deals.proto.Token; -import org.prebid.server.metric.MetricName; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.List; -import java.util.concurrent.TimeoutException; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -public class PlannerServiceTest extends VertxTest { - - private static final String PLAN_ENDPOINT = "plan-endpoint"; - private static final String REGISTER_ENDPOINT = "register-endpoint"; - private static final String USERNAME = "username"; - private static final String PASSWORD = "password"; - private static final String PBS_HOST = "pbs-host"; - private static final String PBS_REGION = "pbs-region"; - private static final String PBS_VENDOR = "pbs-vendor"; - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private HttpClient httpClient; - @Mock - private LineItemService lineItemService; - @Mock - private DeliveryProgressService deliveryProgressService; - @Mock - private AlertHttpService alertHttpService; - @Mock - private Metrics metrics; - @Mock - private Clock clock; - - private PlannerService plannerService; - - private ZonedDateTime now; - - @Before - public void setUp() throws JsonProcessingException { - clock = Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC); - now = ZonedDateTime.now(clock); - - plannerService = new PlannerService( - PlannerProperties.builder() - .planEndpoint(PLAN_ENDPOINT) - .registerEndpoint(REGISTER_ENDPOINT) - .timeoutMs(100L) - .registerPeriodSeconds(60L) - .username(USERNAME) - .password(PASSWORD) - .build(), - DeploymentProperties.builder().pbsHostId(PBS_HOST).pbsRegion(PBS_REGION).pbsVendor(PBS_VENDOR).build(), - lineItemService, - deliveryProgressService, - alertHttpService, - httpClient, - metrics, - clock, - jacksonMapper); - - givenPlanHttpResponse(200, mapper.writeValueAsString( - asList(givenLineItemMetaData("lineItem1", "1001", "rubicon", now), - givenLineItemMetaData("lineItem2", "1002", "appnexus", now)))); - } - - @Test - public void updateLineItemMetaDataShouldRetryOnceWhenResponseCantBeParsed() { - // given - givenPlanHttpResponse(200, "{"); - - // when - plannerService.updateLineItemMetaData(); - - // then - verify(lineItemService, never()).updateLineItems(any(), anyBoolean()); - verify(alertHttpService).alertWithPeriod(eq("planner"), - eq("pbs-planner-client-error"), - eq(AlertPriority.MEDIUM), - eq("Failed to retrieve line items from GP. Reason: Cannot parse response: {")); - verify(metrics, times(2)).updatePlannerRequestMetric(eq(false)); - verify(httpClient, times(2)).get(anyString(), any(), anyLong()); - } - - @Test - public void updateLineItemMetaDataShouldRetryWhenHttpClientReturnsFailedFuture() { - // given - given(httpClient.get(anyString(), any(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("Timeout has been exceeded"))); - - // when - plannerService.updateLineItemMetaData(); - - // then - verify(alertHttpService).alertWithPeriod(eq("planner"), eq("pbs-planner-client-error"), - eq(AlertPriority.MEDIUM), - eq("Failed to retrieve line items from GP. Reason: Timeout has been exceeded")); - verify(httpClient, times(2)).get(anyString(), any(), anyLong()); - } - - @Test - public void updateLineItemMetaDataShouldAlertWithoutRetryWhenPlannerReturnsEmptyLineItemList() - throws JsonProcessingException { - // given - givenPlanHttpResponse(200, mapper.writeValueAsString(emptyList())); - - // when - plannerService.updateLineItemMetaData(); - - // then - verify(alertHttpService).alertWithPeriod(eq("planner"), eq("pbs-planner-empty-response-error"), - eq(AlertPriority.LOW), eq("Response without line items was received from planner")); - verify(httpClient).get(anyString(), any(), anyLong()); - verify(lineItemService).updateLineItems(eq(emptyList()), anyBoolean()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemsShouldReturnLineItemsSuccessfulInitialization() { - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - assertThat(planResponseCaptor.getValue()).isEqualTo(asList( - givenLineItemMetaData("lineItem1", "1001", "rubicon", now), - givenLineItemMetaData("lineItem2", "1002", "appnexus", now))); - verify(alertHttpService).resetAlertCount(eq("pbs-planner-empty-response-error")); - verify(metrics).updatePlannerRequestMetric(eq(true)); - verify(metrics).updateLineItemsNumberMetric(eq(2L)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.planner_request_time), anyLong()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemsShouldReturnOverwrittenMetaDataAfterSchedulerCallsRefresh() - throws JsonProcessingException { - // given - givenHttpClientReturnsResponses( - Future.succeededFuture(HttpClientResponse.of(200, null, - mapper.writeValueAsString(singletonList(LineItemMetaData.builder().lineItemId("id1") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .planId("id1") - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .tokens(singleton(Token.of(1, 300))).build())) - .accountId("1").build())))), - Future.succeededFuture(HttpClientResponse.of(200, null, - mapper.writeValueAsString(singletonList(LineItemMetaData.builder().lineItemId("id2") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .planId("id2") - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .tokens(singleton(Token.of(1, 300))).build())) - .accountId("2").build()))))); - - // when and then - plannerService.updateLineItemMetaData(); - - // fire request seconds time - plannerService.updateLineItemMetaData(); - - verify(httpClient, times(2)).get(anyString(), any(), anyLong()); - verify(lineItemService, times(2)).updateLineItems(any(), anyBoolean()); - - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, times(2)).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - - assertThat(planResponseCaptor.getAllValues().get(1)) - .isEqualTo(singletonList(LineItemMetaData.builder().lineItemId("id2") - .deliverySchedules(singletonList(DeliverySchedule.builder() - .planId("id2") - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .tokens(singleton(Token.of(1, 300))).build())) - .accountId("2").build())); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemMetaDataShouldReturnExpectedResult() { - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - - assertThat(planResponseCaptor.getValue()) - .containsOnly( - givenLineItemMetaData("lineItem1", "1001", "rubicon", now), - givenLineItemMetaData("lineItem2", "1002", "appnexus", now)); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemMetaDataShouldNotCallUpdateLineItemAfterFailedRequest() { - // given - givenPlanHttpResponse(404, null); - - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, never()).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemMetaDataShouldNotCallUpdateLineItemsWhenBodyIsNull() { - // given - givenPlanHttpResponse(200, null); - - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, never()).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemMetaDataShouldNotCallUpdateLineItemWhenBodyCantBeParsed() { - // given - givenPlanHttpResponse(200, "{"); - - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, never()).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemsShouldNotCallLineItemsUpdateAfter404Response() { - // given - givenPlanHttpResponse(404, null); - - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, never()).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - } - - @SuppressWarnings("unchecked") - @Test - public void getIdToLineItemsShouldNotCallLineItemsUpdateWhenBodyIsNull() { - // given - givenPlanHttpResponse(200, null); - - // when - plannerService.updateLineItemMetaData(); - - // then - final ArgumentCaptor> planResponseCaptor = ArgumentCaptor.forClass(List.class); - verify(lineItemService, never()).updateLineItems(planResponseCaptor.capture(), anyBoolean()); - } - - private void givenPlanHttpResponse(int statusCode, String response) { - final HttpClientResponse httpClientResponse = HttpClientResponse.of(statusCode, null, response); - given(httpClient.get(startsWith(PLAN_ENDPOINT), any(), anyLong())) - .willReturn(Future.succeededFuture(httpClientResponse)); - } - - private static LineItemMetaData givenLineItemMetaData(String lineItemId, String account, String bidderCode, - ZonedDateTime now) { - return LineItemMetaData.builder() - .lineItemId(lineItemId) - .dealId("dealId") - .accountId(account) - .source(bidderCode) - .price(Price.of(BigDecimal.ONE, "USD")) - .relativePriority(5) - .startTimeStamp(now) - .endTimeStamp(now) - .updatedTimeStamp(now) - .frequencyCaps(singletonList(FrequencyCap.builder() - .fcapId("fcap").count(6L).periods(7).periodType("day").build())) - .deliverySchedules(singletonList(DeliverySchedule.builder() - .planId("plan") - .startTimeStamp(now.minusHours(1)) - .endTimeStamp(now.plusHours(1)) - .updatedTimeStamp(now) - .tokens(singleton(Token.of(1, 300))).build())) - .targeting(mapper.createObjectNode()) - .build(); - } - - @SafeVarargs - private void givenHttpClientReturnsResponses(Future... futureHttpClientResponses) { - BDDMockito.BDDMyOngoingStubbing> stubbing = - given(httpClient.get(anyString(), any(), anyLong())); - - // setup multiple answers - for (Future futureHttpClientResponse : futureHttpClientResponses) { - stubbing = stubbing.willReturn(futureHttpClientResponse); - } - } -} diff --git a/src/test/java/org/prebid/server/deals/RegisterServiceTest.java b/src/test/java/org/prebid/server/deals/RegisterServiceTest.java deleted file mode 100644 index 1f65a78fd79..00000000000 --- a/src/test/java/org/prebid/server/deals/RegisterServiceTest.java +++ /dev/null @@ -1,269 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import io.vertx.core.MultiMap; -import io.vertx.core.Vertx; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.currency.CurrencyConversionService; -import org.prebid.server.deals.events.AdminEventService; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.deals.model.AlertPriority; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.model.ServicesCommand; -import org.prebid.server.deals.proto.CurrencyServiceState; -import org.prebid.server.deals.proto.RegisterRequest; -import org.prebid.server.deals.proto.Status; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.health.HealthMonitor; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.math.BigDecimal; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class RegisterServiceTest extends VertxTest { - - private static final String PLAN_ENDPOINT = "plan-endpoint"; - private static final String REGISTER_ENDPOINT = "register-endpoint"; - private static final String USERNAME = "username"; - private static final String PASSWORD = "password"; - private static final String PBS_HOST = "pbs-host"; - private static final String PBS_REGION = "pbs-region"; - private static final String PBS_VENDOR = "pbs-vendor"; - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private RegisterService registerService; - @Mock - private HealthMonitor healthMonitor; - @Mock - private CurrencyConversionService currencyConversionService; - @Mock - private AdminEventService adminEventService; - @Mock - private DeliveryProgressService deliveryProgressService; - @Mock - private HttpClient httpClient; - @Mock - private AlertHttpService alertHttpService; - @Mock - private Vertx vertx; - - private ZonedDateTime fixedDate; - - @Before - public void setUp() { - fixedDate = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC)); - registerService = new RegisterService( - PlannerProperties.builder() - .planEndpoint(PLAN_ENDPOINT) - .registerEndpoint(REGISTER_ENDPOINT) - .timeoutMs(100L) - .registerPeriodSeconds(60L) - .username(USERNAME) - .password(PASSWORD) - .build(), - DeploymentProperties.builder().pbsHostId(PBS_HOST).pbsRegion(PBS_REGION).pbsVendor(PBS_VENDOR).build(), - adminEventService, - deliveryProgressService, - alertHttpService, - healthMonitor, - currencyConversionService, - httpClient, - vertx, - jacksonMapper); - - givenRegisterHttpResponse(200); - } - - @Test - public void initializeShouldSetRegisterTimer() throws JsonProcessingException { - // given - given(vertx.setPeriodic(anyLong(), any())).willReturn(1L); - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(currencyConversionService.getLastUpdated()).willReturn(fixedDate); - - // when - registerService.initialize(); - - // then - verify(vertx).setPeriodic(eq(60000L), any()); - verify(vertx, never()).cancelTimer(anyLong()); - - final ArgumentCaptor registerBodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClient).post(startsWith(REGISTER_ENDPOINT), any(), registerBodyCaptor.capture(), anyLong()); - assertThat(registerBodyCaptor.getValue()).isEqualTo(mapper.writeValueAsString( - RegisterRequest.of(BigDecimal.ONE, Status.of(CurrencyServiceState.of("2019-07-26T10:00:00.000Z"), null), - PBS_HOST, PBS_REGION, PBS_VENDOR))); - } - - @Test - public void initializeShouldSetDeliveryReportToRegisterRequest() throws JsonProcessingException { - // given - given(vertx.setPeriodic(anyLong(), any())).willReturn(1L); - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(deliveryProgressService.getOverallDeliveryProgressReport()).willReturn(DeliveryProgressReport.builder() - .reportId("reportId").build()); - - // when - registerService.initialize(); - - // then - final ArgumentCaptor registerBodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpClient).post(startsWith(REGISTER_ENDPOINT), any(), registerBodyCaptor.capture(), anyLong()); - assertThat(registerBodyCaptor.getValue()).isEqualTo(mapper.writeValueAsString( - RegisterRequest.of(BigDecimal.ONE, - Status.of(null, DeliveryProgressReport.builder().reportId("reportId").build()), - PBS_HOST, PBS_REGION, PBS_VENDOR))); - } - - @Test - public void registerShouldNotCallAdminCentralWhenResponseIsEmpty() { - // given - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, MultiMap.caseInsensitiveMultiMap(), ""))); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verifyNoInteractions(adminEventService); - } - - @Test - public void registerShouldCallAdminCentralWhenResponseIsNotEmpty() throws JsonProcessingException { - // given - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, MultiMap.caseInsensitiveMultiMap(), - mapper.writeValueAsString(AdminCentralResponse.of(null, null, null, null, null, - ServicesCommand.of("stop")))))); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verify(adminEventService).publishAdminCentralEvent(any()); - } - - @Test - public void registerShouldNotCallAdminCentralWhenFutureFailed() { - // given - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.failedFuture("failed")); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verifyNoInteractions(adminEventService); - } - - @Test - public void registerShouldCallAlertServiceWhenFutureFailed() { - // given - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.failedFuture("failed")); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verify(alertHttpService).alertWithPeriod(eq("register"), eq("pbs-register-client-error"), - eq(AlertPriority.MEDIUM), - eq("Error occurred while registering with the Planner:" - + " io.vertx.core.impl.NoStackTraceThrowable: failed")); - } - - @Test - public void registerShouldCallAlertServiceResetWhenRequestWasSuccessful() { - // given - given(healthMonitor.calculateHealthIndex()).willReturn(BigDecimal.ONE); - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, MultiMap.caseInsensitiveMultiMap(), ""))); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verify(alertHttpService).resetAlertCount(eq("pbs-register-client-error")); - } - - @Test - public void registerShouldNotSendAdminEventWhenResponseStatusIsBadRequest() { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(400, null, null))); - - // when - registerService.register(MultiMap.caseInsensitiveMultiMap()); - - // then - verifyNoInteractions(adminEventService); - } - - @Test - public void registerShouldThrowPrebidExceptionWhenResponseIsInvalidJson() { - // given - given(httpClient.post(anyString(), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, "{"))); - - // when and then - assertThatThrownBy(() -> registerService.register(MultiMap.caseInsensitiveMultiMap())) - .isInstanceOf(PreBidException.class) - .hasMessage("Cannot parse register response: {"); - } - - @Test - public void suspendShouldStopRegisterTimer() { - // when - registerService.suspend(); - - // then - verify(vertx).cancelTimer(anyLong()); - } - - @Test - public void initializeShouldCallHealthMonitor() { - // when - registerService.initialize(); - - // then - verify(healthMonitor).calculateHealthIndex(); - } - - private void givenRegisterHttpResponse(int statusCode) { - final HttpClientResponse httpClientResponse = HttpClientResponse.of(statusCode, null, null); - given(httpClient.post(startsWith(REGISTER_ENDPOINT), any(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(httpClientResponse)); - } -} diff --git a/src/test/java/org/prebid/server/deals/TargetingServiceTest.java b/src/test/java/org/prebid/server/deals/TargetingServiceTest.java deleted file mode 100644 index 30274979ef8..00000000000 --- a/src/test/java/org/prebid/server/deals/TargetingServiceTest.java +++ /dev/null @@ -1,919 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.IntNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Data; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Publisher; -import com.iab.openrtb.request.Segment; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.User; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.targeting.TargetingDefinition; -import org.prebid.server.deals.targeting.interpret.And; -import org.prebid.server.deals.targeting.interpret.DomainMetricAwareExpression; -import org.prebid.server.deals.targeting.interpret.InIntegers; -import org.prebid.server.deals.targeting.interpret.InStrings; -import org.prebid.server.deals.targeting.interpret.IntersectsIntegers; -import org.prebid.server.deals.targeting.interpret.IntersectsSizes; -import org.prebid.server.deals.targeting.interpret.IntersectsStrings; -import org.prebid.server.deals.targeting.interpret.Matches; -import org.prebid.server.deals.targeting.interpret.Not; -import org.prebid.server.deals.targeting.interpret.Or; -import org.prebid.server.deals.targeting.interpret.Within; -import org.prebid.server.deals.targeting.model.GeoRegion; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; -import org.prebid.server.deals.targeting.syntax.TargetingCategory.Type; -import org.prebid.server.exception.TargetingSyntaxException; -import org.prebid.server.proto.openrtb.ext.request.ExtDevice; -import org.prebid.server.proto.openrtb.ext.request.ExtGeo; -import org.prebid.server.proto.openrtb.ext.request.ExtUser; - -import java.io.IOException; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class TargetingServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private TargetingService targetingService; - - @Before - public void setUp() { - targetingService = new TargetingService(jacksonMapper); - } - - @Test - public void parseTargetingDefinitionShouldReturnValidExpression() throws IOException { - // when - final TargetingDefinition definition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-valid-targeting-definition.json"), "lineItemId"); - - // then - assertThat(definition).isNotNull().isEqualTo(TargetingDefinition.of( - new And(asList( - new IntersectsSizes(category(Type.size), asList(Size.of(300, 250), Size.of(400, 200))), - new IntersectsStrings(category(Type.mediaType), asList("banner", "video")), - new Or(asList( - new Or(asList( - new DomainMetricAwareExpression(new Matches(category(Type.domain), - "*nba.com*"), "lineItemId"), - new DomainMetricAwareExpression(new Matches(category(Type.publisherDomain), - "*nba.com*"), "lineItemId"))), - new Or(asList( - new DomainMetricAwareExpression(new Matches(category(Type.domain), - "nba.com*"), "lineItemId"), - new DomainMetricAwareExpression(new Matches(category(Type.publisherDomain), - "nba.com*"), "lineItemId"))), - new Or(asList( - new DomainMetricAwareExpression(new InStrings(category(Type.domain), - asList("nba.com", "cnn.com")), "lineItemId"), - new DomainMetricAwareExpression(new InStrings(category(Type.publisherDomain), - asList("nba.com", "cnn.com")), "lineItemId"))) - )), - new Or(asList( - new Matches(category(Type.referrer), "*sports*"), - new Matches(category(Type.referrer), "http://nba.com/lalakers*"), - new InStrings(category(Type.referrer), - asList("http://cnn.com/culture", "http://cnn.com/weather")) - )), - new Or(asList( - new Matches(category(Type.appBundle), "*com.google.calendar*"), - new Matches(category(Type.appBundle), "com.google.calendar*"), - new InStrings(category(Type.appBundle), - asList("com.google.calendar", "com.tmz")) - )), - new Or(asList( - new Matches(category(Type.adslot), "*/home/top*"), - new Matches(category(Type.adslot), "/home/top*"), - new InStrings(category(Type.adslot), asList("/home/top", "/home/bottom")) - )), - new InStrings(category(Type.deviceGeoExt, "vendor.attribute"), - asList("device_geo_ext_value1", "device_geo_ext_value2")), - new InStrings(category(Type.deviceGeoExt, "vendor.nested.attribute"), - asList("device_geo_ext_nested_value1", "device_geo_ext_nested_value2")), - new InStrings(category(Type.deviceExt, "vendor.attribute"), - asList("device_ext_value1", "device_ext_value2")), - new InStrings(category(Type.deviceExt, "vendor.nested.attribute"), - asList("device_ext_nested_value1", "device_ext_nested_value2")), - new InIntegers(category(Type.pagePosition), asList(1, 3)), - new Within(category(Type.location), GeoRegion.of(123.456f, 789.123f, 10.0f)), - new Or(asList( - new InIntegers(category(Type.bidderParam, "siteId"), asList(123, 321)), - new IntersectsIntegers(category(Type.bidderParam, "siteId"), asList(123, 321)) - )), - new Or(asList( - new Matches(category(Type.bidderParam, "placementName"), "*somePlacement*"), - new Matches(category(Type.bidderParam, "placementName"), "somePlacement*"), - new InStrings(category(Type.bidderParam, "placementName"), - asList("somePlacement1", "somePlacement2")), - new IntersectsStrings(category(Type.bidderParam, "placementName"), - asList("somePlacement1", "somePlacement2")) - )), - new Or(asList( - new IntersectsStrings( - category(Type.userSegment, "rubicon"), asList("123", "234", "345")), - new IntersectsStrings( - category(Type.userSegment, "bluekai"), asList("123", "234", "345")) - )), - new Or(asList( - new InIntegers(category(Type.userFirstPartyData, "someId"), asList(123, 321)), - new IntersectsIntegers(category(Type.userFirstPartyData, "someId"), asList(123, 321)) - )), - new Or(asList( - new Matches(category(Type.userFirstPartyData, "sport"), "*hockey*"), - new Matches(category(Type.userFirstPartyData, "sport"), "hockey*"), - new InStrings(category(Type.userFirstPartyData, "sport"), asList("hockey", "soccer")), - new IntersectsStrings( - category(Type.userFirstPartyData, "sport"), asList("hockey", "soccer")) - )), - new Or(asList( - new InIntegers(category(Type.siteFirstPartyData, "someId"), asList(123, 321)), - new IntersectsIntegers(category(Type.siteFirstPartyData, "someId"), asList(123, 321)) - )), - new Or(asList( - new Matches(category(Type.siteFirstPartyData, "sport"), "*hockey*"), - new Matches(category(Type.siteFirstPartyData, "sport"), "hockey*"), - new InStrings(category(Type.siteFirstPartyData, "sport"), asList("hockey", "soccer")), - new IntersectsStrings( - category(Type.siteFirstPartyData, "sport"), asList("hockey", "soccer")) - )), - new InIntegers(category(Type.dow), asList(5, 6)), - new InIntegers(category(Type.hour), asList(10, 11, 12, 13, 14)) - )))); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenTopLevelFieldIsNonObject() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-non-object.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected array, got NUMBER"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenTopLevelObjectHasMultipleFields() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-multiple-fields.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected only one element in the object, got 2"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenBooleanOperatorArgumentHasMultipleFields() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-multiple-fields-boolean-args.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected only one element in the object, got 2"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenFieldIsUnknown() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-unknown-field.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected either boolean operator or targeting category, got aaa"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenAndWithNonArray() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-and-with-non-array.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected array, got OBJECT"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenNotWithNonObject() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-not-with-non-object.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected object, got ARRAY"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithNonObject() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-category-non-object.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected object, got NUMBER"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenFunctionHasMultipleFields() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-multiple-fields-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected only one element in the object, got 2"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenUnknownFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-unknown-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected matching function, got $abc"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithIncompatibleFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-category-incompatible-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected $intersects matching function, got $in"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsNonArray() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-non-array.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected array, got OBJECT"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsSizesWithNonObjects() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-sizes-non-objects.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected object, got NUMBER"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsSizesWithNonReadableSize() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-sizes-non-readable-size.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessageStartingWith("Exception occurred while parsing size: " - + "Cannot deserialize value of type `java.lang.Integer`"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsSizesWithEmptySize() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-sizes-empty-size.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Height and width in size definition could not be null or missing"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsStringsWithNonString() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-strings-non-string.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected string, got NUMBER"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenIntersectsStringsWithEmptyString() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-intersects-strings-empty.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("String value could not be empty"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenUnknownStringFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-unknown-string-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected matching function, got $abc"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithIncompatibleStringFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-category-incompatible-string-function.json"), - null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected one of $matches, $in matching functions, got $intersects"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenMatchesWithNonString() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-matches-non-string.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected string, got NUMBER"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenMatchesWithEmptyString() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-matches-empty.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("String value could not be empty"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenInIntegersWithNonInteger() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-in-integers-non-integer.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected integer, got STRING"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithIncompatibleGeoFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-category-incompatible-geo-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected $within matching function, got $intersects"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenWithinWithNonObject() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-within-non-object.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected object, got ARRAY"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenWithinWithNonReadableGeoRegion() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-within-non-readable-georegion.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessageStartingWith("Exception occurred while parsing geo region: " - + "Cannot deserialize value of type `java.lang.Float`"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenWithinWithEmptyGeoRegion() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-within-empty-georegion.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Lat, lon and radiusMiles in geo region definition could not be null or missing"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithIncompatibleSegmentFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom( - "targeting/test-invalid-targeting-definition-category-incompatible-segment-function.json"), - null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected $intersects matching function, got $in"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenUnknownTypedFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-unknown-typed-function.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected matching function, got $abc"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenCategoryWithIncompatibleTypedFunction() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-category-incompatible-typed-function.json"), - null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected one of $matches, $in, $intersects matching functions, got $within"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenTypedFunctionWithIncompatibleType() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-typed-function-incompatible-type.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected integer or string, got BOOLEAN"); - } - - @Test - public void parseTargetingDefinitionShouldFailWhenTypedFunctionWithMixedTypes() { - assertThatThrownBy(() -> targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-invalid-targeting-definition-typed-function-mixed-types.json"), null)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Expected integer, got STRING"); - } - - @Test - public void matchesTargetingShouldReturnTrue() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new And(asList( - new IntersectsSizes(category(Type.size), asList(Size.of(300, 250), Size.of(400, 200))), - new IntersectsStrings(category(Type.mediaType), asList("banner", "video")), - new DomainMetricAwareExpression( - new Matches(category(Type.domain), "*nba.com*"), "lineItemId"), - new DomainMetricAwareExpression( - new Matches(category(Type.domain), "lakers.nba.com"), "lineItemId"), - new DomainMetricAwareExpression( - new Matches(category(Type.publisherDomain), "nba.com"), "lineItemId"), - new InIntegers(category(Type.pagePosition), asList(1, 3)), - new Within(category(Type.location), GeoRegion.of(50.424744f, 30.506435f, 10.0f)), - new InIntegers(category(Type.bidderParam, "siteId"), asList(123, 321)), - new IntersectsStrings(category(Type.userSegment, "rubicon"), asList("123", "234", "345")), - new IntersectsIntegers(category(Type.userFirstPartyData, "someId"), asList(123, 321))))); - - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder() - .domain("lakers.nba.com") - .publisher(Publisher.builder().domain("nba.com").build()) - .build()) - .device(Device.builder() - .geo(Geo.builder() - .lat(50.432069f) - .lon(30.516455f) - .build()) - .build()) - .user(User.builder() - .data(asList( - Data.builder() - .id("rubicon") - .segment(asList( - Segment.builder().id("234").build(), - Segment.builder().id("567").build())) - .build(), - Data.builder() - .id("bluekai") - .segment(asList( - Segment.builder().id("789").build(), - Segment.builder().id("890").build())) - .build())) - .ext(ExtUser.builder().data(mapper.valueToTree(singletonMap("someId", asList(123, 456)))) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .pos(3) - .build()) - .ext(mapper.createObjectNode().set("bidder", mapper.valueToTree(singletonMap("siteId", 123)))) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - assertThat(txnLog.lineItemsMatchedDomainTargeting()).containsOnly("lineItemId"); - } - - @Test - public void matchesTargetingShouldReturnTrueForIntersectsStringsOnSingleString() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new IntersectsStrings(category(Type.userFirstPartyData, "segment"), asList("test", "111"))); - - final BidRequest bidRequest = BidRequest.builder() - .user(User.builder() - .ext(ExtUser.builder() - .data(mapper.createObjectNode().set("segment", TextNode.valueOf("test"))) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder().build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForIntersectsIntegersOnSingleInteger() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new IntersectsIntegers(category(Type.userFirstPartyData, "segment"), asList(123, 456))); - - final BidRequest bidRequest = BidRequest.builder() - .user(User.builder() - .ext(ExtUser.builder() - .data(mapper.createObjectNode().set("segment", IntNode.valueOf(123))) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder().build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotInIntegers() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-in-integers-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder() - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .ext(mapper.createObjectNode() - .set("prebid", mapper.createObjectNode() - .set("bidder", mapper.valueToTree( - singletonMap("rubicon", singletonMap("siteId", 123)))))) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotInStrings() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-in-strings-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder() - .domain("lakers.nba.com") - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotIntersectsInteger() throws IOException { - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-intersects-integer-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder() - .user(User.builder() - .ext(ExtUser.builder().data(mapper.valueToTree(singletonMap("someId", asList(123, 456)))) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder().build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotIntersectsSizes() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-intersects-sizes-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder().build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .build()) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotWithin() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-within-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder() - .device(Device.builder() - .geo(Geo.builder() - .lat(50.432069f) - .lon(30.516455f) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotFalseAnd() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-and-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder().build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .build()) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnTrueForNotMatches() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-matches-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder() - .domain("lakers.uefa.com") - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotTrueOr() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-not-or-definition.json"), "lineItemId"); - - final BidRequest bidRequest = BidRequest.builder().build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .build()) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnTrueForDeviceExt() throws IOException { - // given - final TargetingDefinition targetingDefinition = targetingService.parseTargetingDefinition( - jsonFrom("targeting/test-device-targeting.json"), "lineItemId"); - - final ExtGeo extGeo = ExtGeo.of(); - extGeo.addProperty("geoprovider", mapper.createObjectNode().set("country", new TextNode("us"))); - final ExtDevice extDevice = ExtDevice.empty(); - extDevice.addProperty("deviceinfoprovider", mapper.createObjectNode().set("browser", new TextNode("Chrome"))); - final BidRequest bidRequest = BidRequest.builder() - .device(Device - .builder() - .geo(Geo.builder().ext(extGeo) - .build()) - .ext(extDevice) - .build()).build(); - - final TxnLog txnLog = TxnLog.create(); - - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder().build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)).isTrue(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotInIntegers() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new InIntegers(category(Type.bidderParam, "siteId"), asList(123, 778)))); - - final BidRequest bidRequest = BidRequest.builder() - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .ext(mapper.createObjectNode().set("bidder", mapper.valueToTree(singletonMap("siteId", 123)))) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotInStrings() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new InStrings(category(Type.domain), asList("nba.com", "cnn.com")))); - - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder() - .domain("nba.com") - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotIntersectsInteger() { - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new IntersectsIntegers(category(Type.userFirstPartyData, "someId"), asList(123, 321)))); - - final BidRequest bidRequest = BidRequest.builder() - .user(User.builder() - .ext(ExtUser.builder().data(mapper.valueToTree(singletonMap("someId", asList(123, 456)))) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder().build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotIntersectsSizes() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new IntersectsSizes(category(Type.size), asList(Size.of(300, 250), Size.of(400, 200))))); - - final BidRequest bidRequest = BidRequest.builder().build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .build()) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotWithin() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new Within(category(Type.location), GeoRegion.of(50.424744f, 30.506435f, 10.0f)))); - - final BidRequest bidRequest = BidRequest.builder() - .device(Device.builder() - .geo(Geo.builder() - .lat(50.432069f) - .lon(30.516455f) - .build()) - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotTrueAnd() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new And(asList( - new IntersectsSizes(category(Type.size), asList(Size.of(300, 250), Size.of(400, 200))), - new IntersectsStrings(category(Type.mediaType), asList("banner", "video")))))); - - final BidRequest bidRequest = BidRequest.builder().build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - .banner(Banner.builder() - .format(asList( - Format.builder().w(300).h(500).build(), - Format.builder().w(300).h(250).build(), - Format.builder().w(400).h(500).build())) - .build()) - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - @Test - public void matchesTargetingShouldReturnFalseForNotMatches() { - // given - final TargetingDefinition targetingDefinition = TargetingDefinition.of( - new Not(new Matches(category(Type.domain), "*nba.com*"))); - - final BidRequest bidRequest = BidRequest.builder() - .site(Site.builder() - .domain("lakers.nba.com") - .build()) - .build(); - - final TxnLog txnLog = TxnLog.create(); - final AuctionContext auctionContext = AuctionContext.builder().txnLog(txnLog).build(); - - final Imp imp = Imp.builder() - - .build(); - - // when and then - assertThat(targetingService.matchesTargeting(bidRequest, imp, targetingDefinition, auctionContext)) - .isFalse(); - } - - private static JsonNode jsonFrom(String file) throws IOException { - return mapper.readTree(TargetingServiceTest.class.getResourceAsStream(file)); - } - - private static TargetingCategory category(Type type) { - return new TargetingCategory(type); - } - - private static TargetingCategory category(Type type, String path) { - return new TargetingCategory(type, path); - } -} diff --git a/src/test/java/org/prebid/server/deals/UserAdditionalInfoServiceTest.java b/src/test/java/org/prebid/server/deals/UserAdditionalInfoServiceTest.java deleted file mode 100644 index c11d278412f..00000000000 --- a/src/test/java/org/prebid/server/deals/UserAdditionalInfoServiceTest.java +++ /dev/null @@ -1,507 +0,0 @@ -package org.prebid.server.deals; - -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Data; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Segment; -import com.iab.openrtb.request.User; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.auction.model.TimeoutContext; -import org.prebid.server.deals.deviceinfo.DeviceInfoService; -import org.prebid.server.deals.model.DeviceInfo; -import org.prebid.server.deals.model.UserData; -import org.prebid.server.deals.model.UserDetails; -import org.prebid.server.geolocation.GeoLocationService; -import org.prebid.server.geolocation.model.GeoInfo; -import org.prebid.server.log.CriteriaLogManager; -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.ExtDeviceVendor; -import org.prebid.server.proto.openrtb.ext.request.ExtGeo; -import org.prebid.server.proto.openrtb.ext.request.ExtGeoVendor; -import org.prebid.server.proto.openrtb.ext.request.ExtUser; -import org.prebid.server.proto.openrtb.ext.request.ExtUserTime; -import org.prebid.server.settings.model.Account; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.util.ArrayList; -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static java.util.function.UnaryOperator.identity; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class UserAdditionalInfoServiceTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private LineItemService lineItemService; - - @Mock - private DeviceInfoService deviceInfoService; - - @Mock - private GeoLocationService geoLocationService; - - @Mock - private UserService userService; - - @Mock - private CriteriaLogManager criteriaLogManager; - - private UserAdditionalInfoService userAdditionalInfoService; - - private static final Clock CLOCK = Clock.fixed(Instant.parse("2019-10-10T00:01:00Z"), ZoneOffset.UTC); - - @Before - public void setUp() { - given(lineItemService.accountHasDeals(any())).willReturn(true); - - given(deviceInfoService.getDeviceInfo(any())) - .willReturn(Future.failedFuture("deviceInfoService error")); - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.failedFuture("geoLocationService error")); - given(userService.getUserDetails(any(), any())) - .willReturn(Future.failedFuture("userService error")); - - userAdditionalInfoService = new UserAdditionalInfoService( - lineItemService, - deviceInfoService, - geoLocationService, - userService, - CLOCK, - jacksonMapper, - criteriaLogManager); - } - - @Test - public void populateShouldReturnOriginalContextIfAccountHasNoDeals() { - // given - given(lineItemService.accountHasDeals(any())).willReturn(false); - - final AuctionContext auctionContext = AuctionContext.builder() - .account(givenAccount(identity())) - .bidRequest(givenBidRequest(identity())) - .build(); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result).isSameAs(auctionContext); - } - - @Test - public void populateShouldPopulateDevice() { - // given - given(deviceInfoService.getDeviceInfo(any())) - .willReturn(Future.succeededFuture(DeviceInfo.builder() - .vendor("vendor") - .deviceTypeRaw("mobile") - .os("os") - .osVersion("osVersion") - .browser("browser") - .browserVersion("browserVersion") - .language("ENG") - .carrier("AT&T") - .manufacturer("Apple") - .model("iPhone 8") - .build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder() - .ip("ip") - .ua("ua") - .ext(ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(640, 480)))) - .build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - final ExtDevice expectedExtDevice = ExtDevice.of(null, ExtDevicePrebid.of(ExtDeviceInt.of(640, 480))); - expectedExtDevice.addProperty("vendor", mapper.valueToTree(ExtDeviceVendor.builder() - .type("mobile") - .os("os") - .osver("osVersion") - .browser("browser") - .browserver("browserVersion") - .make("Apple") - .model("iPhone 8") - .language("ENG") - .carrier("AT&T") - .build())); - assertThat(result.getBidRequest().getDevice()).isEqualTo(Device.builder() - .ip("ip") - .ua("ua") - .ext(expectedExtDevice) - .build()); - } - - @Test - public void populateShouldPopulateDeviceGeo() { - // given - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.succeededFuture(GeoInfo.builder() - .vendor("vendor") - .continent("continent") - .country("country") - .region("region") - .regionCode(1) - .city("city") - .metroGoogle("metroGoogle") - .metroNielsen(516) - .zip("12345") - .connectionSpeed("broadband") - .lat(11.11F) - .lon(22.22F) - .build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder() - .geo(Geo.builder().zip("zip").build()) - .build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - final ExtGeo expectedExtGeo = ExtGeo.of(); - expectedExtGeo.addProperty("vendor", mapper.valueToTree(ExtGeoVendor.builder() - .continent("continent") - .country("country") - .region(1) - .metro(516) - .city("city") - .zip("12345") - .build())); - final ExtDevice expectedDevice = ExtDevice.of(null, null); - expectedDevice.addProperty("vendor", mapper.valueToTree(ExtDeviceVendor.builder() - .connspeed("broadband") - .build())); - assertThat(result.getBidRequest().getDevice()).isEqualTo(Device.builder() - .geo(Geo.builder() - .zip("zip") - .country("country") - .region("region") - .metro("metroGoogle") - .lat(11.11F) - .lon(22.22F) - .ext(expectedExtGeo) - .build()) - .ext(expectedDevice) - .build()); - } - - @Test - public void populateShouldPopulateUserWithUserDetails() { - // given - given(userService.getUserDetails(any(), any())) - .willReturn(Future.succeededFuture(UserDetails.of( - singletonList(UserData.of( - null, - "rubicon", - singletonList(org.prebid.server.deals.model.Segment.of("segmentId")))), - singletonList("fcapId")))); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ip("ip").ua("ua").build()) - .user(User.builder() - .consent("consent") - .build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getUser()).isEqualTo(User.builder() - .data(singletonList(Data.builder() - .id("rubicon") - .segment(singletonList(Segment.builder().id("segmentId").build())) - .build())) - .consent("consent") - .ext(ExtUser.builder() - .fcapIds(singletonList("fcapId")) - .time(ExtUserTime.of(5, 0)) - .build()) - .build()); - } - - @Test - public void populateShouldUseForGeoLocationIpV6IfIpV4IsNotDefined() { - // given - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ipv6("ipv6").build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - userAdditionalInfoService.populate(auctionContext).result(); - - // then - verify(geoLocationService).lookup(eq("ipv6"), any()); - } - - @Test - public void populateShouldPopulateUserExtWithGeoInfo() { - // given - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.succeededFuture(GeoInfo.builder() - .vendor("vendor") - .timeZone(ZoneId.of("America/Los_Angeles")) - .build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ip("ip").ua("ua").build()) - .user(User.builder().consent("consent").build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getUser()).isEqualTo(User.builder() - .consent("consent") - .ext(ExtUser.builder().time(ExtUserTime.of(4, 17)).build()) - .build()); - } - - @Test - public void populateShouldPopulateUserExtWithGeoInfoIfTimeZoneIsMissing() { - // given - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.succeededFuture(GeoInfo.builder().vendor("vendor").build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ip("ip").ua("ua").build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getUser()).isEqualTo(User.builder() - .ext(ExtUser.builder().time(ExtUserTime.of(5, 0)).build()) - .build()); - } - - @Test - public void populateShouldPopulateUserWithEmptyCappedIds() { - // given - given(userService.getUserDetails(any(), any())) - .willReturn(Future.succeededFuture(UserDetails.of(null, null))); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ip("ip").ua("ua").build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getUser()).isEqualTo(User.builder() - .ext(ExtUser.builder() - .fcapIds(emptyList()) - .time(ExtUserTime.of(5, 0)) - .build()) - .build()); - } - - @Test - public void populateShouldPopulateUserWithNullCappedIds() { - // given - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().ip("ip").ua("ua").build()) - .user(User.builder().consent("consent").build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getUser()).isEqualTo(User.builder() - .consent("consent") - .ext(ExtUser.builder().time(ExtUserTime.of(5, 0)).build()) - .build()); - } - - @Test - public void populateShouldNotPopulateDeviceGeoIfGeolocationServiceIsNotDefined() { - // given - userAdditionalInfoService = new UserAdditionalInfoService( - lineItemService, - deviceInfoService, - null, - userService, - CLOCK, - jacksonMapper, - criteriaLogManager); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().build())); - - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getBidRequest().getDevice().getGeo()).isNull(); - } - - @Test - public void populateShouldCreateExtDeviceIfDeviceInfoIsNotEmptyAndExtDidNotExistBefore() { - // given - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.succeededFuture(GeoInfo.builder().vendor("geoVendor").build())); - - given(deviceInfoService.getDeviceInfo(any())) - .willReturn(Future.succeededFuture(DeviceInfo.builder() - .vendor("deviceVendor") - .browser("browser") - .build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().build())); - - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - final ExtDevice expectedExtDevice = ExtDevice.of(null, null); - expectedExtDevice.addProperty( - "deviceVendor", mapper.valueToTree(ExtDeviceVendor.builder().browser("browser").build())); - assertThat(result.getBidRequest().getDevice().getExt()).isEqualTo(expectedExtDevice); - } - - @Test - public void populateShouldCreateExtDeviceIfGeoInfoIsNotEmptyAndExtDidNotExistBefore() { - // given - given(geoLocationService.lookup(any(), any())) - .willReturn(Future.succeededFuture(GeoInfo.builder() - .vendor("geoVendor") - .connectionSpeed("100") - .continent("continent") - .build())); - - given(deviceInfoService.getDeviceInfo(any())) - .willReturn(Future.succeededFuture(DeviceInfo.builder().vendor("deviceVendor").build())); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().build())); - - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - final ExtDevice expectedExtDevice = ExtDevice.of(null, null); - expectedExtDevice.addProperty( - "geoVendor", mapper.valueToTree(ExtDeviceVendor.builder().connspeed("100").build())); - assertThat(result.getBidRequest().getDevice().getExt()).isEqualTo(expectedExtDevice); - } - - @Test - public void populateShouldUseGeoInfoFromContext() { - // given - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().build())); - final GeoInfo geoInfo = GeoInfo.builder() - .vendor("vendor") - .city("city") - .build(); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())).toBuilder() - .geoInfo(geoInfo) - .build(); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - final ExtGeo expectedExtGeo = ExtGeo.of(); - expectedExtGeo.addProperty("vendor", mapper.valueToTree(ExtGeoVendor.builder().city("city").build())); - assertThat(result.getBidRequest().getDevice()).isEqualTo(Device.builder() - .geo(Geo.builder().ext(expectedExtGeo).build()) - .build()); - verifyNoInteractions(geoLocationService); - assertThat(result.getGeoInfo()).isSameAs(geoInfo); - } - - @Test - public void populateShouldStoreGeoInfoInContext() { - // given - final GeoInfo geoInfo = GeoInfo.builder() - .vendor("vendor") - .city("city") - .build(); - given(geoLocationService.lookup(any(), any())).willReturn(Future.succeededFuture(geoInfo)); - - final BidRequest bidRequest = givenBidRequest(builder -> builder - .imp(singletonList(Imp.builder().ext(mapper.createObjectNode()).build())) - .device(Device.builder().build())); - final AuctionContext auctionContext = givenAuctionContext(bidRequest, givenAccount(identity())); - - // when - final AuctionContext result = userAdditionalInfoService.populate(auctionContext).result(); - - // then - assertThat(result.getGeoInfo()).isSameAs(geoInfo); - } - - private static BidRequest givenBidRequest(UnaryOperator customizer) { - return customizer.apply(BidRequest.builder()).build(); - } - - private static Account givenAccount(Function customizer) { - return customizer.apply(Account.builder().id("accountId")).build(); - } - - private static AuctionContext givenAuctionContext(BidRequest bidRequest, Account account) { - return AuctionContext.builder() - .bidRequest(bidRequest) - .account(account) - .timeoutContext(TimeoutContext.of(0, null, 0)) - .debugWarnings(new ArrayList<>()) - .build(); - } -} diff --git a/src/test/java/org/prebid/server/deals/UserServiceTest.java b/src/test/java/org/prebid/server/deals/UserServiceTest.java deleted file mode 100644 index 241e00d99d4..00000000000 --- a/src/test/java/org/prebid/server/deals/UserServiceTest.java +++ /dev/null @@ -1,596 +0,0 @@ -package org.prebid.server.deals; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.cache.model.CacheHttpRequest; -import org.prebid.server.cache.model.DebugHttpCall; -import org.prebid.server.cookie.UidsCookie; -import org.prebid.server.cookie.model.UidWithExpiry; -import org.prebid.server.cookie.proto.Uids; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.model.ExtUser; -import org.prebid.server.deals.model.Segment; -import org.prebid.server.deals.model.User; -import org.prebid.server.deals.model.UserData; -import org.prebid.server.deals.model.UserDetails; -import org.prebid.server.deals.model.UserDetailsProperties; -import org.prebid.server.deals.model.UserDetailsRequest; -import org.prebid.server.deals.model.UserDetailsResponse; -import org.prebid.server.deals.model.UserId; -import org.prebid.server.deals.model.UserIdRule; -import org.prebid.server.deals.model.WinEventNotification; -import org.prebid.server.deals.proto.FrequencyCap; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.execution.Timeout; -import org.prebid.server.execution.TimeoutFactory; -import org.prebid.server.metric.MetricName; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; - -import java.io.IOException; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.TimeoutException; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class UserServiceTest extends VertxTest { - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String USER_DETAILS_ENDPOINT = "http://user-data.com"; - private static final String WIN_EVENT_ENDPOINT = "http://win-event.com"; - private static final String DATA_CENTER_REGION = "region"; - private static final long CONFIG_TIMEOUT = 300L; - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private LineItemService lineItemService; - @Mock - private HttpClient httpClient; - @Mock - private Metrics metrics; - - private List userIdRules; - private Clock clock; - - private UserService userService; - - private UidsCookie uidsCookie; - private AuctionContext auctionContext; - private Timeout timeout; - private ZonedDateTime now; - - @Before - public void setUp() { - clock = Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC); - now = ZonedDateTime.now(clock); - userIdRules = singletonList(UserIdRule.of("khaos", "uid", "rubicon")); - - userService = new UserService( - UserDetailsProperties.of(USER_DETAILS_ENDPOINT, WIN_EVENT_ENDPOINT, CONFIG_TIMEOUT, userIdRules), - DATA_CENTER_REGION, - lineItemService, - httpClient, - clock, - metrics, - jacksonMapper); - - uidsCookie = new UidsCookie(Uids.builder() - .uids(singletonMap("rubicon", new UidWithExpiry("uid", null))) - .build(), jacksonMapper); - auctionContext = AuctionContext.builder().uidsCookie(uidsCookie).debugHttpCalls(new HashMap<>()).build(); - - timeout = new TimeoutFactory(Clock.fixed(Instant.now(), ZoneId.systemDefault())).create(500L); - } - - @Test - public void getUserDetailsShouldReturnEmptyUserDetailsWhenUidsAreEmpty() { - // given - final UidsCookie uidsCookie = new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper); - final AuctionContext context = AuctionContext.builder().uidsCookie(uidsCookie) - .debugHttpCalls(new HashMap<>()).build(); - - // when - final UserDetails result = userService.getUserDetails(context, timeout).result(); - - // then - verify(metrics).updateUserDetailsRequestPreparationFailed(); - verifyNoInteractions(httpClient); - - assertEquals(UserDetails.empty(), result); - } - - @Test - public void getUserDetailsShouldReturnReturnEmptyUserDetailsWhenUidsDoesNotContainRuleLocation() { - // given - final List ruleWithMissingLocation = singletonList( - UserIdRule.of("khaos", "uid", "bad_location")); - - userService = new UserService( - UserDetailsProperties.of( - USER_DETAILS_ENDPOINT, WIN_EVENT_ENDPOINT, CONFIG_TIMEOUT, ruleWithMissingLocation), - DATA_CENTER_REGION, - lineItemService, - httpClient, - clock, - metrics, - jacksonMapper); - - // when - final UserDetails result = userService.getUserDetails(auctionContext, timeout).result(); - - // then - verify(metrics).updateUserDetailsRequestPreparationFailed(); - verifyNoInteractions(httpClient); - - assertEquals(UserDetails.empty(), result); - } - - @Test - public void getUserDetailsShouldSendPostRequestWithExpectedParameters() throws IOException { - // given - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn(Future.failedFuture("something")); - - // when - userService.getUserDetails(auctionContext, timeout); - - // then - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(httpClient).post(eq(USER_DETAILS_ENDPOINT), captor.capture(), eq(CONFIG_TIMEOUT)); - - final UserDetailsRequest capturedRequest = mapper.readValue(captor.getValue(), UserDetailsRequest.class); - - assertThat(ZonedDateTime.parse(capturedRequest.getTime())).isEqualTo(UTC_MILLIS_FORMATTER.format(now)); - assertThat(capturedRequest.getIds()).hasSize(1) - .containsOnly(UserId.of("khaos", "uid")); - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - } - - @Test - public void getUserDetailsShouldUseRemainingGlobalTimeoutIfTimeoutFromConfigurationIsGreaterThanRemaining() { - // given - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn(Future.failedFuture("something")); - - userService = new UserService( - UserDetailsProperties.of(USER_DETAILS_ENDPOINT, WIN_EVENT_ENDPOINT, 600L, userIdRules), - DATA_CENTER_REGION, - lineItemService, - httpClient, - clock, - metrics, - jacksonMapper); - - // when - userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - verify(httpClient).post(anyString(), anyString(), eq(500L)); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenResponseStatusIsNotOk() { - // given - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(400, null, null))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - verify(httpClient).post(eq(USER_DETAILS_ENDPOINT), anyString(), eq(CONFIG_TIMEOUT)); - - assertTrue(result.failed()); - assertThat(result.cause()) - .isInstanceOf(PreBidException.class) - .hasMessage("Bad response status code: 400"); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenErrorOccurs() { - // given - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("Timeout has been exceeded"))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - verify(httpClient).post(eq(USER_DETAILS_ENDPOINT), anyString(), eq(CONFIG_TIMEOUT)); - - assertTrue(result.failed()); - assertThat(result.cause()) - .isInstanceOf(TimeoutException.class) - .hasMessage("Timeout has been exceeded"); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenResponseBodyDecodingFails() { - // given - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, "invalid_body"))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - verify(httpClient).post(eq(USER_DETAILS_ENDPOINT), anyString(), eq(CONFIG_TIMEOUT)); - - assertTrue(result.failed()); - assertThat(result.cause()) - .isInstanceOf(PreBidException.class) - .hasMessage("Cannot parse response: invalid_body"); - } - - @Test - public void getUserDetailsShouldReturnExpectedResult() { - // given - final UserDetailsResponse response = UserDetailsResponse.of(User.of( - asList( - UserData.of("1", "rubicon", asList(Segment.of("2222"), Segment.of("3333"))), - UserData.of("2", "bluekai", asList(Segment.of("5555"), Segment.of("6666")))), - ExtUser.of(asList("L-1111", "O-2222")))); - - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn( - Future.succeededFuture(HttpClientResponse.of(200, null, jacksonMapper.encodeToString(response)))); - - // when - final UserDetails result = userService.getUserDetails(auctionContext, timeout).result(); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(true)); - verify(metrics).updateRequestTimeMetric(eq(MetricName.user_details_request_time), anyLong()); - verify(httpClient).post(eq(USER_DETAILS_ENDPOINT), anyString(), eq(CONFIG_TIMEOUT)); - - final UserDetails expectedDetails = UserDetails.of( - asList(UserData.of("1", "rubicon", asList(Segment.of("2222"), Segment.of("3333"))), - UserData.of("2", "bluekai", asList(Segment.of("5555"), Segment.of("6666")))), - asList("L-1111", "O-2222")); - - assertEquals(expectedDetails, result); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenUserInResponseIsNull() { - // given - final UserDetailsResponse response = UserDetailsResponse.of(null); - - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn( - Future.succeededFuture(HttpClientResponse.of(200, null, jacksonMapper.encodeToString(response)))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - assertThat(result.failed()).isTrue(); - assertThat(result.cause()).isInstanceOf(PreBidException.class) - .hasMessage("Field 'user' is missing in response: {}"); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenUserDataInResponseIsNull() { - // given - final UserDetailsResponse response = UserDetailsResponse.of(User.of( - null, ExtUser.of(asList("L-1111", "O-2222")))); - - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn( - Future.succeededFuture(HttpClientResponse.of(200, null, jacksonMapper.encodeToString(response)))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - assertThat(result.failed()).isTrue(); - assertThat(result.cause()).isInstanceOf(PreBidException.class) - .hasMessage("Field 'user.data' is missing in response: {\"user\":{\"ext\":{\"fcapIds\":[\"L-1111\"," - + "\"O-2222\"]}}}"); - } - - @Test - public void getUserDetailsShouldReturnFailedFutureWhenExtUserInResponseIsNull() { - // given - final UserDetailsResponse response = UserDetailsResponse.of(User.of( - singletonList(UserData.of("2", "bluekai", singletonList(Segment.of("6666")))), null)); - - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn( - Future.succeededFuture(HttpClientResponse.of(200, null, jacksonMapper.encodeToString(response)))); - - // when - final Future result = userService.getUserDetails(auctionContext, timeout); - - // then - verify(metrics).updateUserDetailsRequestMetric(eq(false)); - assertThat(result.failed()).isTrue(); - assertThat(result.cause()).isInstanceOf(PreBidException.class) - .hasMessage("Field 'user.ext' is missing in response: {\"user\":{\"data\":[{\"id\":\"2\",\"name\":" - + "\"bluekai\",\"segment\":[{\"id\":\"6666\"}]}]}}"); - } - - @Test - public void getUserDetailsShouldAddEmptyCachedHttpCallWhenUidsAreNotDefined() { - // given - final UidsCookie uidsCookie = new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper); - final AuctionContext context = AuctionContext.builder().uidsCookie(uidsCookie) - .debugHttpCalls(new HashMap<>()).build(); - - // when - userService.getUserDetails(context, timeout).result(); - - // then - assertThat(context.getDebugHttpCalls()).hasSize(1) - .containsEntry("userservice", singletonList(DebugHttpCall.empty())); - } - - @Test - public void getUserDetailsShouldAddEmptyCachedHttpCallWhenUserIdsAreNotDefined() { - // given - final List ruleWithMissingLocation = singletonList( - UserIdRule.of("khaos", "uid", "bad_location")); - - userService = new UserService( - UserDetailsProperties.of( - USER_DETAILS_ENDPOINT, WIN_EVENT_ENDPOINT, CONFIG_TIMEOUT, ruleWithMissingLocation), - DATA_CENTER_REGION, - lineItemService, - httpClient, - clock, - metrics, - jacksonMapper); - - // when - userService.getUserDetails(auctionContext, timeout).result(); - - // then - assertThat(auctionContext.getDebugHttpCalls()).hasSize(1) - .containsEntry("userservice", singletonList(DebugHttpCall.empty())); - } - - @Test - public void getUserDetailsShouldAddCachedHttpCallWhenThrowsPrebidException() throws JsonProcessingException { - // given - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, "invalid_body"))); - - // when - userService.getUserDetails(auctionContext, timeout); - - // then - assertThat(auctionContext.getDebugHttpCalls()).hasSize(1) - .containsEntry("userservice", singletonList(DebugHttpCall.builder() - .requestUri("http://user-data.com") - .requestBody(mapper.writeValueAsString(UserDetailsRequest.of(UTC_MILLIS_FORMATTER.format(now), - singletonList(UserId.of("khaos", "uid"))))) - .responseStatus(200) - .responseBody("invalid_body") - .responseTimeMillis(0) - .build())); - } - - @Test - public void getUserDetailsShouldAddCachedHttpCallWhenCallCompletesSuccessful() throws JsonProcessingException { - // given - final UserDetailsResponse response = UserDetailsResponse.of(User.of( - singletonList( - UserData.of("1", "rubicon", asList(Segment.of("2222"), Segment.of("3333")))), - ExtUser.of(asList("L-1111", "O-2222")))); - - given(httpClient.post(anyString(), anyString(), anyLong())).willReturn( - Future.succeededFuture(HttpClientResponse.of(200, null, jacksonMapper.encodeToString(response)))); - - // when - userService.getUserDetails(auctionContext, timeout).result(); - - CacheHttpRequest.of("http://user-data.com", - mapper.writeValueAsString(UserDetailsRequest.of(UTC_MILLIS_FORMATTER.format(now), - singletonList(UserId.of("khaos", "uid"))))); - - // then - assertThat(auctionContext.getDebugHttpCalls()).hasSize(1) - .containsEntry("userservice", singletonList(DebugHttpCall.builder() - .requestUri("http://user-data.com") - .requestBody(mapper.writeValueAsString(UserDetailsRequest.of(UTC_MILLIS_FORMATTER.format(now), - singletonList(UserId.of("khaos", "uid"))))) - .responseStatus(200) - .responseBody(mapper.writeValueAsString( - UserDetailsResponse.of(User.of(singletonList(UserData.of("1", "rubicon", - asList(Segment.of("2222"), Segment.of("3333")))), - ExtUser.of(asList("L-1111", "O-2222")))))) - .responseTimeMillis(0) - .build())); - } - - @Test - public void getUserDetailsShouldAddCachedHttpCallWhenCallFailed() throws JsonProcessingException { - // given - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(400, null, null))); - - // when - userService.getUserDetails(auctionContext, timeout); - - // then - assertThat(auctionContext.getDebugHttpCalls()).hasSize(1) - .containsEntry("userservice", singletonList(DebugHttpCall.builder() - .requestUri("http://user-data.com") - .requestBody(mapper.writeValueAsString(UserDetailsRequest.of(UTC_MILLIS_FORMATTER.format(now), - singletonList(UserId.of("khaos", "uid"))))) - .responseTimeMillis(0) - .build())); - } - - @Test - public void processWinEventShouldCallMetricsPreparationFailedMetricWhenHttpClientWhenMetaDataIsMissing() { - // given - given(lineItemService.getLineItemById(any())).willReturn( - null, - LineItem.of(LineItemMetaData.builder().build(), null, null, ZonedDateTime.now(clock))); - - // when - userService.processWinEvent("lineItem1", "bidId", uidsCookie); - - // then - verify(metrics).updateWinRequestPreparationFailed(); - verifyNoInteractions(httpClient); - } - - @Test - public void processWinEventShouldCallMetricsPreparationFailedMetricWhenHttpClientWhenUserIdsAreMissing() { - // given - final List frequencyCaps = singletonList(FrequencyCap.builder().fcapId("213").build()); - final UidsCookie emptyCookie = new UidsCookie(Uids.builder().uids(emptyMap()).build(), jacksonMapper); - - given(lineItemService.getLineItemById(any())).willReturn(LineItem.of( - LineItemMetaData.builder() - .source("rubicon") - .updatedTimeStamp(now) - .frequencyCaps(frequencyCaps) - .build(), - null, null, ZonedDateTime.now(clock))); - - // when - userService.processWinEvent("lineItem1", "bidId", emptyCookie); - - // then - verify(metrics).updateWinRequestPreparationFailed(); - verifyNoInteractions(httpClient); - } - - @Test - public void processWinEventShouldCallMetricsWinRequestWithFalseWhenStatusIsNot200() { - // given - final List frequencyCaps = singletonList(FrequencyCap.builder().fcapId("213").build()); - - given(lineItemService.getLineItemById(any())).willReturn(LineItem.of( - LineItemMetaData.builder() - .source("rubicon") - .updatedTimeStamp(now) - .frequencyCaps(frequencyCaps) - .build(), - null, null, ZonedDateTime.now(clock))); - - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(400, null, null))); - - // when - userService.processWinEvent("lineItem1", "bidId", uidsCookie); - - // then - verify(metrics).updateWinEventRequestMetric(eq(false)); - verify(metrics).updateWinRequestTime(anyLong()); - } - - @Test - public void processWinEventShouldCallMetricsWinRequestWithFalseWhenFailedFuture() { - // given - final List frequencyCaps = singletonList(FrequencyCap.builder().fcapId("213").build()); - - given(lineItemService.getLineItemById(any())).willReturn(LineItem.of( - LineItemMetaData.builder() - .source("rubicon") - .updatedTimeStamp(now) - .frequencyCaps(frequencyCaps) - .build(), - null, null, ZonedDateTime.now(clock))); - - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("timeout"))); - - // when - userService.processWinEvent("lineItem1", "bidId", uidsCookie); - - // then - verify(metrics).updateWinEventRequestMetric(eq(false)); - verify(metrics).updateWinRequestTime(anyLong()); - } - - @Test - public void processWinEventShouldCallExpectedServicesWithExpectedParameters() throws IOException { - // given - final List frequencyCaps = singletonList(FrequencyCap.builder().fcapId("213").build()); - - given(lineItemService.getLineItemById(any())).willReturn(LineItem.of( - LineItemMetaData.builder() - .source("rubicon") - .updatedTimeStamp(now) - .frequencyCaps(frequencyCaps) - .build(), - null, null, ZonedDateTime.now(clock))); - - given(httpClient.post(anyString(), anyString(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, null))); - - // when - userService.processWinEvent("lineItem1", "bidId", uidsCookie); - - // then - verify(lineItemService).getLineItemById(eq("lineItem1")); - verify(metrics).updateWinNotificationMetric(); - verify(metrics).updateWinEventRequestMetric(eq(true)); - verify(metrics).updateWinRequestTime(anyLong()); - final ArgumentCaptor captor = ArgumentCaptor.forClass(String.class); - verify(httpClient).post(eq(WIN_EVENT_ENDPOINT), captor.capture(), eq(CONFIG_TIMEOUT)); - - final WinEventNotification capturedRequest = mapper.readValue(captor.getValue(), WinEventNotification.class); - assertThat(capturedRequest.getWinEventDateTime()).isEqualTo(UTC_MILLIS_FORMATTER.format(now)); - - final WinEventNotification expectedRequestWithoutWinTime = WinEventNotification.builder() - .bidderCode("rubicon") - .bidId("bidId") - .lineItemId("lineItem1") - .region(DATA_CENTER_REGION) - .userIds(singletonList(UserId.of("khaos", "uid"))) - .lineUpdatedDateTime(now) - .frequencyCaps(frequencyCaps) - .build(); - - assertThat(capturedRequest) - .usingRecursiveComparison() - .ignoringFields("winEventDateTime") - .isEqualTo(expectedRequestWithoutWinTime); - } -} diff --git a/src/test/java/org/prebid/server/deals/events/AdminEventServiceTest.java b/src/test/java/org/prebid/server/deals/events/AdminEventServiceTest.java deleted file mode 100644 index 98ef9e34f94..00000000000 --- a/src/test/java/org/prebid/server/deals/events/AdminEventServiceTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.prebid.server.deals.events; - -import io.vertx.core.Context; -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.eventbus.EventBus; -import io.vertx.ext.unit.Async; -import io.vertx.ext.unit.TestContext; -import io.vertx.ext.unit.junit.VertxUnitRunner; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.prebid.server.deals.model.AdminCentralResponse; -import org.prebid.server.vertx.LocalMessageCodec; - -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(VertxUnitRunner.class) -public class AdminEventServiceTest { - - private Vertx vertx; - private EventBus eventBus; - - @Before - public void setUp(TestContext context) { - vertx = Vertx.vertx(); - vertx.exceptionHandler(context.exceptionHandler()); - - eventBus = vertx.eventBus(); - eventBus.registerCodec(LocalMessageCodec.create()); - } - - @After - public void tearDown(TestContext context) { - vertx.close(context.asyncAssertSuccess()); - } - - @Test - public void publishAuctionEventShouldPassEventToAllRecorders(TestContext testContext) { - // given - final Context initContext = vertx.getOrCreateContext(); - final Context publishContext = vertx.getOrCreateContext(); - - final AdminCentralResponse adminCentralResponse = AdminCentralResponse.of(null, null, null, null, null, null); - - final Handler consumeHandler = event -> { - // then - assertThat(event).isSameAs(adminCentralResponse); - assertThat(Vertx.currentContext()).isSameAs(initContext); - }; - - final AdminEventService adminEventService = new AdminEventService(eventBus); - final EventServiceInitializer eventServiceInitializer = new EventServiceInitializer( - emptyList(), singletonList(new ProcessorStub(consumeHandler)), eventBus); - - // when - final Async initAsync = testContext.async(); - initContext.runOnContext(ignored -> { - eventServiceInitializer.initialize(); - initAsync.complete(); - }); - initAsync.await(); - - publishContext.runOnContext(ignored -> adminEventService.publishAdminCentralEvent(adminCentralResponse)); - } - - private static class ProcessorStub implements AdminEventProcessor { - - private final Handler handler; - - ProcessorStub(Handler handler) { - this.handler = handler; - } - - @Override - public void processAdminCentralEvent(AdminCentralResponse adminCentralResponse) { - handler.handle(adminCentralResponse); - } - } -} diff --git a/src/test/java/org/prebid/server/deals/events/ApplicationEventServiceTest.java b/src/test/java/org/prebid/server/deals/events/ApplicationEventServiceTest.java deleted file mode 100644 index 4aeae4e52d8..00000000000 --- a/src/test/java/org/prebid/server/deals/events/ApplicationEventServiceTest.java +++ /dev/null @@ -1,156 +0,0 @@ -package org.prebid.server.deals.events; - -import io.vertx.core.Context; -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.eventbus.EventBus; -import io.vertx.ext.unit.Async; -import io.vertx.ext.unit.TestContext; -import io.vertx.ext.unit.junit.VertxUnitRunner; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.prebid.server.auction.model.AuctionContext; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.vertx.LocalMessageCodec; - -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(VertxUnitRunner.class) -public class ApplicationEventServiceTest { - - private Vertx vertx; - private EventBus eventBus; - - @Before - public void setUp(TestContext context) { - vertx = Vertx.vertx(); - vertx.exceptionHandler(context.exceptionHandler()); - - eventBus = vertx.eventBus(); - eventBus.registerCodec(LocalMessageCodec.create()); - } - - @After - public void tearDown(TestContext context) { - vertx.close(context.asyncAssertSuccess()); - } - - @Test - public void publishAuctionEventShouldPassEventToAllRecorders(TestContext testContext) { - // given - final Context initContext = vertx.getOrCreateContext(); - final Context publishContext = vertx.getOrCreateContext(); - - final AuctionContext auctionContext = AuctionContext.builder().txnLog(TxnLog.create()).build(); - - final Async async = testContext.async(2); - final Handler consumeHandler = event -> { - // then - assertThat(event).isSameAs(auctionContext); - assertThat(Vertx.currentContext()).isSameAs(initContext); - async.countDown(); - }; - - final ApplicationEventService applicationEventService = new ApplicationEventService(eventBus); - final EventServiceInitializer eventServiceInitializer = new EventServiceInitializer( - asList(new ProcessorStub(consumeHandler), new ProcessorStub(consumeHandler)), emptyList(), eventBus); - - // when - final Async initAsync = testContext.async(); - initContext.runOnContext(ignored -> { - eventServiceInitializer.initialize(); - initAsync.complete(); - }); - initAsync.await(); - - publishContext.runOnContext(ignored -> applicationEventService.publishAuctionEvent(auctionContext)); - } - - @Test - public void publishLineItemWinEventShouldPassEventToAllRecorders(TestContext testContext) { - // given - final Context initContext = vertx.getOrCreateContext(); - final Context publishContext = vertx.getOrCreateContext(); - - final String lineItemId = "lineItemId1"; - - final Async async = testContext.async(2); - final Handler consumeHandler = event -> { - // then - assertThat(event).isSameAs(lineItemId); - assertThat(Vertx.currentContext()).isSameAs(initContext); - async.countDown(); - }; - - final ApplicationEventService applicationEventService = new ApplicationEventService(eventBus); - final EventServiceInitializer eventServiceInitializer = new EventServiceInitializer( - asList(new ProcessorStub(consumeHandler), new ProcessorStub(consumeHandler)), emptyList(), eventBus); - - // when - final Async initAsync = testContext.async(); - initContext.runOnContext(ignored -> { - eventServiceInitializer.initialize(); - initAsync.complete(); - }); - initAsync.await(); - - publishContext.runOnContext(ignored -> applicationEventService.publishLineItemWinEvent(lineItemId)); - } - - @Test - public void publishDeliveryProgressUpdateEventShouldPassEventToAllRecorders(TestContext testContext) { - // given - final Context initContext = vertx.getOrCreateContext(); - final Context publishContext = vertx.getOrCreateContext(); - - final Async async = testContext.async(2); - final Handler consumeHandler = event -> { - // then - assertThat(event).isSameAs(null); - assertThat(Vertx.currentContext()).isSameAs(initContext); - async.countDown(); - }; - - final ApplicationEventService applicationEventService = new ApplicationEventService(eventBus); - final EventServiceInitializer eventServiceInitializer = new EventServiceInitializer( - asList(new ProcessorStub(consumeHandler), new ProcessorStub(consumeHandler)), emptyList(), eventBus); - - // when - final Async initAsync = testContext.async(); - initContext.runOnContext(ignored -> { - eventServiceInitializer.initialize(); - initAsync.complete(); - }); - initAsync.await(); - - publishContext.runOnContext(ignored -> applicationEventService.publishDeliveryUpdateEvent()); - } - - private static class ProcessorStub implements ApplicationEventProcessor { - - private final Handler handler; - - ProcessorStub(Handler handler) { - this.handler = handler; - } - - @Override - public void processAuctionEvent(AuctionContext auctionContext) { - handler.handle(auctionContext); - } - - @Override - public void processLineItemWinEvent(String lineItemId) { - handler.handle(lineItemId); - } - - @Override - public void processDeliveryProgressUpdateEvent() { - handler.handle(null); - } - } -} diff --git a/src/test/java/org/prebid/server/deals/lineitem/DeliveryPlanTest.java b/src/test/java/org/prebid/server/deals/lineitem/DeliveryPlanTest.java deleted file mode 100644 index 1e104f2f8f2..00000000000 --- a/src/test/java/org/prebid/server/deals/lineitem/DeliveryPlanTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import org.junit.Test; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.Token; - -import java.util.HashSet; -import java.util.Set; -import java.util.stream.IntStream; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DeliveryPlanTest { - - @Test - public void getHighestUnspentTokensClassShouldReturnHighestUnspentToken() { - // given - final Set tokens = new HashSet<>(); - tokens.add(Token.of(1, 100)); - tokens.add(Token.of(2, 100)); - tokens.add(Token.of(3, 100)); - - final DeliveryPlan plan = DeliveryPlan.of(DeliverySchedule.builder().tokens(tokens).build()); - - IntStream.range(0, 150).forEach(i -> plan.incSpentToken()); - - // when and then - assertThat(plan.getHighestUnspentTokensClass()).isEqualTo(2); - } -} diff --git a/src/test/java/org/prebid/server/deals/lineitem/DeliveryProgressTest.java b/src/test/java/org/prebid/server/deals/lineitem/DeliveryProgressTest.java deleted file mode 100644 index bc03de3aa36..00000000000 --- a/src/test/java/org/prebid/server/deals/lineitem/DeliveryProgressTest.java +++ /dev/null @@ -1,365 +0,0 @@ -package org.prebid.server.deals.lineitem; - -import org.assertj.core.groups.Tuple; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.proto.DeliverySchedule; -import org.prebid.server.deals.proto.Token; -import org.prebid.server.deals.proto.report.Event; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import static java.util.Collections.singleton; -import static java.util.Collections.singletonMap; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - -public class DeliveryProgressTest extends VertxTest { - - @Rule - public MockitoRule rule = MockitoJUnit.rule(); - - @Mock - private Clock clock; - - @Mock - private LineItemService lineItemService; - - private ZonedDateTime now; - - private DeliveryProgress deliveryProgress; - - @Before - public void setUp() { - now = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC)); - - given(clock.instant()).willReturn(now.toInstant()); - given(clock.getZone()).willReturn(ZoneOffset.UTC); - deliveryProgress = DeliveryProgress.of(now, lineItemService); - } - - @Test - public void cleanLineItemStatusesShouldRemoveOldestCachedPlans() { - // given - final TxnLog txnLog1 = TxnLog.create(); - txnLog1.lineItemSentToClientAsTopMatch().add("lineItemId1"); - - final TxnLog txnLog2 = TxnLog.create(); - txnLog2.lineItemSentToClientAsTopMatch().add("lineItemId1"); - - final TxnLog txnLog3 = TxnLog.create(); - txnLog3.lineItemSentToClientAsTopMatch().add("lineItemId1"); - - final LineItem lineItem1 = Mockito.mock(LineItem.class); - final DeliveryPlan deliveryPlan1 = Mockito.mock(DeliveryPlan.class); - final DeliveryPlan deliveryPlan2 = Mockito.mock(DeliveryPlan.class); - final DeliveryPlan deliveryPlan3 = Mockito.mock(DeliveryPlan.class); - - given(deliveryPlan1.getPlanId()).willReturn("lineItemId1Plan"); - given(deliveryPlan2.getPlanId()).willReturn("lineItemId2Plan"); - given(deliveryPlan3.getPlanId()).willReturn("lineItemId3Plan"); - - given(deliveryPlan1.withoutSpentTokens()).willReturn(deliveryPlan1); - given(deliveryPlan2.withoutSpentTokens()).willReturn(deliveryPlan2); - given(deliveryPlan3.withoutSpentTokens()).willReturn(deliveryPlan3); - - given(deliveryPlan1.getEndTimeStamp()).willReturn(now.minusMinutes(1)); - given(deliveryPlan2.getEndTimeStamp()).willReturn(now.minusMinutes(2)); - given(deliveryPlan3.getEndTimeStamp()).willReturn(now.minusMinutes(3)); - - given(lineItem1.getEndTimeStamp()).willReturn(now.minusMinutes(1)); - given(lineItem1.getActiveDeliveryPlan()).willReturn(deliveryPlan1, deliveryPlan2, deliveryPlan3); - - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(lineItem1); - - // when and then - deliveryProgress.recordTransactionLog(txnLog1, singletonMap("lineItemId1Plan", 1), "1001"); - deliveryProgress.recordTransactionLog(txnLog2, singletonMap("lineItemId2Plan", 1), "1001"); - deliveryProgress.recordTransactionLog(txnLog3, singletonMap("lineItemId3Plan", 1), "1001"); - - // check that 3 lineItemStatuses - assertThat(deliveryProgress.getLineItemStatuses().get("lineItemId1").getDeliveryPlans()) - .hasSize(3) - .extracting(DeliveryPlan::getPlanId) - .containsOnly("lineItemId1Plan", "lineItemId2Plan", "lineItemId3Plan"); - - deliveryProgress.cleanLineItemStatuses(now, 10000000L, 1); - - assertThat(deliveryProgress.getLineItemStatuses().get("lineItemId1").getDeliveryPlans()) - .hasSize(1) - .extracting(DeliveryPlan::getPlanId) - .containsOnly("lineItemId1Plan"); - } - - @Test - public void cleanLineItemStatusesShouldRemoveExpiredLineItemStatuses() { - // given - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemsSentToClient().add("lineItemId1"); - txnLog.lineItemsSentToClient().add("lineItemId2"); - final Map planIdToTokenPriority = new HashMap<>(); - planIdToTokenPriority.put("lineItemId1Plan", 1); - planIdToTokenPriority.put("lineItemId2Plan", 1); - - final LineItem lineItem1 = Mockito.mock(LineItem.class); - final LineItem lineItem2 = Mockito.mock(LineItem.class); - - given(lineItem1.getEndTimeStamp()).willReturn(now.minusHours(1)); - given(lineItem2.getEndTimeStamp()).willReturn(now.minusHours(2)); - - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(lineItem1); - given(lineItemService.getLineItemById(eq("lineItemId2"))).willReturn(lineItem2); - - // when and then - deliveryProgress.recordTransactionLog(txnLog, planIdToTokenPriority, "1001"); - - // check that 2 lineItemStatuses - assertThat(deliveryProgress.getLineItemStatuses().keySet()).hasSize(2) - .containsOnly("lineItemId1", "lineItemId2"); - - deliveryProgress.cleanLineItemStatuses(now, 6000000, 5); - - assertThat(deliveryProgress.getLineItemStatuses().keySet()).hasSize(1) - .containsOnly("lineItemId1"); - } - - @Test - public void fromAnotherCopyingPlansShouldReturnDeliveryProgressWithPlansAndStatistics() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - final TxnLog txnLog = TxnLog.create(); - txnLog.lineItemsMatchedWholeTargeting().add("lineItemId1"); - txnLog.lineItemsMatchedDomainTargeting().add("lineItemId1"); - txnLog.lineItemsReadyToServe().add("lineItemId1"); - txnLog.lineItemsMatchedTargetingFcapped().add("lineItemId1"); - txnLog.lineItemsMatchedTargetingFcapLookupFailed().add("lineItemId1"); - txnLog.lineItemsPacingDeferred().add("lineItemId1"); - txnLog.lineItemsSentToBidder().get("bidder1").add("lineItemId1"); - txnLog.lineItemsSentToBidderAsTopMatch().put("bidder1", singleton("lineItemId1")); - txnLog.lineItemsReceivedFromBidder().get("bidder1").add("lineItemId1"); - txnLog.lineItemsSentToClient().add("lineItemId1"); - txnLog.lineItemSentToClientAsTopMatch().add("lineItemId1"); - txnLog.lostAuctionToLineItems().put("lineItemId1", singleton("lineItemId2")); - txnLog.lostMatchingToLineItems().put("lineItemId1", singleton("lineItemId3")); - - final LineItem lineItem = mock(LineItem.class); - given(lineItemService.getLineItemById("lineItemId1")).willReturn(lineItem); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - - deliveryProgress.recordTransactionLog(txnLog, singletonMap("planId1", 1), "1001"); - - // when - final DeliveryProgress copiedDeliveryProgress = deliveryProgress.copyWithOriginalPlans(); - - // then - final LineItemStatus lineItemStatusCopied = copiedDeliveryProgress.getLineItemStatuses().get("lineItemId1"); - final LineItemStatus lineItemStatusOriginal = deliveryProgress.getLineItemStatuses().get("lineItemId1"); - - assertThat(lineItemStatusCopied).isNotSameAs(lineItemStatusOriginal); - - assertThat(lineItemStatusCopied.getDomainMatched().sum()) - .isEqualTo(lineItemStatusOriginal.getDomainMatched().sum()); - - assertThat(lineItemStatusCopied.getTargetMatched().sum()) - .isEqualTo(lineItemStatusOriginal.getTargetMatched().sum()); - - assertThat(lineItemStatusCopied.getTargetMatchedButFcapped().sum()) - .isEqualTo(lineItemStatusOriginal.getTargetMatchedButFcapped().sum()); - - assertThat(lineItemStatusCopied.getTargetMatchedButFcapLookupFailed().sum()) - .isEqualTo(lineItemStatusOriginal.getTargetMatchedButFcapLookupFailed().sum()); - - assertThat(lineItemStatusCopied.getPacingDeferred().sum()) - .isEqualTo(lineItemStatusOriginal.getPacingDeferred().sum()); - - assertThat(lineItemStatusCopied.getSentToBidder().sum()) - .isEqualTo(lineItemStatusOriginal.getSentToBidder().sum()); - - assertThat(lineItemStatusCopied.getSentToBidderAsTopMatch().sum()) - .isEqualTo(lineItemStatusOriginal.getSentToBidderAsTopMatch().sum()); - - assertThat(lineItemStatusCopied.getReceivedFromBidder().sum()) - .isEqualTo(lineItemStatusOriginal.getReceivedFromBidder().sum()); - - assertThat(lineItemStatusCopied.getReceivedFromBidderInvalidated().sum()) - .isEqualTo(lineItemStatusOriginal.getReceivedFromBidderInvalidated().sum()); - - assertThat(lineItemStatusCopied.getSentToClient().sum()) - .isEqualTo(lineItemStatusOriginal.getSentToClient().sum()); - - assertThat(lineItemStatusCopied.getSentToClientAsTopMatch().sum()) - .isEqualTo(lineItemStatusOriginal.getSentToClientAsTopMatch().sum()); - - assertThat(lineItemStatusCopied.getSentToClientAsTopMatch().sum()) - .isEqualTo(lineItemStatusOriginal.getSentToClientAsTopMatch().sum()); - - assertThat(copiedDeliveryProgress.getLineItemIdToLost().get("lineItemId1").entrySet()) - .extracting(Map.Entry::getKey, entry -> entry.getValue().getCount().sum()) - .containsOnly(Tuple.tuple("lineItemId2", 1L), Tuple.tuple("lineItemId3", 1L)); - - final DeliveryPlan originDeliveryPlan = lineItemStatusOriginal.getDeliveryPlans().stream().findFirst().get(); - final DeliveryPlan copiedDeliveryPlan = lineItemStatusCopied.getDeliveryPlans().stream().findFirst().get(); - assertThat(originDeliveryPlan).isSameAs(copiedDeliveryPlan); - } - - @Test - public void recordWinEventShouldRecordEventForAbsentInReportLineItemStatus() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - - // when - deliveryProgress.recordWinEvent("lineItemId1"); - - // then - final LineItemStatus lineItemStatus = deliveryProgress.getLineItemStatuses().get("lineItemId1"); - assertThat(lineItemStatus.getEvents()) - .extracting(Event::getType, event -> event.getCount().sum()) - .containsOnly(Tuple.tuple("win", 1L)); - } - - @Test - public void upsertPlanReferenceFromLineItemShouldInsertReferenceToNotExistingLineItemStatus() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - final LineItem lineItem = mock(LineItem.class); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - - // when - deliveryProgress.upsertPlanReferenceFromLineItem(lineItem); - - // then - assertThat(deliveryProgress.getLineItemStatuses()).hasSize(1); - final Set deliveryPlans = deliveryProgress.getLineItemStatuses().get("lineItemId1") - .getDeliveryPlans(); - assertThat(deliveryPlans).hasSize(1).extracting(DeliveryPlan::getDeliverySchedule) - .containsOnly(givenDeliverySchedule(now, "planId1")); - } - - @Test - public void upsertPlanReferenceFromLineItemShouldInsertToExistingWhenNotContainsPlanWithSameId() { - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - deliveryProgress.getLineItemStatuses().put("lineItemId1", LineItemStatus.of("lineItemId1")); - final LineItem lineItem = mock(LineItem.class); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - - // when - deliveryProgress.upsertPlanReferenceFromLineItem(lineItem); - - // then - assertThat(deliveryProgress.getLineItemStatuses()).hasSize(1); - final Set deliveryPlans = deliveryProgress.getLineItemStatuses().get("lineItemId1") - .getDeliveryPlans(); - assertThat(deliveryPlans).hasSize(1).extracting(DeliveryPlan::getDeliverySchedule) - .containsOnly(givenDeliverySchedule(now, "planId1")); - } - - @Test - public void upsertPlanReferenceFromLineItemShouldReplacePlanWhenContainsPlanWithSameId() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - final LineItemStatus lineItemStatus = LineItemStatus.of("lineItemId1"); - lineItemStatus.getDeliveryPlans().add(DeliveryPlan.of(givenDeliverySchedule(now.minusMinutes(1), "planId1"))); - deliveryProgress.getLineItemStatuses().put("lineItemId1", lineItemStatus); - final LineItem lineItem = mock(LineItem.class); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - - // when - deliveryProgress.upsertPlanReferenceFromLineItem(lineItem); - - // then - assertThat(deliveryProgress.getLineItemStatuses()).hasSize(1); - final Set deliveryPlans = deliveryProgress.getLineItemStatuses().get("lineItemId1") - .getDeliveryPlans(); - assertThat(deliveryPlans).hasSize(1).extracting(DeliveryPlan::getDeliverySchedule) - .containsOnly(givenDeliverySchedule(now, "planId1")); - } - - @Test - public void mergePlanFromLineItemShouldMergeCurrentPlanWithNewActiveOne() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - final LineItemStatus lineItemStatus = LineItemStatus.of("lineItemId1"); - lineItemStatus.getDeliveryPlans().add(DeliveryPlan.of(DeliverySchedule.builder().planId("planId1") - .startTimeStamp(now.minusMinutes(1)).endTimeStamp(now.plusMinutes(1)) - .updatedTimeStamp(now.minusMinutes(2)) - .tokens(singleton(Token.of(2, 50))).build())); - deliveryProgress.getLineItemStatuses().put("lineItemId1", lineItemStatus); - final LineItem lineItem = mock(LineItem.class); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - - // when - deliveryProgress.mergePlanFromLineItem(lineItem); - - // then - assertThat(deliveryProgress.getLineItemStatuses()).hasSize(1); - final Set deliveryPlans = deliveryProgress.getLineItemStatuses().get("lineItemId1") - .getDeliveryPlans(); - assertThat(deliveryPlans).hasSize(1) - .flatExtracting(DeliveryPlan::getDeliveryTokens) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, - deliveryToken -> deliveryToken.getSpent().sum()) - .containsOnly(Tuple.tuple(1, 100, 0L), Tuple.tuple(2, 50, 0L)); - - assertThat(deliveryPlans).hasSize(1) - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getUpdatedTimeStamp) - .containsOnly(Tuple.tuple("planId1", now.minusMinutes(1))); - } - - @Test - public void mergePlanFromLineItemShouldReplaceCurrentPlanWithNewActiveOneWithoutSpentTokens() { - // given - final DeliveryProgress deliveryProgress = DeliveryProgress.of(now, lineItemService); - deliveryProgress.getLineItemStatuses().put("lineItemId1", LineItemStatus.of("lineItemId1")); - final LineItem lineItem = mock(LineItem.class); - given(lineItem.getActiveDeliveryPlan()).willReturn(DeliveryPlan.of(givenDeliverySchedule(now, "planId1"))); - given(lineItem.getLineItemId()).willReturn("lineItemId1"); - - // when - deliveryProgress.mergePlanFromLineItem(lineItem); - - // then - assertThat(deliveryProgress.getLineItemStatuses()).hasSize(1); - final Set deliveryPlans = deliveryProgress.getLineItemStatuses().get("lineItemId1") - .getDeliveryPlans(); - assertThat(deliveryPlans).hasSize(1) - .flatExtracting(DeliveryPlan::getDeliveryTokens) - .extracting(DeliveryToken::getPriorityClass, DeliveryToken::getTotal, - deliveryToken -> deliveryToken.getSpent().sum()) - .containsOnly(Tuple.tuple(1, 100, 0L)); - - assertThat(deliveryPlans).hasSize(1) - .extracting(DeliveryPlan::getPlanId, DeliveryPlan::getUpdatedTimeStamp) - .containsOnly(Tuple.tuple("planId1", now.minusMinutes(1))); - } - - private static DeliverySchedule givenDeliverySchedule(ZonedDateTime now, String planId) { - return DeliverySchedule.builder() - .planId(planId) - .startTimeStamp(now.minusMinutes(1)) - .endTimeStamp(now.plusMinutes(1)) - .updatedTimeStamp(now.minusMinutes(1)) - .tokens(singleton(Token.of(1, 100))) - .build(); - } -} diff --git a/src/test/java/org/prebid/server/deals/model/DeepDebugLogTest.java b/src/test/java/org/prebid/server/deals/model/DeepDebugLogTest.java deleted file mode 100644 index 0e70f86ca56..00000000000 --- a/src/test/java/org/prebid/server/deals/model/DeepDebugLogTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.prebid.server.deals.model; - -import org.junit.Test; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal; -import org.prebid.server.proto.openrtb.ext.response.ExtTraceDeal.Category; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.function.Supplier; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class DeepDebugLogTest { - - private final Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); - - @SuppressWarnings("unchecked") - @Test - public void addShouldNotRecordMessageWhenDeepDebugIsDisabled() { - // given - final DeepDebugLog deepDebugLog = DeepDebugLog.create(false, clock); - - final Supplier messageSupplier = (Supplier) mock(Supplier.class); - - // when - deepDebugLog.add(null, Category.pacing, messageSupplier); - - // then - verify(messageSupplier, never()).get(); - - assertThat(deepDebugLog.entries()).isEmpty(); - } - - @Test - public void addShouldRecordMessageWhenDeepDebugIsEnabled() { - // given - final DeepDebugLog deepDebugLog = DeepDebugLog.create(true, clock); - - // when - deepDebugLog.add(null, Category.pacing, () -> "debug message 1"); - - // then - assertThat(deepDebugLog.entries()).containsOnly( - ExtTraceDeal.of(null, ZonedDateTime.now(clock), Category.pacing, "debug message 1")); - } -} diff --git a/src/test/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandlerTest.java b/src/test/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandlerTest.java deleted file mode 100644 index 72069ad5f88..00000000000 --- a/src/test/java/org/prebid/server/deals/simulation/DealsSimulationAdminHandlerTest.java +++ /dev/null @@ -1,227 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.exception.PreBidException; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.startsWith; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; - -public class DealsSimulationAdminHandlerTest extends VertxTest { - - @Rule - public MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private SimulationAwareRegisterService registerService; - - @Mock - private SimulationAwarePlannerService plannerService; - - @Mock - private SimulationAwareDeliveryProgressService deliveryProgressService; - - @Mock - private SimulationAwareDeliveryStatsService deliveryStatsService; - - @Mock - private SimulationAwareHttpBidderRequester httpBidderRequester; - - @Mock - private RoutingContext routingContext; - - @Mock - private HttpServerRequest request; - - @Mock - private HttpServerResponse response; - - private ZonedDateTime now; - - private DealsSimulationAdminHandler dealsSimulationAdminHandler; - - @Before - public void setUp() { - now = ZonedDateTime.now(Clock.fixed(Instant.parse("2019-10-10T00:00:00Z"), ZoneOffset.UTC)); - dealsSimulationAdminHandler = new DealsSimulationAdminHandler(registerService, - plannerService, deliveryProgressService, deliveryStatsService, httpBidderRequester, jacksonMapper, - "endpoint"); - given(routingContext.request()).willReturn(request); - given(routingContext.response()).willReturn(response); - given(request.headers()).willReturn(MultiMap.caseInsensitiveMultiMap() - .add("pg-sim-timestamp", now.toString())); - given(response.setStatusCode(anyInt())).willReturn(response); - } - - @Test - public void handleShouldCallPerformRegistrationHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/planner/register"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(registerService).performRegistration(eq(now)); - } - - @Test - public void handleShouldCallFetchLineItemHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/planner/fetchLineItems"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(plannerService).initiateLineItemsFetching(eq(now)); - } - - @Test - public void handleShouldCallAdvancePlanHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/advancePlans"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(plannerService).advancePlans(eq(now)); - } - - @Test - public void handleShouldCallReportHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/dealstats/report"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(deliveryProgressService).createDeliveryProgressReport(eq(now)); - verify(deliveryStatsService).sendDeliveryProgressReports(eq(now)); - } - - @Test - public void handleShouldCallSetBidRateHandler() throws JsonProcessingException { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/bidRate"); - given(routingContext.getBody()).willReturn(Buffer.buffer( - mapper.writeValueAsString(Collections.singletonMap("lineItemId", 1.00)))); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(httpBidderRequester).setBidRates(any()); - } - - @Test - public void handleShouldRespondWithErrorWhenBidderRequesterIsNotSet() { - // given - dealsSimulationAdminHandler = new DealsSimulationAdminHandler( - registerService, plannerService, deliveryProgressService, deliveryStatsService, null, jacksonMapper, - "endpoint"); - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/bidRate"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(400); - verify(response).end(eq("Calling /bidRate is not make sense since " - + "Prebid Server configured to use real bidder exchanges in simulation mode")); - } - - @Test - public void handleShouldRespondWithNotFoundWhenHandlerNotFound() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/invalid"); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(404); - verify(response).end(eq("Requested url /invalid was not found")); - } - - @Test - public void handleShouldRespondWithBadRequestWhenRequiredDateHeaderNotFound() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/dealstats/startreport"); - given(request.headers()).willReturn(MultiMap.caseInsensitiveMultiMap()); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(400); - verify(response).end(eq("pg-sim-timestamp with simulated current date is required for endpoints:" - + " /planner/register, /planner/fetchLineItems, /advancePlans, /dealstats/report")); - } - - @Test - public void handleShouldRespondWithBadRequestWhenBodyNotFoundForSetBidRatesHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/bidRate"); - given(routingContext.getBody()).willReturn(null); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(400); - verify(response).end(eq("Body is required for /bidRate endpoint")); - } - - @Test - public void handleShouldRespondWithBadRequestWhenBodyHasIncorrectFormatForSetBidRatesHandler() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/bidRate"); - given(routingContext.getBody()).willReturn(Buffer.buffer("{")); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(400); - verify(response).end(startsWith("Failed to parse bid rates body")); - } - - @Test - public void handleShouldRespondWithInternalServerErrorStatus() { - // given - given(request.uri()).willReturn("/pbs-admin/e2eAdmin/advancePlans"); - doThrow(new PreBidException("Error")).when(plannerService).advancePlans(any()); - - // when - dealsSimulationAdminHandler.handle(routingContext); - - // then - verify(response).setStatusCode(eq(500)); - verify(response).end(eq("Error")); - } -} diff --git a/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java b/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java deleted file mode 100644 index 3287ca2e1a1..00000000000 --- a/src/test/java/org/prebid/server/deals/simulation/SimulationAwareHttpBidderRequesterTest.java +++ /dev/null @@ -1,324 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.fasterxml.jackson.databind.node.IntNode; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; -import com.iab.openrtb.response.Bid; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.auction.BidderAliases; -import org.prebid.server.auction.model.BidRejectionTracker; -import org.prebid.server.auction.model.BidderRequest; -import org.prebid.server.bidder.BidderErrorNotifier; -import org.prebid.server.bidder.BidderRequestCompletionTrackerFactory; -import org.prebid.server.bidder.HttpBidderRequestEnricher; -import org.prebid.server.bidder.model.BidderBid; -import org.prebid.server.bidder.model.BidderError; -import org.prebid.server.bidder.model.BidderSeatBid; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.lineitem.LineItem; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.deals.proto.Price; -import org.prebid.server.exception.PreBidException; -import org.prebid.server.model.CaseInsensitiveMultiMap; -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.response.BidType; -import org.prebid.server.vertx.http.HttpClient; -import org.springframework.test.util.ReflectionTestUtils; - -import java.math.BigDecimal; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; - -public class SimulationAwareHttpBidderRequesterTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private SimulationAwareHttpBidderRequester bidderRequester; - - @Mock - private HttpClient httpClient; - @Mock - private BidderAliases bidderAliases; - @Mock - private BidRejectionTracker bidRejectionTracker; - @Mock - private BidderRequestCompletionTrackerFactory bidderRequestCompletionTrackerFactory; - @Mock - private BidderErrorNotifier bidderErrorNotifier; - @Mock - private HttpBidderRequestEnricher requestEnricher; - @Mock - private CaseInsensitiveMultiMap requestHeaders; - @Mock - private LineItemService lineItemService; - - @Before - public void setUp() { - bidderRequester = new SimulationAwareHttpBidderRequester( - httpClient, bidderRequestCompletionTrackerFactory, bidderErrorNotifier, requestEnricher, - lineItemService, jacksonMapper); - } - - @Test - public void requestBidsShouldReturnBidderSeatBidWithOneBidAndFilterOutOne() { - // given - final Map rates = new HashMap<>(); - rates.put("lineItemId1", 1.00); - rates.put("lineItemId2", 0.00); - bidderRequester.setBidRates(rates); - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(LineItem.of( - LineItemMetaData.builder().price(Price.of(BigDecimal.ONE, "USD")).build(), Price.of(BigDecimal.ONE, - "USD"), null, null)); - given(lineItemService.getLineItemById(eq("lineItemId2"))).willReturn(LineItem.of( - LineItemMetaData.builder().price(Price.of(BigDecimal.TEN, "USD")).build(), Price.of(BigDecimal.ONE, - "USD"), null, null)); - - final BidRequest bidRequest = BidRequest.builder().imp(asList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId1", null, - singletonList(Format.builder().w(100).h(100).build()), null)))) - .build())).build()).build(), - Imp.builder().id("impId2").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId2") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId2", null, - singletonList(Format.builder().w(100).h(100).build()), null)))) - .build())).build()).build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when - final Future result = bidderRequester - .requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false); - - // then - assertThat(result.succeeded()).isTrue(); - assertThat(result.result()).isEqualTo(BidderSeatBid.of(singletonList( - BidderBid.of( - Bid.builder().id("impId1-lineItemId1").impid("impId1").dealid("dealId1").price(BigDecimal.ONE) - .adm("").crid("crid").w(100).h(100) - .build(), - BidType.banner, - "USD")))); - } - - @Test - public void requestBidsShouldFilterBidderSeatBidForWhichImpPmpIsNull() { - // given - bidderRequester.setBidRates(Collections.singletonMap("lineItemId1", 1.00)); - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(LineItem.of( - LineItemMetaData.builder().price(Price.of(BigDecimal.ONE, "USD")).build(), - Price.of(BigDecimal.ONE, "USD"), null, null)); - - final BidRequest bidRequest = BidRequest.builder().imp(asList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId1", null, - singletonList(Format.builder().w(100).h(100).build()), null)))) - .build())).build()).build(), - Imp.builder().id("impId2").build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when - final Future result = bidderRequester.requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false); - - // then - assertThat(result.succeeded()).isTrue(); - assertThat(result.result()).isEqualTo(BidderSeatBid.of(singletonList( - BidderBid.of( - Bid.builder().id("impId1-lineItemId1").impid("impId1").dealid("dealId1").price(BigDecimal.ONE) - .adm("").crid("crid").w(100).h(100) - .build(), - BidType.banner, - "USD")))); - } - - @Test - public void requestBidsShouldSetSizesAsZeroIfExtDealsLinesDoesNotHaveSizes() { - // given - final Map rates = new HashMap<>(); - rates.put("lineItemId1", 1.00); - bidderRequester.setBidRates(rates); - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(LineItem.of( - LineItemMetaData.builder().price(Price.of(BigDecimal.ONE, "USD")).build(), - Price.of(BigDecimal.ONE, "USD"), null, null)); - - final BidRequest bidRequest = BidRequest.builder().imp(singletonList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId1", null, null, null)))) - .build())).build()).build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when - final Future result = bidderRequester.requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false); - - // then - assertThat(result.succeeded()).isTrue(); - assertThat(result.result()).isEqualTo(BidderSeatBid.of(singletonList( - BidderBid.of( - Bid.builder().id("impId1-lineItemId1").impid("impId1").dealid("dealId1").price(BigDecimal.ONE) - .adm("").crid("crid").w(0).h(0) - .build(), - BidType.banner, - "USD")))); - } - - @Test - public void requestBidsShouldThrowPrebidExceptionWhenExtDealsInvalidFormat() { - // given - final Map rates = new HashMap<>(); - rates.put("lineItemId1", 1.00); - bidderRequester.setBidRates(rates); - given(lineItemService.getLineItemById(eq("lineItemId1"))).willReturn(LineItem.of( - LineItemMetaData.builder().price(Price.of(BigDecimal.ONE, "USD")).build(), - Price.of(BigDecimal.ONE, "USD"), null, null)); - - final BidRequest bidRequest = BidRequest.builder().imp(singletonList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1") - .ext(mapper.createObjectNode().set("line", new IntNode(5))) - .build())).build()).build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when and then - assertThatThrownBy(() -> bidderRequester - .requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false)) - .isInstanceOf(PreBidException.class) - .hasMessageStartingWith("Error decoding bidRequest.imp.pmp.deal.ext:"); - } - - @Test - public void requestBidsShouldReturnBidderSeatBidWithoutBidderBidsAndWithError() { - // given - bidderRequester.setBidRates(Collections.singletonMap("lineItemId1", 1.00)); - - final BidRequest bidRequest = BidRequest.builder().imp(singletonList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1").build())).build()).build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when - final Future result = bidderRequester - .requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false); - - // then - assertThat(result.succeeded()).isTrue(); - assertThat(result.result()).isEqualTo(BidderSeatBid.builder() - .errors(singletonList(BidderError.failedToRequestBids( - "Matched or ready to serve line items were not found, but required in simulation mode"))) - .build()); - } - - @Test - public void requestBidsShouldThrowPrebidExceptionWhenBidRatesForLineItemWereNotFound() { - // given - bidderRequester.setBidRates(Collections.singletonMap("lineItemId1", 1.00)); - - final BidRequest bidRequest = BidRequest.builder().imp(singletonList( - Imp.builder().id("impId1").pmp(Pmp.builder().deals(singletonList(Deal.builder() - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId2", null, null, null)))) - .build())).build()).build())) - .build(); - final BidderRequest bidderRequest = BidderRequest.builder().bidder("bidder").bidRequest(bidRequest).build(); - - // when - assertThatThrownBy(() -> bidderRequester - .requestBids( - null, - bidderRequest, - bidRejectionTracker, - null, - requestHeaders, - bidderAliases, - false)) - .isInstanceOf(PreBidException.class) - .hasMessage("Bid rate for line item with id lineItemId2 was not found"); - } - - @Test - public void setBidRatesShouldMergeRates() { - // given - final Map initialBidRates = new HashMap<>(); - initialBidRates.put("lineItemId1", 1.00); - initialBidRates.put("lineItemId2", 0.5); - bidderRequester.setBidRates(initialBidRates); - - final Map updateBidRates = new HashMap<>(); - updateBidRates.put("lineItemId1", 0.00); - updateBidRates.put("lineItemId3", 0.75); - - // when - bidderRequester.setBidRates(updateBidRates); - - // then - @SuppressWarnings("unchecked") final Map resultBidRates = - (Map) ReflectionTestUtils.getField(bidderRequester, "bidRates"); - - assertThat(resultBidRates).isNotNull(); - assertThat(resultBidRates.entrySet()).hasSize(3) - .extracting(Map.Entry::getKey, Map.Entry::getValue) - .containsOnly(tuple("lineItemId1", 0.00), tuple("lineItemId2", 0.5), tuple("lineItemId3", 0.75)); - } -} diff --git a/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java b/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java deleted file mode 100644 index 0774f31314d..00000000000 --- a/src/test/java/org/prebid/server/deals/simulation/SimulationAwarePlannerServiceTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.prebid.server.deals.simulation; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.vertx.core.Future; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.model.DeploymentProperties; -import org.prebid.server.deals.model.PlannerProperties; -import org.prebid.server.deals.proto.LineItemMetaData; -import org.prebid.server.metric.Metrics; -import org.prebid.server.vertx.http.HttpClient; -import org.prebid.server.vertx.http.model.HttpClientResponse; -import org.springframework.test.util.ReflectionTestUtils; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.TimeoutException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyList; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class SimulationAwarePlannerServiceTest extends VertxTest { - - private static final String PLAN_ENDPOINT = "plan-endpoint"; - private static final String REGISTER_ENDPOINT = "register-endpoint"; - private static final String USERNAME = "username"; - private static final String PASSWORD = "password"; - private static final String PBS_HOST = "pbs-host"; - private static final String PBS_REGION = "pbs-region"; - private static final String PBS_VENDOR = "pbs-vendor"; - - @Rule - public final MockitoRule rule = MockitoJUnit.rule(); - - @Mock - private HttpClient httpClient; - @Mock - private SimulationAwareLineItemService lineItemService; - @Mock - private DeliveryProgressService deliveryProgressService; - @Mock - private AlertHttpService alertHttpService; - @Mock - private Metrics metrics; - - private SimulationAwarePlannerService simulationAwarePlannerService; - - private ZonedDateTime now; - - @Before - public void setUp() { - final Clock clock = Clock.fixed(Instant.parse("2019-07-26T10:00:00Z"), ZoneOffset.UTC); - now = ZonedDateTime.now(clock); - - simulationAwarePlannerService = new SimulationAwarePlannerService( - PlannerProperties.builder() - .planEndpoint(PLAN_ENDPOINT) - .registerEndpoint(REGISTER_ENDPOINT) - .timeoutMs(100L) - .registerPeriodSeconds(60L) - .username(USERNAME) - .password(PASSWORD) - .build(), - DeploymentProperties.builder().pbsHostId(PBS_HOST).pbsRegion(PBS_REGION).pbsVendor(PBS_VENDOR).build(), - lineItemService, - deliveryProgressService, - alertHttpService, - httpClient, - metrics, - clock, - jacksonMapper); - } - - @Test - public void initiateLineItemFetchingShouldNotCallLineItemServiceUpdateMethod() throws JsonProcessingException { - // given - given(httpClient.get(anyString(), any(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, mapper.writeValueAsString( - Collections.singletonList(LineItemMetaData.builder().lineItemId("id").build()))))); - - // when - simulationAwarePlannerService.initiateLineItemsFetching(now); - - // then - verify(lineItemService, never()).updateLineItems(any(), anyBoolean()); - } - - @Test - public void initiateLineItemFetchingShouldNotRetryWhenCallToPlannerFailed() { - // given - given(httpClient.get(anyString(), any(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("time out"))); - - // when - simulationAwarePlannerService.initiateLineItemsFetching(now); - - // then - verify(httpClient).get(anyString(), any(), anyLong()); - } - - @Test - public void initiateLineItemFetchingShouldUpdateMetricsAndLineItemServiceWithResponsiveFlagWhenCallSuccessful() - throws JsonProcessingException { - // given - given(httpClient.get(anyString(), any(), anyLong())) - .willReturn(Future.succeededFuture(HttpClientResponse.of(200, null, mapper.writeValueAsString( - Collections.singletonList(LineItemMetaData.builder().lineItemId("id").build()))))); - - // when - simulationAwarePlannerService.initiateLineItemsFetching(now); - - // then - @SuppressWarnings("unchecked") - final List lineItemMetaData = (List) ReflectionTestUtils - .getField(simulationAwarePlannerService, "lineItemMetaData"); - assertThat(lineItemMetaData).hasSize(1) - .containsOnly(LineItemMetaData.builder().lineItemId("id").build()); - verify(metrics).updatePlannerRequestMetric(eq(true)); - verify(lineItemService).updateIsPlannerResponsive(eq(true)); - } - - @Test - public void initiateLineItemFetchingShouldUpdateMetricsAndLineItemServiceWithResponsiveFlagWhenCallFailed() { - // given - given(httpClient.get(anyString(), any(), anyLong())) - .willReturn(Future.failedFuture(new TimeoutException("time out"))); - - // when - simulationAwarePlannerService.initiateLineItemsFetching(now); - - // then - verify(metrics).updatePlannerRequestMetric(eq(false)); - verify(lineItemService).updateIsPlannerResponsive(eq(false)); - } - - @Test - public void advancePlansShouldCallUpdateLineItemsAndUpdateProgress() { - // given and when - simulationAwarePlannerService.advancePlans(now); - - // then - verify(lineItemService).updateLineItems(anyList(), anyBoolean(), eq(now)); - verify(lineItemService).advanceToNextPlan(now); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/RequestContextTest.java b/src/test/java/org/prebid/server/deals/targeting/RequestContextTest.java deleted file mode 100644 index 7d80fd036bb..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/RequestContextTest.java +++ /dev/null @@ -1,1262 +0,0 @@ -package org.prebid.server.deals.targeting; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.fasterxml.jackson.databind.node.TextNode; -import com.iab.openrtb.request.App; -import com.iab.openrtb.request.Banner; -import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Data; -import com.iab.openrtb.request.Device; -import com.iab.openrtb.request.Format; -import com.iab.openrtb.request.Geo; -import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Native; -import com.iab.openrtb.request.Publisher; -import com.iab.openrtb.request.Segment; -import com.iab.openrtb.request.Site; -import com.iab.openrtb.request.User; -import com.iab.openrtb.request.Video; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.model.TxnLog; -import org.prebid.server.deals.targeting.model.GeoLocation; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; -import org.prebid.server.exception.TargetingSyntaxException; -import org.prebid.server.proto.openrtb.ext.request.ExtApp; -import org.prebid.server.proto.openrtb.ext.request.ExtDevice; -import org.prebid.server.proto.openrtb.ext.request.ExtGeo; -import org.prebid.server.proto.openrtb.ext.request.ExtSite; -import org.prebid.server.proto.openrtb.ext.request.ExtUser; -import org.prebid.server.proto.openrtb.ext.request.ExtUserTime; - -import java.util.function.Function; - -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static java.util.function.Function.identity; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class RequestContextTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private TxnLog txnLog; - - @Before - public void setUp() { - txnLog = TxnLog.create(); - } - - @Test - public void lookupStringShouldReturnDomainFromSite() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.domain("domain.com")))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("domain.com"); - } - - @Test - public void lookupStringShouldReturnDomainFromSitePublisher() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s - .publisher(Publisher.builder().domain("domain.com").build())))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("domain.com"); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenDomainIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(r -> r.site(site(identity()))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultForDomainWhenSiteIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnPublisherDomainFromSitePublisher() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.publisherDomain); - final RequestContext context = - new RequestContext( - request(r -> r.site(site(s -> s - .publisher(Publisher.builder().domain("domain.com").build())))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("domain.com"); - } - - @Test - public void lookupStringShouldReturnEmptyResultForPublisherDomainWhenSiteIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.publisherDomain); - final RequestContext context = new RequestContext(request(identity()), imp(identity()), txnLog, jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnReferrer() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.referrer); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.page("https://domain.com/index")))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("https://domain.com/index"); - } - - @Test - public void lookupStringShouldReturnAppBundle() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.appBundle); - final RequestContext context = new RequestContext( - request(r -> r.app(app(a -> a.bundle("com.google.calendar")))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("com.google.calendar"); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenBundleIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.appBundle); - final RequestContext context = new RequestContext( - request(r -> r.app(app(identity()))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenAppIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.appBundle); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnAdslotFromTagId() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.adslot); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.tagid("/123/456")), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("/123/456"); - } - - @Test - public void lookupStringShouldReturnAdslotFromGpid() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.adslot); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(mapper.createObjectNode().set("gpid", TextNode.valueOf("/234/567")))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("/234/567"); - } - - @Test - public void lookupStringShouldReturnAdslotFromDataPbadslot() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.adslot); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(mapper.createObjectNode() - .set("data", mapper.createObjectNode().put("pbadslot", "/345/678")))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("/345/678"); - } - - @Test - public void lookupStringShouldReturnAdslotFromDataAdserverAdslot() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.adslot); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(mapper.createObjectNode() - .set("data", mapper.createObjectNode() - .set("adserver", obj("adslot", "/456/789"))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("/456/789"); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenAdslotIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.adslot); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("context", obj("data", mapper.createObjectNode())))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnCountryFromDeviceGeoExtValue() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.deviceGeoExt, - "vendor.attribute"); - final ExtGeo extGeo = ExtGeo.of(); - extGeo.addProperty("vendor", obj("attribute", "value")); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.geo(geo(g -> g.ext(extGeo)))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("value"); - } - - @Test - public void lookupStringShouldReturnRegionFromDeviceGeoExtValue() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.deviceGeoExt, - "vendor.nested.attribute"); - final ExtGeo extGeo = ExtGeo.of(); - extGeo.addProperty("vendor", obj("nested", obj("attribute", "value"))); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.geo(geo(g -> g.ext(extGeo)))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("value"); - } - - @Test - public void lookupStringShouldReturnMetroFromDeviceExtValue() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.deviceExt, - "vendor.attribute"); - final ExtDevice extDevice = ExtDevice.of(null, null); - extDevice.addProperty("vendor", obj("attribute", "value")); - - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.ext(extDevice)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("value"); - } - - @Test - public void lookupStringShouldReturnMetroFromDeviceExtNestedValue() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.deviceExt, - "vendor.nested.attribute"); - final ExtDevice extDevice = ExtDevice.of(null, null); - extDevice.addProperty("vendor", obj("nested", obj("attribute", "value"))); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.ext(extDevice)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("value"); - } - - @Test - public void lookupStringShouldReturnSimpleBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", "123")))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("123"); - } - - @Test - public void lookupStringShouldReturnNestedBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "inv.code"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("inv", obj("code", "123"))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("123"); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenBidderParamIsNotString() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("rubicon", obj("siteId", mapper.valueToTree(123))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenBidderParamIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("rubicon", "phony"))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenImpExtIsMissingForBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnSimpleUserFirstPartyDataFromObject() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "buyeruid"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.buyeruid("123")))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("123"); - } - - @Test - public void lookupStringShouldReturnSimpleUserFirstPartyDataFromExt() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "sport"); - final ExtUser extUser = ExtUser.builder().data(obj("sport", "hockey")).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupStringShouldReturnUserFirstPartyDataFromExtWhenObjectAttributeTypeIsNotString() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "yob"); - final ExtUser extUser = ExtUser.builder().data(obj("yob", "1900")).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.yob(1800).ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("1900"); - } - - @Test - public void lookupStringShouldReturnNestedUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "section.sport"); - final ExtUser extUser = ExtUser.builder().data(obj("section", obj("sport", "hockey"))).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenUserFirstPartyDataIsNotString() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "sport"); - final ExtUser extUser = ExtUser.builder().data(obj("sport", mapper.valueToTree(123))).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenUserExtIsMissingForUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(identity()))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnEmptyResultWhenUserIsMissingForUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.userFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringShouldReturnSiteFirstPartyDataFromImpExt() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.siteFirstPartyData, "section.sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("context", obj("data", obj("section", obj("sport", "hockey")))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupStringShouldReturnSiteFirstPartyDataFromSiteExt() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.siteFirstPartyData, "section.sport"); - final ExtSite extSite = ExtSite.of(null, obj("section", obj("sport", "hockey"))); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.ext(extSite)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupStringShouldReturnSiteFirstPartyDataFromAppExt() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.siteFirstPartyData, "section.sport"); - final ExtApp extApp = ExtApp.of(null, obj("section", obj("sport", "hockey"))); - final RequestContext context = new RequestContext( - request(r -> r.app(app(a -> a.ext(extApp)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupStringShouldReturnSiteFirstPartyDataFromImpExtData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(imp -> imp.ext(obj("data", obj("sport", "hockey")))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupString(category).getValues()).containsExactly("hockey"); - } - - @Test - public void lookupIntegerShouldReturnDowFromUserExt() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.dow); - final ExtUser extUser = ExtUser.builder().time(ExtUserTime.of(5, 15)).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(5); - } - - @Test - public void lookupIntegerShouldReturnHourFromExt() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.hour); - final ExtUser extUser = ExtUser.builder().time(ExtUserTime.of(5, 15)).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(15); - } - - @Test - public void lookupIntegerShouldReturnBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.valueToTree(123))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(123); - } - - @Test - public void lookupIntegerShouldReturnEmptyResultWhenBidderParamIsNotInteger() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("rubicon", obj("siteId", mapper.valueToTree(123.456d))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupIntegerShouldReturnEmptyResultWhenBidderParamIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("rubicon", "phony"))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupIntegerShouldReturnUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userFirstPartyData, "sport"); - final ExtUser extUser = ExtUser.builder().data(obj("sport", mapper.valueToTree(123))).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(123); - } - - @Test - public void lookupIntegerShouldReturnSiteFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final ExtSite extSite = ExtSite.of(null, obj("sport", mapper.valueToTree(123))); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.ext(extSite)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(123); - } - - @Test - public void lookupIntegerShouldReturnSiteFirstPartyDataFromImpExtData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(imp -> imp.ext(obj("data", obj("sport", 1)))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupInteger(category).getValues()).containsExactly(1); - } - - @Test - public void lookupStringsShouldReturnMediaTypeBannerAndVideo() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.mediaType); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.banner(banner(identity())).video(Video.builder().build())), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("banner", "video")); - } - - @Test - public void lookupStringsShouldReturnMediaTypeVideoAndNative() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.mediaType); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.video(Video.builder().build()).xNative(Native.builder().build())), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("video", "native")); - } - - @Test - public void lookupStringsShouldReturnBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.valueToTree(asList("123", "456")))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("123", "456")); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenBidderParamIsNotArray() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.createObjectNode())))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldReturnListOfSingleStringWhenBidderParamIsString() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", "value")))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(singletonList("value")); - } - - @Test - public void lookupStringsShouldReturnOnlyStringsWhenNonStringBidderParamPresent() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.valueToTree(asList("123", 456)))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(singletonList("123")); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenBidderParamIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("bidder", obj("rubicon", "phony"))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldReturnUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userFirstPartyData, "buyeruid"); - final ExtUser extUser = ExtUser.builder() - .data(obj("buyeruid", mapper.valueToTree(asList("buyeruid1", "buyeruid2")))) - .build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.buyeruid("buyeruid3").ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()) - .containsExactly(singletonList("buyeruid3"), asList("buyeruid1", "buyeruid2")); - } - - @Test - public void lookupStringsShouldReturnSiteFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final ExtSite extSite = ExtSite.of(null, obj("sport", mapper.valueToTree(asList("123", "456")))); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.ext(extSite)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("123", "456")); - } - - @Test - public void lookupStringsShouldReturnSiteFirstPartyDataFromImpExtData() { - // given - final TargetingCategory category = new TargetingCategory( - TargetingCategory.Type.siteFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(imp -> imp.ext(obj("data", obj("sport", mapper.valueToTree(asList("hockey", "football")))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("hockey", "football")); - } - - @Test - public void lookupStringsShouldReturnSegmentsWithDesiredSource() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.data(asList( - data(d -> d.id("rubicon").segment(asList(segment(s -> s.id("1")), segment(s -> s.id("2"))))), - data(d -> d.id("bluekai").segment( - asList(segment(s -> s.id("3")), segment(s -> s.id("4")))))))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(asList("1", "2")); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenDesiredSourceIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.data(singletonList( - data(d -> d.id("bluekai").segment( - asList(segment(s -> s.id("3")), segment(s -> s.id("4")))))))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldSkipSegmentsWithoutIds() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.data(singletonList( - data(d -> d.id("rubicon").segment(asList(segment(s -> s.id("1")), segment(identity()))))))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category).getValues()).containsExactly(singletonList("1")); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenSegmentsAreMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.data(singletonList(data(d -> d.id("rubicon"))))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldTolerateMissingSource() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.data(singletonList(data(identity())))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenDataIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(r -> r.user(user(identity()))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupStringsShouldReturnEmptyResultWhenUserIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userSegment, "rubicon"); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupStrings(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupIntegersShouldReturnBidderParam() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.valueToTree(asList(123, 456)))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(asList(123, 456)); - } - - @Test - public void lookupIntegersShouldReturnEmptyResultWhenBidderParamIsNotArray() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.createObjectNode())))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupIntegersShouldReturnListOfSingleIntegerWhenBidderParamIsInteger() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", 123)))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(singletonList(123)); - } - - @Test - public void lookupIntegersShouldReturnOnlyIntegersWhenNonIntegerBidderParamPresent() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", obj("siteId", mapper.valueToTree(asList(123, "456")))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(singletonList(123)); - } - - @Test - public void lookupIntegersShouldReturnEmptyResultWhenBidderParamIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.bidderParam, "rubicon.siteId"); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.ext(obj("bidder", "phony"))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupIntegersShouldReturnUserFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.userFirstPartyData, "yob"); - final ExtUser extUser = ExtUser.builder().data(obj("yob", mapper.valueToTree(asList(123, 456)))).build(); - final RequestContext context = new RequestContext( - request(r -> r.user(user(u -> u.yob(789).ext(extUser)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(singletonList(789), asList(123, 456)); - } - - @Test - public void lookupIntegersShouldReturnSiteFirstPartyData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final ExtSite extSite = ExtSite.of(null, obj("sport", mapper.valueToTree(asList(123, 456)))); - final RequestContext context = new RequestContext( - request(r -> r.site(site(s -> s.ext(extSite)))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(asList(123, 456)); - } - - @Test - public void lookupIntegersShouldReturnSiteFirstPartyDataFromImpExtData() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.siteFirstPartyData, "sport"); - final RequestContext context = new RequestContext( - request(identity()), - imp(imp -> imp.ext(obj("data", obj("sport", mapper.valueToTree(asList(1, 2)))))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupIntegers(category).getValues()).containsExactly(asList(1, 2)); - } - - @Test - public void lookupSizesShouldReturnSizes() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.size); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i - .banner(banner(b -> b.format(asList(format(300, 250), format(400, 300))))) - .video(Video.builder().w(350).h(350).build())), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupSizes(category).getValues()) - .containsExactly(asList(Size.of(300, 250), Size.of(400, 300), Size.of(350, 350))); - } - - @Test - public void lookupSizesShouldReturnEmptyResultWhenFormatIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.size); - final RequestContext context = new RequestContext( - request(identity()), - imp(i -> i.banner(banner(identity()))), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupSizes(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupSizesShouldReturnEmptyResultWhenBannerIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.size); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupSizes(category)).isEqualTo(LookupResult.empty()); - } - - @Test - public void lookupSizesShouldThrowExceptionWhenUnexpectedCategory() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThatThrownBy(() -> context.lookupSizes(category)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Unexpected category for fetching sizes for: domain"); - } - - @Test - public void lookupGeoLocationShouldReturnLocation() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.geo(geo(g -> g.lat(50f).lon(60f)))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupGeoLocation(category)).isEqualTo(GeoLocation.of(50f, 60f)); - } - - @Test - public void lookupGeoLocationShouldReturnNullWhenLonIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.geo(geo(g -> g.lat(50f)))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupGeoLocation(category)).isNull(); - } - - @Test - public void lookupGeoLocationShouldReturnNullWhenLatIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location); - final RequestContext context = new RequestContext( - request(r -> r.device(device(d -> d.geo(geo(g -> g.lon(60f)))))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupGeoLocation(category)).isNull(); - } - - @Test - public void lookupGeoLocationShouldReturnNullWhenGeoIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location); - final RequestContext context = new RequestContext( - request(r -> r.device(device(identity()))), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupGeoLocation(category)).isNull(); - } - - @Test - public void lookupGeoLocationShouldReturnNullWhenDeviceIsMissing() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.location); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThat(context.lookupGeoLocation(category)).isNull(); - } - - @Test - public void lookupGeoLocationShouldThrowExceptionWhenUnexpectedCategory() { - // given - final TargetingCategory category = new TargetingCategory(TargetingCategory.Type.domain); - final RequestContext context = new RequestContext( - request(identity()), - imp(identity()), - txnLog, - jacksonMapper); - - // when and then - assertThatThrownBy(() -> context.lookupGeoLocation(category)) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("Unexpected category for fetching geo location for: domain"); - } - - private static BidRequest request(Function customizer) { - return customizer.apply(BidRequest.builder()).build(); - } - - private static Site site(Function customizer) { - return customizer.apply(Site.builder()).build(); - } - - private static App app(Function customizer) { - return customizer.apply(App.builder()).build(); - } - - private static Device device(Function customizer) { - return customizer.apply(Device.builder()).build(); - } - - private static Geo geo(Function customizer) { - return customizer.apply(Geo.builder()).build(); - } - - private static User user(Function customizer) { - return customizer.apply(User.builder()).build(); - } - - private static Data data(Function customizer) { - return customizer.apply(Data.builder()).build(); - } - - private static Segment segment(Function customizer) { - return customizer.apply(Segment.builder()).build(); - } - - private static Imp imp(Function customizer) { - return customizer.apply(Imp.builder()).build(); - } - - private static Banner banner(Function customizer) { - return customizer.apply(Banner.builder()).build(); - } - - private static Format format(int w, int h) { - return Format.builder().w(w).h(h).build(); - } - - private static ObjectNode obj(String field, String value) { - return mapper.createObjectNode().put(field, value); - } - - private static ObjectNode obj(String field, Integer value) { - return mapper.createObjectNode().put(field, value); - } - - private static ObjectNode obj(String field, JsonNode value) { - return mapper.createObjectNode().set(field, value); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/AndTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/AndTest.java deleted file mode 100644 index 0cb4b0d02cd..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/AndTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -public class AndTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private TerminalExpression trueExpression; - @Mock - private TerminalExpression falseExpression; - @Mock - private RequestContext context; - - @Before - public void setUp() { - given(trueExpression.matches(any())).willReturn(true); - given(falseExpression.matches(any())).willReturn(false); - } - - @Test - public void matchesShouldReturnTrue() { - assertThat(new And(asList(trueExpression, trueExpression, trueExpression)).matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalse() { - assertThat(new And(asList(falseExpression, falseExpression, falseExpression)).matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseAndNotEvaluateRemainingExpressions() { - assertThat(new And(asList(trueExpression, falseExpression, trueExpression)).matches(context)).isFalse(); - - verify(trueExpression).matches(context); - verify(falseExpression).matches(context); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/InIntegersTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/InIntegersTest.java deleted file mode 100644 index 805060bd30d..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/InIntegersTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class InIntegersTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = new TargetingCategory(TargetingCategory.Type.pagePosition); - expression = new InIntegers(category, asList(1, 2, 3)); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(LookupResult.ofValue(2)).given(context).lookupInteger(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupInteger(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(LookupResult.ofValue(4)).given(context).lookupInteger(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(LookupResult.empty()).given(context).lookupInteger(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/InStringsTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/InStringsTest.java deleted file mode 100644 index abad9a83326..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/InStringsTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class InStringsTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = new TargetingCategory(TargetingCategory.Type.referrer); - expression = new InStrings(category, asList("Munich", "Berlin", "Stuttgart", "123")); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(LookupResult.ofValue("Berlin")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupString(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(LookupResult.ofValue("Ingolstadt")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldPerformCaseInsensitiveComparison() { - // given - willReturn(LookupResult.ofValue("BERLIN")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(LookupResult.empty()).given(context).lookupString(any()); - willReturn(LookupResult.empty()).given(context).lookupInteger(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnTrueWhenActualValueIsInteger() { - // given - willReturn(LookupResult.empty()).given(context).lookupString(any()); - willReturn(LookupResult.ofValue(123)).given(context).lookupInteger(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegersTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegersTest.java deleted file mode 100644 index 56ec56d1de2..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsIntegersTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class IntersectsIntegersTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = TargetingCategory.fromString("bidp.rubicon.invCodes"); - expression = new IntersectsIntegers(category, asList(1, 2, 3)); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(LookupResult.ofValue(asList(2, 3, 4))).given(context).lookupIntegers(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupIntegers(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(LookupResult.ofValue(asList(4, 5))).given(context).lookupIntegers(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(LookupResult.empty()).given(context).lookupIntegers(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsNotDefined() { - // given - willReturn(LookupResult.empty()).given(context).lookupIntegers(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsSizesTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsSizesTest.java deleted file mode 100644 index 236c8a9f3eb..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsSizesTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.model.Size; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class IntersectsSizesTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = TargetingCategory.fromString("adunit.size"); - expression = new IntersectsSizes(category, asList(Size.of(250, 300), Size.of(300, 350), Size.of(350, 400))); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(LookupResult.ofValue(asList(Size.of(300, 350), Size.of(350, 400), Size.of(450, 500)))) - .given(context).lookupSizes(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupSizes(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(LookupResult.ofValue(asList(Size.of(450, 500), Size.of(500, 550)))) - .given(context).lookupSizes(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(LookupResult.empty()).given(context).lookupSizes(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsNotDefined() { - // given - willReturn(LookupResult.empty()).given(context).lookupSizes(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsStringsTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsStringsTest.java deleted file mode 100644 index d41ddd4db9d..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/IntersectsStringsTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class IntersectsStringsTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = TargetingCategory.fromString("adunit.mediatype"); - expression = new IntersectsStrings(category, asList("Pop", "Rock", "Alternative")); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(LookupResult.ofValue(asList("Rock", "Alternative", "Folk"))).given(context).lookupStrings(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupStrings(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(LookupResult.ofValue(asList("Folk", "Trance"))).given(context).lookupStrings(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldPerformCaseInsensitiveComparison() { - // given - willReturn(LookupResult.ofValue(asList("ROCK", "ALTERNATIVE", "FOLK"))).given(context).lookupStrings(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(LookupResult.empty()).given(context).lookupStrings(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsNotDefined() { - // given - willReturn(LookupResult.empty()).given(context).lookupStrings(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/MatchesTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/MatchesTest.java deleted file mode 100644 index c4fbab9a98b..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/MatchesTest.java +++ /dev/null @@ -1,168 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.LookupResult; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class MatchesTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = TargetingCategory.fromString("adunit.adslot"); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForEquals() { - // given - expression = new Matches(category, "adunit"); - - willReturn(LookupResult.ofValue("adunit")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupString(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatchForEquals() { - // given - expression = new Matches(category, "adunit"); - - willReturn(LookupResult.ofValue("notadunit")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForStartsWith() { - // given - expression = new Matches(category, "adunit*"); - - willReturn(LookupResult.ofValue("adunitOne")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatchForStartsWith() { - // given - expression = new Matches(category, "adunit"); - - willReturn(LookupResult.ofValue("somedunit")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForEndsWith() { - // given - expression = new Matches(category, "*adunit"); - - willReturn(LookupResult.ofValue("someadunit")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatchForEndsWith() { - // given - expression = new Matches(category, "*adunit"); - - willReturn(LookupResult.ofValue("adunitOne")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForContainsInTheMiddle() { - // given - expression = new Matches(category, "*adunit*"); - - willReturn(LookupResult.ofValue("someadunitOne")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForContainsInTheBeginning() { - // given - expression = new Matches(category, "*adunit*"); - - willReturn(LookupResult.ofValue("adunitOne")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatchForContainsInTheEnd() { - // given - expression = new Matches(category, "*adunit*"); - - willReturn(LookupResult.ofValue("someadunit")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatchForContains() { - // given - expression = new Matches(category, "*adunit*"); - - willReturn(LookupResult.ofValue("One")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldPerformCaseInsensitiveComparison() { - // given - expression = new Matches(category, "AdUnIt"); - - willReturn(LookupResult.ofValue("aDuNiT")).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - expression = new Matches(category, "adunit"); - - willReturn(LookupResult.empty()).given(context).lookupString(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/NotTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/NotTest.java deleted file mode 100644 index ef1fec7e66f..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/NotTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; - -public class NotTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private TerminalExpression trueExpression; - @Mock - private TerminalExpression falseExpression; - @Mock - private RequestContext context; - - @Before - public void setUp() { - given(trueExpression.matches(any())).willReturn(true); - given(falseExpression.matches(any())).willReturn(false); - } - - @Test - public void matchesShouldReturnTrue() { - assertThat(new Not(trueExpression).matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalse() { - assertThat(new Not(falseExpression).matches(context)).isTrue(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/OrTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/OrTest.java deleted file mode 100644 index f677fd09da4..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/OrTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -public class OrTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private TerminalExpression trueExpression; - @Mock - private TerminalExpression falseExpression; - @Mock - private RequestContext context; - - @Before - public void setUp() { - given(trueExpression.matches(any())).willReturn(true); - given(falseExpression.matches(any())).willReturn(false); - } - - @Test - public void matchesShouldReturnTrue() { - assertThat(new Or(asList(trueExpression, trueExpression, trueExpression)).matches(context)).isTrue(); - } - - @Test - public void matchesShouldReturnFalse() { - assertThat(new Or(asList(falseExpression, falseExpression, falseExpression)).matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnTrueAndNotEvaluateRemainingExpressions() { - assertThat(new Or(asList(falseExpression, trueExpression, falseExpression)).matches(context)).isTrue(); - - verify(falseExpression).matches(context); - verify(trueExpression).matches(context); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/interpret/WithinTest.java b/src/test/java/org/prebid/server/deals/targeting/interpret/WithinTest.java deleted file mode 100644 index c6dccf1e537..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/interpret/WithinTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.prebid.server.deals.targeting.interpret; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.targeting.RequestContext; -import org.prebid.server.deals.targeting.model.GeoLocation; -import org.prebid.server.deals.targeting.model.GeoRegion; -import org.prebid.server.deals.targeting.syntax.TargetingCategory; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.willReturn; -import static org.mockito.Mockito.verify; - -public class WithinTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private RequestContext context; - - private Expression expression; - private TargetingCategory category; - - @Before - public void setUp() { - // given - category = new TargetingCategory(TargetingCategory.Type.location); - expression = new Within(category, GeoRegion.of(50.424782f, 30.506423f, 10f)); - } - - @Test - public void matchesShouldReturnTrueWhenThereIsMatch() { - // given - willReturn(GeoLocation.of(50.442406f, 30.521439f)).given(context).lookupGeoLocation(any()); - - // when and then - assertThat(expression.matches(context)).isTrue(); - verify(context).lookupGeoLocation(eq(category)); - } - - @Test - public void matchesShouldReturnFalseWhenThereIsNoMatch() { - // given - willReturn(GeoLocation.of(50.588196f, 30.512357f)).given(context).lookupGeoLocation(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } - - @Test - public void matchesShouldReturnFalseWhenActualValueIsMissing() { - // given - willReturn(null).given(context).lookupGeoLocation(any()); - - // when and then - assertThat(expression.matches(context)).isFalse(); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/syntax/BooleanOperatorTest.java b/src/test/java/org/prebid/server/deals/targeting/syntax/BooleanOperatorTest.java deleted file mode 100644 index bfc03545845..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/syntax/BooleanOperatorTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import org.assertj.core.api.SoftAssertions; -import org.junit.Test; - -import java.util.EnumMap; -import java.util.Map; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class BooleanOperatorTest { - - @Test - public void isBooleanOperatorShouldReturnTrueForKnownFunctions() { - SoftAssertions.assertSoftly(softly -> { - for (final String functionString : asList("$and", "$or", "$not")) { - softly.assertThat(BooleanOperator.isBooleanOperator(functionString)).isTrue(); - } - }); - } - - @Test - public void isBooleanOperatorShouldReturnFalseForUnknownFunctions() { - assertThat(BooleanOperator.isBooleanOperator("unknown")).isFalse(); - } - - @Test - public void fromStringShouldReturnEnumValue() { - // given - final EnumMap enumToString = new EnumMap<>(BooleanOperator.class); - enumToString.put(BooleanOperator.AND, "$and"); - enumToString.put(BooleanOperator.OR, "$or"); - enumToString.put(BooleanOperator.NOT, "$not"); - - // when and then - SoftAssertions.assertSoftly(softly -> { - for (final Map.Entry entry : enumToString.entrySet()) { - softly.assertThat(BooleanOperator.fromString(entry.getValue())).isEqualTo(entry.getKey()); - } - }); - } - - @Test - public void fromStringShouldThrowExceptionWhenUnkownFunction() { - assertThatThrownBy(() -> BooleanOperator.fromString("unknown")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Unrecognized boolean operator: unknown"); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/syntax/MatchingFunctionTest.java b/src/test/java/org/prebid/server/deals/targeting/syntax/MatchingFunctionTest.java deleted file mode 100644 index 748ffd3289c..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/syntax/MatchingFunctionTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import org.assertj.core.api.SoftAssertions; -import org.junit.Test; - -import java.util.EnumMap; -import java.util.Map; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class MatchingFunctionTest { - - @Test - public void isMatchingFunctionShouldReturnTrueForKnownFunctions() { - SoftAssertions.assertSoftly(softly -> { - for (final String functionString : asList("$matches", "$in", "$intersects", "$within")) { - softly.assertThat(MatchingFunction.isMatchingFunction(functionString)).isTrue(); - } - }); - } - - @Test - public void isMatchingFunctionShouldReturnFalseForUnknownFunctions() { - assertThat(MatchingFunction.isMatchingFunction("unknown")).isFalse(); - } - - @Test - public void fromStringShouldReturnEnumValue() { - // given - final EnumMap enumToString = new EnumMap<>(MatchingFunction.class); - enumToString.put(MatchingFunction.MATCHES, "$matches"); - enumToString.put(MatchingFunction.IN, "$in"); - enumToString.put(MatchingFunction.INTERSECTS, "$intersects"); - enumToString.put(MatchingFunction.WITHIN, "$within"); - - // when and then - SoftAssertions.assertSoftly(softly -> { - for (final Map.Entry entry : enumToString.entrySet()) { - softly.assertThat(MatchingFunction.fromString(entry.getValue())).isEqualTo(entry.getKey()); - } - }); - } - - @Test - public void fromStringShouldThrowExceptionWhenUnkownFunction() { - assertThatThrownBy(() -> MatchingFunction.fromString("unknown")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Unrecognized matching function: unknown"); - } -} diff --git a/src/test/java/org/prebid/server/deals/targeting/syntax/TargetingCategoryTest.java b/src/test/java/org/prebid/server/deals/targeting/syntax/TargetingCategoryTest.java deleted file mode 100644 index 8b75e609ed5..00000000000 --- a/src/test/java/org/prebid/server/deals/targeting/syntax/TargetingCategoryTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.prebid.server.deals.targeting.syntax; - -import org.assertj.core.api.AutoCloseableSoftAssertions; -import org.junit.Test; -import org.prebid.server.exception.TargetingSyntaxException; - -import java.util.List; - -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class TargetingCategoryTest { - - @Test - public void isTargetingCategoryShouldReturnTrueForKnownCategories() { - final List categories = asList( - "adunit.size", - "adunit.mediatype", - "adunit.adslot", - "site.domain", - "site.publisher.domain", - "site.referrer", - "app.bundle", - "device.geo.ext.vendor.attribute", - "device.geo.ext.vendor.nested.attribute", - "device.ext.vendor.attribute", - "device.ext.vendor.nested.attribute", - "pos", - "geo.distance", - "segment.bluekai", - "user.ext.time.userdow", - "user.ext.time.userhour", - "bidp.rubicon.siteId", - "ufpd.sport", - "sfpd.sport"); - - try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { - categories.forEach(categoryString -> - softly.assertThat(TargetingCategory.isTargetingCategory(categoryString)).isTrue()); - } - } - - @Test - public void isTargetingCategoryShouldReturnFalseForUnknownCategory() { - assertThat(TargetingCategory.isTargetingCategory("phony")).isFalse(); - } - - @Test - public void fromStringShouldReturnCategoryWithoutPathForStaticTypes() { - final List categories = asList( - "adunit.size", - "adunit.mediatype", - "adunit.adslot", - "site.domain", - "site.publisher.domain", - "site.referrer", - "app.bundle", - "pos", - "geo.distance", - "user.ext.time.userdow", - "user.ext.time.userhour"); - - try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) { - for (final String categoryString : categories) { - final TargetingCategory category = TargetingCategory.fromString(categoryString); - softly.assertThat(category.type()).isEqualTo(TargetingCategory.Type.fromString(categoryString)); - softly.assertThat(category.path()).isNull(); - } - } - } - - @Test - public void fromStringShouldReturnCategoryWithPathForDynamicTypes() { - // when - final TargetingCategory bidderParamCategory = TargetingCategory.fromString("bidp.rubicon.siteId"); - // then - assertThat(bidderParamCategory.type()).isEqualTo(TargetingCategory.Type.bidderParam); - assertThat(bidderParamCategory.path()).isEqualTo("siteId"); - - // when - final TargetingCategory userSegmentCategory = TargetingCategory.fromString("segment.bluekai"); - // then - assertThat(userSegmentCategory.type()).isEqualTo(TargetingCategory.Type.userSegment); - assertThat(userSegmentCategory.path()).isEqualTo("bluekai"); - - // when - final TargetingCategory userFirstPartyDataCategory = TargetingCategory.fromString("ufpd.sport"); - // then - assertThat(userFirstPartyDataCategory.type()).isEqualTo(TargetingCategory.Type.userFirstPartyData); - assertThat(userFirstPartyDataCategory.path()).isEqualTo("sport"); - - // when - final TargetingCategory siteFirstPartyDataCategory = TargetingCategory.fromString("sfpd.sport"); - // then - assertThat(siteFirstPartyDataCategory.type()).isEqualTo(TargetingCategory.Type.siteFirstPartyData); - assertThat(siteFirstPartyDataCategory.path()).isEqualTo("sport"); - } - - @Test - public void fromStringShouldThrowExceptionWhenCategoryIsUnknown() { - assertThatThrownBy(() -> TargetingCategory.fromString("unknown")) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("Unrecognized targeting category: unknown"); - } - - @Test - public void fromStringShouldThrowExceptionWhenBidderParamIsIncorrect() { - assertThatThrownBy(() -> TargetingCategory.fromString("bidp.rubicon")) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("BidderParam path is incorrect: rubicon"); - - assertThatThrownBy(() -> TargetingCategory.fromString("bidp.rubicon.")) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("BidderParam path is incorrect: rubicon."); - - assertThatThrownBy(() -> TargetingCategory.fromString("bidp.rubicon.siteId.")) - .isInstanceOf(TargetingSyntaxException.class) - .hasMessage("BidderParam path is incorrect: rubicon.siteId."); - } -} diff --git a/src/test/java/org/prebid/server/events/EventUtilTest.java b/src/test/java/org/prebid/server/events/EventUtilTest.java index 59a8b1044aa..12fe4381fe0 100644 --- a/src/test/java/org/prebid/server/events/EventUtilTest.java +++ b/src/test/java/org/prebid/server/events/EventUtilTest.java @@ -216,8 +216,7 @@ public void fromShouldReturnExpectedEventRequest() { .add("b", "bidId") .add("ts", "1000") .add("f", "i") - .add("x", "0") - .add("l", "lineItemId")); + .add("x", "0")); // when final EventRequest result = EventUtil.from(routingContext); @@ -231,7 +230,6 @@ public void fromShouldReturnExpectedEventRequest() { .timestamp(1000L) .format(EventRequest.Format.image) .analytics(EventRequest.Analytics.disabled) - .lineItemId("lineItemId") .build()); } @@ -273,7 +271,6 @@ public void toUrlShouldReturnExpectedUrl() { .integration("pbjs") .analytics(EventRequest.Analytics.enabled) .timestamp(1000L) - .lineItemId("lineItemId") .build(); // when @@ -282,12 +279,11 @@ public void toUrlShouldReturnExpectedUrl() { // then assertThat(result).isEqualTo( "http://external-url/event?t=win&b=bidId&a=accountId" - + "&aid=auctionId&ts=1000&bidder=bidder&f=b&int=pbjs&x=1" - + "&l=lineItemId"); + + "&aid=auctionId&ts=1000&bidder=bidder&f=b&int=pbjs&x=1"); } @Test - public void toUrlShouldReturnExpectedUrlWithoutFormatAndAnalyticsAndLineItemId() { + public void toUrlShouldReturnExpectedUrlWithoutFormatAndAnalytics() { // given final EventRequest eventRequest = EventRequest.builder() .type(EventRequest.Type.win) diff --git a/src/test/java/org/prebid/server/events/EventsServiceTest.java b/src/test/java/org/prebid/server/events/EventsServiceTest.java index 6ebab3978e6..d423044670a 100644 --- a/src/test/java/org/prebid/server/events/EventsServiceTest.java +++ b/src/test/java/org/prebid/server/events/EventsServiceTest.java @@ -30,30 +30,12 @@ public void createEventsShouldReturnExpectedEvent() { .build(); // when - final Events events = eventsService.createEvent("bidId", "bidder", "accountId", "lineItemId", true, - eventsContext); + final Events events = eventsService.createEvent("bidId", "bidder", "accountId", true, eventsContext); // then assertThat(events).isEqualTo(Events.of( - "http://external-url/event?t=win&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs&l=lineItemId", - "http://external-url/event?t=imp&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs&l=lineItemId")); - } - - @Test - public void createEventsShouldSkipLineItemIdIfMissing() { - // given - final EventsContext eventsContext = EventsContext.builder().auctionId("auctionId").integration( - "pbjs").auctionTimestamp(1000L).build(); - - // when - final Events events = eventsService.createEvent("bidId", "bidder", "accountId", null, true, eventsContext); - - // then - assertThat(events).isEqualTo(Events.of( - "http://external-url/event?t=win&b=bidId&a=accountId" - + "&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs", - "http://external-url/event?t=imp&b=bidId&a=accountId" - + "&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs")); + "http://external-url/event?t=win&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs", + "http://external-url/event?t=imp&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=i&int=pbjs")); } @Test @@ -62,15 +44,12 @@ public void createEventsShouldSetAnalyticsDisabled() { final EventsContext eventsContext = EventsContext.builder().integration("pbjs").auctionTimestamp(1000L).build(); // when - final Events events = eventsService.createEvent("bidId", "bidder", "accountId", "lineItemId", false, - eventsContext); + final Events events = eventsService.createEvent("bidId", "bidder", "accountId", false, eventsContext); // then assertThat(events).isEqualTo(Events.of( - "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0" - + "&l=lineItemId", - "http://external-url/event?t=imp&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0" - + "&l=lineItemId")); + "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0", + "http://external-url/event?t=imp&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0")); } @Test @@ -79,11 +58,11 @@ public void winUrlShouldReturnExpectedUrl() { final EventsContext eventsContext = EventsContext.builder().integration("pbjs").auctionTimestamp(1000L).build(); // when - final String winUrl = eventsService.winUrl("bidId", "bidder", "accountId", "lineItemId", true, eventsContext); + final String winUrl = eventsService.winUrl("bidId", "bidder", "accountId", true, eventsContext); // then assertThat(winUrl).isEqualTo( - "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&l=lineItemId"); + "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs"); } @Test @@ -92,12 +71,11 @@ public void winUrlShouldSEtAnalyticsDisabled() { final EventsContext eventsContext = EventsContext.builder().integration("pbjs").auctionTimestamp(1000L).build(); // when - final String winUrl = eventsService.winUrl("bidId", "bidder", "accountId", "lineItemId", false, eventsContext); + final String winUrl = eventsService.winUrl("bidId", "bidder", "accountId", false, eventsContext); // then assertThat(winUrl).isEqualTo( - "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0" - + "&l=lineItemId"); + "http://external-url/event?t=win&b=bidId&a=accountId&ts=1000&bidder=bidder&f=i&int=pbjs&x=0"); } @Test @@ -109,11 +87,10 @@ public void vastUrlShouldReturnExpectedUrl() { .build(); // when - final String vastUrl = eventsService.vastUrlTracking("bidId", "bidder", "accountId", "lineItemId", - eventsContext); + final String vastUrl = eventsService.vastUrlTracking("bidId", "bidder", "accountId", eventsContext); // then assertThat(vastUrl).isEqualTo( - "http://external-url/event?t=imp&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=b&int=pbjs&l=lineItemId"); + "http://external-url/event?t=imp&b=bidId&a=accountId&aid=auctionId&ts=1000&bidder=bidder&f=b&int=pbjs"); } } diff --git a/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java b/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java deleted file mode 100644 index 68e4a2fed66..00000000000 --- a/src/test/java/org/prebid/server/handler/DealsStatusHandlerTest.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.prebid.server.handler; - -import io.netty.handler.codec.http.HttpHeaderValues; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.util.HttpUtil; - -import java.io.IOException; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class DealsStatusHandlerTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - private DealsStatusHandler dealsStatusHandler; - - @Mock - private DeliveryProgressService deliveryProgressService; - - @Mock - private RoutingContext routingContext; - - @Mock - private HttpServerResponse httpServerResponse; - - @Before - public void setUp() { - dealsStatusHandler = new DealsStatusHandler(deliveryProgressService, jacksonMapper); - given(routingContext.response()).willReturn(httpServerResponse); - given(httpServerResponse.putHeader(any(CharSequence.class), any(CharSequence.class))) - .willReturn(httpServerResponse); - given(httpServerResponse.closed()).willReturn(false); - given(httpServerResponse.exceptionHandler(any())).willReturn(httpServerResponse); - } - - @Test - public void handleShouldNotSendDeliveryProgressReportWhenClientHasGone() { - // given - given(httpServerResponse.closed()).willReturn(true); - - // when - dealsStatusHandler.handle(routingContext); - - // then - verify(httpServerResponse, never()).end(); - } - - @Test - public void handleShouldReturnDeliveryProgressReport() throws IOException { - // given - given(deliveryProgressService.getOverallDeliveryProgressReport()) - .willReturn(DeliveryProgressReport.builder().reportId("reportId").build()); - - // when - dealsStatusHandler.handle(routingContext); - - // then - final String responseBody = getResponseBody(); - verify(httpServerResponse).putHeader(eq(HttpUtil.CONTENT_TYPE_HEADER), eq(HttpHeaderValues.APPLICATION_JSON)); - assertThat(mapper.readValue(responseBody, DeliveryProgressReport.class)) - .isEqualTo(DeliveryProgressReport.builder().reportId("reportId").build()); - } - - private String getResponseBody() { - final ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(String.class); - verify(httpServerResponse).end(bodyCaptor.capture()); - return bodyCaptor.getValue(); - } -} diff --git a/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java b/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java deleted file mode 100644 index 3a414d3eb36..00000000000 --- a/src/test/java/org/prebid/server/handler/ForceDealsUpdateHandlerTest.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.prebid.server.handler; - -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.deals.AlertHttpService; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.DeliveryStatsService; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.PlannerService; -import org.prebid.server.deals.RegisterService; -import org.prebid.server.exception.PreBidException; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; - -public class ForceDealsUpdateHandlerTest { - - private static final String ACTION_NAME_PARAM = "action_name"; - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private DeliveryStatsService deliveryStatsService; - @Mock - private PlannerService plannerService; - @Mock - private RegisterService registerService; - @Mock - private AlertHttpService alertHttpService; - @Mock - private DeliveryProgressService deliveryProgressService; - @Mock - private LineItemService lineItemService; - - private ForceDealsUpdateHandler handler; - @Mock - private RoutingContext routingContext; - @Mock - private HttpServerRequest httpRequest; - @Mock - private HttpServerResponse httpResponse; - - @Before - public void setUp() { - handler = new ForceDealsUpdateHandler( - deliveryStatsService, - plannerService, - registerService, - alertHttpService, - deliveryProgressService, - lineItemService, - "/endpoint"); - - given(routingContext.request()).willReturn(httpRequest); - given(routingContext.response()).willReturn(httpResponse); - - given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); - given(httpResponse.closed()).willReturn(false); - } - - @Test - public void shouldReturnBadRequestWhenActionParamIsMissing() { - // given - given(httpRequest.getParam(any())).willReturn(null); - - // when - handler.handle(routingContext); - - // then - verify(httpRequest).getParam(eq(ACTION_NAME_PARAM)); - - verify(httpResponse).setStatusCode(400); - verify(httpResponse).end("Parameter '%s' is required and can't be empty".formatted(ACTION_NAME_PARAM)); - } - - @Test - public void shouldReturnBadRequestWhenBadActionParamIsGiven() { - // given - final String badParamName = "bad_param_name"; - given(httpRequest.getParam(any())).willReturn(badParamName); - - // when - handler.handle(routingContext); - - // then - verify(httpRequest).getParam(eq(ACTION_NAME_PARAM)); - - verify(httpResponse).setStatusCode(400); - verify(httpResponse).end("Given '%s' parameter value '%s' is not among possible actions" - .formatted(ACTION_NAME_PARAM, badParamName)); - } - - @Test - public void shouldCallLineItemsUpdateMethodWhenUpdateLineItemsParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.UPDATE_LINE_ITEMS.name()); - - // when - handler.handle(routingContext); - - // then - verify(plannerService).updateLineItemMetaData(); - verifyNoInteractions(deliveryStatsService, registerService, alertHttpService, deliveryProgressService, - lineItemService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldCallReportSendingMethodWhenSendReportParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.SEND_REPORT.name()); - - // when - handler.handle(routingContext); - - // then - verify(deliveryStatsService).sendDeliveryProgressReports(); - verifyNoInteractions(plannerService, registerService, alertHttpService, deliveryProgressService, - lineItemService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldCallRegisterInstanceMethodWhenRegisterInstanceParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.REGISTER_INSTANCE.name()); - - // when - handler.handle(routingContext); - - // then - verify(registerService).performRegistration(); - verifyNoInteractions(plannerService, deliveryStatsService, alertHttpService, deliveryProgressService, - lineItemService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldCallResetAlertCountMethodWhenResetAlertCounterParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.RESET_ALERT_COUNT.name()); - - // when - handler.handle(routingContext); - - // then - verify(alertHttpService).resetAlertCount("pbs-register-client-error"); - verify(alertHttpService).resetAlertCount("pbs-planner-client-error"); - verify(alertHttpService).resetAlertCount("pbs-planner-empty-response-error"); - verify(alertHttpService).resetAlertCount("pbs-delivery-stats-client-error"); - verifyNoInteractions(plannerService, deliveryStatsService, registerService, deliveryProgressService, - lineItemService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldCallCreateReportMethodWhenCreateReportParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.CREATE_REPORT.name()); - - // when - handler.handle(routingContext); - - // then - verify(deliveryProgressService).createDeliveryProgressReports(any()); - verifyNoInteractions(registerService, plannerService, deliveryStatsService, alertHttpService, - lineItemService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldCallInvalidateLineItemsMethodWhenInvalidateLineItemsParamIsGiven() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.INVALIDATE_LINE_ITEMS.name()); - - // when - handler.handle(routingContext); - - // then - verify(lineItemService).invalidateLineItems(); - verifyNoInteractions(registerService, plannerService, deliveryStatsService, alertHttpService, - deliveryProgressService); - - verify(httpResponse).setStatusCode(204); - verify(httpResponse).end(); - } - - @Test - public void shouldReturnInternalServerExceptionWhenUpdatingLineItemActionFailed() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.UPDATE_LINE_ITEMS.name()); - final String exceptionMessage = "Failed to fetch data from Planner"; - doThrow(new PreBidException(exceptionMessage)).when(plannerService).updateLineItemMetaData(); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(500); - verify(httpResponse).end(exceptionMessage); - } - - @Test - public void shouldReturnInternalServerExceptionWhenSendingReportActionFailed() { - // given - given(httpRequest.getParam(any())).willReturn(ForceDealsUpdateHandler.DealsAction.SEND_REPORT.name()); - final String exceptionMessage = "Sending report failed"; - doThrow(new PreBidException(exceptionMessage)).when(deliveryStatsService).sendDeliveryProgressReports(); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(500); - verify(httpResponse).end(exceptionMessage); - } -} diff --git a/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java b/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java deleted file mode 100644 index d05dbe49b76..00000000000 --- a/src/test/java/org/prebid/server/handler/LineItemStatusHandlerTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.prebid.server.handler; - -import io.vertx.core.MultiMap; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.ext.web.RoutingContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.DeliveryProgressService; -import org.prebid.server.deals.proto.report.LineItemStatusReport; -import org.prebid.server.exception.PreBidException; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; - -public class LineItemStatusHandlerTest extends VertxTest { - - @Rule - public final MockitoRule mockitoRule = MockitoJUnit.rule(); - - @Mock - private DeliveryProgressService deliveryProgressService; - - private LineItemStatusHandler handler; - @Mock - private RoutingContext routingContext; - @Mock - private HttpServerRequest httpRequest; - @Mock - private HttpServerResponse httpResponse; - - @Before - public void setUp() { - given(routingContext.request()).willReturn(httpRequest); - given(routingContext.response()).willReturn(httpResponse); - - given(httpRequest.headers()).willReturn(MultiMap.caseInsensitiveMultiMap()); - given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); - - given(routingContext.request().getParam(any())).willReturn("lineItemId"); - - handler = new LineItemStatusHandler(deliveryProgressService, jacksonMapper, "endpoint"); - } - - @Test - public void handleShouldRespondWithErrorIfNoLineItemIdSpecified() { - // given - given(routingContext.request().getParam(any())).willReturn(null); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(400); - verify(httpResponse).end("id parameter is required"); - } - - @Test - public void handleShouldRespondWithErrorIfProcessingFailed() { - // given - given(deliveryProgressService.getLineItemStatusReport(any())).willThrow(new PreBidException("error")); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(400); - verify(httpResponse).end("error"); - } - - @Test - public void handleShouldRespondWithErrorIfUnexpectedExceptionOccurred() { - // given - given(deliveryProgressService.getLineItemStatusReport(any())).willThrow(new RuntimeException("error")); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(500); - verify(httpResponse).end("error"); - } - - @Test - public void handleShouldRespondWithExpectedResult() { - // given - given(deliveryProgressService.getLineItemStatusReport(any())) - .willReturn(LineItemStatusReport.builder().lineItemId("lineItemId").build()); - - // when - handler.handle(routingContext); - - // then - verify(httpResponse).setStatusCode(200); - verify(httpResponse).end("{\"lineItemId\":\"lineItemId\"}"); - } -} diff --git a/src/test/java/org/prebid/server/handler/NotificationEventHandlerTest.java b/src/test/java/org/prebid/server/handler/NotificationEventHandlerTest.java index 42a5a78bad7..3262830eba7 100644 --- a/src/test/java/org/prebid/server/handler/NotificationEventHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/NotificationEventHandlerTest.java @@ -19,9 +19,6 @@ import org.prebid.server.analytics.model.NotificationEvent; import org.prebid.server.analytics.reporter.AnalyticsReporterDelegator; import org.prebid.server.auction.model.Tuple2; -import org.prebid.server.cookie.UidsCookieService; -import org.prebid.server.deals.UserService; -import org.prebid.server.deals.events.ApplicationEventService; import org.prebid.server.exception.PreBidException; import org.prebid.server.execution.TimeoutFactory; import org.prebid.server.model.CaseInsensitiveMultiMap; @@ -38,8 +35,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -49,12 +44,6 @@ public class NotificationEventHandlerTest extends VertxTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock - private UidsCookieService uidsCookieService; - @Mock - private ApplicationEventService applicationEventService; - @Mock - private UserService userService; @Mock private ActivityInfrastructureCreator activityInfrastructureCreator; @Mock @@ -85,15 +74,11 @@ public void setUp() { given(httpResponse.setStatusCode(anyInt())).willReturn(httpResponse); notificationHandler = new NotificationEventHandler( - uidsCookieService, - applicationEventService, - userService, activityInfrastructureCreator, analyticsReporterDelegator, timeoutFactory, applicationSettings, - 1000, - true); + 1000); } @Test @@ -315,117 +300,6 @@ public void shouldPassEventToAnalyticsReporterWhenAccountEventEnabled() { }); } - @Test - public void shouldUpdateEventForLineItemForEventTypeWinAndAccountEventsEnabled() { - // given - given(httpRequest.params()).willReturn(MultiMap.caseInsensitiveMultiMap() - .add("t", "win") - .add("b", "bidId") - .add("l", "lineItemId") - .add("a", "accountId")); - - final Account account = Account.builder() - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build(); - given(applicationSettings.getAccountById(anyString(), any())) - .willReturn(Future.succeededFuture(account)); - - // when - notificationHandler.handle(routingContext); - - // then - verify(applicationEventService).publishLineItemWinEvent(eq("lineItemId")); - } - - @Test - public void shouldProcessLineItemEventWhenRequestAnalyticsFlagDisabled() { - // given - given(httpRequest.params()).willReturn(MultiMap.caseInsensitiveMultiMap() - .add("t", "win") - .add("b", "bidId") - .add("l", "lineItemId") - .add("a", "accountId") - .add("x", "0")); - - final Account account = Account.builder() - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build(); - given(applicationSettings.getAccountById(anyString(), any())) - .willReturn(Future.succeededFuture(account)); - - // when - notificationHandler.handle(routingContext); - - // then - verify(applicationEventService).publishLineItemWinEvent(eq("lineItemId")); - verify(userService).processWinEvent(eq("lineItemId"), eq("bidId"), any()); - } - - @Test - public void shouldProcessLineItemEventWhenAccountEventsDisabled() { - // given - given(httpRequest.params()).willReturn(MultiMap.caseInsensitiveMultiMap() - .add("t", "win") - .add("b", "bidId") - .add("l", "lineItemId") - .add("a", "accountId")); - - final Account account = Account.builder() - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(false)) - .build()) - .build(); - given(applicationSettings.getAccountById(anyString(), any())) - .willReturn(Future.succeededFuture(account)); - - // when - notificationHandler.handle(routingContext); - - // then - verify(applicationEventService).publishLineItemWinEvent(eq("lineItemId")); - verify(userService).processWinEvent(eq("lineItemId"), eq("bidId"), any()); - } - - @Test - public void shouldNotProcessLineItemEventWhenDealsDisabled() { - // given - notificationHandler = new NotificationEventHandler( - uidsCookieService, - applicationEventService, - userService, - activityInfrastructureCreator, - analyticsReporterDelegator, - timeoutFactory, - applicationSettings, - 1000, - false); - - given(httpRequest.params()).willReturn(MultiMap.caseInsensitiveMultiMap() - .add("t", "win") - .add("b", "bidId") - .add("l", "lineItemId") - .add("a", "accountId")); - - final Account account = Account.builder() - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build(); - given(applicationSettings.getAccountById(anyString(), any())) - .willReturn(Future.succeededFuture(account)); - - // when - notificationHandler.handle(routingContext); - - // then - verifyNoInteractions(applicationEventService); - verifyNoInteractions(userService); - } - @Test public void shouldNotPassEventToAnalyticsReporterWhenAnalyticsValueIsZero() { // given @@ -567,56 +441,6 @@ public void shouldPassExpectedEventToAnalyticsReporter() { }); } - @Test - public void shouldPassEventObjectToUserServiceWhenLineItemIdParameterIsPresent() { - // given - given(httpRequest.params()) - .willReturn(MultiMap.caseInsensitiveMultiMap() - .add("t", "win") - .add("b", "bidId") - .add("a", "accountId") - .add("l", "lineItemId")); - - given(applicationSettings.getAccountById(anyString(), any())) - .willReturn(Future.succeededFuture(Account.builder() - .id("accountId") - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build())); - - // when - notificationHandler.handle(routingContext); - - // then - verify(uidsCookieService).parseFromRequest(eq(routingContext)); - - final CaseInsensitiveMultiMap.Builder queryParams = CaseInsensitiveMultiMap.builder() - .add("t", "win") - .add("b", "bidId") - .add("a", "accountId") - .add("l", "lineItemId"); - - final HttpRequestContext expectedHttpContext = HttpRequestContext.builder() - .queryParams(queryParams.build()) - .headers(CaseInsensitiveMultiMap.empty()) - .build(); - - verify(userService).processWinEvent(eq("lineItemId"), eq("bidId"), isNull()); - assertThat(captureAnalyticEvent()).satisfies(event -> { - assertThat(event.getType()).isEqualTo(NotificationEvent.Type.win); - assertThat(event.getBidId()).isEqualTo("bidId"); - assertThat(event.getAccount()).isEqualTo(Account.builder() - .id("accountId") - .auction(AccountAuctionConfig.builder() - .events(AccountEventsConfig.of(true)) - .build()) - .build()); - assertThat(event.getHttpContext()).isEqualTo(expectedHttpContext); - assertThat(event.getLineItemId()).isEqualTo("lineItemId"); - }); - } - private Integer captureResponseStatusCode() { final ArgumentCaptor captor = ArgumentCaptor.forClass(Integer.class); verify(httpResponse).setStatusCode(captor.capture()); diff --git a/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java b/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java index fe86539c68c..0d94217fea3 100644 --- a/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/TracerLogHandlerTest.java @@ -54,7 +54,7 @@ public void handleShouldReturnBadRequestWhenNoParametersInRequest() { // then verify(httpResponse).setStatusCode(eq(400)); - verify(httpResponse).end(eq("At least one parameter should ne defined: account, bidderCode, lineItemId")); + verify(httpResponse).end(eq("At least one parameter should be defined: account, bidderCode")); } @Test @@ -90,7 +90,7 @@ public void handleShouldReturnBadRequestWhenLogLevelHasIncorrectValue() { given(httpRequest.params()).willReturn(MultiMap.caseInsensitiveMultiMap().add("account", "1001") .add("duration", "200").add("level", "invalid")); doThrow(new IllegalArgumentException("Invalid LoggingLevel: invalid")) - .when(criteriaManager).addCriteria(any(), any(), any(), any(), any()); + .when(criteriaManager).addCriteria(any(), any(), any(), any()); // when tracerLogHandler.handle(routingContext); diff --git a/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java b/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java index 33b071d9a95..502f13fccc6 100644 --- a/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/openrtb2/AmpHandlerTest.java @@ -566,7 +566,7 @@ public void shouldRespondWithDebugInfoIncludedIfTestFlagIsTrue() { givenHoldAuction(givenBidResponseWithExt( ExtBidResponse.builder() - .debug(ExtResponseDebug.of(null, auctionContext.getBidRequest(), null, null)) + .debug(ExtResponseDebug.of(null, auctionContext.getBidRequest(), null)) .prebid(ExtBidResponsePrebid.builder().auctiontimestamp(1000L).targeting(emptyMap()).build()) .build())); diff --git a/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java b/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java index 17ef6934398..14f83a310f9 100644 --- a/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java +++ b/src/test/java/org/prebid/server/handler/openrtb2/AuctionHandlerTest.java @@ -395,8 +395,7 @@ public void shouldRespondWithCorrectResolvedRequestMediaTypePriceGranularity() { final BidResponse bidResponse = BidResponse.builder() .ext(ExtBidResponse.builder() - .debug(ExtResponseDebug.of(null, resolvedRequest, - null, null)) + .debug(ExtResponseDebug.of(null, resolvedRequest, null)) .build()) .build(); final AuctionContext auctionContext = AuctionContext.builder() diff --git a/src/test/java/org/prebid/server/it/ApplicationTest.java b/src/test/java/org/prebid/server/it/ApplicationTest.java index 4184a06f04c..ac40c02648c 100644 --- a/src/test/java/org/prebid/server/it/ApplicationTest.java +++ b/src/test/java/org/prebid/server/it/ApplicationTest.java @@ -649,7 +649,6 @@ public void traceHandlerShouldReturn200Ok() { .param("duration", "1000") .param("account", "1001") .param("bidderCode", "rubicon") - .param("lineitemId", "1001") .post("/pbs-admin/tracelog") .then() .assertThat() diff --git a/src/test/java/org/prebid/server/it/DealsSimulationTest.java b/src/test/java/org/prebid/server/it/DealsSimulationTest.java deleted file mode 100644 index ffed682509e..00000000000 --- a/src/test/java/org/prebid/server/it/DealsSimulationTest.java +++ /dev/null @@ -1,269 +0,0 @@ -package org.prebid.server.it; - -import com.github.tomakehurst.wiremock.client.VerificationException; -import com.github.tomakehurst.wiremock.junit.WireMockClassRule; -import com.github.tomakehurst.wiremock.matching.AnythingPattern; -import com.github.tomakehurst.wiremock.verification.LoggedRequest; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; -import org.json.JSONException; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.LineItemService; -import org.skyscreamer.jsonassert.ArrayValueMatcher; -import org.skyscreamer.jsonassert.Customization; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; -import org.skyscreamer.jsonassert.ValueMatcher; -import org.skyscreamer.jsonassert.comparator.CustomComparator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.IOException; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeFormatterBuilder; -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static io.restassured.RestAssured.given; -import static java.util.Collections.singletonList; -import static org.awaitility.Awaitility.await; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) -@RunWith(SpringRunner.class) -@TestPropertySource(locations = { - "test-application.properties", - "deals/test-deals-application.properties", - "deals/test-deals-simulation-application.properties"}) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -public class DealsSimulationTest extends VertxTest { - - private static final int APP_PORT = 10080; - private static final int WIREMOCK_PORT = 8090; - - private static final RequestSpecification SPEC = IntegrationTest.spec(APP_PORT); - - @ClassRule - public static final WireMockClassRule WIRE_MOCK_RULE = new WireMockClassRule(options().port(WIREMOCK_PORT)); - - private static final ZonedDateTime NOW = ZonedDateTime.now( - Clock.fixed(Instant.parse("2019-10-10T00:00:00Z"), ZoneOffset.UTC)); - - private static final DateTimeFormatter UTC_MILLIS_FORMATTER = new DateTimeFormatterBuilder() - .appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - .toFormatter(); - - private static final String RUBICON = "rubicon"; - - @Autowired - private LineItemService lineItemService; - - @Autowired - private Clock clock; - - @BeforeClass - public static void setUpInner() throws IOException { - // given - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/planner-plan")) - .withQueryParam("instanceId", equalTo("localhost")) - .withQueryParam("region", equalTo("local")) - .withQueryParam("vendor", equalTo("local")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .withHeader("pg-sim-timestamp", equalTo(UTC_MILLIS_FORMATTER.format(NOW))) - .willReturn(aResponse() - .withBody(IntegrationTest.jsonFrom("deals/simulation/test-planner-plan-response-1.json")))); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/planner-register")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .withHeader("pg-sim-timestamp", equalTo(NOW.toString())) - .withRequestBody(equalToJson(IntegrationTest.jsonFrom( - "deals/simulation/test-planner-register-request-1.json"))) - .willReturn(aResponse())); - } - - @Test - public void openrtb2AuctionShouldRespondWithDealBids() throws IOException, JSONException, InterruptedException { - // given - given(SPEC) - .header("pg-sim-timestamp", NOW.plusSeconds(0).toString()) - .when() - .post("/pbs-admin/e2eAdmin/planner/fetchLineItems"); - - TimeUnit.SECONDS.sleep(1); // no way to check that planner response handling is complete - - given(SPEC) - .when() - .header("pg-sim-timestamp", NOW.plusSeconds(1).toString()) - .post("/pbs-admin/e2eAdmin/advancePlans"); - - awaitForLineItemMetadata(NOW.plusSeconds(1)); - - given(SPEC) - .when() - .body(IntegrationTest.jsonFrom("deals/simulation/test-bid-rates.json")) - .post("/pbs-admin/e2eAdmin/bidRate"); - - final Response beforePlansUpdateResponse = given(SPEC) - .header("Referer", "http://www.example.com") - .header("User-Agent", "userAgent") - .header("X-Forwarded-For", "185.199.110.153") - .header("pg-sim-timestamp", NOW.plusSeconds(2).toString()) - // this uids cookie value stands for {"uids":{"rubicon":"J5VLCWQP-26-CWFT"}} - .cookie("uids", "eyJ1aWRzIjp7InJ1Ymljb24iOiJKNVZMQ1dRUC0yNi1DV0ZUIn19") - .body(IntegrationTest.jsonFrom("deals/simulation/test-auction-request.json")) - .post("/openrtb2/auction"); - - assertResponse("deals/simulation/test-auction-response-1.json", beforePlansUpdateResponse, - singletonList(RUBICON)); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/delivery-stats-progress")) - .withBasicAuth("username", "password") - .withHeader("pg-sim-timestamp", equalTo(UTC_MILLIS_FORMATTER.format(NOW.plusSeconds(3)))) - .withHeader("pg-trx-id", new AnythingPattern()) - .willReturn(aResponse())); - - given(SPEC) - .when() - .header("pg-sim-timestamp", NOW.plusSeconds(3).toString()) - .post("/pbs-admin/e2eAdmin/dealstats/report"); - - // update plans for now date = 2019-10-10T00:15:00Z - making lineItem1 inactive due to absence of active plan - given(SPEC) - .when() - .header("pg-sim-timestamp", NOW.plusMinutes(15).toString()) - .post("/pbs-admin/e2eAdmin/advancePlans"); - - final Response afterPlansUpdateResponse = given(SPEC) - .header("Referer", "http://www.example.com") - .header("User-Agent", "userAgent") - .header("X-Forwarded-For", "185.199.110.153") - .header("pg-sim-timestamp", NOW.plusMinutes(16).toString()) - // this uids cookie value stands for {"uids":{"rubicon":"J5VLCWQP-26-CWFT"}} - .cookie("uids", "eyJ1aWRzIjp7InJ1Ymljb24iOiJKNVZMQ1dRUC0yNi1DV0ZUIn19") - .body(IntegrationTest.jsonFrom("deals/simulation/test-auction-request.json")) - .post("/openrtb2/auction"); - - assertResponse("deals/simulation/test-auction-response-2.json", afterPlansUpdateResponse, - singletonList(RUBICON)); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/delivery-stats-progress")) - .withBasicAuth("username", "password") - .withHeader("pg-sim-timestamp", equalTo(UTC_MILLIS_FORMATTER.format(NOW.plusMinutes(17)))) - .withHeader("pg-trx-id", new AnythingPattern()) - .willReturn(aResponse())); - - given(SPEC) - .when() - .header("pg-sim-timestamp", NOW.plusMinutes(17).toString()) - .post("/pbs-admin/e2eAdmin/dealstats/report"); - - assertDeliveryStatsProgressRequests( - "deals/simulation/test-delivery-stats-progress-request-1.json", - "deals/simulation/test-delivery-stats-progress-request-2.json"); - - given(SPEC) - .header("pg-sim-timestamp", NOW.toString()) - .when() - .post("/pbs-admin/e2eAdmin/planner/register"); - } - - private void awaitForLineItemMetadata(ZonedDateTime now) { - await().atMost(20, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS) - .until(() -> lineItemService.accountHasDeals("2001", now)); - } - - /** - * Timestamps in response are always generated anew. - * This comparator allows to just verify they are present and parsable. - */ - private static CustomComparator openrtbDeepDebugTimeComparator() { - final ValueMatcher timeValueMatcher = (actual, expected) -> { - try { - return mapper.readValue("\"" + actual.toString() + "\"", ZonedDateTime.class) != null; - } catch (IOException e) { - return false; - } - }; - - final ArrayValueMatcher arrayValueMatcher = new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.trace.deals[*].time", timeValueMatcher))); - - final List arrayValueMatchers = IntStream.range(1, 5) - .mapToObj(i -> new Customization("ext.debug.trace.lineitems.lineItem" + i, - new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.trace.lineitems.lineItem" + i + "[*].time", - timeValueMatcher))))) - .collect(Collectors.toCollection(ArrayList::new)); - - arrayValueMatchers.add(new Customization("ext.debug.trace.deals", arrayValueMatcher)); - - return new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, - arrayValueMatchers.toArray(Customization[]::new)); - } - - private void assertResponse(String expectedResponsePath, Response response, List bidders) - throws IOException, JSONException { - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - expectedResponsePath, response, bidders)); - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - public static void assertDeliveryStatsProgressRequests(String path1, String path2) - throws IOException, JSONException { - final String firstReportRequest = IntegrationTest.jsonFrom(path1); - final String secondReportRequest = IntegrationTest.jsonFrom(path2); - - await().atMost(20, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> - verify(() -> WIRE_MOCK_RULE.verify(2, postRequestedFor(urlPathEqualTo("/delivery-stats-progress"))))); - - final List loggedRequests = - WIRE_MOCK_RULE.findAll(postRequestedFor(urlPathEqualTo("/delivery-stats-progress"))); - - JSONAssert.assertEquals(firstReportRequest, loggedRequests.get(0).getBodyAsString(), JSONCompareMode.LENIENT); - JSONAssert.assertEquals(secondReportRequest, loggedRequests.get(1).getBodyAsString(), JSONCompareMode.LENIENT); - } - - private String withTemporalFields(String auctionResponse) { - final ZonedDateTime dateTime = ZonedDateTime.now(clock); - - return auctionResponse - .replaceAll("\"?\\{\\{ userdow }}\"?", Integer.toString( - dateTime.getDayOfWeek().get(WeekFields.SUNDAY_START.dayOfWeek()))) - .replaceAll("\"?\\{\\{ userhour }}\"?", Integer.toString(dateTime.getHour())); - } - - private static boolean verify(Runnable verify) { - try { - verify.run(); - return true; - } catch (VerificationException e) { - return false; - } - } -} diff --git a/src/test/java/org/prebid/server/it/DealsTest.java b/src/test/java/org/prebid/server/it/DealsTest.java deleted file mode 100644 index 78f775288d8..00000000000 --- a/src/test/java/org/prebid/server/it/DealsTest.java +++ /dev/null @@ -1,333 +0,0 @@ -package org.prebid.server.it; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.github.tomakehurst.wiremock.client.CountMatchingStrategy; -import com.github.tomakehurst.wiremock.client.VerificationException; -import com.github.tomakehurst.wiremock.junit.WireMockClassRule; -import com.github.tomakehurst.wiremock.matching.AnythingPattern; -import com.github.tomakehurst.wiremock.verification.LoggedRequest; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; -import org.apache.commons.collections4.CollectionUtils; -import org.json.JSONException; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.LineItemService; -import org.prebid.server.deals.proto.report.DeliveryProgressReport; -import org.prebid.server.deals.proto.report.Event; -import org.prebid.server.deals.proto.report.LineItemStatus; -import org.skyscreamer.jsonassert.ArrayValueMatcher; -import org.skyscreamer.jsonassert.Customization; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; -import org.skyscreamer.jsonassert.ValueMatcher; -import org.skyscreamer.jsonassert.comparator.CustomComparator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.IOException; -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static io.restassured.RestAssured.given; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; -import static org.prebid.server.it.IntegrationTest.equalToBidCacheRequest; -import static org.prebid.server.it.IntegrationTest.openrtbAuctionResponseFrom; -import static org.prebid.server.util.IntegrationTestsUtil.jsonFrom; -import static org.skyscreamer.jsonassert.JSONCompare.compareJSON; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) -@RunWith(SpringRunner.class) -@TestPropertySource(locations = {"test-application.properties", "deals/test-deals-application.properties"}) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -public class DealsTest extends VertxTest { - - private static final int APP_PORT = 8070; - private static final int WIREMOCK_PORT = 8090; - - private static final RequestSpecification SPEC = IntegrationTest.spec(APP_PORT); - - @SuppressWarnings("unchecked") - @ClassRule - public static final WireMockClassRule WIRE_MOCK_RULE = new WireMockClassRule(options() - .port(WIREMOCK_PORT) - .extensions( - IntegrationTest.CacheResponseTransformer.class, - IntegrationTest.ResponseOrderTransformer.class)); - - private static final String GENERIC = "generic"; - - @Autowired - private LineItemService lineItemService; - - @Autowired - private Clock clock; - - @BeforeClass - public static void setUpInner() throws IOException { - // given - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/periodic-update")) - .willReturn(aResponse() - .withJsonBody(mapper.createObjectNode() - .putPOJO("requests", emptyMap()) - .putPOJO("imps", emptyMap())))); - - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/currency-rates")) - .willReturn(aResponse().withJsonBody(mapper.createObjectNode()))); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/delivery-stats-progress")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .willReturn(aResponse())); - - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/planner-plan")) - .withQueryParam("instanceId", equalTo("localhost")) - .withQueryParam("region", equalTo("local")) - .withQueryParam("vendor", equalTo("local")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .willReturn(aResponse().withBody(plannerResponseFrom("deals/test-planner-plan-response.json")))); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/planner-register")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .withRequestBody(equalToJson(jsonFrom("deals/test-planner-register-request.json"), false, true)) - .willReturn(aResponse().withBody(jsonFrom("deals/test-planner-register-response.json")))); - - // pre-bid cache - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/cache")) - .withRequestBody(equalToBidCacheRequest(jsonFrom("deals/test-cache-deals-request.json"))) - .willReturn(aResponse() - .withTransformers("cache-response-transformer") - .withTransformerParameter("matcherName", "deals/test-cache-matcher.json"))); - } - - @Before - public void setUp() throws IOException { - // given - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/user-data-win-event")) - .withRequestBody(equalToJson(jsonFrom("deals/test-user-data-win-event-request.json"), false, true)) - .willReturn(aResponse())); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/user-data-details")) - .withRequestBody(equalToJson(jsonFrom("deals/test-user-data-details-request.json"), false, true)) - .willReturn(aResponse().withBody(jsonFrom("deals/test-user-data-details-generic-response.json")))); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/generic-exchange")) - .withRequestBody(equalToJson(jsonFrom("deals/test-generic-bid-request.json"), false, true)) - .willReturn(aResponse() - .withFixedDelay(600) - .withBody(jsonFrom("deals/test-generic-bid-response.json")))); - } - - @Test - public void openrtb2AuctionShouldRespondWithDealBids() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - // when - final Response response = given(SPEC) - .header("Referer", "http://www.example.com") - .header("User-Agent", "userAgent") - .header("X-Forwarded-For", "185.199.110.153") - // this uids cookie value stands for { "tempUIDs":{ "rubicon":{ "uid":"J5VLCWQP-26-CWFT", - // "expires":"2023-12-05T19:00:05.103329-03:00" } } } - .cookie("uids", "eyAidGVtcFVJRHMiOnsgInJ1Ymljb24iOnsgInVpZCI6Iko1VkxDV1FQ" - + "LTI2LUNXRlQiLCAiZXhwaXJlcyI6IjIwMjMtMTItMDVUMTk6MDA6MDUuMTAzMzI5LTAzOjAwIiB9IH0gfQ==") - .body(jsonFrom("deals/test-auction-request.json")) - .post("/openrtb2/auction"); - - // then - JSONAssert.assertEquals( - withTemporalFields(openrtbAuctionResponseFrom( - "deals/test-auction-response.json", response, singletonList(GENERIC))), - response.asString(), - openrtbDeepDebugTimeComparator()); - - // when - final Response eventResponse = given(SPEC) - .queryParam("t", "win") - .queryParam("b", "bidId") - .queryParam("a", "14062") - .queryParam("l", "lineItem1") - .queryParam("f", "i") - // this uids cookie value stands for { "tempUIDs":{ "rubicon":{ "uid":"J5VLCWQP-26-CWFT", - // "expires":"2023-12-05T19:00:05.103329-03:00" } } } - .cookie("uids", "eyAidGVtcFVJRHMiOnsgInJ1Ymljb24iOnsgInVpZCI6Iko1VkxDV1FQ" - + "LTI2LUNXRlQiLCAiZXhwaXJlcyI6IjIwMjMtMTItMDVUMTk6MDA6MDUuMTAzMzI5LTAzOjAwIiB9IH0gfQ==") - .get("/event"); - - // then - assertThat(eventResponse.getStatusCode()).isEqualTo(200); - await().atMost(5, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> - verify(() -> WIRE_MOCK_RULE.verify(postRequestedFor(urlPathEqualTo("/user-data-win-event"))))); - - // verify delivery stats report - await().atMost(10, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS).until(() -> - verify(() -> WIRE_MOCK_RULE.verify( - new CountMatchingStrategy(CountMatchingStrategy.GREATER_THAN_OR_EQUAL, 2), - postRequestedFor(urlPathEqualTo("/delivery-stats-progress"))))); - - final List requestList = WIRE_MOCK_RULE.findAll( - postRequestedFor(urlPathEqualTo("/delivery-stats-progress"))); - final DeliveryProgressReport report = chooseReportToCompare(requestList); - - JSONAssert.assertEquals( - jsonFrom("deals/test-delivery-stats-progress-request.json"), - mapper.writeValueAsString(report), - JSONCompareMode.LENIENT); - } - - private static String plannerResponseFrom(String templatePath) throws IOException { - final ZonedDateTime now = ZonedDateTime.now().withFixedOffsetZone(); - - return jsonFrom(templatePath) - .replaceAll("\\{\\{ now }}", now.toString()) - .replaceAll("\\{\\{ lineItem.startTime }}", now.minusDays(5).toString()) - .replaceAll("\\{\\{ lineItem.endTime }}", now.plusDays(5).toString()) - .replaceAll("\\{\\{ plan.startTime }}", now.minusHours(1).toString()) - .replaceAll("\\{\\{ plan.endTime }}", now.plusHours(1).toString()); - } - - private String withTemporalFields(String auctionResponse) { - final ZonedDateTime dateTime = ZonedDateTime.now(clock); - final int dayOfWeek = dateTime.getDayOfWeek().get(WeekFields.SUNDAY_START.dayOfWeek()); - - return auctionResponse - .replaceAll("\"?\\{\\{ userdow }}\"?", Integer.toString(dayOfWeek)) - .replaceAll("\"?\\{\\{ userhour }}\"?", Integer.toString(dateTime.getHour())); - } - - private void awaitForLineItemMetadata() { - await().atMost(5, TimeUnit.SECONDS).pollInterval(1, TimeUnit.SECONDS) - .until(() -> lineItemService.accountHasDeals("2001", ZonedDateTime.now(clock))); - } - - /** - * Timestamps in response are always generated anew. - * This comparator allows to just verify they are present and parsable. - */ - private static CustomComparator openrtbDeepDebugTimeComparator() { - final ValueMatcher timeValueMatcher = (actual, expected) -> { - try { - return mapper.readValue("\"" + actual.toString() + "\"", ZonedDateTime.class) != null; - } catch (IOException e) { - return false; - } - }; - - final ArrayValueMatcher arrayValueMatcher = new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.trace.deals[*].time", timeValueMatcher))); - - final ValueMatcher jsonStringValueMatcher = (actual, expected) -> { - try { - return compareJSON(actual.toString(), expected.toString(), JSONCompareMode.NON_EXTENSIBLE).passed(); - } catch (JSONException e) { - throw new RuntimeException("Unexpected json exception", e); - } - }; - - final ArrayValueMatcher cacheArrayValueMatcher = new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.httpcalls.cache[*].requestbody", jsonStringValueMatcher), - new Customization("ext.debug.httpcalls.cache[*].responsebody", jsonStringValueMatcher))); - - final List arrayValueMatchers = IntStream.range(1, 5) - .mapToObj(i -> new Customization( - "ext.debug.trace.lineitems.lineItem" + i, - new ArrayValueMatcher<>( - new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization( - "ext.debug.trace.lineitems.lineItem" + i + "[*].time", - timeValueMatcher))))) - .collect(Collectors.toCollection(ArrayList::new)); - - arrayValueMatchers.add(new Customization("ext.debug.trace.deals", arrayValueMatcher)); - arrayValueMatchers.add(new Customization("ext.debug.httpcalls.cache", cacheArrayValueMatcher)); - arrayValueMatchers.add(new Customization("ext.debug.httpcalls.generic", new ArrayValueMatcher<>( - new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("**.requestheaders", (o1, o2) -> true), - new Customization("**.requestbody", (o1, o2) -> true), - new Customization("**.responsebody", (o1, o2) -> true))))); - - return new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, arrayValueMatchers.toArray(Customization[]::new)); - } - - private static boolean verify(Runnable verify) { - try { - verify.run(); - return true; - } catch (VerificationException e) { - return false; - } - } - - private static DeliveryProgressReport chooseReportToCompare(List requestList) - throws JsonProcessingException { - - final int size = requestList.size(); - final DeliveryProgressReport firstReport = readDeliveryProgressReport(requestList.get(size - 2)); - final DeliveryProgressReport secondReport = readDeliveryProgressReport(requestList.get(size - 1)); - - // in a reason cron high dependent on time value, report with statistic should be chosen - final DeliveryProgressReport report = firstReport.getClientAuctions() != 0 ? firstReport : secondReport; - final LineItemStatus lineItem1 = firstReport.getLineItemStatus().stream() - .filter(lineItemStatus -> lineItemStatus.getLineItemId().equals("lineItem1")) - .findFirst().orElse(null); - - // if report does not contain win event for lineItem1 it is possible that it got by the second report - if (lineItem1 != null && CollectionUtils.isEmpty(lineItem1.getEvents())) { - final Set mergedEvents = lineItem1.getEvents(); - - firstReport.getLineItemStatus().stream() - .filter(lineItemStatus -> lineItemStatus.getLineItemId().equals("lineItem1")) - .map(LineItemStatus::getEvents) - .filter(CollectionUtils::isNotEmpty) - .findFirst() - .ifPresent(mergedEvents::addAll); - - secondReport.getLineItemStatus().stream() - .filter(lineItemStatus -> lineItemStatus.getLineItemId().equals("lineItem1")) - .map(LineItemStatus::getEvents) - .filter(CollectionUtils::isNotEmpty) - .findFirst() - .ifPresent(mergedEvents::addAll); - } - - return report; - } - - private static DeliveryProgressReport readDeliveryProgressReport(LoggedRequest loggedRequest) - throws JsonProcessingException { - - return mapper.readValue(loggedRequest.getBodyAsString(), DeliveryProgressReport.class); - } -} diff --git a/src/test/java/org/prebid/server/it/IntegrationTest.java b/src/test/java/org/prebid/server/it/IntegrationTest.java index ab1af668b7c..119537ba161 100644 --- a/src/test/java/org/prebid/server/it/IntegrationTest.java +++ b/src/test/java/org/prebid/server/it/IntegrationTest.java @@ -42,13 +42,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -240,10 +233,6 @@ static Customization openrtbCacheDebugCustomization() { return new Customization("ext.debug.httpcalls.cache", arrayValueMatcher); } - static Customization headersDebugCustomization() { - return new Customization("**.requestheaders.x-prebid", (o1, o2) -> true); - } - protected static void assertJsonEquals(String file, Response response, List bidders, @@ -303,77 +292,6 @@ public boolean applyGlobally() { } } - static final String LINE_ITEM_RESPONSE_ORDER = "lineItemResponseOrder"; - static final String ID_TO_EXECUTION_PARAMETERS = "idToExecutionParameters"; - - public static class ResponseOrderTransformer extends ResponseTransformer { - - private static final String LINE_ITEM_PATH = "/imp/0/ext/rp/target/line_item"; - - private final Lock lock = new ReentrantLock(); - private final Condition lockCondition = lock.newCondition(); - - @Override - @SuppressWarnings("unchecked") - public com.github.tomakehurst.wiremock.http.Response transform( - Request request, - com.github.tomakehurst.wiremock.http.Response response, - FileSource files, - Parameters parameters) { - - final Queue lineItemResponseOrder = - (Queue) parameters.get(LINE_ITEM_RESPONSE_ORDER); - final Map idToParameters = - (Map) parameters.get(ID_TO_EXECUTION_PARAMETERS); - - final String requestDealId; - try { - requestDealId = readStringValue(mapper.readTree(request.getBodyAsString()), LINE_ITEM_PATH); - } catch (IOException e) { - throw new RuntimeException("Request should contain imp/ext/rp/target/line_item for deals request"); - } - - final BidRequestExecutionParameters requestParameters = idToParameters.get(requestDealId); - - waitForTurn(lineItemResponseOrder, requestParameters.getDealId(), requestParameters.getDelay()); - - return com.github.tomakehurst.wiremock.http.Response.response() - .body(requestParameters.getBody()) - .status(requestParameters.getStatus()) - .build(); - } - - private void waitForTurn(Queue dealsResponseOrder, String id, Long delay) { - lock.lock(); - try { - while (!Objects.equals(dealsResponseOrder.peek(), id)) { - lockCondition.await(); - } - TimeUnit.MILLISECONDS.sleep(delay); - dealsResponseOrder.poll(); - lockCondition.signalAll(); - } catch (InterruptedException e) { - throw new RuntimeException("Failed on waiting to return bid request for lineItem id = " + id); - } finally { - lock.unlock(); - } - } - - private String readStringValue(JsonNode jsonNode, String path) { - return jsonNode.at(path).asText(); - } - - @Override - public String getName() { - return "response-order-transformer"; - } - - @Override - public boolean applyGlobally() { - return false; - } - } - @Value @AllArgsConstructor(staticName = "of") static class BidRequestExecutionParameters { diff --git a/src/test/java/org/prebid/server/it/PrematureReturnTest.java b/src/test/java/org/prebid/server/it/PrematureReturnTest.java deleted file mode 100644 index dec6e307a14..00000000000 --- a/src/test/java/org/prebid/server/it/PrematureReturnTest.java +++ /dev/null @@ -1,451 +0,0 @@ -package org.prebid.server.it; - -import com.github.tomakehurst.wiremock.junit.WireMockClassRule; -import com.github.tomakehurst.wiremock.matching.AnythingPattern; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; -import org.json.JSONException; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.prebid.server.VertxTest; -import org.prebid.server.deals.LineItemService; -import org.skyscreamer.jsonassert.ArrayValueMatcher; -import org.skyscreamer.jsonassert.Customization; -import org.skyscreamer.jsonassert.JSONAssert; -import org.skyscreamer.jsonassert.JSONCompareMode; -import org.skyscreamer.jsonassert.ValueMatcher; -import org.skyscreamer.jsonassert.comparator.CustomComparator; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.io.IOException; -import java.time.Clock; -import java.time.ZonedDateTime; -import java.time.temporal.WeekFields; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; -import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.post; -import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static io.restassured.RestAssured.given; -import static java.util.Collections.singletonList; -import static org.awaitility.Awaitility.await; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) -@RunWith(SpringRunner.class) -@TestPropertySource(locations = {"test-application.properties", "deals/test-deals-application.properties"}) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -public class PrematureReturnTest extends VertxTest { - - private static final int APP_PORT = 8070; - private static final int WIREMOCK_PORT = 8090; - - private static final RequestSpecification SPEC = IntegrationTest.spec(APP_PORT); - - @SuppressWarnings("unchecked") - @ClassRule - public static final WireMockClassRule WIRE_MOCK_RULE = new WireMockClassRule(options() - .port(WIREMOCK_PORT) - .extensions(IntegrationTest.ResponseOrderTransformer.class)); - - private static final String RUBICON = "rubicon"; - - @Autowired - private LineItemService lineItemService; - - @Autowired - private Clock clock; - - @BeforeClass - public static void setUpInner() throws IOException { - // given - WIRE_MOCK_RULE.stubFor(get(urlPathEqualTo("/planner-plan")) - .withQueryParam("instanceId", equalTo("localhost")) - .withQueryParam("region", equalTo("local")) - .withQueryParam("vendor", equalTo("local")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .willReturn(aResponse() - .withBody(plannerResponseFrom("deals/premature/test-planner-plan-response.json")))); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/planner-register")) - .withBasicAuth("username", "password") - .withHeader("pg-trx-id", new AnythingPattern()) - .withRequestBody(equalToJson(IntegrationTest.jsonFrom("deals/test-planner-register-request.json"), - false, true)) - .willReturn(aResponse())); - - WIRE_MOCK_RULE.stubFor(post(urlPathEqualTo("/user-data-details")) - .withRequestBody(equalToJson(IntegrationTest - .jsonFrom("deals/test-user-data-details-request.json"), false, true)) - .willReturn(aResponse().withBody(IntegrationTest - .jsonFrom("deals/test-user-data-details-rubicon-response.json")))); - } - - @Test - public void openrtb2AuctionWhenAllThreeBidsReturnsInOrderWithMinimalDelay() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 20L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-in-order-response.json", response, singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenAllThreeBidsReturnsInReverseOrderWithMinimalDelay() throws IOException, - JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem3"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem1"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 0L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-in-reverse-order-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenAllThreeBidsReturnsInOrderWithHighDelay() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 200L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-in-order-response.json", response, singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenAllThreeBidsReturnsInReverseOrderWithHighDelay() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem3"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem1"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 0L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-in-reverse-order-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenOnlyFirstBidComesBack() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-2.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-3.json"), 200, 20L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-first-bid-only-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenOnlySecondBidComesBack() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-1.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-3.json"), 200, 20L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-second-bid-only-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenOnlyThirdBidComesBack() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-1.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-2.json"), 200, 20L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 20L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-third-bid-only-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenFirstAndSecondBidsComesBackReverseWithHighDelay() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem1"); - lineItemResponseOrder.add("extLineItem3"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-1.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 0L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-3.json"), 200, 200L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-first-and-second-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - @Test - public void openrtb2AuctionWhenSecondAndThirdBidsComesBackReverseWithHighDelay() throws IOException, JSONException { - // given - awaitForLineItemMetadata(); - - final Queue lineItemResponseOrder = new LinkedList<>(); - lineItemResponseOrder.add("extLineItem3"); - lineItemResponseOrder.add("extLineItem2"); - lineItemResponseOrder.add("extLineItem1"); - - final Map idToExecutionParameters = new HashMap<>(); - idToExecutionParameters.put("extLineItem1", IntegrationTest.BidRequestExecutionParameters.of("extLineItem1", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-no-bid-response-1.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem2", IntegrationTest.BidRequestExecutionParameters.of("extLineItem2", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-2.json"), 200, 200L)); - idToExecutionParameters.put("extLineItem3", IntegrationTest.BidRequestExecutionParameters.of("extLineItem3", - IntegrationTest.jsonFrom("deals/premature/test-rubicon-bid-response-3.json"), 200, 0L)); - - stubExchange(lineItemResponseOrder, idToExecutionParameters); - - // when - final Response response = givenResponse(); - - final String expectedAuctionResponse = withTemporalFields(IntegrationTest.openrtbAuctionResponseFrom( - "deals/premature/responses/test-auction-third-and-second-response.json", response, - singletonList(RUBICON))); - - JSONAssert.assertEquals(expectedAuctionResponse, response.asString(), openrtbDeepDebugTimeComparator()); - } - - private Response givenResponse() throws IOException { - return given(SPEC) - .header("Referer", "http://www.example.com") - .header("User-Agent", "userAgent") - .header("X-Forwarded-For", "185.199.110.153") - // this uids cookie value stands for { "tempUIDs":{ "rubicon":{ "uid":"J5VLCWQP-26-CWFT", - // "expires":"2023-12-05T19:00:05.103329-03:00" } } } - .cookie("uids", "eyAidGVtcFVJRHMiOnsgInJ1Ymljb24iOnsgInVpZCI6Iko1VkxDV1FQ" - + "LTI2LUNXRlQiLCAiZXhwaXJlcyI6IjIwMjMtMTItMDVUMTk6MDA6MDUuMTAzMzI5LTAzOjAwIiB9IH0gfQ==") - .body(IntegrationTest.jsonFrom("deals/premature/test-auction-request.json")) - .post("/openrtb2/auction"); - } - - private void stubExchange(Queue lineItemResponseOrder, - Map idToExecutionParameters) { - WIRE_MOCK_RULE.stubFor(post(urlMatching("/rubicon-exchange.*")) - .willReturn(aResponse() - .withTransformers("response-order-transformer") - .withTransformerParameter(IntegrationTest.LINE_ITEM_RESPONSE_ORDER, lineItemResponseOrder) - .withTransformerParameter(IntegrationTest.ID_TO_EXECUTION_PARAMETERS, - idToExecutionParameters))); - } - - private void awaitForLineItemMetadata() { - await().atMost(20, TimeUnit.SECONDS).pollInterval(100, TimeUnit.MILLISECONDS) - .until(() -> lineItemService.accountHasDeals("2001", ZonedDateTime.now(clock))); - } - - private static String plannerResponseFrom(String templatePath) throws IOException { - final ZonedDateTime now = ZonedDateTime.now().withFixedOffsetZone(); - - return IntegrationTest.jsonFrom(templatePath) - .replaceAll("\\{\\{ now }}", now.toString()) - .replaceAll("\\{\\{ lineItem.startTime }}", now.minusDays(5).toString()) - .replaceAll("\\{\\{ lineItem.endTime }}", now.plusDays(5).toString()) - .replaceAll("\\{\\{ plan.startTime }}", now.minusHours(1).toString()) - .replaceAll("\\{\\{ plan.endTime }}", now.plusHours(1).toString()); - } - - private static CustomComparator openrtbDeepDebugTimeComparator() { - final ValueMatcher timeValueMatcher = (actual, expected) -> { - try { - return mapper.readValue("\"" + actual.toString() + "\"", ZonedDateTime.class) != null; - } catch (IOException e) { - return false; - } - }; - - final ArrayValueMatcher arrayValueMatcher = new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.trace.deals[*].time", timeValueMatcher))); - - final List arrayValueMatchers = IntStream.range(1, 5) - .mapToObj(i -> new Customization("ext.debug.trace.lineitems.lineItem" + i, - new ArrayValueMatcher<>(new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("ext.debug.trace.lineitems.lineItem" + i + "[*].time", - timeValueMatcher))))) - .collect(Collectors.toCollection(ArrayList::new)); - - arrayValueMatchers.add(new Customization("ext.debug.trace.deals", arrayValueMatcher)); - arrayValueMatchers.add(new Customization("ext.debug.httpcalls.rubicon", new ArrayValueMatcher<>( - new CustomComparator( - JSONCompareMode.NON_EXTENSIBLE, - new Customization("**.requestheaders", (o1, o2) -> true), - new Customization("**.requestbody", (o1, o2) -> true), - new Customization("**.responsebody", (o1, o2) -> true))))); - - return new CustomComparator(JSONCompareMode.NON_EXTENSIBLE, - arrayValueMatchers.toArray(new Customization[0])); - } - - private String withTemporalFields(String auctionResponse) { - final ZonedDateTime dateTime = ZonedDateTime.now(clock); - - return auctionResponse - .replaceAll("\"?\\{\\{ userdow }}\"?", Integer.toString( - dateTime.getDayOfWeek().get(WeekFields.SUNDAY_START.dayOfWeek()))) - .replaceAll("\"?\\{\\{ userhour }}\"?", Integer.toString(dateTime.getHour())); - } -} diff --git a/src/test/java/org/prebid/server/log/CriteriaManagerTest.java b/src/test/java/org/prebid/server/log/CriteriaManagerTest.java index 7be8a0c8af7..b8dd599c790 100644 --- a/src/test/java/org/prebid/server/log/CriteriaManagerTest.java +++ b/src/test/java/org/prebid/server/log/CriteriaManagerTest.java @@ -8,7 +8,6 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.prebid.server.VertxTest; -import org.prebid.server.deals.model.LogCriteriaFilter; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.ArgumentMatchers.any; @@ -35,14 +34,14 @@ public void setUp() { @Test public void addCriteriaShouldThrowIllegalArgumentExceptionWhenLoggerLevelHasInvalidValue() { assertThatIllegalArgumentException() - .isThrownBy(() -> criteriaManager.addCriteria("1001", "rubicon", "lineItemId1", "invalid", 800)) + .isThrownBy(() -> criteriaManager.addCriteria("1001", "rubicon", "invalid", 800)) .withMessage("Invalid LoggingLevel: invalid"); } @Test public void addCriteriaShouldAddVertxTimerWithLimitedDurationInMillis() { // given and when - criteriaManager.addCriteria("1001", "rubicon", "lineItemId1", "error", 800000); + criteriaManager.addCriteria("1001", "rubicon", "error", 800000); // then verify(vertx).setTimer(eq(300000L), any()); @@ -51,25 +50,7 @@ public void addCriteriaShouldAddVertxTimerWithLimitedDurationInMillis() { @Test public void addCriteriaShouldAddVertxTimerWithDefaultDurationInMillis() { // given and when - criteriaManager.addCriteria("1001", "rubicon", "lineItemId1", "error", 200000); - - // then - verify(vertx).setTimer(eq(200000L), any()); - } - - @Test - public void addCriteriaByFilterShouldAddVertxTimeWithLimitedDurationInMillis() { - // given and when - criteriaManager.addCriteria(LogCriteriaFilter.of("1001", "rubicon", "lineItemId1"), 800L); - - // then - verify(vertx).setTimer(eq(300000L), any()); - } - - @Test - public void addCriteriaByFilterShouldAddVertxTimeWithNotLimitedDurationInMillis() { - // given and when - criteriaManager.addCriteria(LogCriteriaFilter.of("1001", "rubicon", "lineItemId1"), 200L); + criteriaManager.addCriteria("1001", "rubicon", "error", 200000); // then verify(vertx).setTimer(eq(200000L), any()); diff --git a/src/test/java/org/prebid/server/log/CriteriaTest.java b/src/test/java/org/prebid/server/log/CriteriaTest.java index 4e5fcad3839..dd24d167fa0 100644 --- a/src/test/java/org/prebid/server/log/CriteriaTest.java +++ b/src/test/java/org/prebid/server/log/CriteriaTest.java @@ -20,73 +20,22 @@ public class CriteriaTest { @Mock private Logger logger; - @Test - public void logShouldChooseCriteriaLoggerLevelWhenAccountsMatchedAndElseFieldsAreNull() { - // given - final Criteria criteria = Criteria.create("account", null, null, Logger::error); - - // when - criteria.log(Criteria.builder().account("account").bidder("rubicon").build(), logger, "message", logger::info); - - // then - verify(logger).error(anyString()); - } - - @Test - public void logShouldChooseDefaultLogLevelWhenAccountsMatchedAndElseFieldsAreNotNullAndNotMatched() { - // given - final Criteria criteria = Criteria.create("account", "appnexus", null, Logger::error); - - // when - criteria.log(Criteria.builder().account("account").bidder("rubicon").build(), - logger, "message", logger::info); - - // then - verify(logger).info(anyString()); - } - - @Test - public void logShouldChooseCriteriaLogLevelAccountAndBidderMatchedLineItemIsNull() { - // given - final Criteria criteria = Criteria.create("account", "rubicon", null, Logger::error); - - // when - criteria.log(Criteria.builder().account("account").bidder("rubicon") - .lineItemId("lineItemId").build(), logger, "message", logger::info); - - // then - verify(logger).error(anyString()); - } - - @Test - public void logShouldChooseCriteriaLogLevelWhenAllMatched() { - // given - final Criteria criteria = Criteria.create("account", "rubicon", "lineItemId", Logger::error); - - // when - criteria.log(Criteria.builder().account("account").bidder("rubicon") - .lineItemId("lineItemId").build(), logger, "message", logger::info); - - // then - verify(logger).error(anyString()); - } - @Test public void logResponseShouldLogResponseWhenAllNotNullCriteriasPresent() { // given - final Criteria criteria = Criteria.create("account", null, "lineItemId", Logger::error); + final Criteria criteria = Criteria.create("account", null, Logger::error); // when - criteria.logResponse("Response has account and lineItemId", logger); + criteria.logResponse("Response has account", logger); // then verify(logger).error(anyString()); } @Test - public void logResponseShouldNotLogResponseWhenOneOfNutNullCriteriaMissing() { + public void logResponseShouldNotLogResponseWhenOneOfNotNullCriteriaMissing() { // given - final Criteria criteria = Criteria.create("account", null, "lineItemId", Logger::error); + final Criteria criteria = Criteria.create("account", "bidder", Logger::error); // when criteria.logResponse("Response has account", logger); @@ -98,19 +47,19 @@ public void logResponseShouldNotLogResponseWhenOneOfNutNullCriteriaMissing() { @Test public void logResponseAndRequestShouldLogResponseWhenAllNotNullCriteriasPresent() { // given - final Criteria criteria = Criteria.create("account", null, "lineItemId", Logger::error); + final Criteria criteria = Criteria.create("account", null, Logger::error); // when - criteria.logResponseAndRequest("Response has account", "Request has lineItemId", logger); + criteria.logResponseAndRequest("Response has account", "Request", logger); // then verify(logger, times(2)).error(anyString()); } @Test - public void logResponseAndRequestShouldNotLogResponseWhenOneOfNutNullCriteriaMissing() { + public void logResponseAndRequestShouldNotLogResponseWhenOneOfNotNullCriteriaMissing() { // given - final Criteria criteria = Criteria.create("account", null, "lineItemId", Logger::error); + final Criteria criteria = Criteria.create("account", "bidder", Logger::error); // when criteria.logResponseAndRequest("Response has account", "Request", logger); diff --git a/src/test/java/org/prebid/server/metric/MetricsTest.java b/src/test/java/org/prebid/server/metric/MetricsTest.java index 8a6518666d5..cf1d8d56225 100644 --- a/src/test/java/org/prebid/server/metric/MetricsTest.java +++ b/src/test/java/org/prebid/server/metric/MetricsTest.java @@ -672,140 +672,6 @@ public void updateCookieSyncFilteredMetricShouldIncrementMetric() { assertThat(metricRegistry.counter("cookie_sync.conversant.filtered").getCount()).isEqualTo(2); } - @Test - public void updateGpRequestMetricShouldIncrementPlannerRequestAndPlannerSuccessfulRequest() { - // when - metrics.updatePlannerRequestMetric(true); - - // then - assertThat(metricRegistry.counter("pg.planner_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("pg.planner_request_successful").getCount()).isEqualTo(1); - } - - @Test - public void updateGpRequestMetricShouldIncrementPlannerRequestAndPlannerFailedRequest() { - // when - metrics.updatePlannerRequestMetric(false); - - // then - assertThat(metricRegistry.counter("pg.planner_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("pg.planner_request_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateGpRequestMetricShouldIncrementUserDetailsSuccessfulRequest() { - // when - metrics.updateUserDetailsRequestMetric(true); - - // then - assertThat(metricRegistry.counter("user_details_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("user_details_request_successful").getCount()).isEqualTo(1); - } - - @Test - public void updateGpRequestMetricShouldIncrementUserDetailsFailedRequest() { - // when - metrics.updateUserDetailsRequestMetric(false); - - // then - assertThat(metricRegistry.counter("user_details_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("user_details_request_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateGpRequestMetricShouldIncrementWinSuccessfulRequest() { - // when - metrics.updateWinEventRequestMetric(true); - - // then - assertThat(metricRegistry.counter("win_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("win_request_successful").getCount()).isEqualTo(1); - } - - @Test - public void updateGpRequestMetricShouldIncrementWinFailedRequest() { - // when - metrics.updateWinEventRequestMetric(false); - - // then - assertThat(metricRegistry.counter("win_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("win_request_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateWinRequestTimeShouldLogTime() { - // when - metrics.updateWinRequestTime(20L); - - // then - assertThat(metricRegistry.timer("win_request_time").getCount()).isEqualTo(1); - } - - @Test - public void updateWinRequestPreparationFailedShouldIncrementMetric() { - // when - metrics.updateWinRequestPreparationFailed(); - - // then - assertThat(metricRegistry.counter("win_request_preparation_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateUserDetailsRequestPreparationFailedShouldIncrementMetric() { - // when - metrics.updateUserDetailsRequestPreparationFailed(); - - // then - assertThat(metricRegistry.counter("user_details_request_preparation_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateDeliveryRequestMetricShouldIncrementDeliveryRequestAndSuccessfulDeliveryRequest() { - // when - metrics.updateDeliveryRequestMetric(true); - - // then - assertThat(metricRegistry.counter("pg.delivery_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("pg.delivery_request_successful").getCount()).isEqualTo(1); - } - - @Test - public void updateDeliveryRequestMetricShouldIncrementDeliveryRequestAndFailedDeliveryRequest() { - // when - metrics.updateDeliveryRequestMetric(false); - - // then - assertThat(metricRegistry.counter("pg.delivery_requests").getCount()).isEqualTo(1); - assertThat(metricRegistry.counter("pg.delivery_request_failed").getCount()).isEqualTo(1); - } - - @Test - public void updateLineItemsNumberMetricShouldIncrementLineItemsNumberForAAcountValue() { - // when - metrics.updateLineItemsNumberMetric(20L); - - // then - assertThat(metricRegistry.counter("pg.planner_lineitems_received").getCount()).isEqualTo(20); - } - - @Test - public void updatePlannerRequestTimeShouldLogTime() { - // when - metrics.updatePlannerRequestTime(20L); - - // then - assertThat(metricRegistry.timer("pg.planner_request_time").getCount()).isEqualTo(1); - } - - @Test - public void updateDeliveryRequestTimeShouldLogTime() { - // when - metrics.updateDeliveryRequestTime(20L); - - // then - assertThat(metricRegistry.timer("pg.delivery_request_time").getCount()).isEqualTo(1); - } - @Test public void updateAuctionTcfMetricsShouldIncrementMetrics() { // when @@ -1353,15 +1219,6 @@ public void updateAccountModuleDurationMetricShouldNotIncrementMetricsIfVerbosit .isZero(); } - @Test - public void shouldIncrementWinNotificationMetric() { - // when - metrics.updateWinNotificationMetric(); - - // then - assertThat(metricRegistry.counter("win_notifications").getCount()).isEqualTo(1); - } - @Test public void shouldIncrementRequestsActivityDisallowedCount() { // when diff --git a/src/test/java/org/prebid/server/util/HttpUtilTest.java b/src/test/java/org/prebid/server/util/HttpUtilTest.java index 7abfcc6532f..d516ad2c6d8 100644 --- a/src/test/java/org/prebid/server/util/HttpUtilTest.java +++ b/src/test/java/org/prebid/server/util/HttpUtilTest.java @@ -11,18 +11,15 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.prebid.server.exception.PreBidException; import org.prebid.server.model.CaseInsensitiveMultiMap; import org.prebid.server.model.HttpRequestContext; -import java.time.ZonedDateTime; import java.util.Map; import java.util.function.Consumer; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.tuple; import static org.mockito.ArgumentMatchers.any; @@ -204,53 +201,4 @@ public void executeSafelyShouldReturnFalseIfResponseFailed() { // then assertThat(result).isFalse(); } - - @Test - public void getDateFromHeaderShouldReturnDate() { - // given - final MultiMap headers = MultiMap.caseInsensitiveMultiMap().add("date-header", - "2019-11-04T13:31:24.365+02:00[Europe/Kiev]"); - - // when - final ZonedDateTime result = HttpUtil.getDateFromHeader(headers, "date-header"); - - // then - assertThat(result).isEqualTo(ZonedDateTime.parse("2019-11-04T13:31:24.365+02:00[Europe/Kiev]")); - } - - @Test - public void getDateFromHeaderShouldReturnNullWhenHeaderWasNotFound() { - // given - final MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - - // when - final ZonedDateTime result = HttpUtil.getDateFromHeader(headers, "not-exist"); - - // then - assertThat(result).isNull(); - } - - @Test - public void getDateFromHeaderShouldThrowExceptionWhenHeaderHasIncorrectFormat() { - // given - final MultiMap headers = MultiMap.caseInsensitiveMultiMap().add("date-header", "invalid"); - - // when and then - assertThatThrownBy(() -> HttpUtil.getDateFromHeader(headers, "date-header")) - .isInstanceOf(PreBidException.class) - .hasMessage("date-header header is not compatible to ISO-8601 format: invalid"); - } - - @Test - public void getDateFromHeaderShouldReturnDateFromHeaders() { - // given - final MultiMap headers = MultiMap.caseInsensitiveMultiMap().add("date-header", - "2019-11-04T13:31:24.365+02:00[Europe/Kiev]"); - - // when - final ZonedDateTime result = HttpUtil.getDateFromHeader(headers, "date-header"); - - // then - assertThat(result).isEqualTo(ZonedDateTime.parse("2019-11-04T13:31:24.365+02:00[Europe/Kiev]")); - } } diff --git a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java index 2b87c30ae63..bd312b447c1 100644 --- a/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java +++ b/src/test/java/org/prebid/server/validation/ResponseBidValidatorTest.java @@ -3,10 +3,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.iab.openrtb.request.Banner; import com.iab.openrtb.request.BidRequest; -import com.iab.openrtb.request.Deal; import com.iab.openrtb.request.Format; import com.iab.openrtb.request.Imp; -import com.iab.openrtb.request.Pmp; import com.iab.openrtb.response.Bid; import org.junit.Before; import org.junit.Rule; @@ -20,8 +18,6 @@ import org.prebid.server.bidder.model.BidderBid; import org.prebid.server.metric.MetricName; import org.prebid.server.metric.Metrics; -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.response.BidType; import org.prebid.server.settings.model.Account; import org.prebid.server.settings.model.AccountAuctionConfig; @@ -29,7 +25,6 @@ import org.prebid.server.validation.model.ValidationResult; import java.math.BigDecimal; -import java.util.List; import java.util.function.UnaryOperator; import static java.util.Arrays.asList; @@ -37,7 +32,6 @@ import static java.util.function.UnaryOperator.identity; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verify; import static org.prebid.server.settings.model.BidValidationEnforcement.enforce; @@ -62,7 +56,7 @@ public class ResponseBidValidatorTest extends VertxTest { @Before public void setUp() { - target = new ResponseBidValidator(enforce, enforce, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(enforce, enforce, metrics, 0.01); given(bidderAliases.resolveBidder(anyString())).willReturn(BIDDER_NAME); } @@ -359,7 +353,7 @@ public void validateShouldReturnSuccessfulResultForValidBid() { @Test public void validateShouldReturnSuccessIfBannerSizeValidationNotEnabled() { // given - target = new ResponseBidValidator(skip, enforce, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(skip, enforce, metrics, 0.01); // when final ValidationResult result = target.validate( @@ -375,7 +369,7 @@ public void validateShouldReturnSuccessIfBannerSizeValidationNotEnabled() { @Test public void validateShouldReturnSuccessWithWarningIfBannerSizeEnforcementIsWarn() { // given - target = new ResponseBidValidator(warn, enforce, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(warn, enforce, metrics, 0.01); // when final ValidationResult result = target.validate( @@ -396,7 +390,7 @@ public void validateShouldReturnSuccessWithWarningIfBannerSizeEnforcementIsWarn( @Test public void validateShouldReturnSuccessIfSecureMarkupValidationNotEnabled() { // given - target = new ResponseBidValidator(enforce, skip, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(enforce, skip, metrics, 0.01); // when final ValidationResult result = target.validate( @@ -412,7 +406,7 @@ public void validateShouldReturnSuccessIfSecureMarkupValidationNotEnabled() { @Test public void validateShouldReturnSuccessWithWarningIfSecureMarkupEnforcementIsWarn() { // given - target = new ResponseBidValidator(enforce, warn, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(enforce, warn, metrics, 0.01); // when final ValidationResult result = target.validate( @@ -446,7 +440,7 @@ public void validateShouldIncrementSizeValidationErrMetrics() { @Test public void validateShouldIncrementSizeValidationWarnMetrics() { // given - target = new ResponseBidValidator(warn, warn, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(warn, warn, metrics, 0.01); // when target.validate( @@ -475,7 +469,7 @@ public void validateShouldIncrementSecureValidationErrMetrics() { @Test public void validateShouldIncrementSecureValidationWarnMetrics() { // given - target = new ResponseBidValidator(warn, warn, metrics, jacksonMapper, true, 0.01); + target = new ResponseBidValidator(warn, warn, metrics, 0.01); // when target.validate( @@ -488,189 +482,6 @@ public void validateShouldIncrementSecureValidationWarnMetrics() { verify(metrics).updateSecureValidationMetrics(BIDDER_NAME, ACCOUNT_ID, MetricName.warn); } - @Test - public void validateShouldReturnSuccessfulResultForValidNonDealBid() { - final ValidationResult result = target.validate( - givenVideoBid(identity()), - BIDDER_NAME, - givenAuctionContext(), - bidderAliases); - - assertThat(result.hasErrors()).isFalse(); - } - - @Test - public void validateShouldFailIfBidHasNoDealid() { - final ValidationResult result = target.validate( - givenVideoBid(identity()), - BIDDER_NAME, - givenAuctionContext(givenRequest(identity())), - bidderAliases); - - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Bid \"bidId1\" missing required field 'dealid'"); - } - - @Test - public void validateShouldSuccessIfBidHasDealidAndImpHasNoDeals() { - final ValidationResult result = target.validate( - givenVideoBid(bid -> bid.dealid("dealId1")), - BIDDER_NAME, - givenAuctionContext(givenRequest(identity())), - bidderAliases); - - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getWarnings()).isEmpty(); - } - - @Test - public void validateShouldWarnIfBidHasDealidMissingInImp() { - given(bidderAliases.isSame(eq(BIDDER_NAME), eq(BIDDER_NAME))).willReturn(true); - - final ValidationResult result = target.validate( - givenVideoBid(bid -> bid.dealid("dealId1")), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp.pmp(pmp(asList( - deal(builder -> builder - .id("dealId2") - .ext(mapper.valueToTree(ExtDeal.of( - ExtDealLine.of(null, null, null, BIDDER_NAME))))), - deal(builder -> builder - .id("dealId3") - .ext(mapper.valueToTree(ExtDeal.of( - ExtDealLine.of(null, null, null, BIDDER_NAME))))), - deal(builder -> builder - .id("dealId4") - .ext(mapper.valueToTree(ExtDeal.of( - ExtDealLine.of(null, null, null, "anotherBidder")))))))))), - bidderAliases); - - assertThat(result.getWarnings()).hasSize(1) - .containsOnly("WARNING: Bid \"bidId1\" has 'dealid' not present in corresponding imp in request." - + " 'dealid' in bid: 'dealId1', deal Ids in imp: 'dealId2,dealId3'"); - } - - @Test - public void validateShouldFailIfBidIsBannerAndImpHasNoBanner() { - target = new ResponseBidValidator(skip, enforce, metrics, jacksonMapper, true, 0.01); - - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1")), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder.id("dealId1"))))))), - bidderAliases); - - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Bid \"bidId1\" has banner media type but corresponding imp in request is missing " - + "'banner' object"); - } - - @Test - public void validateShouldFailIfBidIsBannerAndSizeHasNoMatchInBannerFormats() { - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1").w(300).h(400)), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder.id("dealId1"))))) - .banner(Banner.builder() - .format(singletonList(Format.builder().w(400).h(500).build())) - .build()))), - bidderAliases); - - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Bid \"bidId1\" has 'w' and 'h' not supported by corresponding imp in request. Bid " - + "dimensions: '300x400', formats in imp: '400x500'"); - } - - @Test - public void validateShouldFailIfBidIsBannerAndSizeHasNoMatchInLineItem() { - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1").w(300).h(400)), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId", null, - singletonList(Format.builder().w(500).h(600).build()), null)))))))) - .banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(400).build())) - .build()))), - bidderAliases); - - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Bid \"bidId1\" has 'w' and 'h' not matched to Line Item. Bid dimensions: '300x400', " - + "Line Item sizes: '500x600'"); - } - - @Test - public void validateShouldFailIfBidIsBannerAndMatchingLineItemDoesNotHaveSizes() { - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1").w(300).h(400)), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of("lineItemId", null, - null, null)))))))) - .banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(400).build())) - .build()))), - bidderAliases); - - assertThat(result.getErrors()).hasSize(1) - .containsOnly("Line item sizes were not found for bidId bidId1 and dealId dealId1"); - } - - @Test - public void validateShouldSuccessIfBidIsBannerAndSizeHasNoMatchInLineItemForNonPgDeal() { - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1").w(300).h(400)), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of(null, null, - singletonList(Format.builder().w(500).h(600).build()), null)))))))) - .banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(400).build())) - .build()))), - bidderAliases); - - assertThat(result.getErrors()).isEmpty(); - assertThat(result.getWarnings()).isEmpty(); - } - - @Test - public void validateShouldReturnSuccessfulResultForValidDealNonBannerBid() { - final ValidationResult result = target.validate( - givenVideoBid(bid -> bid.dealid("dealId1")), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp.pmp(pmp(singletonList( - deal(builder -> builder.id("dealId1"))))))), - bidderAliases); - - assertThat(result.hasErrors()).isFalse(); - } - - @Test - public void validateShouldReturnSuccessfulResultForValidDealBannerBid() { - final ValidationResult result = target.validate( - givenBid(bid -> bid.dealid("dealId1").w(300).h(400)), - BIDDER_NAME, - givenAuctionContext(givenRequest(imp -> imp - .pmp(pmp(singletonList(deal(builder -> builder - .id("dealId1") - .ext(mapper.valueToTree(ExtDeal.of(ExtDealLine.of(null, null, - singletonList(Format.builder().w(300).h(400).build()), null)))))))) - .banner(Banner.builder() - .format(singletonList(Format.builder().w(300).h(400).build())) - .build()))), - bidderAliases); - - assertThat(result.hasErrors()).isFalse(); - } - private BidRequest givenRequest(UnaryOperator impCustomizer) { final ObjectNode ext = mapper.createObjectNode().set( "prebid", mapper.createObjectNode().set( @@ -686,14 +497,6 @@ private BidRequest givenRequest(UnaryOperator impCustomizer) { return BidRequest.builder().imp(singletonList(imp)).build(); } - private static Pmp pmp(List deals) { - return Pmp.builder().deals(deals).build(); - } - - private static Deal deal(UnaryOperator dealCustomizer) { - return dealCustomizer.apply(Deal.builder()).build(); - } - private static BidderBid givenVideoBid(UnaryOperator bidCustomizer) { return givenBid(BidType.video, bidCustomizer); } diff --git a/src/test/java/org/prebid/server/vast/VastModifierTest.java b/src/test/java/org/prebid/server/vast/VastModifierTest.java index 5593a535028..fed272f1524 100644 --- a/src/test/java/org/prebid/server/vast/VastModifierTest.java +++ b/src/test/java/org/prebid/server/vast/VastModifierTest.java @@ -35,7 +35,6 @@ public class VastModifierTest { private static final String VAST_URL_TRACKING = "http://external-url/event"; private static final String BID_ID = "bidId"; private static final String BID_NURL = "nurl1"; - private static final String LINEITEM_ID = "lineItemId"; private static final long AUCTION_TIMESTAMP = 1000L; @Rule @@ -52,7 +51,7 @@ public class VastModifierTest { @Before public void setUp() { - given(eventsService.vastUrlTracking(any(), any(), any(), any(), any())) + given(eventsService.vastUrlTracking(any(), any(), any(), any())) .willReturn(VAST_URL_TRACKING); given(bidderCatalog.isModifyingVastXmlAllowed(any())).willReturn(true); @@ -97,7 +96,7 @@ public void modifyVastXmlShouldNotModifyVastAndAppendUrlWhenValueWithoutImpressi final JsonNode result = target.modifyVastXml(true, singleton(BIDDER), givenPutObject(vastWithoutImpression), ACCOUNT_ID, INTEGRATION); - verify(eventsService).vastUrlTracking(any(), any(), any(), any(), any()); + verify(eventsService).vastUrlTracking(any(), any(), any(), any()); assertThat(result).isEqualTo(vastWithoutImpression); } @@ -111,11 +110,11 @@ public void modifyVastXmlShouldModifyVastAndAppendUrl() { // then final String modifiedVast = """ - prebid.org wrapper\ - \ - \ - \ - """; + prebid.org wrapper\ + \ + \ + \ + """; assertThat(result).isEqualTo(new TextNode(modifiedVast)); } @@ -127,8 +126,7 @@ public void createBidVastXmlShouldNotModifyWhenBidderNotAllowed() { // when final String result = target - .createBidVastXml(BIDDER, adm(), BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, adm(), BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then assertThat(result).isEqualTo(adm()); @@ -137,8 +135,8 @@ public void createBidVastXmlShouldNotModifyWhenBidderNotAllowed() { @Test public void createBidVastXmlShouldInjectBidNurlWhenBidAdmIsNullAndEventsDisabledByAccount() { // when - final String result = target.createBidVastXml(BIDDER, null, BID_NURL, BID_ID, ACCOUNT_ID, - givenEventsContext(false), emptyList(), LINEITEM_ID); + final String result = target + .createBidVastXml(BIDDER, null, BID_NURL, BID_ID, ACCOUNT_ID, givenEventsContext(false), emptyList()); // then assertThat(result).isEqualTo(modifiedAdm(BID_NURL)); @@ -147,8 +145,8 @@ public void createBidVastXmlShouldInjectBidNurlWhenBidAdmIsNullAndEventsDisabled @Test public void createBidVastXmlShouldInjectBidNurlWhenBidAdmIsEmptyAndEventsDisabledByAccount() { // when - final String result = target.createBidVastXml(BIDDER, "", BID_NURL, BID_ID, ACCOUNT_ID, - givenEventsContext(false), emptyList(), LINEITEM_ID); + final String result = target + .createBidVastXml(BIDDER, "", BID_NURL, BID_ID, ACCOUNT_ID, givenEventsContext(false), emptyList()); // then assertThat(result).isEqualTo(modifiedAdm(BID_NURL)); @@ -157,8 +155,8 @@ public void createBidVastXmlShouldInjectBidNurlWhenBidAdmIsEmptyAndEventsDisable @Test public void createBidVastXmlShouldReturnAdmWhenBidAdmIsPresentAndEventsDisabledByAccount() { // when - final String result = target.createBidVastXml(BIDDER, adm(), BID_NURL, BID_ID, ACCOUNT_ID, - givenEventsContext(false), emptyList(), LINEITEM_ID); + final String result = target + .createBidVastXml(BIDDER, adm(), BID_NURL, BID_ID, ACCOUNT_ID, givenEventsContext(false), emptyList()); // then assertThat(result).isEqualTo(adm()); @@ -169,11 +167,10 @@ public void createBidVastXmlShouldBeModifiedWithNewImpressionVastUrlWhenEventsEn // when final String bidAdm = "http:/test.com"; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo("http:/test.com" + ""); @@ -185,11 +182,10 @@ public void createBidVastXmlShouldBeModifiedWithNewImpressionAfterExistingImpres final String bidAdm = "http:/test.com" + "http:/test2.com"; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo("http:/test.com" + "http:/test2.com" @@ -201,11 +197,10 @@ public void createBidVastXmlShouldInsertImpressionTagForEmptyInLine() { // when final String bidAdm = ""; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(""); } @@ -215,11 +210,10 @@ public void createBidVastXmlShouldNotInsertImpressionTagForNoInLineCloseTag() { // when final String bidAdm = ""; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(bidAdm); } @@ -229,11 +223,10 @@ public void createBidVastXmlShouldModifyWrapperTagInCaseInsensitiveMode() { // when final String bidAdm = "http:/test.com"; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo("http:/test.com" + ""); @@ -242,13 +235,11 @@ public void createBidVastXmlShouldModifyWrapperTagInCaseInsensitiveMode() { @Test public void createBidVastXmlShouldInsertImpressionTagForEmptyWrapper() { // when - final String result = target - .createBidVastXml(BIDDER, "", BID_NURL, - BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + final String result = target.createBidVastXml( + BIDDER, "", BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result) .isEqualTo(""); @@ -259,11 +250,10 @@ public void createBidVastXmlShouldNotInsertImpressionTagForNoWrapperCloseTag() { // when final String bidAdm = ""; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(bidAdm); } @@ -273,11 +263,10 @@ public void createBidVastXmlShouldModifyInlineTagInCaseInsensitiveMode() { // when final String bidAdm = "http:/test.com"; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo("http:/test.com" + ""); @@ -288,11 +277,10 @@ public void createBidVastXmlShouldBeModifiedIfInLineHasNoImpressionTags() { // when final String bidAdm = ""; final String result = target - .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList(), - LINEITEM_ID); + .createBidVastXml(BIDDER, bidAdm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), emptyList()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(""); } @@ -303,10 +291,10 @@ public void createBidVastXmlShouldNotBeModifiedIfNoParentTagsPresent() { final String adm = "http:/test.com"; final List warnings = new ArrayList<>(); final String result = target - .createBidVastXml(BIDDER, adm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), warnings, LINEITEM_ID); + .createBidVastXml(BIDDER, adm, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), warnings); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(adm); assertThat(warnings).containsExactly("VastXml does not contain neither InLine nor Wrapper for bidder response"); verify(metrics).updateAdapterRequestErrorMetric(BIDDER, MetricName.badserverresponse); @@ -316,11 +304,11 @@ public void createBidVastXmlShouldNotBeModifiedIfNoParentTagsPresent() { public void createBidVastXmlShouldNotModifyWhenEventsEnabledAndAdmHaveNoImpression() { // when final String admWithNoImpression = "no impression"; - final String result = target.createBidVastXml(BIDDER, admWithNoImpression, BID_NURL, BID_ID, - ACCOUNT_ID, eventsContext(), new ArrayList<>(), LINEITEM_ID); + final String result = target.createBidVastXml( + BIDDER, admWithNoImpression, BID_NURL, BID_ID, ACCOUNT_ID, eventsContext(), new ArrayList<>()); // then - verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, LINEITEM_ID, eventsContext()); + verify(eventsService).vastUrlTracking(BID_ID, BIDDER, ACCOUNT_ID, eventsContext()); assertThat(result).isEqualTo(admWithNoImpression); } diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-device-targeting.json b/src/test/resources/org/prebid/server/deals/targeting/test-device-targeting.json deleted file mode 100644 index b28efce2c2f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-device-targeting.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$and": [ - { - "device.ext.deviceinfoprovider.browser": { - "$in": [ - "Chrome", - "Firefox" - ] - } - }, - { - "device.geo.ext.geoprovider.country": { - "$in": [ - "us", - "jp" - ] - } - } - ] -} diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-and-with-non-array.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-and-with-non-array.json deleted file mode 100644 index 4459a762640..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-and-with-non-array.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$and": {} -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-function.json deleted file mode 100644 index 8315dec8997..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.size": { - "$in": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-geo-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-geo-function.json deleted file mode 100644 index 07ac026bd2b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-geo-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "geo.distance": { - "$intersects": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-segment-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-segment-function.json deleted file mode 100644 index ea2a189602f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-segment-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "segment.bluekai": { - "$in": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-string-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-string-function.json deleted file mode 100644 index b451647996b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-string-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.adslot": { - "$intersects": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-typed-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-typed-function.json deleted file mode 100644 index eddac02192f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-incompatible-typed-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "bidp.rubicon.siteId": { - "$within": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-non-object.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-non-object.json deleted file mode 100644 index f67d1e4a258..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-category-non-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "adunit.size": 123 -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-in-integers-non-integer.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-in-integers-non-integer.json deleted file mode 100644 index 19fd40b0906..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-in-integers-non-integer.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "user.ext.time.userhour": { - "$in": [ - "abc" - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-non-array.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-non-array.json deleted file mode 100644 index 85710c883e9..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-non-array.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.size": { - "$intersects": {} - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-empty-size.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-empty-size.json deleted file mode 100644 index e3c0b26ba08..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-empty-size.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "adunit.size": { - "$intersects": [ - { - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-objects.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-objects.json deleted file mode 100644 index 91b6c932bde..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-objects.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "adunit.size": { - "$intersects": [ - 123, - 234 - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-readable-size.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-readable-size.json deleted file mode 100644 index 57ef2fce627..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-sizes-non-readable-size.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "adunit.size": { - "$intersects": [ - { - "w": {} - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-empty.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-empty.json deleted file mode 100644 index 5a1cd32db73..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-empty.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "adunit.mediatype": { - "$intersects": [ - "" - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-non-string.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-non-string.json deleted file mode 100644 index 974de4e4c1a..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-intersects-strings-non-string.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "adunit.mediatype": { - "$intersects": [ - 123 - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-empty.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-empty.json deleted file mode 100644 index 413e4c7b71f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-empty.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.adslot": { - "$matches": "" - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-non-string.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-non-string.json deleted file mode 100644 index 3f2439279d9..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-matches-non-string.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.adslot": { - "$matches": 123 - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-boolean-args.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-boolean-args.json deleted file mode 100644 index d544404457e..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-boolean-args.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$and": [ - { - "aaa": {}, - "bbb": {} - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-function.json deleted file mode 100644 index f4d51caf96b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields-function.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "adunit.size": { - "aaa": {}, - "bbb": {} - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields.json deleted file mode 100644 index 186dd09685f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-multiple-fields.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "aaa": {}, - "bbb": {} -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-non-object.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-non-object.json deleted file mode 100644 index 5862557ee7f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-non-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$and": 123 -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-not-with-non-object.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-not-with-non-object.json deleted file mode 100644 index 6741ef4d8ef..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-not-with-non-object.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "$not": [] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-incompatible-type.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-incompatible-type.json deleted file mode 100644 index edafbc6a05b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-incompatible-type.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "bidp.rubicon.siteId": { - "$in": [ - false - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-mixed-types.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-mixed-types.json deleted file mode 100644 index 40b94d6ec36..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-typed-function-mixed-types.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "bidp.rubicon.siteId": { - "$in": [ - 123, - "321" - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-field.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-field.json deleted file mode 100644 index 81cc228d55f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-field.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "aaa": {} -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-function.json deleted file mode 100644 index ccea774510a..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.size": { - "$abc": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-string-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-string-function.json deleted file mode 100644 index d83962f0989..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-string-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "adunit.adslot": { - "$abc": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-typed-function.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-typed-function.json deleted file mode 100644 index 0cc0c3a781b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-unknown-typed-function.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "bidp.rubicon.siteId": { - "$abc": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-empty-georegion.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-empty-georegion.json deleted file mode 100644 index 22a638b0b53..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-empty-georegion.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "geo.distance": { - "$within": { - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-object.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-object.json deleted file mode 100644 index d10af646564..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-object.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "geo.distance": { - "$within": [] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-readable-georegion.json b/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-readable-georegion.json deleted file mode 100644 index b21c6a2523d..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-invalid-targeting-definition-within-non-readable-georegion.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "geo.distance": { - "$within": { - "lat": {} - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-and-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-and-definition.json deleted file mode 100644 index ddb8501fd06..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-and-definition.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$not": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 450, - "h": 250 - }, - { - "w": 400, - "h": 200 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner", - "video" - ] - } - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-in-integers-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-in-integers-definition.json deleted file mode 100644 index 27284bdc6d3..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-in-integers-definition.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$not": { - "bidp.rubicon.siteId": { - "$in": [ - 785, - 778 - ] - } - } -} diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-in-strings-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-in-strings-definition.json deleted file mode 100644 index 011d00d81c1..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-in-strings-definition.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$not": { - "site.domain": { - "$in": [ - "nba.com", - "cnn.com" - ] - } - } -} diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-integer-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-integer-definition.json deleted file mode 100644 index 08c0b5c166c..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-integer-definition.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$not": { - "ufpd.data.someId": { - "$intersects": [ - 123, - 321 - ] - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-sizes-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-sizes-definition.json deleted file mode 100644 index 50f0f524a4b..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-intersects-sizes-definition.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$not": { - "adunit.size": { - "$intersects": [ - { - "w": 450, - "h": 250 - }, - { - "w": 400, - "h": 200 - } - ] - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-matches-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-matches-definition.json deleted file mode 100644 index 4f3d9a69c3f..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-matches-definition.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$not": { - "site.domain": { - "$matches": "*nba.com*" - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-or-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-or-definition.json deleted file mode 100644 index b8da565c351..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-or-definition.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$not": { - "$or": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 450, - "h": 250 - }, - { - "w": 400, - "h": 200 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner", - "video" - ] - } - } - ] - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-not-within-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-not-within-definition.json deleted file mode 100644 index 98a0670f5fa..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-not-within-definition.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$not": { - "geo.distance": { - "$within": { - "lat": 2.424744, - "lon": 3.506435, - "radiusMiles": 10 - } - } - } -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/deals/targeting/test-valid-targeting-definition.json b/src/test/resources/org/prebid/server/deals/targeting/test-valid-targeting-definition.json deleted file mode 100644 index cd2acc99523..00000000000 --- a/src/test/resources/org/prebid/server/deals/targeting/test-valid-targeting-definition.json +++ /dev/null @@ -1,354 +0,0 @@ -{ - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - }, - { - "w": 400, - "h": 200 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner", - "video" - ] - } - }, - { - "$or": [ - { - "site.domain": { - "$matches": "*nba.com*" - } - }, - { - "site.domain": { - "$matches": "nba.com*" - } - }, - { - "site.domain": { - "$in": [ - "nba.com", - "cnn.com" - ] - } - } - ] - }, - { - "$or": [ - { - "site.referrer": { - "$matches": "*sports*" - } - }, - { - "site.referrer": { - "$matches": "http://nba.com/lalakers*" - } - }, - { - "site.referrer": { - "$in": [ - "http://cnn.com/culture", - "http://cnn.com/weather" - ] - } - } - ] - }, - { - "$or": [ - { - "app.bundle": { - "$matches": "*com.google.calendar*" - } - }, - { - "app.bundle": { - "$matches": "com.google.calendar*" - } - }, - { - "app.bundle": { - "$in": [ - "com.google.calendar", - "com.tmz" - ] - } - } - ] - }, - { - "$or": [ - { - "adunit.adslot": { - "$matches": "*/home/top*" - } - }, - { - "adunit.adslot": { - "$matches": "/home/top*" - } - }, - { - "adunit.adslot": { - "$in": [ - "/home/top", - "/home/bottom" - ] - } - } - ] - }, - { - "device.geo.ext.vendor.attribute": { - "$in": [ - "device_geo_ext_value1", - "device_geo_ext_value2" - ] - } - }, - { - "device.geo.ext.vendor.nested.attribute": { - "$in": [ - "device_geo_ext_nested_value1", - "device_geo_ext_nested_value2" - ] - } - }, - { - "device.ext.vendor.attribute": { - "$in": [ - "device_ext_value1", - "device_ext_value2" - ] - } - }, - { - "device.ext.vendor.nested.attribute": { - "$in": [ - "device_ext_nested_value1", - "device_ext_nested_value2" - ] - } - }, - { - "pos": { - "$in": [ - 1, - 3 - ] - } - }, - { - "geo.distance": { - "$within": { - "lat": 123.456, - "lon": 789.123, - "radiusMiles": 10 - } - } - }, - { - "$or": [ - { - "bidp.rubicon.siteId": { - "$in": [ - 123, - 321 - ] - } - }, - { - "bidp.rubicon.siteId": { - "$intersects": [ - 123, - 321 - ] - } - } - ] - }, - { - "$or": [ - { - "bidp.appnexus.placementName": { - "$matches": "*somePlacement*" - } - }, - { - "bidp.appnexus.placementName": { - "$matches": "somePlacement*" - } - }, - { - "bidp.appnexus.placementName": { - "$in": [ - "somePlacement1", - "somePlacement2" - ] - } - }, - { - "bidp.appnexus.placementName": { - "$intersects": [ - "somePlacement1", - "somePlacement2" - ] - } - } - ] - }, - { - "$or": [ - { - "segment.rubicon": { - "$intersects": [ - "123", - "234", - "345" - ] - } - }, - { - "segment.bluekai": { - "$intersects": [ - "123", - "234", - "345" - ] - } - } - ] - }, - { - "$or": [ - { - "ufpd.someId": { - "$in": [ - 123, - 321 - ] - } - }, - { - "ufpd.someId": { - "$intersects": [ - 123, - 321 - ] - } - } - ] - }, - { - "$or": [ - { - "ufpd.sport": { - "$matches": "*hockey*" - } - }, - { - "ufpd.sport": { - "$matches": "hockey*" - } - }, - { - "ufpd.sport": { - "$in": [ - "hockey", - "soccer" - ] - } - }, - { - "ufpd.sport": { - "$intersects": [ - "hockey", - "soccer" - ] - } - } - ] - }, - { - "$or": [ - { - "sfpd.someId": { - "$in": [ - 123, - 321 - ] - } - }, - { - "sfpd.someId": { - "$intersects": [ - 123, - 321 - ] - } - } - ] - }, - { - "$or": [ - { - "sfpd.sport": { - "$matches": "*hockey*" - } - }, - { - "sfpd.sport": { - "$matches": "hockey*" - } - }, - { - "sfpd.sport": { - "$in": [ - "hockey", - "soccer" - ] - } - }, - { - "sfpd.sport": { - "$intersects": [ - "hockey", - "soccer" - ] - } - } - ] - }, - { - "user.ext.time.userdow": { - "$in": [ - 5, - 6 - ] - } - }, - { - "user.ext.time.userhour": { - "$in": [ - 10, - 11, - 12, - 13, - 14 - ] - } - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-and-second-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-and-second-response.json deleted file mode 100644 index 19264d25845..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-and-second-response.json +++ /dev/null @@ -1,444 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "price": 10.6, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "10.60", - "hb_pb_rubicon": "10.60", - "hb_deal_rubicon": "dealId1", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId1" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 10.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId1\",\"impid\":\"impId1\",\"dealid\":\"dealId1\",\"price\":10.6,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId2\",\"impid\":\"impId1\",\"dealid\":\"dealId2\",\"price\":9.6,\"adm\":\"\",\"crid\":\"crid2\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}" - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "domain": "example.com", - "id": "2001" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem1" - ], - "sent_to_client_as_top_match": [ - "lineItem1" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem1", - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-bid-only-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-bid-only-response.json deleted file mode 100644 index 297f0518a8e..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-first-bid-only-response.json +++ /dev/null @@ -1,441 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "price": 10.6, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "10.60", - "hb_pb_rubicon": "10.60", - "hb_deal_rubicon": "dealId1", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId1" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 10.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId1\",\"impid\":\"impId1\",\"dealid\":\"dealId1\",\"price\":10.6,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}" - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}" - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem1" - ], - "sent_to_client_as_top_match": [ - "lineItem1" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem1" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-order-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-order-response.json deleted file mode 100644 index 297f0518a8e..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-order-response.json +++ /dev/null @@ -1,441 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "price": 10.6, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "10.60", - "hb_pb_rubicon": "10.60", - "hb_deal_rubicon": "dealId1", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId1" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 10.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId1\",\"impid\":\"impId1\",\"dealid\":\"dealId1\",\"price\":10.6,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}" - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}" - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem1" - ], - "sent_to_client_as_top_match": [ - "lineItem1" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem1" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-reverse-order-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-reverse-order-response.json deleted file mode 100644 index 6b0db95f32e..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-in-reverse-order-response.json +++ /dev/null @@ -1,447 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "price": 10.6, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "10.60", - "hb_pb_rubicon": "10.60", - "hb_deal_rubicon": "dealId1", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId1" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 10.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId2\",\"impid\":\"impId1\",\"dealid\":\"dealId2\",\"price\":9.6,\"adm\":\"\",\"crid\":\"crid2\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId3\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId3\",\"impid\":\"impId1\",\"dealid\":\"dealId3\",\"price\":8.6,\"adm\":\"\",\"crid\":\"crid3\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId1\",\"impid\":\"impId1\",\"dealid\":\"dealId1\",\"price\":10.6,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "source": { - "tid": "someTid" - }, - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem1" - ], - "sent_to_client_as_top_match": [ - "lineItem1" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:07:36.045Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:07:36.064Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:07:36.049Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:07:36.064Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:07:36.056Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:07:36.064Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-second-bid-only-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-second-bid-only-response.json deleted file mode 100644 index a0ccf324d82..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-second-bid-only-response.json +++ /dev/null @@ -1,445 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId2", - "impid": "impId1", - "price": 9.6, - "adm": "", - "crid": "crid2", - "dealid": "dealId2", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "9.60", - "hb_pb_rubicon": "9.60", - "hb_deal_rubicon": "dealId2", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId2" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2", - "imp": "http://localhost:8080/event?t=imp&b=bidId2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2" - } - }, - "origbidcpm": 9.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId2\",\"impid\":\"impId1\",\"dealid\":\"dealId2\",\"price\":9.6,\"adm\":\"\",\"crid\":\"crid2\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId3\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[]}]}", - "status": 200 - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem2" - ], - "sent_to_client_as_top_match": [ - "lineItem2" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-and-second-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-and-second-response.json deleted file mode 100644 index 3fbc3594c12..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-and-second-response.json +++ /dev/null @@ -1,446 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId2", - "impid": "impId1", - "price": 9.6, - "adm": "", - "crid": "crid2", - "dealid": "dealId2", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "9.60", - "hb_pb_rubicon": "9.60", - "hb_deal_rubicon": "dealId2", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId2" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2", - "imp": "http://localhost:8080/event?t=imp&b=bidId2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2" - } - }, - "origbidcpm": 9.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId2\",\"impid\":\"impId1\",\"dealid\":\"dealId2\",\"price\":9.6,\"adm\":\"\",\"crid\":\"crid2\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId3\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId3\",\"impid\":\"impId1\",\"dealid\":\"dealId3\",\"price\":8.6,\"adm\":\"\",\"crid\":\"crid3\",\"w\":300,\"h\":250}]}]}", - "status": 200 - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem2" - ], - "sent_to_client_as_top_match": [ - "lineItem2" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem3", - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-bid-only-response.json b/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-bid-only-response.json deleted file mode 100644 index 7bea97d3c61..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/responses/test-auction-third-bid-only-response.json +++ /dev/null @@ -1,445 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId3", - "impid": "impId1", - "price": 8.6, - "adm": "", - "crid": "crid3", - "dealid": "dealId3", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "8.60", - "hb_pb_rubicon": "8.60", - "hb_deal_rubicon": "dealId3", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId3" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId3&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem3", - "imp": "http://localhost:8080/event?t=imp&b=bidId3&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem3" - } - }, - "origbidcpm": 8.6 - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "rubicon": [ - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[]}]}", - "status": 200 - }, - { - "uri": "{{ rubicon.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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\":\"dealId2\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem2\",\"extlineitemid\":\"extLineItem2\",\"sizes\":[{\"w\":300,\"h\":250}]}}},{\"id\":\"dealId3\",\"ext\":{\"line\":{\"lineitemid\":\"lineItem3\",\"extlineitemid\":\"extLineItem3\",\"sizes\":[{\"w\":300,\"h\":250}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId3\",\"seatbid\":[{\"seat\":\"seatId\",\"bid\":[{\"id\":\"bidId3\",\"impid\":\"impId1\",\"dealid\":\"dealId3\",\"price\":8.6,\"adm\":\"\",\"crid\":\"crid3\",\"w\":300,\"h\":250}]}]}", - "status": 200 - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"rubicon\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "auctiontimestamp": 1000, - "debug": 1, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "channel": { - "name": "web" - }, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem3" - ], - "sent_to_client_as_top_match": [ - "lineItem3" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem1" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem3" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.044Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:08:59.061Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.048Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.053Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:08:59.062Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-auction-request.json b/src/test/resources/org/prebid/server/it/deals/premature/test-auction-request.json deleted file mode 100644 index 307b091e591..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-auction-request.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "id": "tid", - "imp": [ - { - "id": "impId1", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "cur": [ - "USD" - ], - "user": { - "ext": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" - } - }, - "source": { - "tid": "someTid" - }, - "site": { - "publisher": { - "id": "2001" - } - }, - "ext": { - "prebid": { - "debug": 1, - "trace": "verbose", - "targeting": { - }, - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-planner-plan-response.json b/src/test/resources/org/prebid/server/it/deals/premature/test-planner-plan-response.json deleted file mode 100644 index d80ece7ad26..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-planner-plan-response.json +++ /dev/null @@ -1,209 +0,0 @@ -[ - { - "lineItemId": "lineItem1", - "extLineItemId": "extLineItem1", - "dealId": "dealId1", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 10.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 9.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId2", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem3", - "extLineItemId": "extLineItem3", - "dealId": "dealId3", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 8.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - } -] diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-1.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-1.json deleted file mode 100644 index 9b3e45e74e4..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-1.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "bidResponseId1", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "dealid": "dealId1", - "price": 10.60, - "adm": "", - "crid": "crid1", - "w": 300, - "h": 250 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-2.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-2.json deleted file mode 100644 index ba3e19d5887..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-2.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "bidResponseId2", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - { - "id": "bidId2", - "impid": "impId1", - "dealid": "dealId2", - "price": 9.60, - "adm": "", - "crid": "crid2", - "w": 300, - "h": 250 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-3.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-3.json deleted file mode 100644 index 3583fa59b7f..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-bid-response-3.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "bidResponseId3", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - { - "id": "bidId3", - "impid": "impId1", - "dealid": "dealId3", - "price": 8.60, - "adm": "", - "crid": "crid3", - "w": 300, - "h": 250 - } - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-1.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-1.json deleted file mode 100644 index 533d6537f8f..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-1.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "bidResponseId1", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-2.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-2.json deleted file mode 100644 index b3c9444dd24..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-2.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "id": "bidResponseId2", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-3.json b/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-3.json deleted file mode 100644 index 5363e36c8f9..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/premature/test-rubicon-no-bid-response-3.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "bidResponseId3", - "seatbid": [ - { - "seat": "seatId", - "bid": [ - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-request.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-request.json deleted file mode 100644 index ba27f286b81..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-request.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "id": "tid", - "imp": [ - { - "id": "impId1", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "cur": [ - "USD" - ], - "source": { - "tid": "someTid" - }, - "site": { - "publisher": { - "id": "2001" - } - }, - "user": { - "ext": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" - } - }, - "ext": { - "prebid": { - "debug": 1, - "trace": "verbose", - "targeting": { - }, - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-1.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-1.json deleted file mode 100644 index 6d8a30fe28b..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-1.json +++ /dev/null @@ -1,349 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "impId1-lineItem1", - "impid": "impId1", - "price": 10.0, - "adm": "", - "crid": "crid", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "10.00", - "hb_pb_rubicon": "10.00", - "hb_deal_rubicon": "dealId1", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId1" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=impId1-lineItem1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=impId1-lineItem1&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 10.0, - "origbidcur": "USD" - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "debug": 1, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - }, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem1" - ], - "sent_to_client_as_top_match": [ - "lineItem1" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem3" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem1", - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T13:54:17.715Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T13:54:17.733Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T13:54:17.72Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T13:54:17.734Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T13:54:17.725Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T13:54:17.734Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-2.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-2.json deleted file mode 100644 index cb8373269fd..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-auction-response-2.json +++ /dev/null @@ -1,333 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "impId1-lineItem2", - "impid": "impId1", - "price": 7.0, - "adm": "", - "crid": "crid", - "dealid": "dealId2", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_pb": "7.00", - "hb_pb_rubicon": "7.00", - "hb_deal_rubicon": "dealId2", - "hb_size": "300x250", - "hb_bidder": "rubicon", - "hb_size_rubicon": "300x250", - "hb_bidder_rubicon": "rubicon", - "hb_deal": "dealId2" - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=impId1-lineItem2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2", - "imp": "http://localhost:8080/event?t=imp&b=impId1-lineItem2&a=2001&aid=tid&ts=1000&bidder=rubicon&f=i&int=&x=0&l=lineItem2" - } - }, - "origbidcpm": 7.0, - "origbidcur": "USD" - } - } - ], - "seat": "rubicon", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "resolvedrequest": { - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - }, - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "rubicon" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "rubicon": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "debug": 1, - "trace": "verbose", - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - }, - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem2" - ], - "sent_to_client_as_top_match": [ - "lineItem2" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem2" - ], - "pacing_deferred": [ - "lineItem1" - ], - "sent_to_bidder": { - "rubicon": [ - "lineItem3", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "rubicon": [ - "lineItem3" - ] - }, - "received_from_bidder": { - "rubicon": [ - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:03:17.986Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-24T14:03:18.002Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder rubicon ready to serve. relPriority 3" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:03:17.993Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-24T14:03:18.002Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder rubicon not ready to serve. Will be ready at never, current time is 2019-10-10T00:16:00.000Z" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:03:18.001Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-24T14:03:18.003Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder rubicon ready to serve. relPriority 3" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "rubicon" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "responsetimemillis": { - "rubicon": "{{ rubicon.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-bid-rates.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-bid-rates.json deleted file mode 100644 index fe32f4a040e..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-bid-rates.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "lineItem1": 1.00, - "lineItem2": 1.00, - "lineItem3": 0.00 -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-1.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-1.json deleted file mode 100644 index 07187887734..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-1.json +++ /dev/null @@ -1,149 +0,0 @@ -{ - "reportTimeStamp": "2019-10-10T00:00:03.000Z", - "dataWindowStartTimeStamp": "2019-10-10T00:00:02.000Z", - "dataWindowEndTimeStamp": "2019-10-10T00:00:03.000Z", - "instanceId": "localhost", - "vendor": "local", - "region": "local", - "clientAuctions": 1, - "lineItemStatus": [ - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 0, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 0, - "sentToClientAsTopMatch": 0, - "lostToLineItems": [ - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem3", - "count": 1 - }, - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem1", - "count": 1 - } - ], - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "planStartTimeStamp": "2019-10-10T00:00:00.000Z", - "planExpirationTimeStamp": "2019-10-10T00:10:00.000Z", - "planUpdatedTimeStamp": "2019-10-10T00:00:00.000Z", - "tokens": [ - { - "class": 1, - "total": 5000, - "spent": 0 - }, - { - "class": 2, - "total": 125, - "spent": 0 - } - ] - } - ] - }, - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem3", - "dealId": "dealId3", - "extLineItemId": "extLineItem3", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 1, - "receivedFromBidder": 0, - "receivedFromBidderInvalidated": 0, - "sentToClient": 0, - "sentToClientAsTopMatch": 0, - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "planStartTimeStamp": "2019-10-10T00:00:00.000Z", - "planExpirationTimeStamp": "2019-10-10T00:10:00.000Z", - "planUpdatedTimeStamp": "2019-10-10T00:00:00.000Z", - "tokens": [ - { - "class": 1, - "total": 5000, - "spent": 0 - }, - { - "class": 2, - "total": 125, - "spent": 0 - } - ] - } - ] - }, - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem1", - "dealId": "dealId1", - "extLineItemId": "extLineItem1", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 0, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 1, - "sentToClientAsTopMatch": 1, - "lostToLineItems": [ - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem3", - "count": 1 - } - ], - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "planStartTimeStamp": "2019-10-10T00:00:00.000Z", - "planExpirationTimeStamp": "2019-10-10T00:10:00.000Z", - "planUpdatedTimeStamp": "2019-10-10T00:00:00.000Z", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0, - "totalSpent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 1, - "totalSpent": 1 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-2.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-2.json deleted file mode 100644 index ab3a570202f..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-delivery-stats-progress-request-2.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "reportTimeStamp": "2019-10-10T00:17:00.000Z", - "dataWindowStartTimeStamp": "2019-10-10T00:00:03.000Z", - "dataWindowEndTimeStamp": "2019-10-10T00:17:00.000Z", - "instanceId": "localhost", - "vendor": "local", - "region": "local", - "clientAuctions": 1, - "lineItemStatus": [ - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 0, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 1, - "sentToClientAsTopMatch": 1, - "lostToLineItems": [ - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem3", - "count": 1 - } - ], - "events": [], - "deliverySchedule": [ - { - "planId": "2", - "planStartTimeStamp": "2019-10-10T00:10:00.000Z", - "planExpirationTimeStamp": "2019-10-10T00:20:00.000Z", - "planUpdatedTimeStamp": "2019-10-10T00:10:00.000Z", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0, - "totalSpent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 1, - "totalSpent": 1 - } - ] - } - ] - }, - { - "lineItemSource": "rubicon", - "lineItemId": "lineItem3", - "dealId": "dealId3", - "extLineItemId": "extLineItem3", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 1, - "receivedFromBidder": 0, - "receivedFromBidderInvalidated": 0, - "sentToClient": 0, - "sentToClientAsTopMatch": 0, - "events": [], - "deliverySchedule": [ - { - "planId": "2", - "planStartTimeStamp": "2019-10-10T00:10:00.000Z", - "planExpirationTimeStamp": "2019-10-10T00:20:00.000Z", - "planUpdatedTimeStamp": "2019-10-10T00:10:00.000Z", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 0 - } - ] - } - ] - } - ] -} diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-plan-response-1.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-plan-response-1.json deleted file mode 100644 index 4dc1db3ce10..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-plan-response-1.json +++ /dev/null @@ -1,257 +0,0 @@ -[ - { - "lineItemId": "lineItem1", - "extLineItemId": "extLineItem1", - "dealId": "dealId1", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 10.00, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:20:00Z", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:10:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - }, - { - "planId": "2", - "updatedTimeStamp": "2019-10-10T00:10:00Z", - "startTimeStamp": "2019-10-10T00:20:00Z", - "endTimeStamp": "2019-10-10T00:30:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 7.00, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:20:00Z", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId2", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:10:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - }, - { - "planId": "2", - "updatedTimeStamp": "2019-10-10T00:10:00Z", - "startTimeStamp": "2019-10-10T00:10:00Z", - "endTimeStamp": "2019-10-10T00:20:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem3", - "extLineItemId": "extLineItem3", - "dealId": "dealId3", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "rubicon", - "price": { - "cpm": 15.00, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:20:00Z", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "2019-10-10T00:00:00Z", - "startTimeStamp": "2019-10-10T00:00:00Z", - "endTimeStamp": "2019-10-10T00:10:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - }, - { - "planId": "2", - "updatedTimeStamp": "2019-10-10T00:10:00Z", - "startTimeStamp": "2019-10-10T00:10:00Z", - "endTimeStamp": "2019-10-10T00:20:00Z", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - } -] diff --git a/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-register-request-1.json b/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-register-request-1.json deleted file mode 100644 index c8aa1a6e300..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/simulation/test-planner-register-request-1.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "healthIndex": 0.43, - "hostInstanceId": "localhost", - "region": "local", - "vendor": "local" -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/test-auction-request.json b/src/test/resources/org/prebid/server/it/deals/test-auction-request.json deleted file mode 100644 index bfc31ef4604..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-auction-request.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "id": "tid", - "regs": { - "gdpr": 0 - }, - "imp": [ - { - "id": "impId1", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - }, - { - "id": "impId2", - "banner": { - "format": [ - { - "w": 320, - "h": 320 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - }, - { - "id": "impId3", - "banner": { - "format": [ - { - "w": 300, - "h": 600 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001, - "dealsonly": true, - "pgdealsonly": true - } - } - } - } - }, - { - "id": "impId4", - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "cur": [ - "USD" - ], - "source": { - "tid": "someTid" - }, - "site": { - "publisher": { - "id": "2001" - } - }, - "user": { - "ext": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA" - } - }, - "ext": { - "prebid": { - "debug": 1, - "trace": "verbose", - "targeting": { - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-auction-response.json b/src/test/resources/org/prebid/server/it/deals/test-auction-response.json deleted file mode 100644 index 23703e850eb..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-auction-response.json +++ /dev/null @@ -1,860 +0,0 @@ -{ - "id": "tid", - "seatbid": [ - { - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "price": 8.43, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_deal_generic": "dealId1", - "hb_cache_id": "3f37ff80-b395-449f-a80e-c21a38bb6eec", - "hb_cache_path_generic": "/cache", - "hb_cache_host_generic": "{{ cache.host }}", - "hb_pb": "8.40", - "hb_pb_generic": "8.40", - "hb_cache_id_generic": "3f37ff80-b395-449f-a80e-c21a38bb6eec", - "hb_cache_path": "/cache", - "hb_size": "300x250", - "hb_bidder": "generic", - "hb_size_generic": "300x250", - "hb_bidder_generic": "generic", - "hb_cache_host": "{{ cache.host }}", - "hb_deal": "dealId1" - }, - "cache": { - "bids": { - "url": "{{ cache.resource_url }}3f37ff80-b395-449f-a80e-c21a38bb6eec", - "cacheId": "3f37ff80-b395-449f-a80e-c21a38bb6eec" - } - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1" - } - }, - "origbidcpm": 8.43 - } - }, - { - "id": "bidId2", - "impid": "impId2", - "price": 8.43, - "adm": "", - "crid": "crid2", - "dealid": "dealId2", - "w": 320, - "h": 320, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_deal_generic": "dealId2", - "hb_size_generic": "320x320", - "hb_cache_id": "13e78248-7339-4e35-b297-874d0031bc1a", - "hb_cache_path_generic": "/cache", - "hb_cache_host_generic": "{{ cache.host }}", - "hb_pb": "8.40", - "hb_pb_generic": "8.40", - "hb_cache_id_generic": "13e78248-7339-4e35-b297-874d0031bc1a", - "hb_cache_path": "/cache", - "hb_size": "320x320", - "hb_bidder": "generic", - "hb_bidder_generic": "generic", - "hb_cache_host": "{{ cache.host }}", - "hb_deal": "dealId2" - }, - "cache": { - "bids": { - "url": "{{ cache.resource_url }}13e78248-7339-4e35-b297-874d0031bc1a", - "cacheId": "13e78248-7339-4e35-b297-874d0031bc1a" - } - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2", - "imp": "http://localhost:8080/event?t=imp&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2" - } - }, - "origbidcpm": 8.43 - } - }, - { - "id": "bidId4", - "impid": "impId4", - "price": 8.43, - "adm": "", - "crid": "crid1", - "dealid": "dealId3", - "w": 300, - "h": 250, - "ext": { - "prebid": { - "type": "banner", - "targeting": { - "hb_deal_generic": "dealId3", - "hb_size_generic": "300x250", - "hb_cache_id": "1cdcf339-e59b-4e2c-8382-1fb845d4961c", - "hb_cache_path_generic": "/cache", - "hb_cache_host_generic": "{{ cache.host }}", - "hb_pb": "8.40", - "hb_pb_generic": "8.40", - "hb_cache_id_generic": "1cdcf339-e59b-4e2c-8382-1fb845d4961c", - "hb_cache_path": "/cache", - "hb_size": "300x250", - "hb_bidder": "generic", - "hb_bidder_generic": "generic", - "hb_cache_host": "{{ cache.host }}", - "hb_deal": "dealId3" - }, - "cache": { - "bids": { - "url": "{{ cache.resource_url }}1cdcf339-e59b-4e2c-8382-1fb845d4961c", - "cacheId": "1cdcf339-e59b-4e2c-8382-1fb845d4961c" - } - }, - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3", - "imp": "http://localhost:8080/event?t=imp&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3" - } - }, - "origbidcpm": 8.43 - } - } - ], - "seat": "generic", - "group": 0 - } - ], - "cur": "USD", - "ext": { - "debug": { - "httpcalls": { - "cache": [ - { - "uri": "{{ cache.endpoint }}", - "requestheaders": { - "Accept": [ - "application/json" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"puts\":[{\"type\":\"json\",\"value\":{\"id\":\"bidId1\",\"impid\":\"impId1\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"dealid\":\"dealId1\",\"w\":300,\"h\":250,\"ext\":{\"origbidcpm\":8.43,\"prebid\":{\"type\":\"banner\",\"events\":{\"win\":\"http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1\",\"imp\":\"http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1\"}}},\"wurl\":\"http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1\"},\"aid\":\"tid\"},{\"type\":\"json\",\"value\":{\"id\":\"bidId4\",\"impid\":\"impId4\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"dealid\":\"dealId3\",\"w\":300,\"h\":250,\"ext\":{\"origbidcpm\":8.43,\"prebid\":{\"type\":\"banner\",\"events\":{\"win\":\"http://localhost:8080/event?t=win&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3\",\"imp\":\"http://localhost:8080/event?t=imp&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3\"}}},\"wurl\":\"http://localhost:8080/event?t=win&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3\"},\"aid\":\"tid\"},{\"type\":\"json\",\"value\":{\"id\":\"bidId2\",\"impid\":\"impId2\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid2\",\"dealid\":\"dealId2\",\"w\":320,\"h\":320,\"ext\":{\"origbidcpm\":8.43,\"prebid\":{\"type\":\"banner\",\"events\":{\"win\":\"http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2\",\"imp\":\"http://localhost:8080/event?t=imp&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2\"}}},\"wurl\":\"http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2\"},\"aid\":\"tid\"}]}", - "responsebody": "{\"responses\":[{\"uuid\":\"13e78248-7339-4e35-b297-874d0031bc1a\"},{\"uuid\":\"3f37ff80-b395-449f-a80e-c21a38bb6eec\"},{\"uuid\":\"1cdcf339-e59b-4e2c-8382-1fb845d4961c\"}]}", - "status": 200 - } - ], - "generic": [ - { - "uri": "{{ generic.exchange_uri }}", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId4\",\"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}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId4\",\"seatbid\":[{\"seat\":\"seatId4\",\"bid\":[{\"id\":\"bidId4\",\"impid\":\"impId4\",\"dealid\":\"dealId3\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ generic.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem1\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId1\",\"seatbid\":[{\"seat\":\"seatId1\",\"bid\":[{\"id\":\"bidId1\",\"impid\":\"impId1\",\"dealid\":\"dealId1\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid1\",\"w\":300,\"h\":250}]}]}", - "status": 200 - }, - { - "uri": "{{ generic.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId2\",\"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}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem2\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId2\",\"seatbid\":[{\"seat\":\"seatId2\",\"bid\":[{\"id\":\"bidId2\",\"impid\":\"impId2\",\"dealid\":\"dealId2\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid2\",\"w\":320,\"h\":320}]}]}", - "status": 200 - }, - { - "uri": "{{ generic.exchange_uri }}?tk_xint=rp-pbs", - "requestheaders": { - "Accept": [ - "application/json" - ], - "x-prebid": [ - "pbs-java/1.70.0" - ], - "User-Agent": [ - "prebid-server/1.0" - ], - "Content-Type": [ - "application/json;charset=utf-8" - ] - }, - "requestbody": "{\"id\":\"tid\",\"imp\":[{\"id\":\"impId1\",\"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}]}}}]},\"secure\":1,\"ext\":{\"rp\":{\"zone_id\":4001,\"target\":{\"page\":[\"http://www.example.com\"],\"line_item\":\"extLineItem3\"},\"track\":{\"mint\":\"\",\"mint_version\":\"\"}},\"maxbids\":1}}],\"site\":{\"domain\":\"www.example.com\",\"page\":\"http://www.example.com\",\"publisher\":{\"ext\":{\"rp\":{\"account_id\":2001}}},\"ext\":{\"amp\":0,\"rp\":{\"site_id\":3001}}},\"device\":{\"ua\":\"userAgent\",\"ip\":\"185.199.110.0\",\"ext\":{\"rp\":{}}},\"user\":{\"buyeruid\":\"J5VLCWQP-26-CWFT\",\"consent\":\"CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA\",\"ext\":{\"fcapids\":[\"fcapId3\"],\"time\":{\"userdow\":{{ userdow }},\"userhour\":{{ userhour }}}}},\"at\":1,\"tmax\":5000,\"source\":{\"tid\":\"someTid\"}}", - "responsebody": "{\"id\":\"bidResponseId3\",\"seatbid\":[{\"seat\":\"seatId3\",\"bid\":[{\"id\":\"bidId3\",\"impid\":\"impId1\",\"dealid\":\"dealId3\",\"price\":8.43,\"adm\":\"\",\"crid\":\"crid3\",\"w\":300,\"h\":250}]}]}", - "status": 200 - } - ], - "userservice": [ - { - "uri": "{{ userservice_uri }}", - "requestbody": "{\"time\":\"{{ userservice_time }}\",\"ids\":[{\"type\":\"khaos\",\"id\":\"J5VLCWQP-26-CWFT\"}]}", - "responsebody": "{\"user\":{\"data\":[{\"id\":\"1111\",\"name\":\"generic\",\"segment\":[{\"id\":\"2222\"},{\"id\":\"3333\"}]},{\"id\":\"4444\",\"name\":\"bluekai\",\"segment\":[{\"id\":\"5555\"},{\"id\":\"6666\"}]}],\"ext\":{\"fcapIds\":[\"fcapId3\"]}}}", - "status": 200 - } - ] - }, - "resolvedrequest": { - "id": "tid", - "regs": { - "gdpr": 0 - }, - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId1", - "ext": { - "line": { - "lineitemid": "lineItem1", - "extlineitemid": "extLineItem1", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "generic" - } - } - }, - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "generic" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - }, - { - "id": "impId2", - "secure": 1, - "banner": { - "format": [ - { - "w": 320, - "h": 320 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 320, - "h": 320 - } - ], - "bidder": "generic" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - }, - { - "id": "impId3", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 600 - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001, - "dealsonly": true, - "pgdealsonly": true - } - } - } - } - }, - { - "id": "impId4", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "bidder": "generic" - } - } - } - ] - }, - "ext": { - "tid": "someTid", - "prebid": { - "bidder": { - "generic": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - } - } - } - } - } - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "page": "http://www.example.com", - "publisher": { - "id": "2001", - "domain": "example.com" - }, - "ext": { - "amp": 0 - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "user": { - "data": [ - { - "id": "generic", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "ext": { - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "{{ userdow }}", - "userhour": "{{ userhour }}" - } - } - }, - "at": 1, - "tmax": 5000, - "cur": [ - "USD" - ], - "ext": { - "prebid": { - "debug": 1, - "server": { - "externalurl": "http://localhost:8080", - "gvlid": 1, - "datacenter": "local", - "endpoint": "/openrtb2/auction" - }, - "trace": "verbose", - "targeting": { - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "max": 20, - "increment": 0.1 - } - ] - }, - "includewinners": true, - "includebidderkeys": true - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - } - } - } - }, - "pgmetrics": { - "sent_to_client": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_client_as_top_match": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "matched_whole_targeting": [ - "lineItem3", - "lineItem4", - "lineItem1", - "lineItem2" - ], - "matched_targeting_fcapped": [ - "lineItem4" - ], - "ready_to_serve": [ - "lineItem3", - "lineItem1", - "lineItem2" - ], - "sent_to_bidder": { - "generic": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "sent_to_bidder_as_top_match": { - "generic": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - }, - "received_from_bidder": { - "generic": [ - "lineItem3", - "lineItem1", - "lineItem2" - ] - } - }, - "trace": { - "lineitems": { - "lineItem3": [ - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:03.963Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:03.981Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder generic ready to serve. relPriority 3" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:03.992Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting did not match imp with id impId2" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:04.009Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting did not match imp with id impId3" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:04.029Z", - "category": "targeting", - "message": "Line Item lineItem3 targeting matched imp with id impId4" - }, - { - "lineitemid": "lineItem3", - "time": "2020-04-27T13:08:04.043Z", - "category": "pacing", - "message": "Matched Line Item lineItem3 for bidder generic ready to serve. relPriority 3" - } - ], - "lineItem4": [ - { - "lineitemid": "lineItem4", - "time": "2020-04-27T13:08:03.967Z", - "category": "targeting", - "message": "Line Item lineItem4 targeting did not match imp with id impId1" - }, - { - "lineitemid": "lineItem4", - "time": "2020-04-27T13:08:03.995Z", - "category": "targeting", - "message": "Line Item lineItem4 targeting did not match imp with id impId2" - }, - { - "lineitemid": "lineItem4", - "time": "2020-04-27T13:08:04.014Z", - "category": "targeting", - "message": "Line Item lineItem4 targeting matched imp with id impId3" - }, - { - "lineitemid": "lineItem4", - "time": "2020-04-27T13:08:04.024Z", - "category": "pacing", - "message": "Matched Line Item lineItem4 for bidder generic is frequency capped by fcap id fcapId3." - }, - { - "lineitemid": "lineItem4", - "time": "2020-04-27T13:08:04.033Z", - "category": "targeting", - "message": "Line Item lineItem4 targeting did not match imp with id impId4" - } - ], - "lineItem1": [ - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:03.971Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId1" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:03.981Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder generic ready to serve. relPriority 3" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:03.999Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting did not match imp with id impId2" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:04.019Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting did not match imp with id impId3" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:04.038Z", - "category": "targeting", - "message": "Line Item lineItem1 targeting matched imp with id impId4" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:04.043Z", - "category": "pacing", - "message": "Matched Line Item lineItem1 for bidder generic ready to serve. relPriority 3" - }, - { - "lineitemid": "lineItem1", - "time": "2020-04-27T13:08:04.044Z", - "category": "cleanup", - "message": "LineItem lineItem1 was dropped from imp with id impId4 because it was top match in another imp" - } - ], - "lineItem2": [ - { - "lineitemid": "lineItem2", - "time": "2020-04-27T13:08:03.975Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting did not match imp with id impId1" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-27T13:08:04.004Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting matched imp with id impId2" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-27T13:08:04.004Z", - "category": "pacing", - "message": "Matched Line Item lineItem2 for bidder generic ready to serve. relPriority 3" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-27T13:08:04.024Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting did not match imp with id impId3" - }, - { - "lineitemid": "lineItem2", - "time": "2020-04-27T13:08:04.043Z", - "category": "targeting", - "message": "Line Item lineItem2 targeting did not match imp with id impId4" - } - ] - }, - "activity_infrastructure": [ - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "fetchBids", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "fetchBids", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitUfpd", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitUfpd", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitPreciseGeo", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitPreciseGeo", - "allowed": true - }, - { - "description": "Invocation of Activity Infrastructure.", - "activity": "transmitTid", - "activity_invocation_payload": { - "component_type": "BIDDER", - "component_name": "generic" - } - }, - { - "description": "Setting the default invocation result.", - "allow_by_default": true - }, - { - "description": "Activity Infrastructure invocation result.", - "activity": "transmitTid", - "allowed": true - } - ] - } - }, - "warnings": { - "prebid": [ - { - "code": 999, - "message": "Not calling generic bidder for impressions impId3 due to pgdealsonly flag and no available PG line items." - } - ] - }, - "responsetimemillis": { - "generic": "{{ generic.response_time_ms }}", - "cache": "{{ cache.response_time_ms }}" - }, - "tmaxrequest": 5000, - "prebid": { - "auctiontimestamp": 1000 - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-cache-deals-request.json b/src/test/resources/org/prebid/server/it/deals/test-cache-deals-request.json deleted file mode 100644 index 5461e5a9cd7..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-cache-deals-request.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "puts": [ - { - "type": "json", - "value": { - "id": "bidId4", - "impid": "impId4", - "price": 8.43, - "adm": "", - "crid": "crid1", - "dealid": "dealId3", - "w": 300, - "h": 250, - "ext": { - "origbidcpm": 8.43, - "prebid": { - "type": "banner", - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3", - "imp": "http://localhost:8080/event?t=imp&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3" - } - } - }, - "wurl": "http://localhost:8080/event?t=win&b=bidId4&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem3" - }, - "aid": "tid" - }, - { - "type": "json", - "value": { - "id": "bidId2", - "impid": "impId2", - "price": 8.43, - "adm": "", - "crid": "crid2", - "dealid": "dealId2", - "w": 320, - "h": 320, - "ext": { - "origbidcpm": 8.43, - "prebid": { - "type": "banner", - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2", - "imp": "http://localhost:8080/event?t=imp&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2" - } - } - }, - "wurl": "http://localhost:8080/event?t=win&b=bidId2&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem2" - }, - "aid": "tid" - }, - { - "type": "json", - "value": { - "id": "bidId1", - "impid": "impId1", - "price": 8.43, - "adm": "", - "crid": "crid1", - "dealid": "dealId1", - "w": 300, - "h": 250, - "ext": { - "origbidcpm": 8.43, - "prebid": { - "type": "banner", - "events": { - "win": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1", - "imp": "http://localhost:8080/event?t=imp&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1" - } - } - }, - "wurl": "http://localhost:8080/event?t=win&b=bidId1&a=2001&aid=tid&ts=1000&bidder=generic&f=i&int=&x=0&l=lineItem1" - }, - "aid": "tid" - } - ] -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-cache-matcher.json b/src/test/resources/org/prebid/server/it/deals/test-cache-matcher.json deleted file mode 100644 index 6ce206a9f25..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-cache-matcher.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "bidId2@8.43": "13e78248-7339-4e35-b297-874d0031bc1a", - "bidId1@8.43": "3f37ff80-b395-449f-a80e-c21a38bb6eec", - "bidId4@8.43": "1cdcf339-e59b-4e2c-8382-1fb845d4961c" -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/test-deals-application.properties b/src/test/resources/org/prebid/server/it/deals/test-deals-application.properties deleted file mode 100644 index 4f6d1b5ab41..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-deals-application.properties +++ /dev/null @@ -1,46 +0,0 @@ -server.http.port=8070 -admin.port=9060 -hostname=localhost -auction.ad-server-currency=USD -admin-endpoints.currency-rates.enabled=true -admin-endpoints.currency-rates.on-application-port=true -admin-endpoints.currency-rates.protected=false -admin-endpoints.e2eadmin.enabled=true -admin-endpoints.e2eadmin.on-application-port=true -admin-endpoints.e2eadmin.protected=false -admin-endpoints.lineitem-status.enabled=true -admin-endpoints.lineitem-status.on-application-port=true -admin-endpoints.lineitem-status.protected=false -admin-endpoints.deals-status.enabled=true -admin-endpoints.deals-status.on-application-port=true -admin-endpoints.deals-status.protected=false -deals.enabled=true -deals.planner.plan-endpoint=http://localhost:8090/planner-plan -deals.planner.register-endpoint=http://localhost:8090/planner-register -deals.planner.username=username -deals.planner.password=password -deals.planner.update-period=*/1 * * * * * -deals.delivery-stats.endpoint=http://localhost:8090/delivery-stats-progress -deals.delivery-stats.delivery-period=*/5 * * * * * -deals.delivery-stats.timeout-ms=1000 -deals.delivery-stats.username=username -deals.delivery-stats.password=password -deals.delivery-stats.reports-interval-ms=0 -deals.delivery-progress.report-reset-period=*/5 * * * * * -deals.user-data.user-details-endpoint=http://localhost:8090/user-data-details -deals.user-data.win-event-endpoint=http://localhost:8090/user-data-win-event -deals.user-data.timeout=1000 -deals.user-data.user-ids[0].type=khaos -deals.user-data.user-ids[0].source=uid -deals.user-data.user-ids[0].location=rubicon -deals.max-deals-per-bidder=3 -deals.alert-proxy.enabled=false -deals.alert-proxy.url=http://localhost -deals.alert-proxy.timeout-sec=5 -deals.alert-proxy.username=username -deals.alert-proxy.password=password -profile=test -infra=vm -data-center=aws -system=PBS -sub-system=Prebid Server diff --git a/src/test/resources/org/prebid/server/it/deals/test-deals-simulation-application.properties b/src/test/resources/org/prebid/server/it/deals/test-deals-simulation-application.properties deleted file mode 100644 index fe11da5609d..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-deals-simulation-application.properties +++ /dev/null @@ -1,3 +0,0 @@ -server.http.port=10080 -admin.port=10060 -deals.simulation.enabled=true diff --git a/src/test/resources/org/prebid/server/it/deals/test-delivery-stats-progress-request.json b/src/test/resources/org/prebid/server/it/deals/test-delivery-stats-progress-request.json deleted file mode 100644 index 1fd1cbf6c7a..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-delivery-stats-progress-request.json +++ /dev/null @@ -1,203 +0,0 @@ -{ - "instanceId": "localhost", - "vendor": "local", - "region": "local", - "clientAuctions": 1, - "lineItemStatus": [ - { - "lineItemSource": "generic", - "lineItemId": "lineItem4", - "dealId": "dealId4", - "extLineItemId": "extLineItem4", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 1, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 0, - "sentToBidderAsTopMatch": 0, - "receivedFromBidder": 0, - "receivedFromBidderInvalidated": 0, - "sentToClient": 0, - "sentToClientAsTopMatch": 0, - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "tokens": [ - { - "class": 1, - "total": 5000, - "spent": 0 - }, - { - "class": 2, - "total": 125, - "spent": 0 - } - ] - } - ] - }, - { - "lineItemSource": "generic", - "lineItemId": "lineItem1", - "dealId": "dealId1", - "extLineItemId": "extLineItem1", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 1, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 1, - "sentToClientAsTopMatch": 1, - "events": [ - { - "type": "win", - "count": 1 - } - ], - "deliverySchedule": [ - { - "planId": "1", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0, - "totalSpent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 1, - "totalSpent": 1 - } - ] - } - ] - }, - { - "lineItemSource": "generic", - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 1, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 1, - "sentToClientAsTopMatch": 1, - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0, - "totalSpent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 1, - "totalSpent": 1 - } - ] - } - ] - }, - { - "lineItemSource": "generic", - "lineItemId": "lineItem5", - "dealId": "dealId5", - "extLineItemId": "extLineItem5", - "domainMatched": 0, - "targetMatched": 0, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 0, - "sentToBidderAsTopMatch": 0, - "receivedFromBidder": 0, - "receivedFromBidderInvalidated": 0, - "sentToClient": 0, - "sentToClientAsTopMatch": 0, - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "tokens": [ - { - "class": 2, - "total": 125, - "spent": 0 - }, - { - "class": 1, - "total": 5000, - "spent": 0 - } - ] - } - ] - }, - { - "lineItemSource": "generic", - "lineItemId": "lineItem3", - "dealId": "dealId3", - "extLineItemId": "extLineItem3", - "accountAuctions": 1, - "domainMatched": 0, - "targetMatched": 1, - "targetMatchedButFcapped": 0, - "targetMatchedButFcapLookupFailed": 0, - "pacingDeferred": 0, - "sentToBidder": 1, - "sentToBidderAsTopMatch": 1, - "receivedFromBidder": 1, - "receivedFromBidderInvalidated": 0, - "sentToClient": 1, - "sentToClientAsTopMatch": 1, - "lostToLineItems": [ - { - "lineItemSource": "generic", - "lineItemId": "lineItem1", - "count": 1 - } - ], - "events": [], - "deliverySchedule": [ - { - "planId": "1", - "tokens": [ - { - "class": 1, - "total": 5000, - "spent": 1 - }, - { - "class": 2, - "total": 125, - "spent": 0 - } - ] - } - ] - } - ] -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-generic-bid-request.json b/src/test/resources/org/prebid/server/it/deals/test-generic-bid-request.json deleted file mode 100644 index feed83c02c2..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-generic-bid-request.json +++ /dev/null @@ -1,236 +0,0 @@ -{ - "id": "tid", - "imp": [ - { - "id": "impId1", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "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": { - "bidder": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - }, - "tid": "someTid" - } - }, - { - "id": "impId2", - "secure": 1, - "banner": { - "format": [ - { - "w": 320, - "h": 320 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId2", - "ext": { - "line": { - "lineitemid": "lineItem2", - "extlineitemid": "extLineItem2", - "sizes": [ - { - "w": 320, - "h": 320 - } - ] - } - } - } - ] - }, - "ext": { - "bidder": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - }, - "tid": "someTid" - } - }, - { - "id": "impId4", - "secure": 1, - "banner": { - "format": [ - { - "w": 300, - "h": 250 - } - ] - }, - "pmp": { - "deals": [ - { - "id": "dealId3", - "ext": { - "line": { - "lineitemid": "lineItem3", - "extlineitemid": "extLineItem3", - "sizes": [ - { - "w": 300, - "h": 250 - } - ] - } - } - } - ] - }, - "ext": { - "bidder": { - "accountId": 2001, - "siteId": 3001, - "zoneId": 4001 - }, - "tid": "someTid" - } - } - ], - "cur": [ - "USD" - ], - "source": { - "tid": "someTid" - }, - "site": { - "domain": "www.example.com", - "ext": { - "amp": 0 - }, - "page": "http://www.example.com", - "publisher": { - "domain": "example.com", - "id": "2001" - } - }, - "user": { - "data": [ - { - "id": "generic", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "ext": { - "consent": "CPBCa-mPBCa-mAAAAAENA0CAAEAAAAAAACiQAaQAwAAgAgABoAAAAAA", - "fcapids": [ - "fcapId3" - ], - "time": { - "userdow": "${json-unit.any-number}", - "userhour": "${json-unit.any-number}" - } - } - }, - "device": { - "ua": "userAgent", - "ip": "185.199.110.0" - }, - "regs": { - "ext": { - "gdpr": 0 - } - }, - "at": 1, - "tmax": "${json-unit.any-number}", - "ext": { - "prebid": { - "debug": 1, - "trace": "verbose", - "targeting": { - "includebidderkeys": true, - "includewinners": true, - "pricegranularity": { - "precision": 2, - "ranges": [ - { - "increment": 0.1, - "max": 20 - } - ] - } - }, - "cache": { - "bids": {}, - "vastxml": { - "ttlseconds": 120 - } - }, - "auctiontimestamp": 1000, - "channel": { - "name": "web" - }, - "server": { - "datacenter": "local", - "endpoint": "/openrtb2/auction", - "externalurl": "http://localhost:8080", - "gvlid": 1 - } - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-generic-bid-response.json b/src/test/resources/org/prebid/server/it/deals/test-generic-bid-response.json deleted file mode 100644 index 95a6159efab..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-generic-bid-response.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "id": "bidResponseId", - "seatbid": [ - { - "seat": "seatId1", - "bid": [ - { - "id": "bidId1", - "impid": "impId1", - "dealid": "dealId1", - "price": 8.43, - "adm": "", - "crid": "crid1", - "w": 300, - "h": 250 - }, - { - "id": "bidId2", - "impid": "impId2", - "dealid": "dealId2", - "price": 8.43, - "adm": "", - "crid": "crid2", - "w": 320, - "h": 320 - }, - { - "id": "bidId4", - "impid": "impId4", - "dealid": "dealId3", - "price": 8.43, - "adm": "", - "crid": "crid1", - "w": 300, - "h": 250 - } - ] - } - ] -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-planner-plan-response.json b/src/test/resources/org/prebid/server/it/deals/test-planner-plan-response.json deleted file mode 100644 index 462a5d6f1f2..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-planner-plan-response.json +++ /dev/null @@ -1,347 +0,0 @@ -[ - { - "lineItemId": "lineItem1", - "extLineItemId": "extLineItem1", - "dealId": "dealId1", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "generic", - "price": { - "cpm": 5.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem2", - "dealId": "dealId2", - "extLineItemId": "extLineItem2", - "status": "active", - "sizes": [ - { - "w": 320, - "h": 320 - } - ], - "accountId": "2001", - "source": "generic", - "price": { - "cpm": 5.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 320, - "h": 320 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId2", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem3", - "extLineItemId": "extLineItem3", - "dealId": "dealId3", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 250 - } - ], - "accountId": "2001", - "source": "generic", - "price": { - "cpm": 4.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 250 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem4", - "extLineItemId": "extLineItem4", - "dealId": "dealId4", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 600 - } - ], - "accountId": "2001", - "source": "generic", - "price": { - "cpm": 5.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 600 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId3", - "count": 10, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - }, - { - "lineItemId": "lineItem5", - "extLineItemId": "extLineItem5", - "dealId": "dealId5", - "status": "active", - "sizes": [ - { - "w": 300, - "h": 600 - } - ], - "accountId": "2002", - "source": "generic", - "price": { - "cpm": 5.60, - "currency": "USD" - }, - "relativePriority": 3, - "startTimeStamp": "{{ lineItem.startTime }}", - "endTimeStamp": "{{ lineItem.endTime }}", - "updatedTimeStamp": "{{ now }}", - "targeting": { - "$and": [ - { - "adunit.size": { - "$intersects": [ - { - "w": 300, - "h": 600 - } - ] - } - }, - { - "adunit.mediatype": { - "$intersects": [ - "banner" - ] - } - } - ] - }, - "frequencyCaps": [ - { - "fcapId": "fcapId5", - "count": 10, - "periods": 7, - "periodType": "day" - } - ], - "deliverySchedules": [ - { - "planId": "1", - "updatedTimeStamp": "{{ now }}", - "startTimeStamp": "{{ plan.startTime }}", - "endTimeStamp": "{{ plan.endTime }}", - "tokens": [ - { - "class": 1, - "total": 5000 - }, - { - "class": 2, - "total": 125 - } - ] - } - ] - } -] diff --git a/src/test/resources/org/prebid/server/it/deals/test-planner-register-request.json b/src/test/resources/org/prebid/server/it/deals/test-planner-register-request.json deleted file mode 100644 index ca88dd51e89..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-planner-register-request.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "healthIndex": 1, - "status": { - "dealsStatus": { - "instanceId": "localhost", - "vendor": "local", - "region": "local", - "clientAuctions": 0, - "lineItemStatus": [] - } - }, - "hostInstanceId": "localhost", - "region": "local", - "vendor": "local" -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/test-planner-register-response.json b/src/test/resources/org/prebid/server/it/deals/test-planner-register-response.json deleted file mode 100644 index 456c5fa32f7..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-planner-register-response.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "tracer": { - "cmd": "start", - "raw": "true", - "durationInSeconds": "300", - "filters": { - "accountId": "1001", - "bidderCode": "pgRubicon", - "lineItemId": "642534" - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-generic-response.json b/src/test/resources/org/prebid/server/it/deals/test-user-data-details-generic-response.json deleted file mode 100644 index ef7c135d760..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-generic-response.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "user": { - "data": [ - { - "id": "1111", - "name": "generic", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "4444", - "name": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "ext": { - "fcapIds": [ - "fcapId3" - ] - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-request.json b/src/test/resources/org/prebid/server/it/deals/test-user-data-details-request.json deleted file mode 100644 index 57e3a12ceec..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-request.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ids": [ - { - "type": "khaos", - "id": "J5VLCWQP-26-CWFT" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-rubicon-response.json b/src/test/resources/org/prebid/server/it/deals/test-user-data-details-rubicon-response.json deleted file mode 100644 index 098785643ee..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-user-data-details-rubicon-response.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "user": { - "data": [ - { - "id": "1111", - "name": "rubicon", - "segment": [ - { - "id": "2222" - }, - { - "id": "3333" - } - ] - }, - { - "id": "4444", - "name": "bluekai", - "segment": [ - { - "id": "5555" - }, - { - "id": "6666" - } - ] - } - ], - "ext": { - "fcapIds": [ - "fcapId3" - ] - } - } -} diff --git a/src/test/resources/org/prebid/server/it/deals/test-user-data-win-event-request.json b/src/test/resources/org/prebid/server/it/deals/test-user-data-win-event-request.json deleted file mode 100644 index 71f6551cc46..00000000000 --- a/src/test/resources/org/prebid/server/it/deals/test-user-data-win-event-request.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "bidderCode": "generic", - "bidId": "bidId", - "lineItemId": "lineItem1", - "region" : "local", - "userIds": [ - { - "type": "khaos", - "id": "J5VLCWQP-26-CWFT" - } - ], - "frequencyCaps": [ - { - "fcapId": "fcapId1", - "count": 3, - "periods": 7, - "periodType": "day" - } - ] -} diff --git a/src/test/resources/org/prebid/server/it/test-application.properties b/src/test/resources/org/prebid/server/it/test-application.properties index 2bef5e71ca2..90a4c6fc75d 100644 --- a/src/test/resources/org/prebid/server/it/test-application.properties +++ b/src/test/resources/org/prebid/server/it/test-application.properties @@ -499,8 +499,6 @@ admin-endpoints.logging-changelevel.protected=false admin-endpoints.tracelog.enabled=true admin-endpoints.tracelog.protected=false admin-endpoints.e2eadmin.enabled=false -admin-endpoints.lineitem-status.enabled=false -admin-endpoints.deals-status.enabled=false status-response=ok analytics.log.enabled=true gdpr.host-vendor-id=1 From dab59d91c3869c43a58ab34325de41be2c7b69d0 Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Tue, 5 Mar 2024 19:45:58 +0200 Subject: [PATCH 5/9] Simplified deployment --- .../ApplicationServerConfiguration.java | 11 ++-- .../verticles/InitializableVerticle.java | 30 ----------- .../vertx/verticles/VerticleDefinition.java | 7 +-- .../vertx/verticles/VerticleDeployer.java | 52 +++++++------------ .../verticles/server/ServerVerticle.java | 19 +++---- 5 files changed, 36 insertions(+), 83 deletions(-) delete mode 100644 src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java diff --git a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java index 456fe5d3b07..35a2245f63a 100644 --- a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java @@ -1,5 +1,6 @@ package org.prebid.server.spring.config.server.application; +import io.vertx.core.Verticle; import io.vertx.core.Vertx; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerOptions; @@ -58,7 +59,6 @@ import org.prebid.server.util.HttpUtil; import org.prebid.server.validation.BidderParamValidator; import org.prebid.server.version.PrebidVersionProvider; -import org.prebid.server.vertx.verticles.InitializableVerticle; import org.prebid.server.vertx.verticles.VerticleDefinition; import org.prebid.server.vertx.verticles.server.ServerVerticle; import org.prebid.server.vertx.verticles.server.application.ApplicationResource; @@ -95,7 +95,7 @@ public class ApplicationServerConfiguration { VerticleDefinition httpApplicationServerVerticleDefinition( @Value("#{'${http.port:${server.http.port}}'}") Integer port, @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") Integer instances, - BiFunction applicationVerticleFactory) { + BiFunction applicationVerticleFactory) { return VerticleDefinition.ofMultiInstance( () -> applicationVerticleFactory.apply( @@ -108,7 +108,7 @@ VerticleDefinition httpApplicationServerVerticleDefinition( VerticleDefinition unixSocketApplicationServerVerticleDefinition( @Value("${server.unix-socket.path}") String path, @Value("${server.unix-socket.server-instances}") Integer instances, - BiFunction applicationVerticleFactory) { + BiFunction applicationVerticleFactory) { return VerticleDefinition.ofMultiInstance( () -> applicationVerticleFactory.apply( @@ -116,7 +116,8 @@ VerticleDefinition unixSocketApplicationServerVerticleDefinition( instances); } - @Bean // TODO: remove support for properties with http prefix after transition period + @Bean + // TODO: remove support for properties with http prefix after transition period HttpServerOptions httpServerOptions( @Value("#{'${http.max-headers-size:${server.max-headers-size:}}'}") int maxHeaderSize, @Value("#{'${http.max-initial-line-length:${server.max-initial-line-length:}}'}") int maxInitialLineLength, @@ -155,7 +156,7 @@ ExceptionHandler exceptionHandler(Metrics metrics) { } @Bean - BiFunction applicationVerticleFactory( + BiFunction applicationVerticleFactory( @Qualifier("applicationServerRouterFactory") Supplier routerFactory, HttpServerOptions httpServerOptions, ExceptionHandler exceptionHandler) { diff --git a/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java deleted file mode 100644 index f17d0328cea..00000000000 --- a/src/main/java/org/prebid/server/vertx/verticles/InitializableVerticle.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.prebid.server.vertx.verticles; - -import io.vertx.core.AbstractVerticle; -import io.vertx.core.Context; -import io.vertx.core.Future; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; - -/** - * Base class for pbs Verticles, exists for making asynchronous verticles initialization synchronous, - * so that server bootstrap will crash if verticle can't init. Every child class should do initialization - * in {@link #initialize(Vertx, Context)} method - */ -public abstract class InitializableVerticle extends AbstractVerticle { - - private final Promise verticleInitialization = Promise.promise(); - - public Future getVerticleInitialization() { - return verticleInitialization.future(); - } - - public abstract Future initialize(Vertx vertx, Context context); - - @Override - public void init(Vertx vertx, Context context) { - initialize(vertx, context) - .onSuccess(verticleInitialization::tryComplete) - .onFailure(verticleInitialization::tryFail); - } -} diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java index 7670e8ea77c..52334bf3c97 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDefinition.java @@ -1,5 +1,6 @@ package org.prebid.server.vertx.verticles; +import io.vertx.core.Verticle; import lombok.Value; import java.util.function.Supplier; @@ -7,15 +8,15 @@ @Value(staticConstructor = "of") public class VerticleDefinition { - Supplier factory; + Supplier factory; int amount; - public static VerticleDefinition ofSingleInstance(Supplier factory) { + public static VerticleDefinition ofSingleInstance(Supplier factory) { return of(factory, 1); } - public static VerticleDefinition ofMultiInstance(Supplier factory, int amount) { + public static VerticleDefinition ofMultiInstance(Supplier factory, int amount) { return of(factory, amount); } } diff --git a/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java index 21559643257..ac84f592bee 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java +++ b/src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java @@ -1,16 +1,14 @@ package org.prebid.server.vertx.verticles; -import io.vertx.core.CompositeFuture; -import io.vertx.core.Future; +import io.vertx.core.AsyncResult; +import io.vertx.core.DeploymentOptions; import io.vertx.core.Vertx; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.IntStream; +import java.util.concurrent.atomic.AtomicReference; public class VerticleDeployer { @@ -28,11 +26,16 @@ public void deploy(VerticleDefinition definition) { return; } + final AtomicReference> deployResult = new AtomicReference<>(); final CountDownLatch latch = new CountDownLatch(1); - final List verticles = toVerticles(definition); - final CompositeFuture verticlesInitialization = toVerticlesInitialization(verticles) - .onComplete(result -> latch.countDown()); - verticles.forEach(vertx::deployVerticle); + + vertx.deployVerticle( + definition.getFactory(), + new DeploymentOptions().setInstances(definition.getAmount()), + (result) -> { + deployResult.set(result); + latch.countDown(); + }); try { if (!latch.await(timeoutMillis, TimeUnit.MILLISECONDS)) { @@ -40,32 +43,15 @@ public void deploy(VerticleDefinition definition) { "Action has not completed within defined timeout %d ms".formatted(timeoutMillis)); } - if (verticlesInitialization.failed()) { - final Throwable cause = verticlesInitialization.cause(); - if (cause != null) { - throw new RuntimeException(cause); - } else { - throw new RuntimeException("Action failed"); - } + final AsyncResult result = deployResult.get(); + if (result.failed()) { + throw Optional.ofNullable(result.cause()) + .map(RuntimeException::new) + .orElse(new RuntimeException("Action failed")); } - } catch ( - InterruptedException e) { + } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("Interrupted while waiting for action to complete", e); } } - - private static List toVerticles(VerticleDefinition definition) { - return IntStream.range(0, definition.getAmount()) - .mapToObj(i -> definition.getFactory().get()) - .toList(); - } - - private static CompositeFuture toVerticlesInitialization(List verticles) { - final List verticlesInitializations = verticles.stream() - .map(InitializableVerticle::getVerticleInitialization) - .collect(Collectors.toCollection(ArrayList::new)); - - return CompositeFuture.all(verticlesInitializations); - } } diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java index 95debd09e8f..533391443f1 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -1,10 +1,8 @@ package org.prebid.server.vertx.verticles.server; +import io.vertx.core.AbstractVerticle; import io.vertx.core.AsyncResult; -import io.vertx.core.Context; -import io.vertx.core.Future; import io.vertx.core.Promise; -import io.vertx.core.Vertx; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.logging.Logger; @@ -13,12 +11,11 @@ import io.vertx.ext.web.Router; import org.apache.commons.lang3.ObjectUtils; import org.prebid.server.handler.ExceptionHandler; -import org.prebid.server.vertx.verticles.InitializableVerticle; import java.util.Objects; import java.util.function.Supplier; -public class ServerVerticle extends InitializableVerticle { +public class ServerVerticle extends AbstractVerticle { private static final Logger logger = LoggerFactory.getLogger(ServerVerticle.class); @@ -50,8 +47,7 @@ public ServerVerticle(String name, SocketAddress address, Supplier route } @Override - public Future initialize(Vertx vertx, Context context) { - final Promise completionPromise = Promise.promise(); + public void start(Promise startPromise) { final HttpServerOptions httpServerOptions = ObjectUtils.defaultIfNull(serverOptions, new HttpServerOptions()); final HttpServer server = vertx.createHttpServer(httpServerOptions) .requestHandler(router); @@ -60,20 +56,19 @@ public Future initialize(Vertx vertx, Context context) { server.exceptionHandler(exceptionHandler); } - server.listen(address, result -> onServerStarted(result, completionPromise)); - return completionPromise.future(); + server.listen(address, result -> onServerStarted(result, startPromise)); } - private void onServerStarted(AsyncResult result, Promise completionPromise) { + private void onServerStarted(AsyncResult result, Promise startPromise) { if (result.succeeded()) { - completionPromise.tryComplete(); + startPromise.tryComplete(); logger.info( "Successfully started {0} instance on address: {1}, thread: {2}", name, address, Thread.currentThread().getName()); } else { - completionPromise.tryFail(result.cause()); + startPromise.tryFail(result.cause()); } } } From 57c85ab48fb3ec6ee332a965200fc4926e7f546f Mon Sep 17 00:00:00 2001 From: Alex Maltsev Date: Wed, 6 Mar 2024 14:27:29 +0200 Subject: [PATCH 6/9] Simplified routing --- .../metrics/PrometheusConfiguration.java | 17 ++++------ .../admin/AdminServerConfiguration.java | 20 +++++------ .../ApplicationServerConfiguration.java | 33 +++++++++---------- .../verticles/server/ServerVerticle.java | 8 ++--- 4 files changed, 34 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java index d6ec05d59bb..4d7447a81e9 100644 --- a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java @@ -28,7 +28,6 @@ import javax.validation.constraints.NotNull; import java.util.List; -import java.util.function.Supplier; @Configuration @ConditionalOnProperty(prefix = "metrics.prometheus", name = "enabled", havingValue = "true") @@ -40,7 +39,7 @@ public class PrometheusConfiguration { @Bean public VerticleDefinition prometheusHttpServerVerticleDefinition( PrometheusConfigurationProperties prometheusConfigurationProperties, - @Qualifier("prometheusRouterFactory") Supplier routerFactory, + @Qualifier("prometheusRouter") Router router, DropwizardExports dropwizardExports) { CollectorRegistry.defaultRegistry.register(dropwizardExports); @@ -49,7 +48,7 @@ public VerticleDefinition prometheusHttpServerVerticleDefinition( () -> new ServerVerticle( "Prometheus Http Server", SocketAddress.inetSocketAddress(prometheusConfigurationProperties.getPort(), "0.0.0.0"), - routerFactory)); + router)); } @Bean @@ -71,13 +70,11 @@ DropwizardExports dropwizardExports(Metrics metrics, MetricRegistry metricRegist return new DropwizardExports(metricRegistry, sampleBuilder); } - @Bean("prometheusRouterFactory") - Supplier prometheusRouterFactory(Vertx vertx) { - return () -> { - final Router router = Router.router(vertx); - router.route("/metrics").handler(new MetricsHandler()); - return router; - }; + @Bean("prometheusRouter") + Router prometheusRouter(Vertx vertx) { + final Router router = Router.router(vertx); + router.route("/metrics").handler(new MetricsHandler()); + return router; } @Data diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java index 25f0a2f80b8..79ccacb5598 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java @@ -12,36 +12,32 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.function.Supplier; - @Configuration @ConditionalOnProperty(prefix = "admin", name = "port") public class AdminServerConfiguration { - @Bean("adminPortAdminServerRouterFactory") - Supplier adminPortAdminServerRouterFactory( + @Bean("adminPortAdminServerRouter") + Router adminPortAdminServerRouter( Vertx vertx, @Qualifier("adminPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, BodyHandler bodyHandler) { - return () -> { - final Router router = Router.router(vertx); - router.route().handler(bodyHandler); + final Router router = Router.router(vertx); + router.route().handler(bodyHandler); - adminResourcesBinder.bind(router); - return router; - }; + adminResourcesBinder.bind(router); + return router; } @Bean VerticleDefinition adminPortAdminHttpServerVerticleDefinition( - @Qualifier("adminPortAdminServerRouterFactory") Supplier routerFactory, + @Qualifier("adminPortAdminServerRouter") Router router, @Value("${admin.port}") int port) { return VerticleDefinition.ofSingleInstance( () -> new ServerVerticle( "Admin Http Server", SocketAddress.inetSocketAddress(port, "0.0.0.0"), - routerFactory)); + router)); } } diff --git a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java index 35a2245f63a..bd1e459be77 100644 --- a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java @@ -79,7 +79,6 @@ import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; -import java.util.function.Supplier; @Configuration public class ApplicationServerConfiguration { @@ -157,16 +156,16 @@ ExceptionHandler exceptionHandler(Metrics metrics) { @Bean BiFunction applicationVerticleFactory( - @Qualifier("applicationServerRouterFactory") Supplier routerFactory, + @Qualifier("applicationServerRouter") Router router, HttpServerOptions httpServerOptions, ExceptionHandler exceptionHandler) { return (name, address) -> new ServerVerticle( - name, httpServerOptions, address, routerFactory, exceptionHandler); + name, httpServerOptions, address, router, exceptionHandler); } - @Bean("applicationServerRouterFactory") - Supplier applicationServerRouterFactory( + @Bean("applicationServerRouter") + Router applicationServerRouter( BodyHandler bodyHandler, NoCacheHandler noCacheHandler, CorsHandler corsHandler, @@ -174,23 +173,21 @@ Supplier applicationServerRouterFactory( @Qualifier("applicationPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, StaticHandler staticHandler) { - return () -> { - final Router router = Router.router(vertx); - router.route().handler(bodyHandler); - router.route().handler(noCacheHandler); - router.route().handler(corsHandler); + final Router router = Router.router(vertx); + router.route().handler(bodyHandler); + router.route().handler(noCacheHandler); + router.route().handler(corsHandler); - resources.forEach(resource -> - resource.endpoints().forEach(endpoint -> - router.route(endpoint.getMethod(), endpoint.getPath()).handler(resource))); + resources.forEach(resource -> + resource.endpoints().forEach(endpoint -> + router.route(endpoint.getMethod(), endpoint.getPath()).handler(resource))); - adminResourcesBinder.bind(router); + adminResourcesBinder.bind(router); - router.get("/static/*").handler(staticHandler); - router.get("/").handler(staticHandler); // serves index.html by default + router.get("/static/*").handler(staticHandler); + router.get("/").handler(staticHandler); // serves index.html by default - return router; - }; + return router; } @Bean diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java index 533391443f1..c66a7fb3826 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -28,21 +28,21 @@ public class ServerVerticle extends AbstractVerticle { public ServerVerticle(String name, HttpServerOptions serverOptions, SocketAddress address, - Supplier routerFactory, + Router router, ExceptionHandler exceptionHandler) { this.name = Objects.requireNonNull(name); this.serverOptions = Objects.requireNonNull(serverOptions); this.address = Objects.requireNonNull(address); - this.router = Objects.requireNonNull(routerFactory.get()); + this.router = Objects.requireNonNull(router); this.exceptionHandler = Objects.requireNonNull(exceptionHandler); } - public ServerVerticle(String name, SocketAddress address, Supplier routerFactory) { + public ServerVerticle(String name, SocketAddress address, Router router) { this.name = Objects.requireNonNull(name); this.serverOptions = null; this.address = Objects.requireNonNull(address); - this.router = Objects.requireNonNull(routerFactory.get()); + this.router = Objects.requireNonNull(router); this.exceptionHandler = null; } From a028f2bb54f24af9745e7f219ad3b854a434071e Mon Sep 17 00:00:00 2001 From: Dubyk Danylo <45672370+CTMBNara@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:56:05 +0200 Subject: [PATCH 7/9] Refactor `ContextRunner`. (#3037) --- .../config/InitializationConfiguration.java | 2 +- .../server/spring/config/VerticleStarter.java | 23 +++++--- .../spring/config/VertxConfiguration.java | 7 --- .../database/DatabaseConfiguration.java | 8 ++- .../prebid/server/vertx/ContextRunner.java | 49 ++++------------ .../vertx/verticles/VerticleDeployer.java | 57 ------------------- .../verticles/server/ServerVerticle.java | 1 - 7 files changed, 32 insertions(+), 115 deletions(-) delete mode 100644 src/main/java/org/prebid/server/vertx/verticles/VerticleDeployer.java diff --git a/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java b/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java index 02035f3f5fe..d52de58ac63 100644 --- a/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/InitializationConfiguration.java @@ -35,7 +35,7 @@ public class InitializationConfiguration { @EventListener(ContextRefreshedEvent.class) public void initializeServices() { - contextRunner.runOnServiceContext(promise -> { + contextRunner.runBlocking(promise -> { initializables.forEach(Initializable::initialize); promise.complete(); }); diff --git a/src/main/java/org/prebid/server/spring/config/VerticleStarter.java b/src/main/java/org/prebid/server/spring/config/VerticleStarter.java index 6869ad1a03e..49bdae234ae 100644 --- a/src/main/java/org/prebid/server/spring/config/VerticleStarter.java +++ b/src/main/java/org/prebid/server/spring/config/VerticleStarter.java @@ -1,24 +1,29 @@ package org.prebid.server.spring.config; +import io.vertx.core.DeploymentOptions; +import io.vertx.core.Vertx; +import org.prebid.server.vertx.ContextRunner; import org.prebid.server.vertx.verticles.VerticleDefinition; -import org.prebid.server.vertx.verticles.VerticleDeployer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; -import javax.annotation.PostConstruct; import java.util.List; @Configuration public class VerticleStarter { @Autowired - private VerticleDeployer deployer; + public void start(Vertx vertx, ContextRunner contextRunner, List definitions) { + for (VerticleDefinition definition : definitions) { + if (definition.getAmount() <= 0) { + continue; + } - @Autowired - private List verticleDefinitions; - - @PostConstruct - public void startVerticles() { - verticleDefinitions.forEach(deployer::deploy); + contextRunner.runBlocking(promise -> + vertx.deployVerticle( + definition.getFactory(), + new DeploymentOptions().setInstances(definition.getAmount()), + promise)); + } } } diff --git a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java index f12cfdfcabb..4636a056783 100644 --- a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java @@ -13,7 +13,6 @@ import org.prebid.server.spring.config.metrics.MetricsConfiguration; import org.prebid.server.vertx.ContextRunner; import org.prebid.server.vertx.LocalMessageCodec; -import org.prebid.server.vertx.verticles.VerticleDeployer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -63,14 +62,8 @@ BodyHandler bodyHandler(@Value("${vertx.uploads-dir}") String uploadsDir) { return BodyHandler.create(uploadsDir); } - // TODO: Remove this class entirely @Bean ContextRunner contextRunner(Vertx vertx, @Value("${vertx.init-timeout-ms}") long initTimeoutMs) { return new ContextRunner(vertx, initTimeoutMs); } - - @Bean - VerticleDeployer verticleDeployer(Vertx vertx, @Value("${vertx.init-timeout-ms}") long initTimeoutMs) { - return new VerticleDeployer(vertx, initTimeoutMs); - } } diff --git a/src/main/java/org/prebid/server/spring/config/database/DatabaseConfiguration.java b/src/main/java/org/prebid/server/spring/config/database/DatabaseConfiguration.java index 69570b59622..065241e7aab 100644 --- a/src/main/java/org/prebid/server/spring/config/database/DatabaseConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/database/DatabaseConfiguration.java @@ -118,7 +118,11 @@ CircuitBreakerProperties databaseCircuitBreakerProperties() { @Bean @ConditionalOnProperty(prefix = "settings.database.circuit-breaker", name = "enabled", havingValue = "true") CircuitBreakerSecuredJdbcClient circuitBreakerSecuredJdbcClient( - Vertx vertx, JDBCClient vertxJdbcClient, Metrics metrics, Clock clock, ContextRunner contextRunner, + Vertx vertx, + JDBCClient vertxJdbcClient, + Metrics metrics, + Clock clock, + ContextRunner contextRunner, @Qualifier("databaseCircuitBreakerProperties") CircuitBreakerProperties circuitBreakerProperties) { final JdbcClient jdbcClient = createBasicJdbcClient(vertx, vertxJdbcClient, metrics, clock, contextRunner); @@ -131,7 +135,7 @@ private static BasicJdbcClient createBasicJdbcClient( Vertx vertx, JDBCClient vertxJdbcClient, Metrics metrics, Clock clock, ContextRunner contextRunner) { final BasicJdbcClient basicJdbcClient = new BasicJdbcClient(vertx, vertxJdbcClient, metrics, clock); - contextRunner.runOnServiceContext(promise -> basicJdbcClient.initialize().onComplete(promise)); + contextRunner.runBlocking(promise -> basicJdbcClient.initialize().onComplete(promise)); return basicJdbcClient; } diff --git a/src/main/java/org/prebid/server/vertx/ContextRunner.java b/src/main/java/org/prebid/server/vertx/ContextRunner.java index 7a61d516419..43dc35c3683 100644 --- a/src/main/java/org/prebid/server/vertx/ContextRunner.java +++ b/src/main/java/org/prebid/server/vertx/ContextRunner.java @@ -1,59 +1,30 @@ package org.prebid.server.vertx; -import io.vertx.core.Context; +import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Promise; import io.vertx.core.Vertx; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; -/** - * Component that manages Vertx contexts and provides interface to run arbitrary code on them. - *

- * Needed mostly to replace verticle deployment model provided by Vertx because it doesn't play nicely when using - * Vertx in embedded mode within Spring application. - */ public class ContextRunner { - private static final Logger logger = LoggerFactory.getLogger(ContextRunner.class); - + private final Vertx vertx; private final long timeoutMs; - private final Context serviceContext; - public ContextRunner(Vertx vertx, long timeoutMs) { + this.vertx = vertx; this.timeoutMs = timeoutMs; - - this.serviceContext = vertx.getOrCreateContext(); - } - - /** - * Runs provided action on a dedicated service context. - */ - public void runOnServiceContext(Handler> action) { - runOnContext(() -> serviceContext, action); } - private void runOnContext(Supplier contextFactory, Handler> action) { + public void runBlocking(Handler> action) { final CountDownLatch completionLatch = new CountDownLatch(1); - final AtomicBoolean actionFailed = new AtomicBoolean(false); - final Context context = contextFactory.get(); - final Promise promise = Promise.promise(); - promise.future().onComplete(ar -> { - if (ar.failed()) { - logger.fatal("Fatal error occurred while running action on Vertx context", ar.cause()); - actionFailed.compareAndSet(false, true); - } - completionLatch.countDown(); - }); + final Future future = promise.future(); - context.runOnContext(v -> { + future.onComplete(ignored -> completionLatch.countDown()); + vertx.runOnContext(v -> { try { action.handle(promise); } catch (RuntimeException e) { @@ -65,12 +36,14 @@ private void runOnContext(Supplier contextFactory, Handler> deployResult = new AtomicReference<>(); - final CountDownLatch latch = new CountDownLatch(1); - - vertx.deployVerticle( - definition.getFactory(), - new DeploymentOptions().setInstances(definition.getAmount()), - result -> { - deployResult.set(result); - latch.countDown(); - }); - - try { - if (!latch.await(timeoutMillis, TimeUnit.MILLISECONDS)) { - throw new RuntimeException( - "Action has not completed within defined timeout %d ms".formatted(timeoutMillis)); - } - - final AsyncResult result = deployResult.get(); - if (result.failed()) { - throw Optional.ofNullable(result.cause()) - .map(RuntimeException::new) - .orElse(new RuntimeException("Action failed")); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Interrupted while waiting for action to complete", e); - } - } -} diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java index c66a7fb3826..9cdd7274d81 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -13,7 +13,6 @@ import org.prebid.server.handler.ExceptionHandler; import java.util.Objects; -import java.util.function.Supplier; public class ServerVerticle extends AbstractVerticle { From efb24937517af6cc7a42b07ef64f24dc26e30671 Mon Sep 17 00:00:00 2001 From: Dubyk Danylo <45672370+CTMBNara@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:06:32 +0200 Subject: [PATCH 8/9] Verticles: Refactoring. (#3047) --- .../server/handler/BidderParamHandler.java | 2 +- .../server/handler/CookieSyncHandler.java | 2 +- .../prebid/server/handler/GetuidsHandler.java | 2 +- .../handler/NotificationEventHandler.java | 2 +- .../prebid/server/handler/OptoutHandler.java | 4 +- .../prebid/server/handler/SetuidHandler.java | 2 +- .../prebid/server/handler/StatusHandler.java | 2 +- .../prebid/server/handler/VtrackHandler.java | 2 +- .../handler/info/BidderDetailsHandler.java | 2 +- .../server/handler/info/BiddersHandler.java | 4 +- .../server/handler/openrtb2/AmpHandler.java | 2 +- .../handler/openrtb2/AuctionHandler.java | 4 +- .../server/handler/openrtb2/VideoHandler.java | 4 +- .../metrics/PrometheusConfiguration.java | 7 +-- .../admin/AdminEndpointsConfiguration.java | 20 +++--- .../server/admin/AdminResourcesBinder.java | 34 +++++++---- .../server/admin/AdminServerAuthProvider.java | 3 +- .../admin/AdminServerConfiguration.java | 19 +++--- .../ApplicationServerConfiguration.java | 61 +++++++++---------- .../verticles/server/ServerVerticle.java | 2 +- 20 files changed, 88 insertions(+), 92 deletions(-) diff --git a/src/main/java/org/prebid/server/handler/BidderParamHandler.java b/src/main/java/org/prebid/server/handler/BidderParamHandler.java index 8dd65b61f40..f27137a2e1e 100644 --- a/src/main/java/org/prebid/server/handler/BidderParamHandler.java +++ b/src/main/java/org/prebid/server/handler/BidderParamHandler.java @@ -22,7 +22,7 @@ public BidderParamHandler(BidderParamValidator bidderParamValidator) { @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/bidders/params")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.bidder_params.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java index 848cdfe4598..437bc19171f 100644 --- a/src/main/java/org/prebid/server/handler/CookieSyncHandler.java +++ b/src/main/java/org/prebid/server/handler/CookieSyncHandler.java @@ -100,7 +100,7 @@ public CookieSyncHandler(long defaultTimeout, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/cookie_sync")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, Endpoint.cookie_sync.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/GetuidsHandler.java b/src/main/java/org/prebid/server/handler/GetuidsHandler.java index d9a91a3e098..705c5f94e27 100644 --- a/src/main/java/org/prebid/server/handler/GetuidsHandler.java +++ b/src/main/java/org/prebid/server/handler/GetuidsHandler.java @@ -31,7 +31,7 @@ public GetuidsHandler(UidsCookieService uidsCookieService, JacksonMapper mapper) @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/getuids")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.getuids.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java index ce3311cbd6d..61c986c12cc 100644 --- a/src/main/java/org/prebid/server/handler/NotificationEventHandler.java +++ b/src/main/java/org/prebid/server/handler/NotificationEventHandler.java @@ -83,7 +83,7 @@ private static TrackingPixel createTrackingPixel() { @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/event")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.event.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/OptoutHandler.java b/src/main/java/org/prebid/server/handler/OptoutHandler.java index 7a967100e87..e8ee98b2683 100644 --- a/src/main/java/org/prebid/server/handler/OptoutHandler.java +++ b/src/main/java/org/prebid/server/handler/OptoutHandler.java @@ -47,8 +47,8 @@ public OptoutHandler(GoogleRecaptchaVerifier googleRecaptchaVerifier, UidsCookie @Override public List endpoints() { return List.of( - HttpEndpoint.of(HttpMethod.GET, "/optout"), - HttpEndpoint.of(HttpMethod.POST, "/optout")); + HttpEndpoint.of(HttpMethod.GET, Endpoint.optout.value()), + HttpEndpoint.of(HttpMethod.POST, Endpoint.optout.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/SetuidHandler.java b/src/main/java/org/prebid/server/handler/SetuidHandler.java index 3ae2b4aa7d3..ef164f1bb02 100644 --- a/src/main/java/org/prebid/server/handler/SetuidHandler.java +++ b/src/main/java/org/prebid/server/handler/SetuidHandler.java @@ -130,7 +130,7 @@ private static Map collectMap(BidderCatalog bidderCa @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/setuid")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.setuid.value())); } private static UsersyncMethodType preferredUserSyncType(Usersyncer usersyncer) { diff --git a/src/main/java/org/prebid/server/handler/StatusHandler.java b/src/main/java/org/prebid/server/handler/StatusHandler.java index 6e8131a6a61..ac4a9983fe7 100644 --- a/src/main/java/org/prebid/server/handler/StatusHandler.java +++ b/src/main/java/org/prebid/server/handler/StatusHandler.java @@ -31,7 +31,7 @@ public StatusHandler(List healthCheckers, JacksonMapper mapper) { @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/status")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.status.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/VtrackHandler.java b/src/main/java/org/prebid/server/handler/VtrackHandler.java index 987d55be810..3a50ee05cfd 100644 --- a/src/main/java/org/prebid/server/handler/VtrackHandler.java +++ b/src/main/java/org/prebid/server/handler/VtrackHandler.java @@ -77,7 +77,7 @@ public VtrackHandler(long defaultTimeout, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/vtrack")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, Endpoint.vtrack.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java index b1a8d65c430..007dd187db3 100644 --- a/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BidderDetailsHandler.java @@ -73,7 +73,7 @@ private ObjectNode allInfos(Map nameToInfo) { @Override public List endpoints() { return Collections.singletonList( - HttpEndpoint.of(HttpMethod.GET, "/info/bidders/:%s".formatted(BIDDER_NAME_PARAM))); + HttpEndpoint.of(HttpMethod.GET, "%s/:%s".formatted(Endpoint.info_bidders.value(), BIDDER_NAME_PARAM))); } @Override diff --git a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java index 90fda2de4c5..ff186e5d63c 100644 --- a/src/main/java/org/prebid/server/handler/info/BiddersHandler.java +++ b/src/main/java/org/prebid/server/handler/info/BiddersHandler.java @@ -12,8 +12,8 @@ import org.prebid.server.vertx.verticles.server.HttpEndpoint; import org.prebid.server.vertx.verticles.server.application.ApplicationResource; -import java.util.List; import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.TreeSet; @@ -37,7 +37,7 @@ public BiddersHandler(BidderCatalog bidderCatalog, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/info/bidders")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.info_bidders.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java index f825f423640..e50e6018293 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AmpHandler.java @@ -119,7 +119,7 @@ public AmpHandler(AmpRequestFactory ampRequestFactory, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, "/openrtb2/amp")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.GET, Endpoint.openrtb2_amp.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java index 20bc3109590..c5a463dce95 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/AuctionHandler.java @@ -5,8 +5,8 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; -import io.vertx.core.http.HttpMethod; import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -80,7 +80,7 @@ public AuctionHandler(double logSamplingRate, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/openrtb2/auction")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, Endpoint.openrtb2_auction.value())); } @Override diff --git a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java index 761135cdd6b..76831745c47 100644 --- a/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java +++ b/src/main/java/org/prebid/server/handler/openrtb2/VideoHandler.java @@ -3,8 +3,8 @@ import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpResponseStatus; import io.vertx.core.AsyncResult; -import io.vertx.core.http.HttpMethod; import io.vertx.core.MultiMap; +import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -82,7 +82,7 @@ public VideoHandler(VideoRequestFactory videoRequestFactory, @Override public List endpoints() { - return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, "/openrtb2/video")); + return Collections.singletonList(HttpEndpoint.of(HttpMethod.POST, Endpoint.openrtb2_video.value())); } @Override diff --git a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java index 4d7447a81e9..72a15515864 100644 --- a/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/metrics/PrometheusConfiguration.java @@ -18,7 +18,6 @@ import org.prebid.server.metric.prometheus.NamespaceSubsystemSampleBuilder; import org.prebid.server.vertx.verticles.VerticleDefinition; import org.prebid.server.vertx.verticles.server.ServerVerticle; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -39,7 +38,7 @@ public class PrometheusConfiguration { @Bean public VerticleDefinition prometheusHttpServerVerticleDefinition( PrometheusConfigurationProperties prometheusConfigurationProperties, - @Qualifier("prometheusRouter") Router router, + Router prometheusRouter, DropwizardExports dropwizardExports) { CollectorRegistry.defaultRegistry.register(dropwizardExports); @@ -48,7 +47,7 @@ public VerticleDefinition prometheusHttpServerVerticleDefinition( () -> new ServerVerticle( "Prometheus Http Server", SocketAddress.inetSocketAddress(prometheusConfigurationProperties.getPort(), "0.0.0.0"), - router)); + prometheusRouter)); } @Bean @@ -70,7 +69,7 @@ DropwizardExports dropwizardExports(Metrics metrics, MetricRegistry metricRegist return new DropwizardExports(metricRegistry, sampleBuilder); } - @Bean("prometheusRouter") + @Bean Router prometheusRouter(Vertx vertx) { final Router router = Router.router(vertx); router.route("/metrics").handler(new MetricsHandler()); diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java index f8e5b4ca69d..31f50e8db6d 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminEndpointsConfiguration.java @@ -181,10 +181,9 @@ AdminResource collectedMetricsAdminEndpoint( new CollectedMetricsHandler(metricRegistry, mapper, path)); } - @Bean(name = "applicationPortAdminResourcesBinder") - AdminResourcesBinder applicationPortAdminResourcesBinder( - @Autowired(required = false) Map adminEndpointCredentials, - List resources) { + @Bean + AdminResourcesBinder applicationPortAdminResourcesBinder(Map adminEndpointCredentials, + List resources) { final List applicationPortAdminResources = resources.stream() .filter(AdminResource::isOnApplicationPort) @@ -193,10 +192,9 @@ AdminResourcesBinder applicationPortAdminResourcesBinder( return new AdminResourcesBinder(adminEndpointCredentials, applicationPortAdminResources); } - @Bean(name = "adminPortAdminResourcesBinder") - AdminResourcesBinder adminPortAdminResourcesBinder( - @Autowired(required = false) Map adminEndpointCredentials, - List resources) { + @Bean + AdminResourcesBinder adminPortAdminResourcesBinder(Map adminEndpointCredentials, + List resources) { final List adminPortAdminResources = resources.stream() .filter(Predicate.not(AdminResource::isOnApplicationPort)) @@ -206,10 +204,8 @@ AdminResourcesBinder adminPortAdminResourcesBinder( } @Bean - Map adminEndpointCredentials( - @Autowired(required = false) AdminEndpointCredentials adminEndpointCredentials) { - - return ObjectUtils.defaultIfNull(adminEndpointCredentials.getCredentials(), Collections.emptyMap()); + Map adminEndpointCredentials(@Autowired(required = false) AdminEndpointCredentials credentials) { + return ObjectUtils.defaultIfNull(credentials.getCredentials(), Collections.emptyMap()); } @Component diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java index 27914fa38d3..11d096d5666 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminResourcesBinder.java @@ -1,7 +1,9 @@ package org.prebid.server.spring.config.server.admin; -import io.vertx.ext.auth.AuthProvider; +import io.vertx.core.Handler; import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.AuthHandler; import io.vertx.ext.web.handler.BasicAuthHandler; import org.prebid.server.vertx.verticles.server.admin.AdminResource; @@ -20,21 +22,29 @@ public AdminResourcesBinder(Map credentials, List } public void bind(Router router) { - resources.forEach(resource -> bindResource(router, resource)); + for (AdminResource resource : resources) { + router + .route(resource.path()) + .handler(resource.isSecured() ? securedAuthHandler() : PassNextHandler.INSTANCE) + .handler(resource); + } + } + + private AuthHandler securedAuthHandler() { + if (credentials == null) { + throw new IllegalArgumentException("Credentials for admin endpoint is empty."); + } + + return BasicAuthHandler.create(new AdminServerAuthProvider(credentials)); } - private void bindResource(Router router, AdminResource resource) { - final String path = resource.path(); + private static class PassNextHandler implements Handler { - if (resource.isSecured()) { - if (credentials == null) { - throw new IllegalArgumentException("Credentials for admin endpoint is empty."); - } + private static final Handler INSTANCE = new PassNextHandler(); - final AuthProvider authProvider = new AdminServerAuthProvider(credentials); - router.route(path).handler(BasicAuthHandler.create(authProvider)).handler(resource); - } else { - router.route(path).handler(resource); + @Override + public void handle(RoutingContext event) { + event.next(); } } } diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java index 15629694ba0..f95980d1a60 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerAuthProvider.java @@ -10,7 +10,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.Map; -import java.util.Objects; public class AdminServerAuthProvider implements AuthProvider { @@ -31,7 +30,7 @@ public void authenticate(JsonObject authInfo, Handler> resultH final String requestPassword = StringUtils.chomp(authInfo.getString("password")); final String storedPassword = credentials.get(requestUsername); - if (StringUtils.isNotBlank(requestPassword) && Objects.equals(storedPassword, requestPassword)) { + if (StringUtils.isNotBlank(requestPassword) && StringUtils.equals(storedPassword, requestPassword)) { resultHandler.handle(Future.succeededFuture()); } else { resultHandler.handle(Future.failedFuture("No such user, or password incorrect.")); diff --git a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java index 79ccacb5598..e88e04be03d 100644 --- a/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/admin/AdminServerConfiguration.java @@ -6,7 +6,6 @@ import io.vertx.ext.web.handler.BodyHandler; import org.prebid.server.vertx.verticles.VerticleDefinition; import org.prebid.server.vertx.verticles.server.ServerVerticle; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -16,28 +15,26 @@ @ConditionalOnProperty(prefix = "admin", name = "port") public class AdminServerConfiguration { - @Bean("adminPortAdminServerRouter") - Router adminPortAdminServerRouter( - Vertx vertx, - @Qualifier("adminPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, - BodyHandler bodyHandler) { + @Bean + Router adminPortAdminServerRouter(Vertx vertx, + AdminResourcesBinder adminPortAdminResourcesBinder, + BodyHandler bodyHandler) { final Router router = Router.router(vertx); router.route().handler(bodyHandler); - adminResourcesBinder.bind(router); + adminPortAdminResourcesBinder.bind(router); return router; } @Bean - VerticleDefinition adminPortAdminHttpServerVerticleDefinition( - @Qualifier("adminPortAdminServerRouter") Router router, - @Value("${admin.port}") int port) { + VerticleDefinition adminPortAdminHttpServerVerticleDefinition(Router adminPortAdminServerRouter, + @Value("${admin.port}") int port) { return VerticleDefinition.ofSingleInstance( () -> new ServerVerticle( "Admin Http Server", SocketAddress.inetSocketAddress(port, "0.0.0.0"), - router)); + adminPortAdminServerRouter)); } } diff --git a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java index c37a867ce93..4740f025320 100644 --- a/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/server/application/ApplicationServerConfiguration.java @@ -1,6 +1,5 @@ package org.prebid.server.spring.config.server.application; -import io.vertx.core.Verticle; import io.vertx.core.Vertx; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerOptions; @@ -62,8 +61,6 @@ import org.prebid.server.vertx.verticles.VerticleDefinition; import org.prebid.server.vertx.verticles.server.ServerVerticle; import org.prebid.server.vertx.verticles.server.application.ApplicationResource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -78,7 +75,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.function.BiFunction; @Configuration public class ApplicationServerConfiguration { @@ -86,32 +82,41 @@ public class ApplicationServerConfiguration { @Value("${logging.sampling-rate:0.01}") private double logSamplingRate; - @Autowired - private Vertx vertx; - @Bean @ConditionalOnProperty(name = "server.http.enabled", havingValue = "true") VerticleDefinition httpApplicationServerVerticleDefinition( + HttpServerOptions httpServerOptions, @Value("#{'${http.port:${server.http.port}}'}") Integer port, - @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") Integer instances, - BiFunction applicationVerticleFactory) { + Router applicationServerRouter, + ExceptionHandler exceptionHandler, + @Value("#{'${vertx.http-server-instances:${server.http.server-instances}}'}") Integer instances) { return VerticleDefinition.ofMultiInstance( - () -> applicationVerticleFactory.apply( - "Application Http Server", SocketAddress.inetSocketAddress(port, "0.0.0.0")), + () -> new ServerVerticle( + "Application Http Server", + httpServerOptions, + SocketAddress.inetSocketAddress(port, "0.0.0.0"), + applicationServerRouter, + exceptionHandler), instances); } @Bean @ConditionalOnProperty(name = "server.unix-socket.enabled", havingValue = "true") VerticleDefinition unixSocketApplicationServerVerticleDefinition( + HttpServerOptions httpServerOptions, @Value("${server.unix-socket.path}") String path, - @Value("${server.unix-socket.server-instances}") Integer instances, - BiFunction applicationVerticleFactory) { + Router applicationServerRouter, + ExceptionHandler exceptionHandler, + @Value("${server.unix-socket.server-instances}") Integer instances) { return VerticleDefinition.ofMultiInstance( - () -> applicationVerticleFactory.apply( - "Application Unix Socket Server", SocketAddress.domainSocketAddress(path)), + () -> new ServerVerticle( + "Application Unix Socket Server", + httpServerOptions, + SocketAddress.domainSocketAddress(path), + applicationServerRouter, + exceptionHandler), instances); } @@ -155,23 +160,13 @@ ExceptionHandler exceptionHandler(Metrics metrics) { } @Bean - BiFunction applicationVerticleFactory( - @Qualifier("applicationServerRouter") Router router, - HttpServerOptions httpServerOptions, - ExceptionHandler exceptionHandler) { - - return (name, address) -> new ServerVerticle( - name, httpServerOptions, address, router, exceptionHandler); - } - - @Bean("applicationServerRouter") - Router applicationServerRouter( - BodyHandler bodyHandler, - NoCacheHandler noCacheHandler, - CorsHandler corsHandler, - List resources, - @Qualifier("applicationPortAdminResourcesBinder") AdminResourcesBinder adminResourcesBinder, - StaticHandler staticHandler) { + Router applicationServerRouter(Vertx vertx, + BodyHandler bodyHandler, + NoCacheHandler noCacheHandler, + CorsHandler corsHandler, + List resources, + AdminResourcesBinder applicationPortAdminResourcesBinder, + StaticHandler staticHandler) { final Router router = Router.router(vertx); router.route().handler(bodyHandler); @@ -182,7 +177,7 @@ Router applicationServerRouter( resource.endpoints().forEach(endpoint -> router.route(endpoint.getMethod(), endpoint.getPath()).handler(resource))); - adminResourcesBinder.bind(router); + applicationPortAdminResourcesBinder.bind(router); router.get("/static/*").handler(staticHandler); router.get("/").handler(staticHandler); // serves index.html by default diff --git a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java index 9cdd7274d81..eed48d09cde 100644 --- a/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java +++ b/src/main/java/org/prebid/server/vertx/verticles/server/ServerVerticle.java @@ -47,7 +47,7 @@ public ServerVerticle(String name, SocketAddress address, Router router) { @Override public void start(Promise startPromise) { - final HttpServerOptions httpServerOptions = ObjectUtils.defaultIfNull(serverOptions, new HttpServerOptions()); + final HttpServerOptions httpServerOptions = ObjectUtils.getIfNull(serverOptions, HttpServerOptions::new); final HttpServer server = vertx.createHttpServer(httpServerOptions) .requestHandler(router); From 7ce85209eb81cfe4a975b2e2f38271ccbc8fa899 Mon Sep 17 00:00:00 2001 From: Danylo Date: Wed, 13 Mar 2024 15:48:46 +0200 Subject: [PATCH 9/9] Remove `LocalMessageCodec` --- .../spring/config/VertxConfiguration.java | 10 ---- .../server/vertx/LocalMessageCodec.java | 46 ------------------- 2 files changed, 56 deletions(-) delete mode 100644 src/main/java/org/prebid/server/vertx/LocalMessageCodec.java diff --git a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java index 4636a056783..5dc0f08fc19 100644 --- a/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java +++ b/src/main/java/org/prebid/server/spring/config/VertxConfiguration.java @@ -2,7 +2,6 @@ import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; -import io.vertx.core.eventbus.EventBus; import io.vertx.core.file.FileSystem; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; @@ -12,7 +11,6 @@ import io.vertx.ext.web.handler.BodyHandler; import org.prebid.server.spring.config.metrics.MetricsConfiguration; import org.prebid.server.vertx.ContextRunner; -import org.prebid.server.vertx.LocalMessageCodec; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -44,14 +42,6 @@ Vertx vertx(@Value("${vertx.worker-pool-size}") int workerPoolSize, return vertx; } - @Bean - EventBus eventBus(Vertx vertx) { - final EventBus eventBus = vertx.eventBus(); - eventBus.registerCodec(LocalMessageCodec.create()); - - return eventBus; - } - @Bean FileSystem fileSystem(Vertx vertx) { return vertx.fileSystem(); diff --git a/src/main/java/org/prebid/server/vertx/LocalMessageCodec.java b/src/main/java/org/prebid/server/vertx/LocalMessageCodec.java deleted file mode 100644 index 302dcb11eff..00000000000 --- a/src/main/java/org/prebid/server/vertx/LocalMessageCodec.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.prebid.server.vertx; - -import io.vertx.core.buffer.Buffer; -import io.vertx.core.eventbus.EventBus; -import io.vertx.core.eventbus.MessageCodec; - -/** - * Message codec intended for use with objects passed around via {@link EventBus} only locally, i.e. within one JVM. - */ -public class LocalMessageCodec implements MessageCodec { - - private static final String CODEC_NAME = "LocalMessageCodec"; - - public static MessageCodec create() { - return new LocalMessageCodec(); - } - - @Override - public void encodeToWire(Buffer buffer, Object source) { - throw new UnsupportedOperationException("Serialization is not supported by this message codec"); - } - - @Override - public Object decodeFromWire(int pos, Buffer buffer) { - throw new UnsupportedOperationException("Deserialization is not supported by this message codec"); - } - - @Override - public Object transform(Object source) { - return source; - } - - @Override - public String name() { - return codecName(); - } - - @Override - public byte systemCodecID() { - return -1; - } - - public static String codecName() { - return CODEC_NAME; - } -}