diff --git a/src/test/groovy/org/prebid/server/functional/model/config/Endpoint.groovy b/src/test/groovy/org/prebid/server/functional/model/config/Endpoint.groovy index eee6d80d319..3d3ee4a1b13 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/Endpoint.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/Endpoint.groovy @@ -6,16 +6,20 @@ import groovy.transform.ToString @ToString enum Endpoint { - OPENRTB2_AUCTION("/openrtb2/auction"), - OPENRTB2_AMP("/openrtb2/amp"), - OPENRTB2_VIDEO("/openrtb2/video"), + AUCTION("/openrtb2/auction"), + AMP("/openrtb2/amp"), + VIDEO("/openrtb2/video"), COOKIE_SYNC("/cookie_sync"), SETUID("/setuid"), BIDDER_PARAMS("/bidders/params"), EVENT("/event"), GETUIDS("/getuids"), INFO_BIDDERS("/info/bidders"), - OPTOUT("/optout"), + CURRENCY_RATES("/currency/rates"), + HTTP_INTERACTION("/logging/httpinteraction"), + COLLECTED_METRICS("/collected-metrics"), + PROMETHEUS_METRICS ("/metrics"), + INFLUX_DB("/query"), STATUS("/status"), VTRACK("/vtrack") diff --git a/src/test/groovy/org/prebid/server/functional/model/config/ExecutionPlan.groovy b/src/test/groovy/org/prebid/server/functional/model/config/ExecutionPlan.groovy index 81e103d68f3..48f7051af32 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/ExecutionPlan.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/ExecutionPlan.groovy @@ -9,13 +9,17 @@ import groovy.transform.ToString class ExecutionPlan { List abTests - Map endpoints + Map endpoints - static ExecutionPlan getSingleEndpointExecutionPlan(Endpoint endpoint, ModuleName moduleName, List stage) { + static ExecutionPlan getSingleEndpointExecutionPlan(HookHttpEndpoint endpoint, ModuleName moduleName, List stage) { new ExecutionPlan(endpoints: [(endpoint): EndpointExecutionPlan.getModuleEndpointExecutionPlan(moduleName, stage)]) } - static ExecutionPlan getSingleEndpointExecutionPlan(Endpoint endpoint, Map> modulesStages) { + static ExecutionPlan getSingleEndpointExecutionPlan(HookHttpEndpoint endpoint, Map> modulesStages) { new ExecutionPlan(endpoints: [(endpoint): EndpointExecutionPlan.getModulesEndpointExecutionPlan(modulesStages)]) } + + List getListOfModuleCodes() { + endpoints.values().stages*.values().groups.hookSequence.moduleCode.flatten() as List + } } diff --git a/src/test/groovy/org/prebid/server/functional/model/config/HookHttpEndpoint.groovy b/src/test/groovy/org/prebid/server/functional/model/config/HookHttpEndpoint.groovy new file mode 100644 index 00000000000..918a3b05e66 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/config/HookHttpEndpoint.groovy @@ -0,0 +1,32 @@ +package org.prebid.server.functional.model.config + +import com.fasterxml.jackson.annotation.JsonValue +import groovy.transform.ToString + +@ToString +enum HookHttpEndpoint { + + AUCTION("/openrtb2/auction"), + AUCTION_GET("GET /openrtb2/auction"), + AUCTION_POST("POST /openrtb2/auction"), + + AMP("/openrtb2/amp"), + AMP_GET("GET /openrtb2/amp"), + AMP_POST("POST /openrtb2/amp"), + + VIDEO("/openrtb2/video"), + VIDEO_GET("GET /openrtb2/video"), + VIDEO_POST("POST /openrtb2/video") + + @JsonValue + final String value + + HookHttpEndpoint(String value) { + this.value = value + } + + @Override + String toString() { + value + } +} diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Server.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Server.groovy index c088163b38b..12238301ca1 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Server.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Server.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.model.request.auction +import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString @@ -12,5 +13,6 @@ class Server { Integer gvlId String datacenter String endpoint + @JsonProperty("http_method") String httpMethod } 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 2e0d0765a0f..c7994152f35 100644 --- a/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy +++ b/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy @@ -43,26 +43,26 @@ import java.time.format.DateTimeFormatter import static io.restassured.RestAssured.given import static java.time.ZoneOffset.UTC +import static org.prebid.server.functional.model.config.Endpoint.AMP +import static org.prebid.server.functional.model.config.Endpoint.AUCTION +import static org.prebid.server.functional.model.config.Endpoint.BIDDER_PARAMS +import static org.prebid.server.functional.model.config.Endpoint.COLLECTED_METRICS +import static org.prebid.server.functional.model.config.Endpoint.COOKIE_SYNC +import static org.prebid.server.functional.model.config.Endpoint.CURRENCY_RATES +import static org.prebid.server.functional.model.config.Endpoint.EVENT +import static org.prebid.server.functional.model.config.Endpoint.GETUIDS +import static org.prebid.server.functional.model.config.Endpoint.HTTP_INTERACTION +import static org.prebid.server.functional.model.config.Endpoint.INFLUX_DB +import static org.prebid.server.functional.model.config.Endpoint.INFO_BIDDERS +import static org.prebid.server.functional.model.config.Endpoint.PROMETHEUS_METRICS +import static org.prebid.server.functional.model.config.Endpoint.SETUID +import static org.prebid.server.functional.model.config.Endpoint.STATUS +import static org.prebid.server.functional.model.config.Endpoint.VTRACK import static org.prebid.server.functional.testcontainers.Dependencies.influxdbContainer class PrebidServerService implements ObjectMapperWrapper { - static final String AUCTION_ENDPOINT = "/openrtb2/auction" - static final String AMP_ENDPOINT = "/openrtb2/amp" - static final String COOKIE_SYNC_ENDPOINT = "/cookie_sync" - static final String SET_UID_ENDPOINT = "/setuid" - static final String GET_UIDS_ENDPOINT = "/getuids" - static final String EVENT_ENDPOINT = "/event" - static final String VTRACK_ENDPOINT = "/vtrack" - static final String STATUS_ENDPOINT = "/status" - static final String INFO_BIDDERS_ENDPOINT = "/info/bidders" - static final String BIDDERS_PARAMS_ENDPOINT = "/bidders/params" - 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 PROMETHEUS_METRICS_ENDPOINT = "/metrics" - static final String INFLUX_DB_ENDPOINT = "/query" static final String UIDS_COOKIE_NAME = "uids" private final PrebidServerContainer pbsContainer @@ -190,7 +190,7 @@ class PrebidServerService implements ObjectMapperWrapper { .cookies(cookies) .queryParams(toMap(request)) .headers(header) - .get(SET_UID_ENDPOINT) + .get(SETUID.value) checkResponseStatusCode(response) @@ -206,7 +206,7 @@ class PrebidServerService implements ObjectMapperWrapper { def uidsCookieAsEncodedJson = Base64.urlEncoder.encodeToString(uidsCookieAsJson.bytes) def response = given(requestSpecification).cookie(UIDS_COOKIE_NAME, uidsCookieAsEncodedJson) - .get(GET_UIDS_ENDPOINT) + .get(GETUIDS.value) checkResponseStatusCode(response) decode(response.body.asString(), GetuidResponse) @@ -215,7 +215,7 @@ class PrebidServerService implements ObjectMapperWrapper { byte[] sendEventRequest(EventRequest eventRequest, Map headers = [:]) { def response = given(requestSpecification).headers(headers) .queryParams(toMap(eventRequest)) - .get(EVENT_ENDPOINT) + .get(EVENT.value) checkResponseStatusCode(response) response.body.asByteArray() @@ -224,7 +224,7 @@ class PrebidServerService implements ObjectMapperWrapper { PrebidCacheResponse sendPostVtrackRequest(VtrackRequest request, String account) { def response = given(requestSpecification).queryParams(["a": account]) .body(request) - .post(VTRACK_ENDPOINT) + .post(VTRACK.value) checkResponseStatusCode(response) decode(response.body.asString(), PrebidCacheResponse) @@ -233,28 +233,28 @@ class PrebidServerService implements ObjectMapperWrapper { TransferValue sendGetVtrackRequest(Map parameters) { def response = given(requestSpecification) .queryParams(parameters) - .get(VTRACK_ENDPOINT) + .get(VTRACK.value) checkResponseStatusCode(response) decode(response.body.asString(), TransferValue) } StatusResponse sendStatusRequest() { - def response = given(requestSpecification).get(STATUS_ENDPOINT) + def response = given(requestSpecification).get(STATUS.value) checkResponseStatusCode(response) decode(response.body.asString(), StatusResponse) } String sendInfoBiddersRequest() { - def response = given(requestSpecification).get(INFO_BIDDERS_ENDPOINT) + def response = given(requestSpecification).get(INFO_BIDDERS.value) checkResponseStatusCode(response) response.body().asString() } List sendInfoBiddersRequest(Map queryParam) { - def response = given(requestSpecification).queryParams(queryParam).get(INFO_BIDDERS_ENDPOINT) + def response = given(requestSpecification).queryParams(queryParam).get(INFO_BIDDERS.value) checkResponseStatusCode(response) decode(response.asString(), new TypeReference>() {}) @@ -262,21 +262,21 @@ class PrebidServerService implements ObjectMapperWrapper { BidderInfoResponse sendBidderInfoRequest(BidderName bidderName) { - def response = given(requestSpecification).get("$INFO_BIDDERS_ENDPOINT/$bidderName.value") + def response = given(requestSpecification).get("${INFO_BIDDERS.value}/$bidderName.value") checkResponseStatusCode(response) decode(response.body.asString(), BidderInfoResponse) } BiddersParamsResponse sendBiddersParamsRequest() { - def response = given(requestSpecification).get(BIDDERS_PARAMS_ENDPOINT) + def response = given(requestSpecification).get(BIDDER_PARAMS.value) checkResponseStatusCode(response) decode(response.body.asString(), BiddersParamsResponse) } CurrencyRatesResponse sendCurrencyRatesRequest() { - def response = given(adminRequestSpecification).get(CURRENCY_RATES_ENDPOINT) + def response = given(adminRequestSpecification).get(CURRENCY_RATES.value) checkResponseStatusCode(response) decode(response.body.asString(), CurrencyRatesResponse) @@ -284,14 +284,14 @@ class PrebidServerService implements ObjectMapperWrapper { String sendLoggingHttpInteractionRequest(HttpInteractionRequest httpInteractionRequest) { def response = given(adminRequestSpecification).queryParams(toMap(httpInteractionRequest)) - .get(HTTP_INTERACTION_ENDPOINT) + .get(HTTP_INTERACTION.value) checkResponseStatusCode(response) response.body().asString() } Map sendCollectedMetricsRequest() { - def response = given(adminRequestSpecification).get(COLLECTED_METRICS_ENDPOINT) + def response = given(adminRequestSpecification).get(COLLECTED_METRICS.value) checkResponseStatusCode(response) decode(response.asString(), new TypeReference>() {}) @@ -301,14 +301,14 @@ class PrebidServerService implements ObjectMapperWrapper { def response = given(influxRequestSpecification) .queryParams(["db": influxdbContainer.getDatabase(), "q" : "SELECT COUNT(count) FROM /.*/ WHERE count >= 1 GROUP BY \"measurement\""]) - .get(INFLUX_DB_ENDPOINT) + .get(INFLUX_DB.value) checkResponseStatusCode(response) collectInToMap(decode(response.getBody().asString(), InfluxResponse)) } String sendPrometheusMetricsRequest() { - def response = given(prometheusRequestSpecification).get(PROMETHEUS_METRICS_ENDPOINT) + def response = given(prometheusRequestSpecification).get(PROMETHEUS_METRICS.value) checkResponseStatusCode(response) response.body().asString() @@ -324,7 +324,7 @@ class PrebidServerService implements ObjectMapperWrapper { given(requestSpecification).headers(headers) .body(payload) - .post(AUCTION_ENDPOINT) + .post(AUCTION.value) } private Response postCookieSync(CookieSyncRequest cookieSyncRequest, @@ -355,7 +355,7 @@ class PrebidServerService implements ObjectMapperWrapper { requestSpecification.headers(headers) } - requestSpecification.post(COOKIE_SYNC_ENDPOINT) + requestSpecification.post(COOKIE_SYNC.value) } private Response getAmp(AmpRequest ampRequest, @@ -369,7 +369,7 @@ class PrebidServerService implements ObjectMapperWrapper { given(requestSpecification).headers(headers) .queryParams(map) - .get(AMP_ENDPOINT) + .get(AMP.value) } private void checkResponseStatusCode(Response response, int statusCode = 200) { diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy index a886a2a3fb2..5a177572122 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/container/PrebidServerContainer.groovy @@ -7,6 +7,7 @@ import org.testcontainers.containers.GenericContainer import org.testcontainers.containers.wait.strategy.Wait import org.testcontainers.images.builder.Transferable +import static org.prebid.server.functional.model.config.Endpoint.STATUS import static org.prebid.server.functional.testcontainers.PbsConfig.DEFAULT_ENV class PrebidServerContainer extends GenericContainer { @@ -30,7 +31,7 @@ class PrebidServerContainer extends GenericContainer { withExposedPorts(PORT, DEBUG_PORT, ADMIN_PORT, PROMETHEUS_PORT) withFixedPorts() withStartupAttempts(3) - waitingFor(Wait.forHttp("/status") + waitingFor(Wait.forHttp(STATUS.value) .forPort(PORT) .forStatusCode(200)) withDebug() diff --git a/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy index 378c1ddd5e6..166f49e4cf6 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy @@ -35,6 +35,7 @@ import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.APPNEXUS import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.bidder.BidderName.GENERIC_CAMEL_CASE +import static org.prebid.server.functional.model.config.Endpoint.AUCTION import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.model.response.cookiesync.UserSyncInfo.Type.REDIRECT import static org.prebid.server.functional.testcontainers.Dependencies.networkServiceContainer @@ -298,7 +299,7 @@ class AuctionSpec extends BaseSpec { then: "BidderRequest should contain endpoint in ext.prebid.server.endpoint instead of ext.prebid.pbs.endpoint" def bidderRequest = bidder.getBidderRequest(bidRequest.id) - assert bidderRequest?.ext?.prebid?.server?.endpoint == "/openrtb2/auction" + assert bidderRequest?.ext?.prebid?.server?.endpoint == AUCTION.value assert bidderRequest?.ext?.prebid?.server?.httpMethod == HttpPost.METHOD_NAME assert !bidderRequest?.ext?.prebid?.pbs?.endpoint diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy index 2a33e6921a7..42579c0f688 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -3,6 +3,7 @@ package org.prebid.server.functional.tests import org.prebid.server.functional.model.bidder.AppNexus import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.bidder.Generic +import org.prebid.server.functional.model.config.Endpoint import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.db.StoredRequest @@ -146,7 +147,7 @@ class BidderParamsSpec extends BaseSpec { then: "vast xml is modified" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) assert prebidCacheRequest.size() == 1 - assert prebidCacheRequest.first().contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + assert prebidCacheRequest.first().contains("${Endpoint.EVENT}?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -178,7 +179,7 @@ class BidderParamsSpec extends BaseSpec { then: "vast xml is not modified" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) assert prebidCacheRequest.size() == 1 - assert !prebidCacheRequest.first().contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + assert !prebidCacheRequest.first().contains("${Endpoint.EVENT}?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) diff --git a/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy index e5637fe80e2..8f817643571 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy @@ -5,6 +5,7 @@ import org.prebid.server.functional.model.config.AccountCacheConfig import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.config.AccountEventsConfig import org.prebid.server.functional.model.config.AccountVtrackConfig +import org.prebid.server.functional.model.config.Endpoint import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.vtrack.VtrackRequest import org.prebid.server.functional.model.request.vtrack.xml.Vast @@ -89,7 +90,7 @@ class CacheVtrackSpec extends BaseSpec { then: "Vast xml is modified" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) assert prebidCacheRequest.size() == 1 - assert prebidCacheRequest[0].contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + assert prebidCacheRequest[0].contains("${Endpoint.EVENT}?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") and: "prebid_cache.creative_size.xml metric should be updated" def metrics = defaultPbsService.sendCollectedMetricsRequest() diff --git a/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy index 682bb2fef8b..45b4a9f8f8a 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy @@ -1,6 +1,7 @@ package org.prebid.server.functional.tests import org.prebid.server.functional.model.UidsCookie +import org.prebid.server.functional.model.config.Endpoint import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.mock.services.httpsettings.HttpAccountsResponse import org.prebid.server.functional.model.request.amp.AmpRequest @@ -280,7 +281,7 @@ class HttpSettingsSpec extends BaseSpec { and: "VastXml that was send to PrebidCache must contain event url" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload)[0] - assert prebidCacheRequest.contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + assert prebidCacheRequest.contains("${Endpoint.EVENT}?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") } def "PBS should take account information from http data source on vtrack request when rfc3986 enabled"() { @@ -305,7 +306,7 @@ class HttpSettingsSpec extends BaseSpec { and: "VastXml that was send to PrebidCache must contain event url" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload)[0] - assert prebidCacheRequest.contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + assert prebidCacheRequest.contains("${Endpoint.EVENT}?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") } def "PBS should return error if account settings isn't found"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/AbTestingModuleSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/AbTestingModuleSpec.groovy index 041e41d4e26..de9d940de43 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/AbTestingModuleSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/AbTestingModuleSpec.groovy @@ -1,10 +1,10 @@ package org.prebid.server.functional.tests.module -import org.prebid.server.functional.model.config.ModuleName import org.prebid.server.functional.model.config.AbTest import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.config.AccountHooksConfiguration import org.prebid.server.functional.model.config.ExecutionPlan +import org.prebid.server.functional.model.config.ModuleName import org.prebid.server.functional.model.config.Stage import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.auction.BidRequest @@ -15,8 +15,8 @@ import org.prebid.server.functional.model.response.auction.InvocationResult import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION import static org.prebid.server.functional.model.config.ModuleName.PB_RESPONSE_CORRECTION -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES import static org.prebid.server.functional.model.config.Stage.BIDDER_REQUEST import static org.prebid.server.functional.model.config.Stage.RAW_BIDDER_RESPONSE @@ -61,7 +61,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def abTest = AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { enabled = false } - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { it.abTests = [abTest] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -104,7 +104,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(prebidServerService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code)] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -147,7 +147,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(moduleName)] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -195,7 +195,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def richMediaAbTestConfig = AbTest.getDefault(PB_RESPONSE_CORRECTION.code).tap { it.percentActive = MAX_PERCENT_AB } - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [ortb2AbTestConfig, richMediaAbTestConfig] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -256,7 +256,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def richMediaAbTestConfig = AbTest.getDefault(PB_RESPONSE_CORRECTION.code).tap { it.percentActive = MIN_PERCENT_AB } - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [ortb2AbTestConfig, richMediaAbTestConfig] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -317,7 +317,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def richMediaAbTestConfig = AbTest.getDefault(PB_RESPONSE_CORRECTION.code).tap { it.percentActive = MAX_PERCENT_AB } - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [ortb2AbTestConfig, richMediaAbTestConfig] } def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) @@ -370,7 +370,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code, [PBSUtils.randomNumber]).tap { percentActive = MIN_PERCENT_AB }] @@ -407,7 +407,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { it.percentActive = percentActive it.percentActiveSnakeCase = percentActiveSnakeCase @@ -456,7 +456,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { it.percentActive = percentActive it.percentActiveSnakeCase = percentActiveSnakeCase @@ -499,7 +499,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { it.percentActive = percentActive it.percentActiveSnakeCase = percentActiveSnakeCase @@ -546,7 +546,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { it.percentActive = percentActive it.percentActiveSnakeCase = percentActiveSnakeCase @@ -599,7 +599,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = MIN_PERCENT_AB it.logAnalyticsTag = logAnalyticsTag @@ -644,7 +644,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = MIN_PERCENT_AB it.logAnalyticsTag = logAnalyticsTag @@ -687,7 +687,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = MAX_PERCENT_AB it.logAnalyticsTag = logAnalyticsTag @@ -735,7 +735,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(ortbModulePbsService) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, ORTB_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, ORTB_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = PBSUtils.getRandomNumber(MIN_PERCENT_AB, MAX_PERCENT_AB) }] @@ -765,7 +765,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def "PBS should apply a/b test config from host config when accounts is not specified when account config and default account doesn't include a/b test config"() { given: "PBS service with specific ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code, accouns).tap { percentActive = MIN_PERCENT_AB }] @@ -825,7 +825,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def "PBS should apply a/b test config from host config for specific accounts and only specified module when account config and default account doesn't include a/b test config"() { given: "PBS service with specific ab test config" def accountId = PBSUtils.randomNumber - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code, [PBSUtils.randomNumber, accountId]).tap { percentActive = MIN_PERCENT_AB }] @@ -891,7 +891,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def richMediaAbTestConfig = AbTest.getDefault(PB_RESPONSE_CORRECTION.code, [accountId]).tap { it.percentActive = MIN_PERCENT_AB } - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [ortb2AbTestConfig, richMediaAbTestConfig] } def pbsConfig = MULTI_MODULE_CONFIG + ['hooks.host-execution-plan': encode(executionPlan)] @@ -951,7 +951,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def "PBS shouldn't apply a/b test config from host config for non specified accounts when account config and default account doesn't include a/b test config"() { given: "PBS service with specific ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code, [PBSUtils.randomNumber]).tap { percentActive = MIN_PERCENT_AB }] @@ -1013,7 +1013,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def "PBS should prioritise a/b test config from default account and only specified module when host and default account contains a/b test configs"() { given: "PBS service with specific ab test config" - def accountExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def accountExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = MIN_PERCENT_AB }] @@ -1022,7 +1022,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { hooks = new AccountHooksConfiguration(executionPlan: accountExecutionPlan) } - def hostExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def hostExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code)] } def pbsConfig = MULTI_MODULE_CONFIG + ['hooks.host-execution-plan': encode(hostExecutionPlan)] + ["settings.default-account-config": encode(defaultAccountConfigSettings)] @@ -1077,7 +1077,9 @@ class AbTestingModuleSpec extends ModuleBaseSpec { def "PBS should prioritise a/b test config from account over default account and only specified module when specific account and default account contains a/b test configs"() { given: "PBS service with specific ab test config" - def accountExecutionPlan = new ExecutionPlan(abTests: [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code)]) + def accountExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { + abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code)] + } def defaultAccountConfigSettings = AccountConfig.defaultAccountConfig.tap { hooks = new AccountHooksConfiguration(executionPlan: accountExecutionPlan) } @@ -1093,7 +1095,7 @@ class AbTestingModuleSpec extends ModuleBaseSpec { flushMetrics(pbsServiceWithMultipleModules) and: "Save account with ab test config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES).tap { + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES).tap { abTests = [AbTest.getDefault(ModuleName.PB_ORTB2_BLOCKING.code).tap { percentActive = MIN_PERCENT_AB }] diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/GeneralModuleSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/GeneralModuleSpec.groovy index a8868878bd8..d883da8f219 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/GeneralModuleSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/GeneralModuleSpec.groovy @@ -1,10 +1,10 @@ package org.prebid.server.functional.tests.module -import org.prebid.server.functional.model.config.ModuleName import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.config.AccountHooksConfiguration import org.prebid.server.functional.model.config.AdminConfig import org.prebid.server.functional.model.config.ExecutionPlan +import org.prebid.server.functional.model.config.ModuleName import org.prebid.server.functional.model.config.Ortb2BlockingConfig import org.prebid.server.functional.model.config.PbResponseCorrection import org.prebid.server.functional.model.config.PbsModulesConfig @@ -13,12 +13,19 @@ import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.auction.RichmediaFilter import org.prebid.server.functional.model.request.auction.TraceLevel import org.prebid.server.functional.model.response.auction.InvocationResult +import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils +import java.time.Instant + +import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.prebid.server.functional.model.AccountStatus.ACTIVE +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION_GET +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION_POST import static org.prebid.server.functional.model.config.ModuleName.PB_ORTB2_BLOCKING import static org.prebid.server.functional.model.config.ModuleName.PB_RICHMEDIA_FILTER -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES import static org.prebid.server.functional.model.config.Stage.BIDDER_REQUEST import static org.prebid.server.functional.model.config.Stage.RAW_BIDDER_RESPONSE @@ -35,9 +42,11 @@ class GeneralModuleSpec extends ModuleBaseSpec { (RAW_BIDDER_RESPONSE): [PB_ORTB2_BLOCKING]] private final static Map> RESPONSE_STAGES = [(ALL_PROCESSED_BID_RESPONSES): [PB_RICHMEDIA_FILTER]] private final static Map> MODULES_STAGES = ORTB_STAGES + RESPONSE_STAGES + private final static ExecutionPlan GLOBAL_EXECUTION_PLAN = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, MODULES_STAGES) private final static Map MULTI_MODULE_CONFIG = getRichMediaFilterSettings(PBSUtils.randomString) + getOrtb2BlockingSettings() + - ['hooks.host-execution-plan': encode(ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, MODULES_STAGES))] + ['settings.enforce-valid-account': 'true', + 'hooks.host-execution-plan' : encode(GLOBAL_EXECUTION_PLAN)] private static final PrebidServerService pbsServiceWithMultipleModule = pbsServiceFactory.getService(MULTI_MODULE_CONFIG + DISABLED_INVOKE_CONFIG) private static final PrebidServerService pbsServiceWithMultipleModuleWithRequireInvoke = pbsServiceFactory.getService(MULTI_MODULE_CONFIG + ENABLED_INVOKE_CONFIG) @@ -149,6 +158,10 @@ class GeneralModuleSpec extends ModuleBaseSpec { and: "Flush metrics" flushMetrics(pbsServiceWithMultipleModules) + and: "Save base active account" + def account = new Account(uuid: bidRequest.getAccountId(), status: ACTIVE) + accountDao.save(account) + when: "PBS processes auction request" def response = pbsServiceWithMultipleModules.sendAuctionRequest(bidRequest) @@ -305,6 +318,10 @@ class GeneralModuleSpec extends ModuleBaseSpec { and: "Flush metrics" flushMetrics(pbsServiceWithMultipleModules) + and: "Save base active account" + def account = new Account(uuid: bidRequest.getAccountId(), status: ACTIVE) + accountDao.save(account) + when: "PBS processes auction request" def response = pbsServiceWithMultipleModules.sendAuctionRequest(bidRequest) @@ -326,7 +343,7 @@ class GeneralModuleSpec extends ModuleBaseSpec { pbsServiceFactory.removeContainer(pbsConfig) } - def "PBS shouldn't call any module without account config when modules disabled in module-execution host config"() { + def "PBS shouldn't call module when disabled in host config and no account config provided"() { given: "PBS service with module-execution config" def pbsConfig = MULTI_MODULE_CONFIG + ENABLED_INVOKE_CONFIG + [("hooks.admin.module-execution.${PB_ORTB2_BLOCKING.code}".toString()): 'false'] @@ -340,6 +357,10 @@ class GeneralModuleSpec extends ModuleBaseSpec { and: "Flush metrics" flushMetrics(pbsServiceWithMultipleModules) + and: "Save account without modules config" + def account = new Account(uuid: bidRequest.getAccountId(), status: ACTIVE) + accountDao.save(account) + when: "PBS processes auction request" def response = pbsServiceWithMultipleModules.sendAuctionRequest(bidRequest) @@ -363,7 +384,7 @@ class GeneralModuleSpec extends ModuleBaseSpec { hooks = new AccountHooksConfiguration(admin: new AdminConfig(moduleExecution: [(PB_ORTB2_BLOCKING): true])) } def pbsConfig = MULTI_MODULE_CONFIG + ENABLED_INVOKE_CONFIG + ["settings.default-account-config": encode(defaultAccountConfigSettings)] + - [("hooks.admin.module-execution.${PB_ORTB2_BLOCKING.code}".toString()): 'false'] + [("hooks.admin.module-execution.${PB_ORTB2_BLOCKING.code}".toString()): 'false'] def pbsServiceWithMultipleModules = pbsServiceFactory.getService(pbsConfig) and: "Default bid request with verbose trace" @@ -528,4 +549,91 @@ class GeneralModuleSpec extends ModuleBaseSpec { cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) } + + def "PBS should merge account level config without any errors when config contains proper request methods"() { + given: "Test start time" + def startTime = Instant.now() + + and: "Default bid request with verbose trace" + def bidRequest = defaultBidRequest.tap { + ext.prebid.trace = TraceLevel.VERBOSE + } + + and: "Save account without modules config" + def pbsModulesConfig = new PbsModulesConfig(pbRichmediaFilter: new RichmediaFilter(filterMraid: true), pbOrtb2Blocking: new Ortb2BlockingConfig()) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(endpoint, RESPONSE_STAGES) + def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan, modules: pbsModulesConfig)) + def account = new Account(uuid: bidRequest.getAccountId(), config: accountConfig) + accountDao.save(account) + + and: "Flush metrics" + flushMetrics(pbsServiceWithMultipleModule) + + when: "PBS processes auction request" + def response = pbsServiceWithMultipleModule.sendAuctionRequest(bidRequest) + + then: "PBS response should include trace information about called modules" + def modulesCodes = GLOBAL_EXECUTION_PLAN.listOfModuleCodes + executionPlan.listOfModuleCodes + verifyAll(response?.ext?.prebid?.modules?.trace?.stages?.outcomes?.groups?.invocationResults?.flatten() as List) { + it.status == [SUCCESS] * modulesCodes.size() + it.action == [NO_ACTION] * modulesCodes.size() + it.hookId.moduleCode.sort() == modulesCodes.sort() + } + + and: "Ortb2blocking module call metrics should be updated" + def metrics = pbsServiceWithMultipleModule.sendCollectedMetricsRequest() + assert metrics[CALL_METRIC(PB_ORTB2_BLOCKING, BIDDER_REQUEST)] == 1 + assert metrics[CALL_METRIC(PB_ORTB2_BLOCKING, RAW_BIDDER_RESPONSE)] == 1 + assert metrics[NOOP_METRIC(PB_ORTB2_BLOCKING, BIDDER_REQUEST)] == 1 + assert metrics[NOOP_METRIC(PB_ORTB2_BLOCKING, RAW_BIDDER_RESPONSE)] == 1 + + and: "RB-Richmedia-Filter module call metrics should be updated" + def richmediaCounts = modulesCodes.count(PB_RICHMEDIA_FILTER.code) + assert metrics[CALL_METRIC(PB_RICHMEDIA_FILTER, ALL_PROCESSED_BID_RESPONSES)] == richmediaCounts + assert metrics[NOOP_METRIC(PB_RICHMEDIA_FILTER, ALL_PROCESSED_BID_RESPONSES)] == richmediaCounts + + and: "Response shouldn't contain warnings and errors" + assert !response.ext?.warnings + assert !response.ext?.errors + + and: "PBS log should not contain deserialization error messages" + def logs = pbsServiceWithMultipleModule.getLogsByTime(startTime) + assert !getLogsByText(logs, "Cannot deserialize value of type `org.prebid.server.hooks.execution.model.HookHttpEndpoint` " + + "from String \"${AUCTION_GET}\": not one of the values accepted for Enum class").size() + + where: + endpoint << [AUCTION, AUCTION_POST] + } + + def "PBS should merge account level config and emit error when config contains invalid request methods"() { + given: "Test start time" + def startTime = Instant.now() + + and: "Default bid request with verbose trace" + def bidRequest = defaultBidRequest.tap { + ext.prebid.trace = TraceLevel.VERBOSE + } + + and: "Save account without modules config" + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION_GET, MODULES_STAGES) + def accountConfig = new AccountConfig(hooks: new AccountHooksConfiguration(executionPlan: executionPlan)) + def account = new Account(uuid: bidRequest.getAccountId(), config: accountConfig) + accountDao.save(account) + + and: "Flush metrics" + flushMetrics(pbsServiceWithMultipleModule) + + when: "PBS processes auction request" + pbsServiceWithMultipleModule.sendAuctionRequest(bidRequest) + + then: "Response should contain error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == UNAUTHORIZED.code() + assert exception.responseBody == "Unauthorized account id: ${account.uuid}" + + and: "PBS log should contain message" + def logs = pbsServiceWithMultipleModule.getLogsByTime(startTime) + assert getLogsByText(logs, "Cannot deserialize value of type `org.prebid.server.hooks.execution.model.HookHttpEndpoint` " + + "from String \"${AUCTION_GET}\": not one of the values accepted for Enum class").size() == 1 + } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/ModuleBaseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/ModuleBaseSpec.groovy index d509d0ac44b..da5057d472b 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/ModuleBaseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/ModuleBaseSpec.groovy @@ -3,6 +3,7 @@ package org.prebid.server.functional.tests.module import org.prebid.server.functional.model.config.ModuleName import org.prebid.server.functional.model.config.Endpoint import org.prebid.server.functional.model.config.ExecutionPlan +import org.prebid.server.functional.model.config.HookHttpEndpoint import org.prebid.server.functional.model.config.Stage import org.prebid.server.functional.model.response.auction.AnalyticResult import org.prebid.server.functional.model.response.auction.BidResponse @@ -15,7 +16,7 @@ import static org.prebid.server.functional.model.config.ModuleName.PB_REQUEST_CO import static org.prebid.server.functional.model.config.ModuleName.PB_RESPONSE_CORRECTION import static org.prebid.server.functional.model.config.ModuleName.PB_RICHMEDIA_FILTER import static org.prebid.server.functional.model.config.ModuleName.PB_RULE_ENGINE -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES import static org.prebid.server.functional.model.config.Stage.PROCESSED_AUCTION_REQUEST import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer @@ -49,7 +50,7 @@ class ModuleBaseSpec extends BaseSpec { "modules.module.${module.code}.stage.${stage.metricValue}.hook.${module.code}-${stage.value}-hook.execution-error" } - protected static Map getResponseCorrectionConfig(Endpoint endpoint = OPENRTB2_AUCTION) { + protected static Map getResponseCorrectionConfig(HookHttpEndpoint endpoint = AUCTION) { ["hooks.${PB_RESPONSE_CORRECTION.code}.enabled": true, "hooks.host-execution-plan" : encode(ExecutionPlan.getSingleEndpointExecutionPlan(endpoint, [(ALL_PROCESSED_BID_RESPONSES): [PB_RESPONSE_CORRECTION]]))] .collectEntries { key, value -> [(key.toString()): value.toString()] } @@ -57,7 +58,7 @@ class ModuleBaseSpec extends BaseSpec { protected static Map getRichMediaFilterSettings(String scriptPattern, Boolean filterMraidEnabled = true, - Endpoint endpoint = OPENRTB2_AUCTION) { + HookHttpEndpoint endpoint = AUCTION) { ["hooks.${PB_RICHMEDIA_FILTER.code}.enabled" : true, "hooks.modules.${PB_RICHMEDIA_FILTER.code}.mraid-script-pattern": scriptPattern, @@ -75,7 +76,7 @@ class ModuleBaseSpec extends BaseSpec { .collectEntries { key, value -> [(key.toString()): value.toString()] } } - protected static Map getOptableTargetingSettings(boolean isEnabled = true, Endpoint endpoint = OPENRTB2_AUCTION) { + protected static Map getOptableTargetingSettings(boolean isEnabled = true, HookHttpEndpoint endpoint = AUCTION) { ["hooks.${OPTABLE_TARGETING.code}.enabled" : isEnabled as String, "hooks.modules.${OPTABLE_TARGETING.code}.api-endpoint": "$networkServiceContainer.rootUri/stored-cache".toString(), "hooks.modules.${OPTABLE_TARGETING.code}.tenant" : PBSUtils.randomString, @@ -88,12 +89,12 @@ class ModuleBaseSpec extends BaseSpec { ["hooks.${PB_ORTB2_BLOCKING.code}.enabled": isEnabled as String] } - protected static Map getRequestCorrectionSettings(Endpoint endpoint = OPENRTB2_AUCTION, Stage stage = PROCESSED_AUCTION_REQUEST) { + protected static Map getRequestCorrectionSettings(HookHttpEndpoint endpoint = AUCTION, Stage stage = PROCESSED_AUCTION_REQUEST) { ["hooks.${PB_REQUEST_CORRECTION.code}.enabled": "true", "hooks.host-execution-plan" : encode(ExecutionPlan.getSingleEndpointExecutionPlan(endpoint, PB_REQUEST_CORRECTION, [stage]))] } - protected static Map getRulesEngineSettings(Endpoint endpoint = OPENRTB2_AUCTION, Stage stage = PROCESSED_AUCTION_REQUEST) { + protected static Map getRulesEngineSettings(HookHttpEndpoint endpoint = AUCTION, Stage stage = PROCESSED_AUCTION_REQUEST) { ["hooks.${PB_RULE_ENGINE.code}.enabled" : "true", "hooks.${PB_RULE_ENGINE.code}.rule-cache.expire-after-minutes" : "10000", "hooks.${PB_RULE_ENGINE.code}.rule-cache.max-size" : "20000", diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/analyticstag/AnalyticsTagsModuleSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/analyticstag/AnalyticsTagsModuleSpec.groovy index 05815a64158..dfd34bccb86 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/analyticstag/AnalyticsTagsModuleSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/analyticstag/AnalyticsTagsModuleSpec.groovy @@ -22,7 +22,7 @@ import org.prebid.server.functional.util.PBSUtils import static org.prebid.server.functional.model.config.ModuleName.PB_ORTB2_BLOCKING import static org.prebid.server.functional.model.config.ModuleName.PB_RICHMEDIA_FILTER import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES import static org.prebid.server.functional.model.config.Stage.RAW_BIDDER_RESPONSE import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE @@ -43,7 +43,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: true)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) @@ -122,7 +122,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { def "PBS should include analytics tag in response when request and default account allow client details"() { given: "Default account with module config" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: true)) @@ -161,7 +161,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { def "PBS should include analytics tag in response when request and account allow client details but default doesn't"() { given: "Default account with module config" - def defaultExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def defaultExecutionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def defaultHooksConfiguration = new AccountHooksConfiguration(executionPlan: defaultExecutionPlan) def defaultAccountConfig = new AccountConfig(hooks: defaultHooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: false)) @@ -175,7 +175,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: true)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) @@ -212,7 +212,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: true)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) @@ -235,7 +235,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: true)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) @@ -258,7 +258,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: false)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) @@ -282,7 +282,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { } and: "Account in the DB" - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [RAW_BIDDER_RESPONSE]) def hooksConfiguration = new AccountHooksConfiguration(executionPlan: executionPlan) def accountConfig = new AccountConfig(hooks: hooksConfiguration, analytics: new AccountAnalyticsConfig(allowClientDetails: false)) def account = new Account(uuid: bidRequest.accountId, config: accountConfig) diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/pbortb2blocking/PbOrtb2BlockingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/pbortb2blocking/PbOrtb2BlockingSpec.groovy index 59b2f30d90b..29e45b86955 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/pbortb2blocking/PbOrtb2BlockingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/pbortb2blocking/PbOrtb2BlockingSpec.groovy @@ -37,7 +37,7 @@ import static org.prebid.server.functional.model.config.ModuleName.PB_ORTB2_BLOC import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.bidder.BidderName.IX -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.AUDIO_BATTR import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BADV import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BAPP @@ -1531,7 +1531,7 @@ class PbOrtb2BlockingSpec extends ModuleBaseSpec { private static Account getAccountWithOrtb2BlockingConfig(String accountId, Map attributes) { def blockingConfig = new Ortb2BlockingConfig(attributes: attributes) - def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_ORTB2_BLOCKING, [BIDDER_REQUEST, RAW_BIDDER_RESPONSE]) + def executionPlan = ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_ORTB2_BLOCKING, [BIDDER_REQUEST, RAW_BIDDER_RESPONSE]) def moduleConfig = new PbsModulesConfig(pbOrtb2Blocking: blockingConfig) def accountHooksConfig = new AccountHooksConfiguration(executionPlan: executionPlan, modules: moduleConfig) def accountConfig = new AccountConfig(hooks: accountHooksConfig) diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/pbrichmedia/PbRichMediaFilterSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/pbrichmedia/PbRichMediaFilterSpec.groovy index a4b2b6b6047..037a38fb922 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/pbrichmedia/PbRichMediaFilterSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/pbrichmedia/PbRichMediaFilterSpec.groovy @@ -16,12 +16,12 @@ import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.tests.module.ModuleBaseSpec import org.prebid.server.functional.util.PBSUtils -import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_INVALID_CREATIVE -import static org.prebid.server.functional.model.config.ModuleName.PB_RICHMEDIA_FILTER import static org.prebid.server.functional.model.bidder.BidderName.GENERIC -import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION +import static org.prebid.server.functional.model.config.HookHttpEndpoint.AUCTION +import static org.prebid.server.functional.model.config.ModuleName.PB_RICHMEDIA_FILTER import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE +import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_INVALID_CREATIVE class PbRichMediaFilterSpec extends ModuleBaseSpec { @@ -30,7 +30,7 @@ class PbRichMediaFilterSpec extends ModuleBaseSpec { private static final Map DISABLED_FILTER_SPECIFIC_PATTERN_NAME_CONFIG = getRichMediaFilterSettings(PATTERN_NAME, false) private static final Map SPECIFIC_PATTERN_NAME_CONFIG = getRichMediaFilterSettings(PATTERN_NAME) private static final Map SNAKE_SPECIFIC_PATTERN_NAME_CONFIG = (getRichMediaFilterSettings(PATTERN_NAME) + - ["hooks.host-execution-plan": encode(ExecutionPlan.getSingleEndpointExecutionPlan(OPENRTB2_AUCTION, PB_RICHMEDIA_FILTER, [ALL_PROCESSED_BID_RESPONSES]).tap { + ["hooks.host-execution-plan": encode(ExecutionPlan.getSingleEndpointExecutionPlan(AUCTION, PB_RICHMEDIA_FILTER, [ALL_PROCESSED_BID_RESPONSES]).tap { endpoints.values().first().stages.values().first().groups.first.hookSequenceSnakeCase = [new HookId(moduleCodeSnakeCase: PB_RICHMEDIA_FILTER.code, hookImplCodeSnakeCase: "${PB_RICHMEDIA_FILTER.code}-${ALL_PROCESSED_BID_RESPONSES.value}-hook")] })]).collectEntries { key, value -> [(key.toString()): value.toString()] }