From b786e9695ba6bf6ee17ac5eeb462c2bc7e4570c2 Mon Sep 17 00:00:00 2001 From: osulzhenko Date: Thu, 12 Feb 2026 19:45:15 +0200 Subject: [PATCH] Tests: ORTB Error Response --- .../model/config/AppVideoHtml.groovy | 2 +- .../config/Ortb2BlockingActionOverride.groovy | 2 +- .../Ortb2BlockingAttributeConfig.groovy | 2 +- .../model/db/StoredProfileRequest.groovy | 4 +- .../functional/model/db/StoredResponse.groovy | 2 +- .../vendorlist/VendorListResponse.groovy | 1 + .../model/request/auction/Prebid.groovy | 2 + .../model/response/BidderError.groovy | 5 +- .../model/response/BidderErrorCode.groovy | 23 ++ .../model/response/amp/AmpResponseExt.groovy | 3 +- .../model/response/amp/RawAmpResponse.groovy | 1 + .../auction/RawAuctionResponse.groovy | 1 + .../response/auction/WarningEntry.groovy | 3 +- .../cookiesync/RawCookieSyncResponse.groovy | 1 + .../HibernateRepositoryService.groovy | 2 +- .../service/PrebidServerService.groovy | 21 +- .../testcontainers/Dependencies.groovy | 2 +- .../testcontainers/PbsConfig.groovy | 4 +- .../functional/tests/AccountSpec.groovy | 54 ++-- .../server/functional/tests/AliasSpec.groovy | 47 +-- .../tests/AlternateBidderCodeSpec.groovy | 271 +++++++++--------- .../server/functional/tests/AmpFpdSpec.groovy | 17 +- .../server/functional/tests/AmpSpec.groovy | 15 +- .../functional/tests/AuctionSpec.groovy | 31 +- .../functional/tests/BidAdjustmentSpec.groovy | 22 +- .../tests/BidExpResponseSpec.groovy | 4 +- .../functional/tests/BidValidationSpec.groovy | 48 ++-- .../functional/tests/BidderFormatSpec.groovy | 66 +++-- .../tests/BidderInsensitiveCaseSpec.groovy | 3 +- .../functional/tests/BidderParamsSpec.groovy | 29 +- .../server/functional/tests/CacheSpec.groovy | 7 +- .../server/functional/tests/DebugSpec.groovy | 35 ++- .../server/functional/tests/EidsSpec.groovy | 37 ++- .../functional/tests/ImpRequestSpec.groovy | 7 +- .../functional/tests/InfluxDBSpec.groovy | 16 +- .../tests/OrtbValidationSpec.groovy | 211 ++++++++++++++ .../functional/tests/ProfileSpec.groovy | 107 ++++--- .../functional/tests/SeatNonBidSpec.groovy | 4 +- .../tests/StoredResponseSpec.groovy | 37 ++- .../functional/tests/TargetingSpec.groovy | 25 +- .../tests/bidder/openx/OpenxSpec.groovy | 20 +- .../tests/module/ModuleBaseSpec.groovy | 3 +- .../AnalyticsTagsModuleSpec.groovy | 3 +- .../ortb2blocking/Ortb2BlockingSpec.groovy | 9 +- .../PbRequestCorrectionSpec.groovy | 2 +- .../pbruleengine/RuleEngineDeviceSpec.groovy | 1 - .../richmedia/RichMediaFilterSpec.groovy | 2 +- .../PriceFloorsAdjustmentSpec.groovy | 7 +- .../PriceFloorsCurrencySpec.groovy | 9 +- .../PriceFloorsEnforcementSpec.groovy | 15 +- .../PriceFloorsFetchingSpec.groovy | 23 +- .../PriceFloorsSignalingSpec.groovy | 27 +- .../tests/privacy/CcpaAmpSpec.groovy | 9 +- .../functional/tests/privacy/DsaSpec.groovy | 12 +- .../tests/privacy/GdprAmpSpec.groovy | 13 +- .../tests/privacy/GdprAuctionSpec.groovy | 4 +- .../tests/privacy/GppAmpSpec.groovy | 7 +- .../tests/privacy/GppAuctionSpec.groovy | 13 +- .../tests/privacy/GppCookieSyncSpec.groovy | 2 +- .../privacy/GppFetchBidActivitiesSpec.groovy | 25 +- .../tests/privacy/GppSetUidSpec.groovy | 2 +- .../GppTransmitEidsActivitiesSpec.groovy | 24 +- ...GppTransmitPreciseGeoActivitiesSpec.groovy | 25 +- .../GppTransmitTidActivitiesSpec.groovy | 4 +- .../GppTransmitUfpdActivitiesSpec.groovy | 27 +- .../tests/privacy/PrivacyBaseSpec.groovy | 2 +- .../TcfBasicTransmitEidsActivitiesSpec.groovy | 2 +- ...smitEidsOrtbConverterActivitiesSpec.groovy | 2 +- .../tests/storage/AccountS3Spec.groovy | 47 +-- .../functional/tests/storage/AmpS3Spec.groovy | 39 +-- .../tests/storage/AuctionS3Spec.groovy | 43 +-- .../tests/storage/StoredResponseS3Spec.groovy | 40 +-- .../util/privacy/gpp/v1/UsCaV1Consent.groovy | 2 +- .../util/privacy/gpp/v1/UsCoV1Consent.groovy | 2 +- .../util/privacy/gpp/v1/UsCtV1Consent.groovy | 2 +- .../util/privacy/gpp/v1/UsNatV1Consent.groovy | 2 +- .../util/privacy/gpp/v1/UsUtV1Consent.groovy | 2 +- .../util/privacy/gpp/v1/UsVaV1Consent.groovy | 2 +- 78 files changed, 1040 insertions(+), 609 deletions(-) create mode 100644 src/test/groovy/org/prebid/server/functional/model/response/BidderErrorCode.groovy create mode 100644 src/test/groovy/org/prebid/server/functional/tests/OrtbValidationSpec.groovy diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AppVideoHtml.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AppVideoHtml.groovy index 6486e292ed5..63777b61897 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/AppVideoHtml.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/AppVideoHtml.groovy @@ -1,6 +1,6 @@ package org.prebid.server.functional.model.config -import com.fasterxml.jackson.annotation.JsonProperty + import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString diff --git a/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingActionOverride.groovy b/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingActionOverride.groovy index de8eae06d04..eb7434fe46e 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingActionOverride.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingActionOverride.groovy @@ -6,8 +6,8 @@ import groovy.transform.ToString 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 import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BANNER_BATTR +import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BAPP import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BCAT import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BTYPE import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.VIDEO_BATTR diff --git a/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingAttributeConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingAttributeConfig.groovy index 9e622472024..0255dd9bfa6 100644 --- a/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingAttributeConfig.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/config/Ortb2BlockingAttributeConfig.groovy @@ -6,8 +6,8 @@ import groovy.transform.ToString 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 import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BANNER_BATTR +import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BAPP import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BCAT import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BTYPE import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.VIDEO_BATTR diff --git a/src/test/groovy/org/prebid/server/functional/model/db/StoredProfileRequest.groovy b/src/test/groovy/org/prebid/server/functional/model/db/StoredProfileRequest.groovy index 8b04143d368..4112f18ac8a 100644 --- a/src/test/groovy/org/prebid/server/functional/model/db/StoredProfileRequest.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/db/StoredProfileRequest.groovy @@ -6,13 +6,13 @@ import jakarta.persistence.Convert import jakarta.persistence.Entity import jakarta.persistence.Id import jakarta.persistence.Table +import org.prebid.server.functional.model.db.typeconverter.BidRequestConfigTypeConverter import org.prebid.server.functional.model.db.typeconverter.ProfileMergePrecedenceConvert import org.prebid.server.functional.model.db.typeconverter.ProfileTypeConvert -import org.prebid.server.functional.model.db.typeconverter.BidRequestConfigTypeConverter import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.profile.ProfileMergePrecedence -import org.prebid.server.functional.model.request.profile.RequestProfile import org.prebid.server.functional.model.request.profile.ProfileType +import org.prebid.server.functional.model.request.profile.RequestProfile @Entity @Table(name = "profiles") diff --git a/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy index ebfc31f3c6d..278dd1e9227 100644 --- a/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/db/StoredResponse.groovy @@ -7,8 +7,8 @@ import jakarta.persistence.Entity import jakarta.persistence.GeneratedValue import jakarta.persistence.Id import jakarta.persistence.Table -import org.prebid.server.functional.model.db.typeconverter.StoredAuctionResponseConfigTypeConverter import org.prebid.server.functional.model.db.typeconverter.BidResponseConfigTypeConverter +import org.prebid.server.functional.model.db.typeconverter.StoredAuctionResponseConfigTypeConverter import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.SeatBid diff --git a/src/test/groovy/org/prebid/server/functional/model/mock/services/vendorlist/VendorListResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/mock/services/vendorlist/VendorListResponse.groovy index d44755978e4..2fbdbebc619 100644 --- a/src/test/groovy/org/prebid/server/functional/model/mock/services/vendorlist/VendorListResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/mock/services/vendorlist/VendorListResponse.groovy @@ -1,6 +1,7 @@ package org.prebid.server.functional.model.mock.services.vendorlist import org.prebid.server.functional.util.PBSUtils + import java.time.Clock import java.time.ZonedDateTime diff --git a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy index 23b4e7f87a5..4b1dacc8f8e 100644 --- a/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/request/auction/Prebid.groovy @@ -49,6 +49,8 @@ class Prebid { List profileNames @JsonProperty("kvps") Map keyValuePairs + @JsonProperty("ortberrors") + Boolean ortbErrors static class Channel { diff --git a/src/test/groovy/org/prebid/server/functional/model/response/BidderError.groovy b/src/test/groovy/org/prebid/server/functional/model/response/BidderError.groovy index 4b6c3bdd820..f1e9a2c2471 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/BidderError.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/BidderError.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.model.response +import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString @@ -8,7 +9,9 @@ import groovy.transform.ToString @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy) class BidderError { - Integer code + BidderErrorCode code String message + @JsonProperty("error") + String errorMessage Set impIds } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/BidderErrorCode.groovy b/src/test/groovy/org/prebid/server/functional/model/response/BidderErrorCode.groovy new file mode 100644 index 00000000000..1bab8a6ecef --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/response/BidderErrorCode.groovy @@ -0,0 +1,23 @@ +package org.prebid.server.functional.model.response + +import com.fasterxml.jackson.annotation.JsonValue +import groovy.transform.ToString + +@ToString(includeNames = true, ignoreNulls = true) +enum BidderErrorCode { + + BAD_INPUT(2), + BAD_SERVER_RESPONSE(3), + FAILED_TO_REQUEST_BIDS(4), + INVALID_BID(5), + REJECTED_IPF(6), + TIMEOUT(1), + GENERIC(999) + + @JsonValue + final Integer value + + BidderErrorCode(Integer value) { + this.value = value + } +} diff --git a/src/test/groovy/org/prebid/server/functional/model/response/amp/AmpResponseExt.groovy b/src/test/groovy/org/prebid/server/functional/model/response/amp/AmpResponseExt.groovy index fbb598dccba..4bfa092e481 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/amp/AmpResponseExt.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/amp/AmpResponseExt.groovy @@ -3,10 +3,11 @@ package org.prebid.server.functional.model.response.amp import org.prebid.server.functional.model.response.BidderError import org.prebid.server.functional.model.response.Debug import org.prebid.server.functional.model.response.auction.ErrorType +import org.prebid.server.functional.model.response.auction.WarningEntry class AmpResponseExt { Debug debug Map> errors - Map> warnings + Map> warnings } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/amp/RawAmpResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/response/amp/RawAmpResponse.groovy index 18e7f705a1e..21616a85f3c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/amp/RawAmpResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/amp/RawAmpResponse.groovy @@ -6,5 +6,6 @@ import groovy.transform.ToString class RawAmpResponse { String responseBody + Integer statusCode Map> headers } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/RawAuctionResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/RawAuctionResponse.groovy index e9f8f01730f..fea6c0a7151 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/RawAuctionResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/RawAuctionResponse.groovy @@ -7,5 +7,6 @@ import org.prebid.server.functional.model.ResponseModel class RawAuctionResponse implements ResponseModel { String responseBody + Integer statusCode Map> headers } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/auction/WarningEntry.groovy b/src/test/groovy/org/prebid/server/functional/model/response/auction/WarningEntry.groovy index 655a0743212..6de8ce6cb6c 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/auction/WarningEntry.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/auction/WarningEntry.groovy @@ -3,12 +3,13 @@ package org.prebid.server.functional.model.response.auction import com.fasterxml.jackson.databind.PropertyNamingStrategies import com.fasterxml.jackson.databind.annotation.JsonNaming import groovy.transform.ToString +import org.prebid.server.functional.model.response.BidderErrorCode @ToString(includeNames = true, ignoreNulls = true) @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy) class WarningEntry { - Integer code + BidderErrorCode code String message Set impIds } diff --git a/src/test/groovy/org/prebid/server/functional/model/response/cookiesync/RawCookieSyncResponse.groovy b/src/test/groovy/org/prebid/server/functional/model/response/cookiesync/RawCookieSyncResponse.groovy index 3854da82dde..030fc92dac2 100644 --- a/src/test/groovy/org/prebid/server/functional/model/response/cookiesync/RawCookieSyncResponse.groovy +++ b/src/test/groovy/org/prebid/server/functional/model/response/cookiesync/RawCookieSyncResponse.groovy @@ -6,5 +6,6 @@ import groovy.transform.ToString class RawCookieSyncResponse { String responseBody + Integer statusCode Map> headers } diff --git a/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy b/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy index cd1b9706f79..48ab82f6126 100644 --- a/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy +++ b/src/test/groovy/org/prebid/server/functional/repository/HibernateRepositoryService.groovy @@ -3,9 +3,9 @@ package org.prebid.server.functional.repository import org.hibernate.SessionFactory import org.hibernate.cfg.Configuration import org.prebid.server.functional.model.db.Account +import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.db.StoredProfileImp import org.prebid.server.functional.model.db.StoredProfileRequest -import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.db.StoredResponse import org.prebid.server.functional.repository.dao.AccountDao 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 249d6fa3f13..b8895d86c32 100644 --- a/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy +++ b/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy @@ -6,6 +6,7 @@ import io.restassured.authentication.BasicAuthScheme import io.restassured.builder.RequestSpecBuilder import io.restassured.response.Response import io.restassured.specification.RequestSpecification +import org.apache.http.HttpStatus import org.prebid.server.functional.model.UidsCookie import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.mock.services.prebidcache.response.PrebidCacheResponse @@ -86,10 +87,14 @@ class PrebidServerService implements ObjectMapperWrapper { prometheusRequestSpecification = buildAndGetRequestSpecification(pbsContainer.prometheusRootUri, authenticationScheme) } - BidResponse sendAuctionRequest(BidRequest bidRequest, Map headers = [:]) { + BidResponse sendAuctionRequest(BidRequest bidRequest, Integer statusCode = HttpStatus.SC_OK) { + sendAuctionRequest(bidRequest, [:], statusCode) + } + + BidResponse sendAuctionRequest(BidRequest bidRequest, Map headers, int statusCode = HttpStatus.SC_OK) { def response = postAuction(bidRequest, headers) - checkResponseStatusCode(response) + checkResponseStatusCode(response, statusCode) decode(response.body.asString(), BidResponse) } @@ -98,6 +103,7 @@ class PrebidServerService implements ObjectMapperWrapper { new RawAuctionResponse().tap { it.headers = getHeaders(response) + it.statusCode = response.statusCode() it.responseBody = response.body.asString() } } @@ -109,10 +115,14 @@ class PrebidServerService implements ObjectMapperWrapper { decode(response.body.asString(), AmpResponse) } - AmpResponse sendAmpRequest(AmpRequest ampRequest, Map headers = [:]) { + AmpResponse sendAmpRequest(AmpRequest ampRequest, int statusCode = HttpStatus.SC_OK) { + sendAmpRequest(ampRequest, [:], statusCode) + } + + AmpResponse sendAmpRequest(AmpRequest ampRequest, Map headers, int statusCode = HttpStatus.SC_OK) { def response = getAmp(ampRequest, headers) - checkResponseStatusCode(response) + checkResponseStatusCode(response, statusCode) decode(response.body.asString(), AmpResponse) } @@ -121,6 +131,7 @@ class PrebidServerService implements ObjectMapperWrapper { new RawAmpResponse().tap { it.headers = getHeaders(response) + it.statusCode = response.statusCode() it.responseBody = response.body.asString() } } @@ -372,7 +383,7 @@ class PrebidServerService implements ObjectMapperWrapper { .get(AMP_ENDPOINT) } - private void checkResponseStatusCode(Response response, int statusCode = 200) { + private void checkResponseStatusCode(Response response, int statusCode = HttpStatus.SC_OK) { def responseStatusCode = response.statusCode if (responseStatusCode != statusCode) { def responseBody = response.body.asString() diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/Dependencies.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/Dependencies.groovy index ab614e0ca5f..b5d6860d4d3 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/Dependencies.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/Dependencies.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.util.SystemProperties import org.testcontainers.containers.InfluxDBContainer import org.testcontainers.containers.MySQLContainer import org.testcontainers.containers.Network -import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.containers.PostgreSQLContainer +import org.testcontainers.containers.localstack.LocalStackContainer import org.testcontainers.lifecycle.Startables import org.testcontainers.utility.DockerImageName diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy index 02d627f141a..3bfcd94db52 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/PbsConfig.groovy @@ -1,6 +1,6 @@ package org.prebid.server.functional.testcontainers -import org.testcontainers.containers.InfluxDBContainer + import org.testcontainers.containers.MySQLContainer import org.testcontainers.containers.PostgreSQLContainer @@ -33,6 +33,7 @@ LIMIT 1 "logging.sampling-rate" : "1.0", "auction.ad-server-currency" : DEFAULT_CURRENCY.value, "auction.stored-requests-timeout-ms" : "1000", + "auction.ortb-error-response" : "true", "metrics.prefix" : "prebid", "status-response" : "ok", "gdpr.default-value" : "0", @@ -101,6 +102,7 @@ LIMIT 1 "settings.database.idle-connection-timeout": "300" ].asImmutable() } + static Map getPostgreSqlConfig(PostgreSQLContainer postgres = Dependencies.postgresqlContainer) { ["settings.database.type" : "postgres", "settings.database.host" : postgres.getNetworkAliases().get(0), diff --git a/src/test/groovy/org/prebid/server/functional/tests/AccountSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AccountSpec.groovy index 6bfb51536cc..d1a1e1bb88a 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AccountSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AccountSpec.groovy @@ -7,10 +7,12 @@ import org.prebid.server.functional.model.db.StoredRequest 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.auction.Site -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class AccountSpec extends BaseSpec { @@ -30,12 +32,14 @@ class AccountSpec extends BaseSpec { } when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Account $accountId is inactive" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Account $accountId is inactive"] + } where: enforceValidAccount << [true, false] @@ -56,12 +60,14 @@ class AccountSpec extends BaseSpec { } when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: $accountId" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: $accountId"] + } where: defaultAccountConfig << [null, AccountConfig.defaultAccountConfig] @@ -79,12 +85,14 @@ class AccountSpec extends BaseSpec { } when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: " + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: "] + } where: defaultAccountConfig << [null, AccountConfig.defaultAccountConfig] @@ -137,13 +145,14 @@ class AccountSpec extends BaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - pbsService.sendAmpRequest(ampRequest) + def response = pbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) def resolvedAccount = requestAccount ?: storedRequestAccount - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: $resolvedAccount" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: $resolvedAccount"] + } where: defaultAccountConfig || requestAccount || storedRequestAccount @@ -175,12 +184,13 @@ class AccountSpec extends BaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - pbsService.sendAmpRequest(ampRequest) + def response = pbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: " + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: "] + } where: defaultAccountConfig << [null, AccountConfig.defaultAccountConfig] diff --git a/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy index 9013978f76f..3de013ad68f 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AliasSpec.groovy @@ -1,14 +1,15 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.bidder.AppNexus import org.prebid.server.functional.model.bidder.Generic import org.prebid.server.functional.model.bidder.Openx import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST 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.BOGUS @@ -17,6 +18,7 @@ import static org.prebid.server.functional.model.bidder.BidderName.GENER_X import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.CompressionType.GZIP import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.networkServiceContainer import static org.prebid.server.functional.util.HttpUtil.CONTENT_ENCODING_HEADER @@ -105,12 +107,17 @@ class AliasSpec extends BaseSpec { bidRequest.ext.prebid.aliases = [(PBSUtils.randomString): GENERIC] when: "Sending auction request to PBS" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + - "vendorId ${validId} refers to unknown bidder alias: ${bidderName.toLowerCase()}") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { + it.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + + "vendorId ${validId} refers to unknown bidder alias: ${bidderName.toLowerCase()}") + } + } } def "PBS should return an error when GVL ID alias value is lower that one"() { @@ -121,13 +128,17 @@ class AliasSpec extends BaseSpec { bidRequest.ext.prebid.aliases = [(bidderName): GENERIC] when: "Sending auction request to PBS" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + - "Invalid vendorId ${invalidId} for alias: ${bidderName.toLowerCase()}. Choose a different vendorId, or remove this entry.") - + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { + it.contains("Invalid request format: request.ext.prebid.aliasgvlids. " + + "Invalid vendorId ${invalidId} for alias: ${bidderName.toLowerCase()}. Choose a different vendorId, or remove this entry.") + } + } where: invalidId << [PBSUtils.randomNegativeNumber, 0] } @@ -140,13 +151,15 @@ class AliasSpec extends BaseSpec { } when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: request.ext.prebid.aliases.${randomString.toLowerCase()} " + - "refers to unknown bidder: $BOGUS.value" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: request.ext.prebid.aliases.${randomString.toLowerCase()} " + + "refers to unknown bidder: $BOGUS.value"] + } } def "PBS aliased bidder config should be independently from parent"() { @@ -224,7 +237,7 @@ class AliasSpec extends BaseSpec { assert !bidResponse.ext.debug.httpcalls and: "Bid response should contain warning" - assert bidResponse.ext?.warnings[PREBID]?.code == [999, 999] + assert bidResponse.ext?.warnings[PREBID]?.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.${APPNEXUS.value} was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.${APPNEXUS.value} failed validation.\n" + diff --git a/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy index 1e2c67fad6f..bbd3dbf5ad6 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AlternateBidderCodeSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests +import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.bidder.Generic import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.config.AlternateBidderCodes @@ -16,11 +17,11 @@ import org.prebid.server.functional.model.request.auction.Targeting import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ErrorType -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils import spock.lang.Shared +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.ALIAS_CAMEL_CASE @@ -28,11 +29,13 @@ import static org.prebid.server.functional.model.bidder.BidderName.AMX import static org.prebid.server.functional.model.bidder.BidderName.AMX_CAMEL_CASE import static org.prebid.server.functional.model.bidder.BidderName.BOGUS import static org.prebid.server.functional.model.bidder.BidderName.EMPTY -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.bidder.BidderName.UNKNOWN import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD +import static org.prebid.server.functional.model.response.BidderErrorCode.GENERIC import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_GENERAL +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer class AlternateBidderCodeSpec extends BaseSpec { @@ -374,7 +377,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -385,7 +388,7 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain exp data" - assert response.seatbid.seat == [GENERIC] + assert response.seatbid.seat == [BidderName.GENERIC] and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource @@ -395,13 +398,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -417,8 +420,8 @@ class AlternateBidderCodeSpec extends BaseSpec { where: requestAlternateBidderCode | accountAlternateBidderCodes - new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null - null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) + new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) } def "PBS shouldn't discard bid amx alias requested when imp[].bidder is same as in bid.ext.bidderCode"() { @@ -626,13 +629,15 @@ class AlternateBidderCodeSpec extends BaseSpec { flushMetrics(pbsServiceWithAmxBidder) when: "PBS processes auction request" - pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) + def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == "Invalid request format: " + - "request.ext.prebid.alternatebiddercodes.bidders.unknown is not a known bidder or alias" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: " + + "request.ext.prebid.alternatebiddercodes.bidders.unknown is not a known bidder or alias"] + } where: @@ -651,12 +656,12 @@ class AlternateBidderCodeSpec extends BaseSpec { amxUpperCase = new Amx() amx = null } - ext.prebid.alternateBidderCodes.bidders[AMX].allowedBidderCodesLowerCase = [GENERIC] + ext.prebid.alternateBidderCodes.bidders[AMX].allowedBidderCodesLowerCase = [BidderName.GENERIC] } and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -670,17 +675,17 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid[0].seat == GENERIC + assert response.seatbid[0].seat == BidderName.GENERIC and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -695,7 +700,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Metric shouldn't be updated" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] } def "PBS shouldn't discard bid when alternate bidder code allows bidder codes fully configured with different case"() { @@ -710,7 +715,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -724,17 +729,17 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid[0].seat == GENERIC + assert response.seatbid[0].seat == BidderName.GENERIC and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -753,9 +758,9 @@ class AlternateBidderCodeSpec extends BaseSpec { where: configAccountAlternateBidderCodes << [ - new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [GENERIC])])), - new AccountConfig(alternateBidderCodes: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [GENERIC])])), - new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]))] + new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [BidderName.GENERIC])])), + new AccountConfig(alternateBidderCodes: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodesSnakeCase: [BidderName.GENERIC])])), + new AccountConfig(alternateBidderCodesSnakeCase: new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]))] } def "PBS should take precede of request and discard the bid and emit a response error when alternate bidder codes enabled and bidder came with different bidder code"() { @@ -887,7 +892,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -901,20 +906,20 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid.seat.flatten() == [GENERIC] + assert response.seatbid.seat.flatten() == [BidderName.GENERIC] and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource @@ -940,7 +945,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -954,17 +959,17 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid.seat.flatten() == [GENERIC] + assert response.seatbid.seat.flatten() == [BidderName.GENERIC] and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -993,7 +998,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1007,20 +1012,20 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid.seat.flatten() == [GENERIC] + assert response.seatbid.seat.flatten() == [BidderName.GENERIC] and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1035,10 +1040,10 @@ class AlternateBidderCodeSpec extends BaseSpec { assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] where: - requestAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])], + requestAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])], [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], - [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]] + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]] } def "PBS shouldn't discard the bid or emit a response warning when account alternate bidder codes are enabled and the allowed bidder codes is same as bidder's request"() { @@ -1053,7 +1058,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1067,7 +1072,7 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain seatbid.seat" - assert response.seatbid.seat.flatten() == [GENERIC] + assert response.seatbid.seat.flatten() == [BidderName.GENERIC] and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1077,13 +1082,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Response shouldn't contain warnings and errors and seatNonBid" assert !response.ext?.warnings @@ -1095,10 +1100,10 @@ class AlternateBidderCodeSpec extends BaseSpec { assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] where: - accountAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])], + accountAlternateBidders << [[(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])], [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC_CAMEL_CASE])], - [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]] + [(AMX_CAMEL_CASE): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]] } def "PBS shouldn't discard the bid or emit a response warning when default account alternate bidder codes are enabled and the allowed bidder codes match the bidder's request"() { @@ -1349,12 +1354,12 @@ class AlternateBidderCodeSpec extends BaseSpec { amx = null alias = new Generic() } - ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])] } and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1365,17 +1370,17 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [ALIAS] and: "Response should contain seat bid" - assert response.seatbid.seat == [GENERIC] + assert response.seatbid.seat == [BidderName.GENERIC] and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1385,7 +1390,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -1408,7 +1413,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1419,7 +1424,7 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain exp data" - assert response.seatbid.seat == [GENERIC] + assert response.seatbid.seat == [BidderName.GENERIC] and: "Response should contain adapter code" assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] @@ -1429,13 +1434,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1448,13 +1453,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] where: requestAlternateBidderCode | accountAlternateBidderCodes - new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null - null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) + new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) } def "PBS shouldn't discard bid when alternate bidder code allow and soft alias with case with base bidder in alternate bidder code"() { @@ -1474,7 +1479,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1485,7 +1490,7 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain exp data" - assert response.seatbid.seat == [GENERIC] + assert response.seatbid.seat == [BidderName.GENERIC] and: "Response should contain adapter code" assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] @@ -1495,13 +1500,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) @@ -1514,13 +1519,13 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(ALIAS)] - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] where: requestAlternateBidderCode | accountAlternateBidderCodes - new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) | null - null | new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])]) + new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) | null + null | new AlternateBidderCodes(enabled: true, bidders: [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])]) } def "PBS should populate adapter code with requested bidder when conflict soft and hard alias and alternate bidder code"() { @@ -1534,13 +1539,13 @@ class AlternateBidderCodeSpec extends BaseSpec { imp[0].ext.prebid.bidder.alias = new Generic() imp[0].ext.prebid.bidder.amx = null imp[0].ext.prebid.bidder.generic = null - it.ext.prebid.aliases = [(ALIAS.value): GENERIC] - it.ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodesLowerCase: [GENERIC])] + it.ext.prebid.aliases = [(ALIAS.value): BidderName.GENERIC] + it.ext.prebid.alternateBidderCodes.bidders = [(ALIAS): new BidderConfig(enabled: true, allowedBidderCodesLowerCase: [BidderName.GENERIC])] } and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, ALIAS).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1551,27 +1556,27 @@ class AlternateBidderCodeSpec extends BaseSpec { assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [ALIAS] and: "Response should contain seat bid" - assert response.seatbid.seat == [GENERIC] + assert response.seatbid.seat == [BidderName.GENERIC] and: "Response shouldn't contain demand source" assert !response.seatbid.first.bid.first.ext.prebid.meta.demandSource and: "Response should contain bidder targeting" def targeting = response.seatbid[0].bid[0].ext.prebid.targeting - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder"] == GENERIC.value - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder"] == BidderName.GENERIC.value + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be valid" assert bidder.getBidderRequests(bidRequest.id) and: "PBS shouldn't emit validation metrics" def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -1581,12 +1586,12 @@ class AlternateBidderCodeSpec extends BaseSpec { given: "Default bid request with amx and generic bidder" def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { imp[0].ext.prebid.bidder.generic = new Generic() - ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])] } and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1597,19 +1602,19 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain seat" - assert response.seatbid.seat.sort() == [GENERIC, GENERIC].sort() + assert response.seatbid.seat.sort() == [BidderName.GENERIC, GENERIC].sort() and: "Response should contain adapter code" - assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten().sort() == [AMX, GENERIC].sort() + assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten().sort() == [AMX, BidderName.GENERIC].sort() and: "Response should contain bidder generic targeting" def targeting = response.seatbid.bid.ext.prebid.targeting.flatten().collectEntries() - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Response shouldn't contain repose millis with amx bidder" assert !response.ext.responsetimemillis.containsKey(AMX.value) @@ -1628,7 +1633,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] } def "PBS should return two seat when same bidder response with different bidder code"() { @@ -1637,12 +1642,12 @@ class AlternateBidderCodeSpec extends BaseSpec { imp.add(Imp.getDefaultImpression()) imp[1].ext.prebid.bidder.amx = new Amx() imp[1].ext.prebid.bidder.generic = null - ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC, AMX])] + ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC, AMX])] } and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) it.seatbid[0].bid[1].ext = new BidExt(bidderCode: AMX) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1654,7 +1659,7 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain seat" - assert response.seatbid.seat.sort() == [GENERIC, AMX].sort() + assert response.seatbid.seat.sort() == [BidderName.GENERIC, AMX].sort() and: "Response should contain adapter code" assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX, AMX] @@ -1666,12 +1671,12 @@ class AlternateBidderCodeSpec extends BaseSpec { assert targeting["hb_bidder_${AMX}"] == AMX.value and: 'Response targeting should contain generic' - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) assert response.ext.responsetimemillis.containsKey(AMX.value) and: "Bidder request should be valid" @@ -1688,7 +1693,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] } def "PBS should populate seat bid from stored bid response when stored bid response and alternate bidder code specified"() { @@ -1696,7 +1701,7 @@ class AlternateBidderCodeSpec extends BaseSpec { def storedResponseId = PBSUtils.randomNumber def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { imp[0].ext.prebid.storedBidResponse = [new StoredBidResponse(id: storedResponseId, bidder: AMX)] - ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])] } and: "Stored bid response in DB" @@ -1706,7 +1711,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1751,7 +1756,7 @@ class AlternateBidderCodeSpec extends BaseSpec { given: "Default bid request" def bidRequest = getBidRequestWithAmxBidderAndAlternateBidderCode().tap { imp[0].ext.prebid.storedRequest = new PrebidStoredRequest(id: PBSUtils.randomString) - ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [GENERIC])] + ext.prebid.alternateBidderCodes.bidders = [(AMX): new BidderConfig(enabled: true, allowedBidderCodes: [BidderName.GENERIC])] } and: "Save storedImp into DB" @@ -1760,7 +1765,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "Bid response with bidder code" def bidResponse = BidResponse.getDefaultBidResponse(bidRequest, AMX).tap { - it.seatbid[0].bid[0].ext = new BidExt(bidderCode: GENERIC) + it.seatbid[0].bid[0].ext = new BidExt(bidderCode: BidderName.GENERIC) } bidder.setResponse(bidRequest.id, bidResponse) @@ -1768,19 +1773,19 @@ class AlternateBidderCodeSpec extends BaseSpec { def response = pbsServiceWithAmxBidder.sendAuctionRequest(bidRequest) then: "Bid response should contain seat" - assert response.seatbid.seat.sort() == [GENERIC].sort() + assert response.seatbid.seat.sort() == [BidderName.GENERIC].sort() and: "Response should contain adapter code" assert response.seatbid.bid.ext.prebid.meta.adapterCode.flatten() == [AMX] and: "Response should contain bidder generic targeting" def targeting = response.seatbid.bid.ext.prebid.targeting.flatten().collectEntries() - assert targeting["hb_pb_${GENERIC}"] - assert targeting["hb_size_${GENERIC}"] - assert targeting["hb_bidder_${GENERIC}"] == GENERIC.value + assert targeting["hb_pb_${BidderName.GENERIC}"] + assert targeting["hb_size_${BidderName.GENERIC}"] + assert targeting["hb_bidder_${BidderName.GENERIC}"] == BidderName.GENERIC.value and: "Response should contain repose millis with corresponding bidder" - assert response.ext.responsetimemillis.containsKey(GENERIC.value) + assert response.ext.responsetimemillis.containsKey(BidderName.GENERIC.value) and: "Bidder request should be called" assert bidder.getBidderRequests(bidRequest.id) @@ -1795,7 +1800,7 @@ class AlternateBidderCodeSpec extends BaseSpec { and: "PBS shouldn't emit validation metrics" def metrics = pbsServiceWithAmxBidder.sendCollectedMetricsRequest() - assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(GENERIC)] + assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(BidderName.GENERIC)] assert !metrics[ADAPTER_RESPONSE_VALIDATION_METRICS.formatted(AMX)] } diff --git a/src/test/groovy/org/prebid/server/functional/tests/AmpFpdSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AmpFpdSpec.groovy index e376f611e84..8c6d1c4b326 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AmpFpdSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AmpFpdSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.bidder.Generic import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.request.amp.AmpRequest @@ -16,15 +17,16 @@ import org.prebid.server.functional.model.request.auction.ImpExtContextDataAdSer import org.prebid.server.functional.model.request.auction.Publisher import org.prebid.server.functional.model.request.auction.Site import org.prebid.server.functional.model.request.auction.User -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.BOGUS 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.request.auction.DistributionChannel.SITE +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID class AmpFpdSpec extends BaseSpec { @@ -125,13 +127,14 @@ class AmpFpdSpec extends BaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - defaultPbsService.sendAmpRequest(ampRequest) + def response = defaultPbsService.sendAmpRequest(ampRequest, SC_BAD_REQUEST) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody.startsWith("Invalid request format: " + - "Error reading targeting json Unrecognized token '$invalidTargeting': was expecting") + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.startsWith("Invalid request format: " + + "Error reading targeting json Unrecognized token '$invalidTargeting': was expecting") } + } } def "PBS shouldn't populate FPD field via targeting when targeting field is absent"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy index 47e08555828..5166db1bbc8 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AmpSpec.groovy @@ -10,11 +10,12 @@ import org.prebid.server.functional.model.request.auction.Site import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.request.auction.User import org.prebid.server.functional.model.request.auction.UserExt +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.SeatBid -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.util.SystemProperties.PBS_VERSION class AmpSpec extends BaseSpec { @@ -51,13 +52,13 @@ class AmpSpec extends BaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - defaultPbsService.sendAmpRequest(ampRequest) + def response = defaultPbsService.sendAmpRequest(ampRequest, SC_BAD_REQUEST) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: request.${channel.value.toLowerCase()} must not exist in AMP stored requests." - + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: request.${channel.value.toLowerCase()} must not exist in AMP stored requests."] + } where: channel << [DistributionChannel.APP, DistributionChannel.DOOH] } 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 1506e2e0a4d..af863823128 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/AuctionSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.UidsCookie import org.prebid.server.functional.model.bidder.Generic import org.prebid.server.functional.model.config.AccountAuctionConfig @@ -17,24 +18,27 @@ import org.prebid.server.functional.model.request.auction.Sdk 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.UserExtPrebid +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.Meta import org.prebid.server.functional.model.response.auction.Prebid import org.prebid.server.functional.model.response.cookiesync.UserSyncInfo -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.HttpUtil import org.prebid.server.functional.util.PBSUtils import spock.lang.Shared +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.AccountStatus.INACTIVE 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.response.BidderErrorCode.BAD_INPUT import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.model.response.cookiesync.UserSyncInfo.Type.REDIRECT import static org.prebid.server.functional.testcontainers.Dependencies.networkServiceContainer import static org.prebid.server.functional.util.HttpUtil.COOKIE_DEPRECATION_HEADER @@ -83,12 +87,14 @@ class AuctionSpec extends BaseSpec { accountDao.save(account) when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 401 - assert exception.responseBody == "Account ${accountId} is inactive" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Account ${accountId} is inactive"] + } and: "account..requests.rejected.invalid-account metric should be updated" def metrics = defaultPbsService.sendCollectedMetricsRequest() @@ -108,13 +114,14 @@ class AuctionSpec extends BaseSpec { def initialMetricCount = getCurrentMetricValue(defaultPbsService, fullMetricName) when: "Requesting PBS auction" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Request fails with an stored request id is not found error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == - "Invalid request format: Stored request processing failed: Id is not found in storedRequest" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Account ${accountId} is inactive"] + } and: "Metric count is updated" assert getCurrentMetricValue(defaultPbsService, fullMetricName) == initialMetricCount + 1 @@ -591,7 +598,7 @@ class AuctionSpec extends BaseSpec { then: "PBS should include warning in responce" def auctionWarnings = response.ext?.warnings?.get(PREBID) assert auctionWarnings.size() == 1 - assert auctionWarnings[0].code == 999 + assert auctionWarnings[0].code == BidderErrorCode.GENERIC assert auctionWarnings[0].message == 'Sec-Cookie-Deprecation header has invalid value' and: "BidderRequest shouldn't have device.ext.cdep" @@ -747,7 +754,7 @@ class AuctionSpec extends BaseSpec { assert !response?.ext?.seatnonbid and: "PBS should emit an warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["Only first $IMP_LIMIT impressions were kept due to the limit, " + "all the subsequent impressions have been dropped for the auction" as String] diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy index 7da1c89fffb..430d24b95a2 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidAdjustmentSpec.groovy @@ -17,16 +17,16 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.VideoPlacementSubtypes import org.prebid.server.functional.model.request.auction.VideoPlcmtSubtype +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.testcontainers.PbsConfig import org.prebid.server.functional.testcontainers.scaffolding.CurrencyConversion import org.prebid.server.functional.util.CurrencyUtil import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.Currency.EUR import static org.prebid.server.functional.model.Currency.GBP import static org.prebid.server.functional.model.Currency.USD @@ -51,6 +51,7 @@ import static org.prebid.server.functional.model.request.auction.DistributionCha import static org.prebid.server.functional.model.request.auction.VideoPlacementSubtypes.IN_STREAM as IN_PLACEMENT_STREAM import static org.prebid.server.functional.model.request.auction.VideoPlcmtSubtype.IN_STREAM as IN_PLCMT_STREAM import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer import static org.prebid.server.functional.util.PBSUtils.getRandomDecimal @@ -187,13 +188,14 @@ class BidAdjustmentSpec extends BaseSpec { bidder.setResponse(bidRequest.id, bidResponse) when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should fail the request" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody.contains("Invalid request format: request.ext.prebid.bidadjustmentfactors.$bidderName.value must be a positive number") - + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.contains("Invalid request format: request.ext.prebid.bidadjustmentfactors.$bidderName.value must be a positive number") } + } where: bidAdjustmentFactor << [MIN_ADJUST_VALUE, PBSUtils.randomNegativeNumber] } @@ -886,7 +888,7 @@ class BidAdjustmentSpec extends BaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=${adjustmentType}, " + "value=${ruleValue}, currency=${currency}] in ${mediaType.value}.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" @@ -1065,7 +1067,7 @@ class BidAdjustmentSpec extends BaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=${adjustmentType}, " + "value=${adjustmentPrice}, currency=null] in banner.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" @@ -1165,7 +1167,7 @@ class BidAdjustmentSpec extends BaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=UNKNOWN, " + "value=$adjustmentPrice, currency=$currency] in banner.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidExpResponseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidExpResponseSpec.groovy index 6ca55f4b7bc..09e601ab113 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidExpResponseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidExpResponseSpec.groovy @@ -10,10 +10,10 @@ import org.prebid.server.functional.model.request.auction.PrebidCacheSettings 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.MediaType.AUDIO import static org.prebid.server.functional.model.response.auction.MediaType.BANNER -import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO import static org.prebid.server.functional.model.response.auction.MediaType.NATIVE -import static org.prebid.server.functional.model.response.auction.MediaType.AUDIO +import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO class BidExpResponseSpec extends BaseSpec { diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidValidationSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidValidationSpec.groovy index 9dd17c31e0a..d846e9efeaa 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidValidationSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidValidationSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests +import org.apache.http.HttpStatus import org.prebid.server.functional.model.request.auction.App import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.DistributionChannel @@ -8,19 +9,22 @@ import org.prebid.server.functional.model.request.auction.Eid import org.prebid.server.functional.model.request.auction.MultiBid import org.prebid.server.functional.model.request.auction.Site import org.prebid.server.functional.model.request.auction.User +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ErrorType -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature import java.time.Instant +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED import static org.prebid.server.functional.model.request.auction.DebugCondition.ENABLED import static org.prebid.server.functional.model.request.auction.DistributionChannel.DOOH +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.util.HttpUtil.REFERER_HEADER class BidValidationSpec extends BaseSpec { @@ -54,12 +58,14 @@ class BidValidationSpec extends BaseSpec { flushMetrics(strictPrebidService) when: "PBS processes auction request" - strictPrebidService.sendAuctionRequest(bidRequest) + def response = strictPrebidService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS throws an exception" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody.contains("no more than one of request.site or request.app or request.dooh can be defined") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.contains("no more than one of request.site or request.app or request.dooh can be defined") } + } and: "Bid validation metric value is incremented" def metrics = strictPrebidService.sendCollectedMetricsRequest() @@ -99,8 +105,8 @@ class BidValidationSpec extends BaseSpec { then: "Response should contain warning" def warningChannelsValues = requestDistributionChannels.collect { "${it.value.toLowerCase()}" }.join(" and ") - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == ["BidRequest contains $warningChannelsValues. Only the first one is applicable, the others are ignored" as String] and: "Bid validation metric value is incremented" @@ -138,12 +144,15 @@ class BidValidationSpec extends BaseSpec { bidDoohRequest.ext.prebid.debug = ENABLED when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidDoohRequest) + def response = defaultPbsService.sendAuctionRequest(bidDoohRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.contains("request.dooh should include at least one of request.dooh.id " + - "or request.dooh.venuetype.") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.contains("request.dooh should include at least one of request.dooh.id " + + "or request.dooh.venuetype.") } + } } def "PBS should validate site when it is present"() { @@ -153,11 +162,14 @@ class BidValidationSpec extends BaseSpec { bidRequest.ext.prebid.debug = ENABLED when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, HttpStatus.SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.contains("request.site should include at least one of request.site.id or request.site.page") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.contains("request.site should include at least one of request.site.id or request.site.page") } + } } def "PBS should treat bids with 0 price as valid when deal id is present"() { @@ -212,8 +224,8 @@ class BidValidationSpec extends BaseSpec { assert !response.ext.seatnonbid and: "PBS should emit an error" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == ["Dropped bid '$bidId'. Does not contain a positive (or zero if there is a deal) 'price'" as String] where: @@ -298,8 +310,8 @@ class BidValidationSpec extends BaseSpec { assert response.seatbid?.first()?.bid*.id == [validBidId] and: "PBS should emit an error" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == ["Dropped bid '$invalidBid.id'. Does not contain a positive (or zero if there is a deal) 'price'" as String] where: diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy index b47a2e47ddf..3ae2b61ccc8 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderFormatSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.bidder.BidderName import org.prebid.server.functional.model.config.AccountAuctionConfig import org.prebid.server.functional.model.config.AccountBidValidationConfig @@ -15,13 +16,14 @@ import org.prebid.server.functional.model.request.auction.Format import org.prebid.server.functional.model.request.auction.Native import org.prebid.server.functional.model.request.auction.StoredBidResponse import org.prebid.server.functional.model.request.auction.Video +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Adm import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature import spock.lang.Shared +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.config.BidValidationEnforcement.ENFORCE import static org.prebid.server.functional.model.config.BidValidationEnforcement.SKIP @@ -29,6 +31,8 @@ import static org.prebid.server.functional.model.config.BidValidationEnforcement import static org.prebid.server.functional.model.request.auction.SecurityLevel.NON_SECURE import static org.prebid.server.functional.model.request.auction.SecurityLevel.SECURE import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class BidderFormatSpec extends BaseSpec { @@ -50,7 +54,7 @@ class BidderFormatSpec extends BaseSpec { assert bidderRequest?.imp[0]?.banner?.format[0].height == bannerFormatHeight where: - bannerFormatWidth | bannerFormatHeight + bannerFormatWidth | bannerFormatHeight 1 | 1 PBSUtils.randomNumber | PBSUtils.randomNumber } @@ -62,16 +66,18 @@ class BidderFormatSpec extends BaseSpec { } when: "Requesting PBS auction" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to banner.format{w.h} validation" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == "Invalid request format: " + - "request.imp[0].banner.format[0] must define a valid \"h\" and \"w\" properties" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: " + + "request.imp[0].banner.format[0] must define a valid \"h\" and \"w\" properties"] + } where: - bannerFormatWidth | bannerFormatHeight + bannerFormatWidth | bannerFormatHeight 0 | PBSUtils.randomNumber PBSUtils.randomNumber | 0 null | PBSUtils.randomNumber @@ -87,17 +93,19 @@ class BidderFormatSpec extends BaseSpec { } when: "Requesting PBS auction" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to banner.format{w.h} validation" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == "Invalid request format: request.imp[0].banner.format[0] " + - "should define *either* {w, h} (for static size requirements) " + - "*or* {wmin, wratio, hratio} (for flexible sizes) to be non-zero positive" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: request.imp[0].banner.format[0] " + + "should define *either* {w, h} (for static size requirements) " + + "*or* {wmin, wratio, hratio} (for flexible sizes) to be non-zero positive"] + } where: - bannerFormatWidth | bannerFormatHeight + bannerFormatWidth | bannerFormatHeight 0 | 0 0 | null 0 | PBSUtils.randomNegativeNumber @@ -121,7 +129,7 @@ class BidderFormatSpec extends BaseSpec { assert bidderRequest?.imp[0]?.banner?.height == bannerFormatHeight where: - bannerFormatWidth | bannerFormatHeight + bannerFormatWidth | bannerFormatHeight 1 | 1 PBSUtils.randomNumber | PBSUtils.randomNumber } @@ -133,16 +141,18 @@ class BidderFormatSpec extends BaseSpec { } when: "Requesting PBS auction" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) - then: "PBs should throw error due to banner{w.h} validation" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == "Invalid request format: " + - "request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements" + then: "PBs should throw error due to banner.format{w.h} validation" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: " + + "request.imp[0].banner has no sizes. Define \"w\" and \"h\", or include \"format\" elements"] + } where: - bannerFormatWidth | bannerFormatHeight + bannerFormatWidth | bannerFormatHeight 0 | 0 0 | PBSUtils.randomNumber PBSUtils.randomNumber | 0 @@ -212,7 +222,7 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight + accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -270,7 +280,7 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - accountCretiveMaxSizeSnakeCase | accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight + accountCretiveMaxSizeSnakeCase | accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight null | null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | null | SKIP.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | null | SKIP.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -341,7 +351,7 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight + accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -451,7 +461,7 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight + accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 null | ENFORCE.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER null | ENFORCE.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 @@ -528,7 +538,7 @@ class BidderFormatSpec extends BaseSpec { assert !bidder.getBidderRequests(bidRequest.id) where: - accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight + accountCretiveMaxSize | configCreativeMaxSize | responseWidth | responseHeight ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER + 1 ENFORCE | WARN.value | RANDOM_NUMBER + 1 | RANDOM_NUMBER ENFORCE | WARN.value | RANDOM_NUMBER | RANDOM_NUMBER + 1 diff --git a/src/test/groovy/org/prebid/server/functional/tests/BidderInsensitiveCaseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/BidderInsensitiveCaseSpec.groovy index f2fb2803f1f..def9c16e9f1 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderInsensitiveCaseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderInsensitiveCaseSpec.groovy @@ -19,6 +19,7 @@ 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.UserExtPrebid import org.prebid.server.functional.model.request.cookiesync.CookieSyncRequest +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ErrorType @@ -321,7 +322,7 @@ class BidderInsensitiveCaseSpec extends BaseSpec { assert response.seatbid.isEmpty() and: "Response should contain error" - assert response.ext?.warnings[ErrorType.GENERIC_CAMEL_CASE]*.code == [2] + assert response.ext?.warnings[ErrorType.GENERIC_CAMEL_CASE]*.code == [BidderErrorCode.BAD_INPUT] assert response.ext?.warnings[ErrorType.GENERIC_CAMEL_CASE]*.message == ["Bidder does not support any media types."] } 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 220585f008f..c01cdbf4a71 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -9,11 +9,11 @@ import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.request.amp.AmpRequest import org.prebid.server.functional.model.request.auction.Adrino import org.prebid.server.functional.model.request.auction.Amx +import org.prebid.server.functional.model.request.auction.AnyUnsupportedBidder import org.prebid.server.functional.model.request.auction.AuctionEnvironment 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.Device -import org.prebid.server.functional.model.request.auction.AnyUnsupportedBidder import org.prebid.server.functional.model.request.auction.Geo import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.ImpExt @@ -28,6 +28,7 @@ import org.prebid.server.functional.model.request.auction.Source import org.prebid.server.functional.model.request.auction.Targeting import org.prebid.server.functional.model.request.vtrack.VtrackRequest import org.prebid.server.functional.model.request.vtrack.xml.Vast +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Adm import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidExt @@ -335,7 +336,7 @@ class BidderParamsSpec extends BaseSpec { def response = pbsService.sendAuctionRequest(bidRequest) then: "Response should contain error" - assert response.ext?.errors[GENERIC]*.code == [999] + assert response.ext?.errors[GENERIC]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[GENERIC]*.message == ["host name must not be empty"] cleanup: "Stop and remove pbs container" @@ -359,7 +360,7 @@ class BidderParamsSpec extends BaseSpec { assert bidder.getRequestCount(bidRequest.id) == 1 and: "Bidder with invalid params should be dropped" - assert response.ext?.warnings[PREBID]*.code == [999, 999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.generic was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.generic failed validation.\n" + @@ -387,7 +388,7 @@ class BidderParamsSpec extends BaseSpec { def response = defaultPbsService.sendAuctionRequest(bidRequest) then: "Bidder should be dropped" - assert response.ext?.warnings[PREBID]*.code == [999, 999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.generic was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.generic failed validation.\n" + @@ -417,7 +418,7 @@ class BidderParamsSpec extends BaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Bidder should be dropped" - assert response.ext?.warnings[PREBID]*.code == [999, 999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.generic was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.generic failed validation.\n" + @@ -444,7 +445,7 @@ class BidderParamsSpec extends BaseSpec { assert response.seatbid.isEmpty() and: "Response should contain error" - assert response.ext?.warnings[GENERIC]*.code == [2] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.BAD_INPUT] assert response.ext?.warnings[GENERIC]*.message == ["Bidder does not support any media types."] cleanup: "Stop and remove pbs container" @@ -573,7 +574,7 @@ class BidderParamsSpec extends BaseSpec { assert bidderRequest.imp[0].nativeObj and: "Response should contain error" - assert response.ext?.warnings[GENERIC]*.code == [2] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.BAD_INPUT] assert response.ext?.warnings[GENERIC]*.message == ["Imp ${bidRequest.imp[0].id} does not have a supported media type and has been removed from the " + "request for this bidder." as String] @@ -670,7 +671,7 @@ class BidderParamsSpec extends BaseSpec { assert bidder.getRequestCount(bidRequest.id) == 0 and: "Response should contain errors" - assert response.ext?.warnings[GENERIC]*.code == [2, 2] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.BAD_INPUT, BidderErrorCode.BAD_INPUT] assert response.ext?.warnings[GENERIC]*.message == ["Imp ${bidRequest.imp[0].id} does not have a supported media type and has been removed from " + "the request for this bidder.", @@ -849,7 +850,7 @@ class BidderParamsSpec extends BaseSpec { assert bidderRequest.imp[0].ext.anyUnsupportedBidder == unsupportedBidder and: "PBS should emit an warning" - assert response?.ext?.warnings[PREBID]*.code == [999] + assert response?.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response?.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.anyUnsupportedBidder was dropped with a reason: " + "request.imp[0].ext.prebid.bidder contains unknown bidder: anyUnsupportedBidder"] @@ -870,7 +871,7 @@ class BidderParamsSpec extends BaseSpec { assert !response.ext?.errors and: "PBS should emit an warning" - assert response?.ext?.warnings[PREBID]*.code == [999] + assert response?.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response?.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.adUnitCode was dropped with a reason: " + "request.imp[0].ext.prebid.bidder contains unknown bidder: adUnitCode"] @@ -1140,7 +1141,7 @@ class BidderParamsSpec extends BaseSpec { assert response.ext.seatnonbid.size() == 1 and: "PBS should emit an warnings" - assert response.ext?.warnings[GENERIC]*.code == [999] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[GENERIC]*.message == ["No match between the configured currencies and bidRequest.cur"] @@ -1234,7 +1235,7 @@ class BidderParamsSpec extends BaseSpec { assert !response.ext?.errors and: "PBS should emit an warnings" - assert response.ext?.warnings[ALIAS]*.code == [999] + assert response.ext?.warnings[ALIAS]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ALIAS]*.message == ["No match between the configured currencies and bidRequest.cur"] @@ -1326,7 +1327,7 @@ class BidderParamsSpec extends BaseSpec { def response = defaultPbsService.sendAuctionRequest(bidRequest) then: "Bidder should be dropped" - assert response.ext?.warnings[PREBID]*.code == [999, 999, 999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.generic was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.generic failed validation.\n" + @@ -1357,7 +1358,7 @@ class BidderParamsSpec extends BaseSpec { def response = defaultPbsService.sendAuctionRequest(bidRequest) then: "Bidder should be dropped" - assert response.ext?.warnings[PREBID]*.code == [999, 999, 999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["WARNING: request.imp[0].ext.prebid.bidder.generic was dropped with a reason: " + "request.imp[0].ext.prebid.bidder.generic failed validation.\n" + diff --git a/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy index ce17a673424..d873a6e6af0 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy @@ -8,13 +8,14 @@ import org.prebid.server.functional.model.request.auction.Asset import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.Targeting +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Adm 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.CACHE import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.bidder.BidderName.GENERIC +import static org.prebid.server.functional.model.response.auction.ErrorType.CACHE import static org.prebid.server.functional.model.response.auction.MediaType.BANNER import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer @@ -499,7 +500,7 @@ class CacheSpec extends BaseSpec { def bidResponse = pbsService.sendAuctionRequest(bidRequest) then: "Response should contain error" - assert bidResponse.ext?.errors[CACHE]*.code == [999] + assert bidResponse.ext?.errors[CACHE]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.errors[CACHE]*.message[0] == ("Failed to resolve '${CACHE_HOST.tokenize(":")[0]}' [A(1)]") and: "Bid response targeting should contain value" @@ -542,7 +543,7 @@ class CacheSpec extends BaseSpec { assert cacheCall.uri == "${HTTP_SCHEME}://${networkServiceContainer.hostAndPort + INTERNAL_CACHE_PATH}" then: "Response should contain error" - assert bidResponse.ext?.errors[CACHE]*.code == [999] + assert bidResponse.ext?.errors[CACHE]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.errors[CACHE]*.message[0] == ("Failed to resolve '${CACHE_HOST.tokenize(":")[0]}' [A(1)]") cleanup: "Stop and remove pbs container" diff --git a/src/test/groovy/org/prebid/server/functional/tests/DebugSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/DebugSpec.groovy index ea169ad00ee..cb4159c74c5 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/DebugSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/DebugSpec.groovy @@ -11,12 +11,12 @@ 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.auction.Site import org.prebid.server.functional.model.request.auction.StoredBidResponse +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.model.response.auction.ErrorType -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.config.AccountMetricsVerbosityLevel.BASIC import static org.prebid.server.functional.model.config.AccountMetricsVerbosityLevel.DETAILED @@ -24,6 +24,8 @@ import static org.prebid.server.functional.model.config.AccountMetricsVerbosityL import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED import static org.prebid.server.functional.model.request.auction.DebugCondition.ENABLED import static org.prebid.server.functional.model.response.auction.BidderCallType.STORED_BID_RESPONSE +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class DebugSpec extends BaseSpec { @@ -106,8 +108,8 @@ class DebugSpec extends BaseSpec { assert !response.ext?.debug?.httpcalls and: "Response should contain specific code and text in ext.warnings.general" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] // [10003] - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == + assert response.ext?.warnings[PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] // [10003] + assert response.ext?.warnings[PREBID]?.collect { it.message } == ["Debug turned off for bidder: $GENERIC.value" as String] } @@ -149,9 +151,9 @@ class DebugSpec extends BaseSpec { and: "Response should contain specific code and text in ext.warnings.general" //TODO change to 10002 after updating debug warnings - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] //TODO possibly change message after clarifications - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == + assert response.ext?.warnings[PREBID]?.collect { it.message } == ["Debug turned off for account"] where: @@ -179,8 +181,8 @@ class DebugSpec extends BaseSpec { and: "Response should contain specific code and text in ext.warnings.general" //TODO change to 10003 after updating debug warnings - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == + assert response.ext?.warnings[PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]?.collect { it.message } == ["Debug turned off for bidder: $GENERIC.value" as String] where: @@ -209,8 +211,8 @@ class DebugSpec extends BaseSpec { and: "Response should contain specific code and text in ext.warnings.general" //TODO change to 10002 after updating debug warnings - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["Debug turned off for account"] + assert response.ext?.warnings[PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]?.collect { it.message } == ["Debug turned off for account"] } def "PBS should use default values = true for bidder-level setting debug.allow and account-level setting debug-allowed when they are not specified"() { @@ -281,8 +283,8 @@ class DebugSpec extends BaseSpec { and: "Response should contain specific code and text in ext.warnings.general" //TODO change to 10002 after updating debug warnings - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["Debug turned off for account"] + assert response.ext?.warnings[PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]?.collect { it.message } == ["Debug turned off for account"] where: headerValue << [StringUtils.swapCase(overrideToken), PBSUtils.randomString] @@ -521,11 +523,14 @@ class DebugSpec extends BaseSpec { flushMetrics(defaultPbsService) when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.contains("request.site should include at least one of request.site.id or request.site.page") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.contains("request.site should include at least one of request.site.id or request.site.page") } + } and: "Debug metrics shouldn't be populated" def metricsRequest = defaultPbsService.sendCollectedMetricsRequest() diff --git a/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy index 6bc172f3fa4..57163879f0d 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/EidsSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.bidder.Generic import org.prebid.server.functional.model.bidder.Openx import org.prebid.server.functional.model.request.auction.BidRequest @@ -10,10 +11,10 @@ import org.prebid.server.functional.model.request.auction.Uid import org.prebid.server.functional.model.request.auction.UidExt import org.prebid.server.functional.model.request.auction.User import org.prebid.server.functional.model.request.auction.UserExt -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST 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.GENERIC_CAMEL_CASE @@ -24,6 +25,7 @@ import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED import static org.prebid.server.functional.model.request.auction.DebugCondition.ENABLED import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer class EidsSpec extends BaseSpec { @@ -141,7 +143,7 @@ class EidsSpec extends BaseSpec { assert !bidderRequest.user.eids and: "Bid response should contain warning" - assert bidResponse.ext.warnings[PREBID]?.code == [999] + assert bidResponse.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert bidResponse.ext.warnings[PREBID]?.message == ["request.ext.prebid.data.eidPermissions[].bidders[] unrecognized biddercode: '$UNKNOWN'"] @@ -231,12 +233,15 @@ class EidsSpec extends BaseSpec { } when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should throw error" - def exception = thrown(PrebidServerException) - assert exception.responseBody == "Invalid request format: request.ext.prebid.data.eidpermissions[].bidders[] " + - "required values but was empty or null" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: request.ext.prebid.data.eidpermissions[].bidders[] " + + "required values but was empty or null"] + } where: eidsBidder << [[WILDCARD], [], null] @@ -288,7 +293,7 @@ class EidsSpec extends BaseSpec { assert bidderRequest.user.eids.uids.id.flatten() == [validUidId] and: "Bid response should contain warning" - assert bidResponse.ext.warnings[PREBID]?.code == [999] + assert bidResponse.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert bidResponse.ext.warnings[PREBID]?.message == ["removed EID ${sourceId} due to empty ID" as String] @@ -313,7 +318,7 @@ class EidsSpec extends BaseSpec { assert !bidderRequest.user.eids and: "Bid response should contain warnings" - assert bidResponse.ext.warnings[PREBID]?.code == [999, 999, 999] + assert bidResponse.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC, BidderErrorCode.GENERIC, BidderErrorCode.GENERIC] assert bidResponse.ext.warnings[PREBID]?.message == ["removed EID ${sourceId} due to empty ID" as String, "removed EID ${sourceId} due to empty ID" as String, @@ -584,13 +589,15 @@ class EidsSpec extends BaseSpec { } when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(bidRequest) + def response = defaultPbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should throw error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: " + - "Missing required parameter(s) in request.ext.prebid.data.eidPermissions[]. " + - "Either one or a combination of inserter, source, matcher, or mm should be defined." + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ["Invalid request format: " + + "Missing required parameter(s) in request.ext.prebid.data.eidPermissions[]. " + + "Either one or a combination of inserter, source, matcher, or mm should be defined."] + } } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/ImpRequestSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/ImpRequestSpec.groovy index 7a2f5923d56..eb705c57cc3 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/ImpRequestSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/ImpRequestSpec.groovy @@ -7,6 +7,7 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.Pmp import org.prebid.server.functional.model.request.auction.PrebidStoredRequest +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils @@ -15,11 +16,11 @@ import static org.prebid.server.functional.model.bidder.BidderName.ALIAS_CAMEL_C import static org.prebid.server.functional.model.bidder.BidderName.EMPTY 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.bidder.BidderName.GENER_X import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.BidderName.RUBICON import static org.prebid.server.functional.model.bidder.BidderName.UNKNOWN import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD -import static org.prebid.server.functional.model.bidder.BidderName.GENER_X import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer @@ -182,7 +183,7 @@ class ImpRequestSpec extends BaseSpec { def response = defaultPbsServiceWithAlias.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == ["WARNING: request.imp[0].ext.prebid.imp.${bidderName} was dropped with the reason: invalid bidder"] @@ -278,7 +279,7 @@ class ImpRequestSpec extends BaseSpec { def response = defaultPbsServiceWithAlias.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == ["imp.ext.prebid.imp.generic can not be merged into original imp [id=${bidRequest.imp.first.id}], " + "reason: imp[id=] missing required field: \"id\""] diff --git a/src/test/groovy/org/prebid/server/functional/tests/InfluxDBSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/InfluxDBSpec.groovy index 4e0253c1f95..7ee86efe49b 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/InfluxDBSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/InfluxDBSpec.groovy @@ -4,10 +4,12 @@ import org.prebid.server.functional.model.AccountStatus import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.influxdbContainer class InfluxDBSpec extends BaseSpec { @@ -43,12 +45,14 @@ class InfluxDBSpec extends BaseSpec { accountDao.save(account) when: "PBS processes auction request" - pbsServiceWithEnforceValidAccount.sendAuctionRequest(bidRequest) + def response = pbsServiceWithEnforceValidAccount.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Account $bidRequest.accountId is inactive" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Account $bidRequest.accountId is inactive"] + } and: "PBS wait until get metric" assert pbsServiceWithEnforceValidAccount.isContainMetricByValue(ACCOUNT_REJECTED_METRIC.formatted(bidRequest.accountId)) diff --git a/src/test/groovy/org/prebid/server/functional/tests/OrtbValidationSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/OrtbValidationSpec.groovy new file mode 100644 index 00000000000..f341c0cf9f9 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/tests/OrtbValidationSpec.groovy @@ -0,0 +1,211 @@ +package org.prebid.server.functional.tests + +import org.prebid.server.functional.model.db.Account +import org.prebid.server.functional.model.db.StoredRequest +import org.prebid.server.functional.model.request.amp.AmpRequest +import org.prebid.server.functional.model.request.auction.BidRequest +import org.prebid.server.functional.service.PrebidServerService + +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED +import static org.prebid.server.functional.model.AccountStatus.INACTIVE +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR + +class OrtbValidationSpec extends BaseSpec { + + private static final PrebidServerService baseValidationPbsService = pbsServiceFactory.getService(["auction.ortb-error-response": "false"]) + private static final Closure ACCOUNT_INVALID_MESSAGE = { accountId -> "Account ${accountId} is inactive" } + + def "PBS auction should provide proper ORTB error response when ortb-error-response host config is enabled"() { + given: "Default basic BidRequest" + def bidRequest = BidRequest.defaultBidRequest + + and: "Invalid account in DB" + def account = new Account(uuid: bidRequest.accountId, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes auction request" + def response = baseValidationPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) + + then: "Request should fail with error" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == [ACCOUNT_INVALID_MESSAGE(bidRequest.accountId)] + } + } + + def "PBS auction should provide raw error response when ortb-error-response host config is disabled"() { + given: "Default basic BidRequest" + def bidRequest = BidRequest.defaultBidRequest + + and: "Invalid account in DB" + def account = new Account(uuid: bidRequest.accountId, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes auction request" + def response = baseValidationPbsService.sendAuctionRequestRaw(bidRequest) + + then: "Request should fail with error" + assert response.statusCode == SC_UNAUTHORIZED + assert response.responseBody == ACCOUNT_INVALID_MESSAGE(bidRequest.accountId) + } + + def "PBS auction should provide raw error response and ignore host config when ortb-errors host config is disabled"() { + given: "Default basic BidRequest" + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.ortbErrors = false + } + + and: "Invalid account in DB" + def account = new Account(uuid: bidRequest.accountId, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequestRaw(bidRequest) + + then: "Request should fail with error" + assert response.statusCode == SC_UNAUTHORIZED + assert response.responseBody == ACCOUNT_INVALID_MESSAGE(bidRequest.accountId) + + where: + pbsService << [baseValidationPbsService, defaultPbsService] + } + + def "PBS auction should provide proper ORTB error response and ignore host config when ortb-errors host config is enabled"() { + given: "Default basic BidRequest" + def bidRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.ortbErrors = true + } + + and: "Invalid account in DB" + def account = new Account(uuid: bidRequest.accountId, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes auction request" + def response = pbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) + + then: "Request should fail with error" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == [ACCOUNT_INVALID_MESSAGE(bidRequest.accountId)] + } + + where: + pbsService << [baseValidationPbsService, defaultPbsService] + } + + def "PBS amp should provide proper ORTB error response when ortb-error-response host config is enabled"() { + given: "Default AmpRequest" + def ampRequest = AmpRequest.defaultAmpRequest + + and: "Default basic BidRequest" + def ampStoredRequest = BidRequest.defaultBidRequest.tap { + setAccountId(ampRequest.account) + } + + and: "Save storedRequest into DB" + def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) + storedRequestDao.save(storedRequest) + + and: "Invalid account in DB" + def account = new Account(uuid: ampRequest.account, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes amp request" + def response = baseValidationPbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) + + then: "Request should fail with error" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == [ACCOUNT_INVALID_MESSAGE(ampRequest.account)] + } + } + + def "PBS amp should provide raw error response when ortb-error-response host config is disabled"() { + given: "Default AmpRequest" + def ampRequest = AmpRequest.defaultAmpRequest + + and: "Default basic BidRequest" + def ampStoredRequest = BidRequest.defaultBidRequest.tap { + setAccountId(ampRequest.account) + } + + and: "Save storedRequest into DB" + def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) + storedRequestDao.save(storedRequest) + + and: "Invalid account in DB" + def account = new Account(uuid: ampRequest.account, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes amp request" + def response = baseValidationPbsService.sendAmpRequestRaw(ampRequest) + + then: "Request should fail with error" + assert response.statusCode == SC_UNAUTHORIZED + assert response.responseBody == ACCOUNT_INVALID_MESSAGE(ampRequest.account) + } + + def "PBS amp should provide raw error response and ignore host config when ortb-errors host config is disabled"() { + given: "Default AmpRequest" + def ampRequest = AmpRequest.defaultAmpRequest + + and: "Default basic BidRequest" + def ampStoredRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.ortbErrors = false + setAccountId(ampRequest.account) + } + + and: "Save storedRequest into DB" + def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) + storedRequestDao.save(storedRequest) + + and: "Invalid account in DB" + def account = new Account(uuid: ampRequest.account, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes amp request" + def response = pbsService.sendAmpRequestRaw(ampRequest) + + then: "Request should fail with error" + assert response.statusCode == SC_UNAUTHORIZED + assert response.responseBody == ACCOUNT_INVALID_MESSAGE(ampRequest.account) + + where: + pbsService << [baseValidationPbsService, defaultPbsService] + } + + def "PBS amp should provide proper ORTB error response and ignore host config when ortb-errors host config is enabled"() { + given: "Default AmpRequest" + def ampRequest = AmpRequest.defaultAmpRequest + + and: "Default basic BidRequest" + def ampStoredRequest = BidRequest.defaultBidRequest.tap { + ext.prebid.ortbErrors = true + setAccountId(ampRequest.account) + } + + and: "Save storedRequest into DB" + def storedRequest = StoredRequest.getStoredRequest(ampRequest, ampStoredRequest) + storedRequestDao.save(storedRequest) + + and: "Invalid account in DB" + def account = new Account(uuid: ampRequest.account, status: INACTIVE) + accountDao.save(account) + + when: "PBS processes amp request" + def response = pbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) + + then: "Request should fail with error" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == [ACCOUNT_INVALID_MESSAGE(ampRequest.account)] + } + + where: + pbsService << [baseValidationPbsService, defaultPbsService] + } +} diff --git a/src/test/groovy/org/prebid/server/functional/tests/ProfileSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/ProfileSpec.groovy index c6d600d518c..5f0885d63b8 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/ProfileSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/ProfileSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.config.AccountAuctionConfig import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.config.AccountProfilesConfigs @@ -17,31 +18,33 @@ import org.prebid.server.functional.model.request.auction.Format 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.ImpExtPrebid +import org.prebid.server.functional.model.request.auction.Site import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.request.auction.StoredBidResponse -import org.prebid.server.functional.model.request.profile.Profile import org.prebid.server.functional.model.request.profile.ImpProfile +import org.prebid.server.functional.model.request.profile.Profile import org.prebid.server.functional.model.request.profile.ProfileMergePrecedence -import org.prebid.server.functional.model.request.profile.RequestProfile import org.prebid.server.functional.model.request.profile.ProfileType -import org.prebid.server.functional.model.request.auction.Site +import org.prebid.server.functional.model.request.profile.RequestProfile +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.model.response.auction.SeatBid import org.prebid.server.functional.repository.dao.ProfileImpDao import org.prebid.server.functional.repository.dao.ProfileRequestDao -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.testcontainers.container.PrebidServerContainer import org.prebid.server.functional.util.PBSUtils import org.testcontainers.images.builder.Transferable import spock.lang.PendingFeature +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.request.profile.ProfileMergePrecedence.PROFILE import static org.prebid.server.functional.model.request.profile.ProfileMergePrecedence.REQUEST +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class ProfileSpec extends BaseSpec { @@ -637,8 +640,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [LIMIT_ERROR_MESSAGE] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [LIMIT_ERROR_MESSAGE] and: "Response should contain error" assert !response.ext?.errors @@ -808,7 +811,7 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.message.contains(LIMIT_ERROR_MESSAGE) + assert response.ext?.warnings[PREBID]*.message.contains(LIMIT_ERROR_MESSAGE) and: "Response should contain error" assert !response.ext?.errors @@ -928,12 +931,14 @@ class ProfileSpec extends BaseSpec { } when: "PBS processes auction request" - prebidServerService.sendAuctionRequest(bidRequest) + def response = prebidServerService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to invalid profile" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId) + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == [INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId)] + } cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(PROFILES_CONFIG + ['auction.profiles.fail-on-unknown': 'true']) @@ -954,12 +959,14 @@ class ProfileSpec extends BaseSpec { } when: "PBS processes auction request" - prebidServerService.sendAuctionRequest(bidRequest) + def response = prebidServerService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to invalid profile" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId) + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == [INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId)] + } cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(PROFILES_CONFIG + ['auction.profiles.fail-on-unknown': null]) @@ -986,12 +993,14 @@ class ProfileSpec extends BaseSpec { flushMetrics(pbsWithStoredProfiles) when: "PBS processes auction request" - pbsWithStoredProfiles.sendAuctionRequest(bidRequest) + def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to invalid profile" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId) + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == [INVALID_REQUEST_PREFIX + NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId)] + } and: "Missing metric should increments" def metrics = pbsWithStoredProfiles.sendCollectedMetricsRequest() @@ -1102,12 +1111,14 @@ class ProfileSpec extends BaseSpec { profileImpDao.save(StoredProfileImp.getProfile(impProfile)) when: "PBS processes auction request" - pbsWithStoredProfiles.sendAuctionRequest(bidRequest) + def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBs should throw error due to invalid request" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == 'Invalid request format: request.imp[0].banner.format[0] must define a valid "h" and "w" properties' + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ['Invalid request format: request.imp[0].banner.format[0] must define a valid "h" and "w" properties'] + } } def "PBS shouldn't emit error or warnings when bidRequest contains multiple imps with same profile"() { @@ -1190,8 +1201,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [LIMIT_ERROR_MESSAGE] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [LIMIT_ERROR_MESSAGE] and: "Response should contain error" assert !response.ext?.errors @@ -1234,8 +1245,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_PROFILE_MESSAGE.formatted(requestProfile.id)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_PROFILE_MESSAGE.formatted(requestProfile.id)] and: "Response should contain error" assert !response.ext?.errors @@ -1288,8 +1299,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_PROFILE_MESSAGE.formatted(requestProfile.id)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_PROFILE_MESSAGE.formatted(requestProfile.id)] and: "Response should contain error" assert !response.ext?.errors @@ -1337,8 +1348,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_IMP_PROFILE_MESSAGE.formatted(invalidProfileId)] and: "Response should contain error" assert !response.ext?.errors @@ -1369,8 +1380,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_REQUEST_PROFILE_MESSAGE.formatted(invalidProfileId)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_REQUEST_PROFILE_MESSAGE.formatted(invalidProfileId)] and: "Response should contain error" assert !response.ext?.errors @@ -1417,8 +1428,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_IMP_PROFILE_MESSAGE.formatted(invalidProfile.id)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_IMP_PROFILE_MESSAGE.formatted(invalidProfile.id)] and: "Response should contain error" assert !response.ext?.errors @@ -1457,8 +1468,8 @@ class ProfileSpec extends BaseSpec { def response = pbsWithStoredProfiles.sendAuctionRequest(bidRequest) then: "PBS should emit proper warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == [NO_REQUEST_PROFILE_MESSAGE.formatted(invalidProfileId)] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == [NO_REQUEST_PROFILE_MESSAGE.formatted(invalidProfileId)] and: "Response should contain error" assert !response.ext?.errors @@ -1500,12 +1511,14 @@ class ProfileSpec extends BaseSpec { def "PBS should throw exception when profiles are not configured and request contain profileId"() { when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(requestWithProfile) + def response = defaultPbsService.sendAuctionRequest(requestWithProfile, SC_BAD_REQUEST) then: "PBs should throw error due to invalid profile config" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == INVALID_REQUEST_PREFIX + CONFIG_ERROR_MESSAGE + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == [INVALID_REQUEST_PREFIX + CONFIG_ERROR_MESSAGE] + } where: requestWithProfile << [ @@ -1538,12 +1551,14 @@ class ProfileSpec extends BaseSpec { } when: "PBS processes auction request" - defaultPbsService.sendAuctionRequest(requestWithProfile) + def response = defaultPbsService.sendAuctionRequest(requestWithProfile, SC_BAD_REQUEST) then: "PBs should throw error due to invalid profile config" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == INVALID_REQUEST_PREFIX + CONFIG_ERROR_MESSAGE + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == [INVALID_REQUEST_PREFIX + CONFIG_ERROR_MESSAGE] + } cleanup: "Stop and remove pbs container" pbsContainer.stop() diff --git a/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy index 02adb2ab5e5..324ffc1674a 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/SeatNonBidSpec.groovy @@ -23,7 +23,6 @@ import static org.mockserver.model.HttpStatusCode.OK_200 import static org.mockserver.model.HttpStatusCode.PROCESSING_102 import static org.mockserver.model.HttpStatusCode.SERVICE_UNAVAILABLE_503 import static org.prebid.server.functional.model.AccountStatus.ACTIVE - import static org.prebid.server.functional.model.config.BidValidationEnforcement.ENFORCE import static org.prebid.server.functional.model.request.auction.DebugCondition.DISABLED import static org.prebid.server.functional.model.request.auction.DebugCondition.ENABLED @@ -32,11 +31,10 @@ import static org.prebid.server.functional.model.request.auction.SecurityLevel.S import static org.prebid.server.functional.model.response.auction.BidRejectionReason.ERROR_BIDDER_UNREACHABLE import static org.prebid.server.functional.model.response.auction.BidRejectionReason.ERROR_INVALID_BID_RESPONSE import static org.prebid.server.functional.model.response.auction.BidRejectionReason.ERROR_NO_BID +import static org.prebid.server.functional.model.response.auction.BidRejectionReason.ERROR_TIMED_OUT import static org.prebid.server.functional.model.response.auction.BidRejectionReason.REQUEST_BLOCKED_UNSUPPORTED_MEDIA_TYPE import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_INVALID_CREATIVE_NOT_SECURE import static org.prebid.server.functional.model.response.auction.BidRejectionReason.RESPONSE_REJECTED_INVALID_CREATIVE_SIZE -import static org.prebid.server.functional.model.response.auction.BidRejectionReason.ERROR_TIMED_OUT -import static org.prebid.server.functional.model.response.auction.ErrorType.GENERIC class SeatNonBidSpec extends BaseSpec { diff --git a/src/test/groovy/org/prebid/server/functional/tests/StoredResponseSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/StoredResponseSpec.groovy index 0b6f62923c7..3c79c7917b8 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/StoredResponseSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/StoredResponseSpec.groovy @@ -1,20 +1,23 @@ package org.prebid.server.functional.tests + import org.prebid.server.functional.model.db.StoredResponse import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.request.auction.StoredBidResponse +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.model.response.auction.SeatBid -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.bidder.BidderName.GENERIC +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class StoredResponseSpec extends BaseSpec { @@ -146,8 +149,8 @@ class StoredResponseSpec extends BaseSpec { def response = pbsService.sendAuctionRequest(bidRequest) then: "Response should contain warning information" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == ['WARNING: request.imp[0].ext.prebid.storedauctionresponse.seatbidarr is not supported at the imp level'] and: "PBS not send request to bidder" @@ -170,8 +173,8 @@ class StoredResponseSpec extends BaseSpec { assert response.seatbid == [storedAuctionResponse] and: "PBs should emit warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] - assert response.ext?.warnings[ErrorType.PREBID]*.message == + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] + assert response.ext?.warnings[PREBID]*.message == ["no auction. response defined by storedauctionresponse" as String] and: "PBS not send request to bidder" @@ -250,7 +253,7 @@ class StoredResponseSpec extends BaseSpec { def response = pbsService.sendAuctionRequest(bidRequest) then: "Response should contain warning information" - assert response.ext?.warnings[ErrorType.PREBID]*.message.contains('SeatBid can\'t be null in stored response') + assert response.ext?.warnings[PREBID]*.message.contains('SeatBid can\'t be null in stored response') and: "PBS not send request to bidder" assert bidder.getRequestCount(bidRequest.id) == 0 @@ -278,12 +281,14 @@ class StoredResponseSpec extends BaseSpec { bidRequest.imp[0].ext.prebid.storedAuctionResponse = new StoredAuctionResponse(seatBidObject: new SeatBid()) when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS throws an exception" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == 'Invalid request format: Seat can\'t be empty in stored response seatBid' + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ['Invalid request format: Seat can\'t be empty in stored response seatBid'] + } and: "PBS not send request to bidder" assert bidder.getRequestCount(bidRequest.id) == 0 @@ -295,12 +300,14 @@ class StoredResponseSpec extends BaseSpec { bidRequest.imp[0].ext.prebid.storedAuctionResponse = new StoredAuctionResponse(seatBidObject: new SeatBid(bid: [], seat: GENERIC)) when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS throws an exception" - def exception = thrown(PrebidServerException) - assert exception.statusCode == 400 - assert exception.responseBody == 'Invalid request format: There must be at least one bid in stored response seatBid' + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ['Invalid request format: There must be at least one bid in stored response seatBid'] + } and: "PBS not send request to bidder" assert bidder.getRequestCount(bidRequest.id) == 0 diff --git a/src/test/groovy/org/prebid/server/functional/tests/TargetingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/TargetingSpec.groovy index d9d337b3c27..986b0e66a44 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/TargetingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/TargetingSpec.groovy @@ -24,6 +24,7 @@ import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.request.auction.StoredBidResponse import org.prebid.server.functional.model.request.auction.Targeting import org.prebid.server.functional.model.request.auction.Video +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidMediaType @@ -32,7 +33,6 @@ import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.model.response.auction.MediaType import org.prebid.server.functional.model.response.auction.Prebid import org.prebid.server.functional.model.response.auction.SeatBid -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.testcontainers.PbsConfig import org.prebid.server.functional.testcontainers.scaffolding.Bidder @@ -41,14 +41,16 @@ import org.prebid.server.functional.util.PBSUtils import java.math.RoundingMode import java.nio.charset.StandardCharsets -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.AccountStatus.ACTIVE import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD import static org.prebid.server.functional.model.config.PriceGranularityType.UNKNOWN +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.model.response.auction.ErrorType.TARGETING import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer class TargetingSpec extends BaseSpec { @@ -1159,12 +1161,14 @@ class TargetingSpec extends BaseSpec { accountDao.save(account) when: "PBS processes auction request" - pbsWithDefaultTargetingLength.sendAuctionRequest(bidRequest) + def response = pbsWithDefaultTargetingLength.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == 'Invalid request format: Price granularity error: empty granularity definition supplied' + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ['Invalid request format: Price granularity error: empty granularity definition supplied'] + } } def "PBS auction should prioritize price granularity from original request over account config"() { @@ -1333,12 +1337,13 @@ class TargetingSpec extends BaseSpec { accountDao.save(account) when: "PBS processes auction request" - pbsWithDefaultTargetingLength.sendAmpRequest(ampRequest) + def response = pbsWithDefaultTargetingLength.sendAmpRequest(ampRequest, SC_BAD_REQUEST) then: "Request should fail with an error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == 'Invalid request format: Price granularity error: empty granularity definition supplied' + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage == ['Invalid request format: Price granularity error: empty granularity definition supplied'] + } } def "PBS amp should include price granularity from account config when original request doesn't contain price granularity"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/bidder/openx/OpenxSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/bidder/openx/OpenxSpec.groovy index 97a0015cea5..683e6a107dc 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/bidder/openx/OpenxSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/bidder/openx/OpenxSpec.groovy @@ -1,5 +1,6 @@ package org.prebid.server.functional.tests.bidder.openx + import org.prebid.server.functional.model.Currency import org.prebid.server.functional.model.bidder.Openx import org.prebid.server.functional.model.config.AccountAuctionConfig @@ -9,13 +10,13 @@ import org.prebid.server.functional.model.request.auction.AuctionEnvironment import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.InterestGroupAuctionSupport import org.prebid.server.functional.model.request.auction.PaaFormat +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.InterestGroupAuctionBuyer import org.prebid.server.functional.model.response.auction.InterestGroupAuctionBuyerExt import org.prebid.server.functional.model.response.auction.InterestGroupAuctionIntent import org.prebid.server.functional.model.response.auction.InterestGroupAuctionSeller import org.prebid.server.functional.model.response.auction.OpenxBidResponse import org.prebid.server.functional.model.response.auction.OpenxBidResponseExt -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.tests.BaseSpec import org.prebid.server.functional.util.PBSUtils @@ -23,6 +24,7 @@ import spock.lang.Shared import java.time.Instant +import static org.apache.http.HttpStatus.SC_BAD_REQUEST import static org.prebid.server.functional.model.bidder.BidderName.OPENX import static org.prebid.server.functional.model.bidder.BidderName.OPENX_ALIAS import static org.prebid.server.functional.model.bidder.BidderName.WILDCARD @@ -33,6 +35,7 @@ import static org.prebid.server.functional.model.request.auction.AuctionEnvironm import static org.prebid.server.functional.model.request.auction.PaaFormat.IAB import static org.prebid.server.functional.model.request.auction.PaaFormat.ORIGINAL import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.testcontainers.Dependencies.networkServiceContainer class OpenxSpec extends BaseSpec { @@ -438,7 +441,7 @@ class OpenxSpec extends BaseSpec { assert getLogsByText(logs, "ExtIgiIgs with absent impId from bidder: ${OPENX.value}") and: "Bid response should contain warning" - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == ["ExtIgiIgs with absent impId from bidder: ${OPENX.value}" as String] @@ -506,13 +509,16 @@ class OpenxSpec extends BaseSpec { bidder.setResponse(bidRequest.id, bidResponse) when: "PBS processes auction request" - pbsService.sendAuctionRequest(bidRequest) + def response = pbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "Request should fail with error" - def exception = thrown(PrebidServerException) - assert exception.responseBody.startsWith("Invalid request format: Error decoding bidRequest: " + - "Cannot deserialize value of type `org.prebid.server.auction.model.PaaFormat` " + - "from String \"invalid\": not one of the values accepted for Enum class: [original, iab]") + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BidderErrorCode.GENERIC] + it.errorMessage.any { it.startsWith("Invalid request format: Error decoding bidRequest: " + + "Cannot deserialize value of type `org.prebid.server.auction.model.PaaFormat` " + + "from String \"invalid\": not one of the values accepted for Enum class: [original, iab]") } + } } def "PBS shouldn't cause error when igs and igb empty array"() { 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 c0933a238e7..c28cfc0da17 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 @@ -5,15 +5,14 @@ import org.prebid.server.functional.model.config.ExecutionPlan 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 -import org.prebid.server.functional.model.response.auction.InvocationResult import org.prebid.server.functional.tests.BaseSpec import org.prebid.server.functional.util.PBSUtils import static org.prebid.server.functional.model.ModuleName.OPTABLE_TARGETING import static org.prebid.server.functional.model.ModuleName.ORTB2_BLOCKING +import static org.prebid.server.functional.model.ModuleName.PB_REQUEST_CORRECTION import static org.prebid.server.functional.model.ModuleName.PB_RESPONSE_CORRECTION import static org.prebid.server.functional.model.ModuleName.PB_RICHMEDIA_FILTER -import static org.prebid.server.functional.model.ModuleName.PB_REQUEST_CORRECTION import static org.prebid.server.functional.model.ModuleName.PB_RULE_ENGINE import static org.prebid.server.functional.model.config.Endpoint.OPENRTB2_AUCTION import static org.prebid.server.functional.model.config.Stage.ALL_PROCESSED_BID_RESPONSES 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 82355a47996..791b9ed2fbd 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 @@ -13,6 +13,7 @@ import org.prebid.server.functional.model.request.auction.FetchStatus import org.prebid.server.functional.model.request.auction.PrebidAnalytics import org.prebid.server.functional.model.request.auction.RichmediaFilter import org.prebid.server.functional.model.request.auction.StoredBidResponse +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ModuleActivityName import org.prebid.server.functional.service.PrebidServerService @@ -271,7 +272,7 @@ class AnalyticsTagsModuleSpec extends ModuleBaseSpec { assert !bidResponse?.ext?.prebid?.analytics?.tags and: "Bid response should contain warning" - assert bidResponse.ext.warnings[PREBID]?.code == [999] + assert bidResponse.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert bidResponse.ext.warnings[PREBID]?.message == ["analytics.options.enableclientdetails not enabled for account"] } diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/ortb2blocking/Ortb2BlockingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/ortb2blocking/Ortb2BlockingSpec.groovy index a7a97bc8816..0ff151da317 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/ortb2blocking/Ortb2BlockingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/ortb2blocking/Ortb2BlockingSpec.groovy @@ -7,8 +7,8 @@ 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.Ortb2BlockingActionOverride -import org.prebid.server.functional.model.config.Ortb2BlockingAttributeConfig import org.prebid.server.functional.model.config.Ortb2BlockingAttribute +import org.prebid.server.functional.model.config.Ortb2BlockingAttributeConfig import org.prebid.server.functional.model.config.Ortb2BlockingConditions import org.prebid.server.functional.model.config.Ortb2BlockingConfig import org.prebid.server.functional.model.config.Ortb2BlockingOverride @@ -17,17 +17,16 @@ import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.request.auction.Asset import org.prebid.server.functional.model.request.auction.Audio 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.BidderControls import org.prebid.server.functional.model.request.auction.GenericPreferredBidder -import org.prebid.server.functional.model.request.auction.Ix -import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp +import org.prebid.server.functional.model.request.auction.Ix import org.prebid.server.functional.model.request.auction.Video import org.prebid.server.functional.model.response.auction.Adm import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidMediaType import org.prebid.server.functional.model.response.auction.BidResponse -import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.model.response.auction.MediaType import org.prebid.server.functional.model.response.auction.SeatBid import org.prebid.server.functional.service.PrebidServerService @@ -41,8 +40,8 @@ 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.Ortb2BlockingAttribute.AUDIO_BATTR import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BADV -import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BAPP import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BANNER_BATTR +import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BAPP import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BCAT import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.BTYPE import static org.prebid.server.functional.model.config.Ortb2BlockingAttribute.VIDEO_BATTR diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/pbrequestcorrection/PbRequestCorrectionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/pbrequestcorrection/PbRequestCorrectionSpec.groovy index 1f6bbcaf13d..f1671468e16 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/pbrequestcorrection/PbRequestCorrectionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/pbrequestcorrection/PbRequestCorrectionSpec.groovy @@ -5,9 +5,9 @@ import org.prebid.server.functional.model.config.AccountHooksConfiguration import org.prebid.server.functional.model.config.PbRequestCorrectionConfig import org.prebid.server.functional.model.config.PbsModulesConfig import org.prebid.server.functional.model.db.Account -import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.AppExt import org.prebid.server.functional.model.request.auction.AppPrebid +import org.prebid.server.functional.model.request.auction.BidRequest 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.auction.OperationState diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/pbruleengine/RuleEngineDeviceSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/pbruleengine/RuleEngineDeviceSpec.groovy index 229e54a0ff0..42ebc8ee959 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/pbruleengine/RuleEngineDeviceSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/pbruleengine/RuleEngineDeviceSpec.groovy @@ -6,7 +6,6 @@ import org.prebid.server.functional.model.pricefloors.Country import org.prebid.server.functional.model.request.auction.Device import org.prebid.server.functional.model.request.auction.DeviceType import org.prebid.server.functional.util.PBSUtils -import spock.lang.RepeatUntilFailure import java.time.Instant diff --git a/src/test/groovy/org/prebid/server/functional/tests/module/richmedia/RichMediaFilterSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/richmedia/RichMediaFilterSpec.groovy index 517da393668..fafdda175b5 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/module/richmedia/RichMediaFilterSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/module/richmedia/RichMediaFilterSpec.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.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.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 RichMediaFilterSpec extends ModuleBaseSpec { diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsAdjustmentSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsAdjustmentSpec.groovy index c04e4d263d7..5fab38eecdb 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsAdjustmentSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsAdjustmentSpec.groovy @@ -20,6 +20,7 @@ import org.prebid.server.functional.model.request.auction.MultiBid import org.prebid.server.functional.model.request.auction.Native import org.prebid.server.functional.model.request.auction.VideoPlacementSubtypes import org.prebid.server.functional.model.request.auction.VideoPlcmtSubtype +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidMediaType @@ -845,7 +846,7 @@ class PriceFloorsAdjustmentSpec extends PriceFloorsBaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=${adjustmentType}, " + "value=${ruleValue}, currency=${currency}] in ${mediaType.value}.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" @@ -996,7 +997,7 @@ class PriceFloorsAdjustmentSpec extends PriceFloorsBaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=${adjustmentType}, " + "value=${adjustmentPrice}, currency=null] in banner.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" @@ -1096,7 +1097,7 @@ class PriceFloorsAdjustmentSpec extends PriceFloorsBaseSpec { and: "Should add a warning when in debug mode" def errorMessage = "bid adjustment from request was invalid: the found rule [adjtype=UNKNOWN, " + "value=$adjustmentPrice, currency=$currency] in banner.generic.* is invalid" as String - assert response.ext.warnings[PREBID]?.code == [999] + assert response.ext.warnings[PREBID]?.code == [BidderErrorCode.GENERIC] assert response.ext.warnings[PREBID]?.message == [errorMessage] and: "Original bid price and currency should be presented in bid.ext" diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy index b569514d0c4..b9da5c12966 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsCurrencySpec.groovy @@ -4,6 +4,7 @@ import org.prebid.server.functional.model.config.AccountPriceFloorsConfig import org.prebid.server.functional.model.config.PriceFloorsFetch import org.prebid.server.functional.model.pricefloors.PriceFloorData import org.prebid.server.functional.model.request.auction.ImpExtPrebidFloors +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ErrorType @@ -207,13 +208,13 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { def response = pbsService.sendAuctionRequest(bidRequest) then: "PBS should log an error" - assert response.ext?.errors[ErrorType.GENERIC]*.code == [999] + assert response.ext?.errors[ErrorType.GENERIC]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[ErrorType.GENERIC]*.message == ["Unable to convert from currency $bidRequest.ext.prebid.floors.floorMinCur to desired ad server" + " currency ${floorsResponse.modelGroups[0].currency}" as String] and: "PBS should log a warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["Error occurred while resolving floor for imp: ${bidRequest.imp[0].id}, cause: Unable " + "to convert from currency $requestFloorCur to desired ad server currency $floorsProviderCur"] @@ -402,7 +403,7 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { def response = currencyFloorsPbsService.sendAuctionRequest(bidRequest) then: "PBS should log a warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["Error occurred while resolving floor for imp: ${bidRequest.imp[0].id}, cause: Unable " + "to convert from currency $requestFloorCur to desired ad server currency $floorsProviderCur"] @@ -463,7 +464,7 @@ class PriceFloorsCurrencySpec extends PriceFloorsBaseSpec { def response = currencyFloorsPbsService.sendAuctionRequest(bidRequest) then: "PBS should log a warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["imp[].ext.prebid.floors.floorMinCur and ext.prebid.floors.floorMinCur has different values"] diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsEnforcementSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsEnforcementSpec.groovy index cec8bb8fa41..77bc554b221 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsEnforcementSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsEnforcementSpec.groovy @@ -12,6 +12,7 @@ import org.prebid.server.functional.model.request.auction.ExtPrebidPriceFloorEnf import org.prebid.server.functional.model.request.auction.MultiBid import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.request.auction.Targeting +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.Bid import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.ErrorType @@ -85,7 +86,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { } and: "PBS should log warning about bid suppression" - assert response.ext?.warnings[ErrorType.ALIAS]*.code == [6] + assert response.ext?.warnings[ErrorType.ALIAS]*.code == [BidderErrorCode.REJECTED_IPF] assert response.ext?.warnings[ErrorType.ALIAS]*.message == ["Bid with id '${aliasBidResponse.seatbid[0].bid[0].id}' was rejected by floor enforcement: " + "price $lowerPrice is below the floor ${floorValue.stripTrailingZeros()}" as String] @@ -136,7 +137,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "PBS should log warning about suppression all bids below the floor value " def impId = bidRequest.imp[0].id - assert response.ext?.warnings[ErrorType.GENERIC]*.code == [6, 6] + assert response.ext?.warnings[ErrorType.GENERIC]*.code == [BidderErrorCode.REJECTED_IPF, BidderErrorCode.REJECTED_IPF] assert response.ext?.warnings[ErrorType.GENERIC]*.message == ["Bid with id '${bidResponse.seatbid[0].bid[1].id}' was rejected by floor enforcement: " + "price ${bidResponse.seatbid[0].bid[1].price} is below the floor ${floorValue.stripTrailingZeros()}" as String, @@ -249,7 +250,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "Response should contain specific code and text in ext.warnings.prebid" verifyAll(bidResponse.ext.warnings[PREBID]) { - it.code == [999] + it.code == [BidderErrorCode.GENERIC] it.message == ["noFloorSignal to bidder generic"] } @@ -370,7 +371,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "Response should contain specific code and text in ext.warnings.prebid" verifyAll(bidResponse.ext.warnings[PREBID]) { - it.code == [999] + it.code == [BidderErrorCode.GENERIC] it.message == ["noFloorSignal to bidder generic"] } @@ -491,7 +492,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "Response should contain specific code and text in ext.warnings.prebid" verifyAll(bidResponse.ext.warnings[PREBID]) { - it.code == [999] + it.code == [BidderErrorCode.GENERIC] it.message == ["noFloorSignal to bidder generic"] } @@ -660,7 +661,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "Response should contain specific code and text in ext.warnings.prebid" verifyAll(bidResponse.ext.warnings[PREBID]) { - it.code == [999] + it.code == [BidderErrorCode.GENERIC] it.message == ["noFloorSignal to bidder generic"] } } @@ -739,7 +740,7 @@ class PriceFloorsEnforcementSpec extends PriceFloorsBaseSpec { and: "Response should contain specific code and text in ext.warnings.prebid" verifyAll(bidResponse.ext.warnings[PREBID]) { - it.code == [999] + it.code == [BidderErrorCode.GENERIC] it.message == ["noFloorSignal to bidder generic"] } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy index b40f6e8cac2..954b12060f9 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsFetchingSpec.groovy @@ -9,6 +9,7 @@ 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.auction.ExtPrebidFloors import org.prebid.server.functional.model.request.auction.PrebidStoredRequest +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.util.PBSUtils @@ -646,7 +647,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { assert metrics[FETCH_FAILURE_METRIC] == 1 and: "PBS should add single warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE("Price floor data useFetchDataRate must be in range(0-100), but was $requestUseFetchDataRate")] @@ -1400,7 +1401,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { and: "Response should contain warning" def message = "Price floor floorMin must be positive float, but was $invalidFloorMin" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] } @@ -1431,7 +1432,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { and: "Response should contain warning" def message = "Price floor rules should contain at least one model group" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] } @@ -1461,7 +1462,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { assert bidderRequest.imp[0].bidFloor == floorValue and: "Response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(PRICE_FLOOR_VALUES_MISSING)] } @@ -1495,7 +1496,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { assert bidderRequest.imp[0].bidFloor == floorValue and: "Response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(MODEL_WEIGHT_INVALID.formatted(invalidModelWeight))] where: @@ -1537,7 +1538,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { assert bidderRequest.imp[0].bidFloor == floorValue and: "Response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(MODEL_WEIGHT_INVALID.formatted(invalidModelWeight))] where: @@ -1580,7 +1581,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { and: "Response should contain warning" def message = "Price floor root skipRate must be in range(0-100), but was $invalidSkipRate" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] where: @@ -1623,7 +1624,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { and: "Response should contain warning" def message = "Price floor data skipRate must be in range(0-100), but was $invalidSkipRate" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] where: @@ -1665,7 +1666,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { assert bidderRequest.imp[0].bidFloor == floorValue and: "Response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(SKIP_RATE_INVALID.formatted(invalidSkipRate))] where: @@ -1704,7 +1705,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { and: "Response should contain warning" def message = "Price floor modelGroup default must be positive float, but was $invalidDefaultFloorValue" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] } @@ -1776,7 +1777,7 @@ class PriceFloorsFetchingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor rules data must be present" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should not add errors" diff --git a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy index b06c2530242..505bdb0fa61 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/pricefloors/PriceFloorsSignalingSpec.groovy @@ -14,6 +14,7 @@ import org.prebid.server.functional.model.request.auction.ExtPrebidFloors import org.prebid.server.functional.model.request.auction.ExtPrebidPriceFloorEnforcement import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.Video +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.MediaType import org.prebid.server.functional.util.PBSUtils @@ -606,7 +607,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor rules number ${getRuleSize(bidRequest)} exceeded its maximum number ${MAX_RULES_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "Alerts.general metrics should be populated" @@ -647,7 +648,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor schema dimensions ${getSchemaSize(bidRequest)} exceeded its maximum number ${MAX_SCHEMA_DIMENSIONS_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "Alerts.general metrics should be populated" @@ -694,7 +695,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor schema dimensions ${getSchemaSize(bidRequest)} exceeded its maximum number ${MAX_SCHEMA_DIMENSIONS_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -747,7 +748,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "Response should includer error warning" def message = "Price floor schema dimensions ${getSchemaSize(bidRequest)} exceeded its maximum number ${MAX_SCHEMA_DIMENSIONS_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS shouldn't log a errors" @@ -788,7 +789,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor schema dimensions ${getSchemaSize(bidRequest)} exceeded its maximum number ${MAX_SCHEMA_DIMENSIONS_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -833,7 +834,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor schema dimensions ${floorSchemaFilesSize} " + "exceeded its maximum number ${MAX_SCHEMA_DIMENSIONS_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -906,7 +907,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor rules number ${getRuleSize(ampStoredRequest)} " + "exceeded its maximum number ${MAX_RULES_SIZE}" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -944,7 +945,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor data skipRate must be in range(0-100), but was $requestSkipRate" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -978,7 +979,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor rules should contain at least one model group" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -1014,7 +1015,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor modelGroup modelWeight must be in range(1-100), but was $requestModelWeight" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -1051,7 +1052,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor modelGroup skipRate must be in range(0-100), but was $requestModelGroupsSkipRate" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log an errors" @@ -1086,7 +1087,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor modelGroup default must be positive float, but was $requestModelGroupsSkipRate" - assert bidResponse.ext?.warnings[PREBID]*.code == [999] + assert bidResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert bidResponse.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" @@ -1126,7 +1127,7 @@ class PriceFloorsSignalingSpec extends PriceFloorsBaseSpec { then: "PBS should log a warning" def message = "Price floor rules data must be present" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == [WARNING_MESSAGE(message)] and: "PBS should log a errors" diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/CcpaAmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/CcpaAmpSpec.groovy index 945ee175ee1..decfc1b27ea 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/CcpaAmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/CcpaAmpSpec.groovy @@ -6,6 +6,7 @@ import org.prebid.server.functional.model.config.AccountPrivacyConfig import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.db.StoredRequest import org.prebid.server.functional.model.request.auction.BidRequest +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.util.privacy.BogusConsent import org.prebid.server.functional.util.privacy.CcpaConsent @@ -199,7 +200,7 @@ class CcpaAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[ErrorType.PREBID]*.code == [999] + assert response.ext?.errors[ErrorType.PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[ErrorType.PREBID]*.message == ["CCPA consent $invalidCcpa has invalid format: us_privacy must contain 4 characters" as String] @@ -227,7 +228,7 @@ class CcpaAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[ErrorType.PREBID]*.code == [999] + assert response.ext?.errors[ErrorType.PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[ErrorType.PREBID]*.message == ["Invalid consent_type param passed"] } @@ -249,7 +250,7 @@ class CcpaAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[ErrorType.PREBID]*.code == [999] + assert response.ext?.errors[ErrorType.PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[ErrorType.PREBID]*.message == ["Consent type tcfV1 is no longer supported"] } @@ -273,7 +274,7 @@ class CcpaAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[ErrorType.PREBID]*.code == [999] + assert response.ext?.errors[ErrorType.PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[ErrorType.PREBID]*.message == ["CCPA consent $tcfConsent has invalid format: us_privacy must contain 4 characters" as String] } diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/DsaSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/DsaSpec.groovy index c2bf06fe50a..0480dfc138e 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/DsaSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/DsaSpec.groovy @@ -8,6 +8,7 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Dsa import org.prebid.server.functional.model.request.auction.Dsa as RequestDsa import org.prebid.server.functional.model.request.auction.RegsExt +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.BidExt import org.prebid.server.functional.model.response.auction.BidResponse import org.prebid.server.functional.model.response.auction.DsaResponse @@ -15,7 +16,6 @@ import org.prebid.server.functional.model.response.auction.DsaResponse as BidDsa import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.TcfConsent - import static org.prebid.server.functional.model.request.auction.DsaPubRender.PUB_CANT_RENDER import static org.prebid.server.functional.model.request.auction.DsaPubRender.PUB_WILL_RENDER import static org.prebid.server.functional.model.request.auction.DsaRequired.NOT_REQUIRED @@ -170,7 +170,7 @@ class DsaSpec extends PrivacyBaseSpec { and: "Response should contain an error" def bidId = bidResponse.seatbid[0].bid[0].id - assert response.ext?.warnings[GENERIC]*.code == [5] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.INVALID_BID] assert response.ext?.warnings[GENERIC]*.message == ["Bid \"$bidId\": DSA object missing when required"] where: @@ -285,7 +285,7 @@ class DsaSpec extends PrivacyBaseSpec { and: "Response should contain an error" def bidId = bidResponse.seatbid[0].bid[0].id - assert response.ext?.warnings[GENERIC]*.code == [5] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.INVALID_BID] assert response.ext?.warnings[GENERIC]*.message == ["Bid \"$bidId\": DSA object missing when required"] where: @@ -323,7 +323,7 @@ class DsaSpec extends PrivacyBaseSpec { and: "Response should contain an error" def bidId = bidResponse.seatbid[0].bid[0].id - assert response.ext?.warnings[GENERIC]*.code == [5] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.INVALID_BID] assert response.ext?.warnings[GENERIC]*.message == ["Bid \"$bidId\": DSA object missing when required"] where: @@ -503,7 +503,7 @@ class DsaSpec extends PrivacyBaseSpec { and: "Response should contain an error" def bidId = bidResponse.seatbid[0].bid[0].id - assert response.ext?.warnings[GENERIC]*.code == [5] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.INVALID_BID] assert response.ext?.warnings[GENERIC]*.message == ["Bid \"$bidId\": ${warningMessage}"] where: @@ -543,7 +543,7 @@ class DsaSpec extends PrivacyBaseSpec { and: "Response should contain an error" def bidId = bidResponse.seatbid[0].bid[0].id - assert response.ext?.warnings[GENERIC]*.code == [5] + assert response.ext?.warnings[GENERIC]*.code == [BidderErrorCode.INVALID_BID] assert response.ext?.warnings[GENERIC]*.message == ["Bid \"$bidId\": ${warningMessage}"] where: diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAmpSpec.groovy index 717c9f32d5b..b0fa39c9738 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAmpSpec.groovy @@ -13,6 +13,7 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.DistributionChannel import org.prebid.server.functional.model.request.auction.Regs import org.prebid.server.functional.model.request.auction.RegsExt +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.BogusConsent import org.prebid.server.functional.util.privacy.CcpaConsent @@ -146,7 +147,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message[0].startsWith("Parsing consent string:\"${invalidTcfConsent}\"") where: @@ -173,7 +174,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[PREBID]*.code == [999] + assert response.ext?.errors[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[PREBID]*.message == ["Consent type tcfV1 is no longer supported"] } @@ -197,7 +198,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[PREBID]*.code == [999] + assert response.ext?.errors[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[PREBID]*.message == ["CCPA consent $consentString has invalid format: " + "us_privacy must contain 4 characters"] @@ -223,7 +224,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.errors[PREBID]*.code == [999] + assert response.ext?.errors[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.errors[PREBID]*.message == ["Invalid consent_type param passed"] } @@ -245,7 +246,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAmpRequest(ampRequest) then: "Response should contain error" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message[0] ==~ /Parsing consent string:"$ccpaConsent" - failed.*/ } @@ -388,7 +389,7 @@ class GdprAmpSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAmpRequest(ampRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message == ["Unknown tcfPolicyVersion ${invalidTcfPolicyVersion}, defaulting to gvlSpecificationVersion=3" as String] diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAuctionSpec.groovy index 299d911a398..5598df8f645 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GdprAuctionSpec.groovy @@ -11,6 +11,7 @@ import org.prebid.server.functional.model.pricefloors.Country import org.prebid.server.functional.model.request.auction.DistributionChannel import org.prebid.server.functional.model.request.auction.Regs import org.prebid.server.functional.model.request.auction.RegsExt +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.BogusConsent @@ -23,7 +24,6 @@ import java.time.Instant import static org.prebid.server.functional.model.ChannelType.PBJS import static org.prebid.server.functional.model.ChannelType.WEB import static org.prebid.server.functional.model.bidder.BidderName.GENERIC - import static org.prebid.server.functional.model.config.AccountMetricsVerbosityLevel.DETAILED import static org.prebid.server.functional.model.config.Purpose.P1 import static org.prebid.server.functional.model.config.Purpose.P2 @@ -336,7 +336,7 @@ class GdprAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]*.code == [999] + assert response.ext?.warnings[ErrorType.PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ErrorType.PREBID]*.message == ["Unknown tcfPolicyVersion ${invalidTcfPolicyVersion}, defaulting to gvlSpecificationVersion=3" as String] diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAmpSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAmpSpec.groovy index ab4d46117ab..169d205b894 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAmpSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAmpSpec.groovy @@ -6,9 +6,10 @@ import org.prebid.server.functional.model.request.amp.ConsentType import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Regs import org.prebid.server.functional.model.request.auction.RegsExt +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.util.PBSUtils -import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import org.prebid.server.functional.util.privacy.gpp.v1.UspV1Consent +import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import static org.prebid.server.functional.model.request.GppSectionId.TCF_EU_V2 import static org.prebid.server.functional.model.request.GppSectionId.USP_V1 @@ -86,7 +87,7 @@ class GppAmpSpec extends PrivacyBaseSpec { assert !bidderRequests.regs.gppSid and: "Repose should contain warning" - assert ampResponse.ext?.warnings[PREBID]*.code == [999] + assert ampResponse.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert ampResponse.ext?.warnings[PREBID]*.message[0].startsWith("Failed to parse gppSid: \'${gppSids}\'") } @@ -107,7 +108,7 @@ class GppAmpSpec extends PrivacyBaseSpec { def response = defaultPbsService.sendAmpRequest(ampRequest) then: "Response should contain warning" - assert response.ext?.warnings[PREBID]*.code == [999] + assert response.ext?.warnings[PREBID]*.code == [BidderErrorCode.GENERIC] assert response.ext?.warnings[PREBID]*.message.every { it.contains("GPP string invalid:") } and: "Bidder request should contain gpp from consent string" diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAuctionSpec.groovy index d0282d48ddd..8506865f1cc 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppAuctionSpec.groovy @@ -4,12 +4,13 @@ import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Regs import org.prebid.server.functional.model.request.auction.RegsExt import org.prebid.server.functional.model.request.auction.User +import org.prebid.server.functional.model.response.BidderErrorCode import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.CcpaConsent import org.prebid.server.functional.util.privacy.TcfConsent -import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import org.prebid.server.functional.util.privacy.gpp.v1.UspV1Consent +import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import static org.prebid.server.functional.model.request.GppSectionId.TCF_EU_V2 import static org.prebid.server.functional.model.request.GppSectionId.USP_V1 @@ -69,7 +70,7 @@ class GppAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["GPP scope does not match TCF2 scope"] @@ -92,7 +93,7 @@ class GppAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["GPP scope does not match TCF2 scope"] @@ -117,7 +118,7 @@ class GppAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } .any { it.contains("GPP string invalid:") } @@ -161,7 +162,7 @@ class GppAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["GPP TCF2 string does not match user.consent"] @@ -222,7 +223,7 @@ class GppAuctionSpec extends PrivacyBaseSpec { def response = privacyPbsService.sendAuctionRequest(bidRequest) then: "Bid response should contain warning" - assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [999] + assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.code } == [BidderErrorCode.GENERIC] assert response.ext?.warnings[ErrorType.PREBID]?.collect { it.message } == ["USP string does not match regs.us_privacy"] diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppCookieSyncSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppCookieSyncSpec.groovy index 045dd33a784..cfdae9f8d36 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppCookieSyncSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppCookieSyncSpec.groovy @@ -17,8 +17,8 @@ import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.CcpaConsent import org.prebid.server.functional.util.privacy.TcfConsent import org.prebid.server.functional.util.privacy.gpp.v1.UsNatV1Consent -import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import org.prebid.server.functional.util.privacy.gpp.v1.UspV1Consent +import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import static org.prebid.server.functional.model.bidder.BidderName.ALIAS import static org.prebid.server.functional.model.bidder.BidderName.GENERIC diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppFetchBidActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppFetchBidActivitiesSpec.groovy index d292bd9e6f1..5274454f7ef 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppFetchBidActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppFetchBidActivitiesSpec.groovy @@ -20,7 +20,6 @@ import org.prebid.server.functional.model.request.auction.Condition 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.RegsExt -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.gpp.v1.UsCaV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsCoV1Consent @@ -32,7 +31,7 @@ import org.prebid.server.functional.util.privacy.gpp.v2.UsNatV2Consent import java.time.Instant -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED import static org.prebid.server.functional.model.config.ConfigCase.CAMEL_CASE import static org.prebid.server.functional.model.config.ConfigCase.KEBAB_CASE import static org.prebid.server.functional.model.config.ConfigCase.SNAKE_CASE @@ -79,6 +78,9 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -814,12 +816,14 @@ class GppFetchBidActivitiesSpec extends PrivacyBaseSpec { accountDao.save(account) when: "PBS processes auction requests" - activityPbsService.sendAuctionRequest(genericBidRequest) + def response = activityPbsService.sendAuctionRequest(genericBidRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS auction call when privacy regulation don't match custom requirement should call to bidder"() { @@ -1606,12 +1610,13 @@ class GppFetchBidActivitiesSpec extends PrivacyBaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - activityPbsService.sendAmpRequest(ampRequest) + def response = activityPbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS amp call when privacy regulation don't match custom requirement should call to bidder"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSetUidSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSetUidSpec.groovy index d49565222d2..39a4d7c5b55 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSetUidSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppSetUidSpec.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.model.request.GppSectionId import org.prebid.server.functional.model.request.setuid.SetuidRequest import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils -import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import org.prebid.server.functional.util.privacy.gpp.v1.UspV1Consent +import org.prebid.server.functional.util.privacy.gpp.v2.TcfEuV2Consent import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.request.GppSectionId.US_NAT_V1 diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy index 1db77ef0b90..69b029913d7 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitEidsActivitiesSpec.groovy @@ -20,7 +20,6 @@ import org.prebid.server.functional.model.request.auction.Condition 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.RegsExt -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.gpp.v1.UsCaV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsCoV1Consent @@ -32,7 +31,7 @@ import org.prebid.server.functional.util.privacy.gpp.v2.UsNatV2Consent import java.time.Instant -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.AND import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.OR import static org.prebid.server.functional.model.config.UsNationalPrivacySection.CHILD_CONSENTS_BELOW_13 @@ -76,7 +75,9 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -1123,12 +1124,14 @@ class GppTransmitEidsActivitiesSpec extends PrivacyBaseSpec { accountDao.save(account) when: "PBS processes auction requests" - activityPbsService.sendAuctionRequest(bidRequest) + def response = activityPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS auction call when privacy regulation don't match custom requirement should leave EIDS fields in request"() { @@ -2399,12 +2402,13 @@ class GppTransmitEidsActivitiesSpec extends PrivacyBaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - activityPbsService.sendAmpRequest(ampRequest) + def response = activityPbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS amp call when privacy regulation don't match custom requirement should leave EIDS fields in request"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitPreciseGeoActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitPreciseGeoActivitiesSpec.groovy index e3be1b13e98..50c7d1899f2 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitPreciseGeoActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitPreciseGeoActivitiesSpec.groovy @@ -19,7 +19,6 @@ import org.prebid.server.functional.model.request.auction.AllowActivities import org.prebid.server.functional.model.request.auction.Condition import org.prebid.server.functional.model.request.auction.Geo import org.prebid.server.functional.model.request.auction.RegsExt -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.gpp.v1.UsCaV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsCoV1Consent @@ -31,7 +30,7 @@ import org.prebid.server.functional.util.privacy.gpp.v2.UsNatV2Consent import java.time.Instant -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.AND import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.OR import static org.prebid.server.functional.model.config.UsNationalPrivacySection.CHILD_CONSENTS_BELOW_13 @@ -75,6 +74,9 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -1459,12 +1461,14 @@ class GppTransmitPreciseGeoActivitiesSpec extends PrivacyBaseSpec { accountDao.save(account) when: "PBS processes auction requests" - activityPbsService.sendAuctionRequest(bidRequest) + def response = activityPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS auction call when privacy regulation don't match custom requirement should not round lat/lon data"() { @@ -2808,12 +2812,13 @@ class GppTransmitPreciseGeoActivitiesSpec extends PrivacyBaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - activityPbsService.sendAmpRequest(ampRequest) + def response = activityPbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS amp call when privacy regulation don't match custom requirement should not round lat/lon data in request"() { diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitTidActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitTidActivitiesSpec.groovy index df0d0ab531f..30919f8643b 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitTidActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitTidActivitiesSpec.groovy @@ -12,10 +12,10 @@ import org.prebid.server.functional.util.PBSUtils import java.time.Instant -import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_ACCOUNT_DISALLOWED_COUNT import static org.prebid.server.functional.model.privacy.Metric.ACCOUNT_PROCESSED_RULES_COUNT -import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_ADAPTER_DISALLOWED_COUNT import static org.prebid.server.functional.model.privacy.Metric.PROCESSED_ACTIVITY_RULES_COUNT +import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_ACCOUNT_DISALLOWED_COUNT +import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_ADAPTER_DISALLOWED_COUNT import static org.prebid.server.functional.model.privacy.Metric.TEMPLATE_REQUEST_DISALLOWED_COUNT import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_TID import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy index b648a4fe91c..daba3f79897 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/GppTransmitUfpdActivitiesSpec.groovy @@ -15,6 +15,7 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsNationalV1ChildSensitiveData +import org.prebid.server.functional.model.privacy.gpp.UsNationalV1SensitiveData import org.prebid.server.functional.model.privacy.gpp.UsNationalV2ChildSensitiveData import org.prebid.server.functional.model.privacy.gpp.UsNationalV2SensitiveData import org.prebid.server.functional.model.request.amp.AmpRequest @@ -25,7 +26,8 @@ import org.prebid.server.functional.model.request.auction.Condition 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.RegsExt -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.auction.ErrorType +import org.prebid.server.functional.model.response.auction.NoBidResponse import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.gpp.v1.UsCaV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsCoV1Consent @@ -33,12 +35,11 @@ import org.prebid.server.functional.util.privacy.gpp.v1.UsCtV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsNatV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsUtV1Consent import org.prebid.server.functional.util.privacy.gpp.v1.UsVaV1Consent -import org.prebid.server.functional.model.privacy.gpp.UsNationalV1SensitiveData import org.prebid.server.functional.util.privacy.gpp.v2.UsNatV2Consent import java.time.Instant -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.AND import static org.prebid.server.functional.model.config.LogicalRestrictedRule.LogicalOperation.OR import static org.prebid.server.functional.model.config.UsNationalPrivacySection.CHILD_CONSENTS_BELOW_13 @@ -82,6 +83,7 @@ import static org.prebid.server.functional.model.request.auction.PrivacyModule.I import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_CUSTOM_LOGIC import static org.prebid.server.functional.model.request.auction.PrivacyModule.IAB_US_GENERAL import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID import static org.prebid.server.functional.util.privacy.model.State.ALABAMA import static org.prebid.server.functional.util.privacy.model.State.ONTARIO @@ -1653,12 +1655,14 @@ class GppTransmitUfpdActivitiesSpec extends PrivacyBaseSpec { accountDao.save(account) when: "PBS processes auction requests" - activityPbsService.sendAuctionRequest(bidRequest) + def response = activityPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS auction call when privacy regulation don't match custom requirement should leave UFPD fields in request"() { @@ -3389,12 +3393,13 @@ class GppTransmitUfpdActivitiesSpec extends PrivacyBaseSpec { storedRequestDao.save(storedRequest) when: "PBS processes amp request" - activityPbsService.sendAmpRequest(ampRequest) + def response = activityPbsService.sendAmpRequest(ampRequest, SC_UNAUTHORIZED) then: "Response should contain error" - def error = thrown(PrebidServerException) - assert error.statusCode == UNAUTHORIZED.code() - assert error.responseBody == "Unauthorized account id: ${accountId}" + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS amp call when privacy regulation don't match custom requirement should leave UFPD fields in request"() { 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 7d8ed79de7d..72b880b64e6 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 @@ -58,8 +58,8 @@ import static org.prebid.server.functional.model.config.PurposeEnforcement.BASIC import static org.prebid.server.functional.model.config.PurposeEnforcement.FULL import static org.prebid.server.functional.model.config.PurposeEnforcement.NO import static org.prebid.server.functional.model.mock.services.vendorlist.VendorListResponse.getDefaultVendorListResponse -import static org.prebid.server.functional.model.pricefloors.Country.USA import static org.prebid.server.functional.model.pricefloors.Country.BULGARIA +import static org.prebid.server.functional.model.pricefloors.Country.USA import static org.prebid.server.functional.model.request.GppSectionId.US_CA_V1 import static org.prebid.server.functional.model.request.GppSectionId.US_CO_V1 import static org.prebid.server.functional.model.request.GppSectionId.US_CT_V1 diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/TcfBasicTransmitEidsActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/TcfBasicTransmitEidsActivitiesSpec.groovy index 924ee285661..9ffecfc6b5e 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/TcfBasicTransmitEidsActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/TcfBasicTransmitEidsActivitiesSpec.groovy @@ -13,6 +13,7 @@ import org.prebid.server.functional.util.privacy.TcfUtils 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.config.Purpose.P1 +import static org.prebid.server.functional.model.config.Purpose.P10 import static org.prebid.server.functional.model.config.Purpose.P2 import static org.prebid.server.functional.model.config.Purpose.P3 import static org.prebid.server.functional.model.config.Purpose.P4 @@ -21,7 +22,6 @@ import static org.prebid.server.functional.model.config.Purpose.P6 import static org.prebid.server.functional.model.config.Purpose.P7 import static org.prebid.server.functional.model.config.Purpose.P8 import static org.prebid.server.functional.model.config.Purpose.P9 -import static org.prebid.server.functional.model.config.Purpose.P10 import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_EIDS import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/TransmitEidsOrtbConverterActivitiesSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/TransmitEidsOrtbConverterActivitiesSpec.groovy index e5534476613..82e25df1fa4 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/TransmitEidsOrtbConverterActivitiesSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/TransmitEidsOrtbConverterActivitiesSpec.groovy @@ -14,6 +14,7 @@ import spock.lang.Shared import static org.prebid.server.functional.model.bidder.BidderName.GENERIC import static org.prebid.server.functional.model.config.Purpose.P1 +import static org.prebid.server.functional.model.config.Purpose.P10 import static org.prebid.server.functional.model.config.Purpose.P2 import static org.prebid.server.functional.model.config.Purpose.P3 import static org.prebid.server.functional.model.config.Purpose.P4 @@ -22,7 +23,6 @@ import static org.prebid.server.functional.model.config.Purpose.P6 import static org.prebid.server.functional.model.config.Purpose.P7 import static org.prebid.server.functional.model.config.Purpose.P8 import static org.prebid.server.functional.model.config.Purpose.P9 -import static org.prebid.server.functional.model.config.Purpose.P10 import static org.prebid.server.functional.model.request.auction.ActivityType.TRANSMIT_EIDS import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE diff --git a/src/test/groovy/org/prebid/server/functional/tests/storage/AccountS3Spec.groovy b/src/test/groovy/org/prebid/server/functional/tests/storage/AccountS3Spec.groovy index 3a87be7b9e7..0fa0eb101be 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/storage/AccountS3Spec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/storage/AccountS3Spec.groovy @@ -1,15 +1,18 @@ package org.prebid.server.functional.tests.storage +import org.apache.http.HttpStatus import org.prebid.server.functional.model.AccountStatus import org.prebid.server.functional.model.config.AccountConfig import org.prebid.server.functional.model.request.auction.BidRequest -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.PrebidServerService import org.prebid.server.functional.service.S3Service import org.prebid.server.functional.testcontainers.PbsServiceFactory import org.prebid.server.functional.util.PBSUtils -import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED +import static org.apache.http.HttpStatus.SC_UNAUTHORIZED +import static org.prebid.server.functional.model.response.BidderErrorCode.BAD_INPUT +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class AccountS3Spec extends StorageBaseSpec { @@ -51,12 +54,14 @@ class AccountS3Spec extends StorageBaseSpec { s3Service.uploadAccount(DEFAULT_BUCKET, account) when: "PBS processes auction request" - s3StorageAccountPbsService.sendAuctionRequest(bidRequest) + def response = s3StorageAccountPbsService.sendAuctionRequest(bidRequest, HttpStatus.SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Account $accountId is inactive" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Account $accountId is inactive"] + } } def "PBS should throw exception when account id isn't match with bid request account id"() { @@ -73,12 +78,14 @@ class AccountS3Spec extends StorageBaseSpec { s3Service.uploadAccount(DEFAULT_BUCKET, account, accountId) when: "PBS processes auction request" - s3StorageAccountPbsService.sendAuctionRequest(bidRequest) + def response = s3StorageAccountPbsService.sendAuctionRequest(bidRequest, HttpStatus.SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS should throw exception when account is invalid in S3 storage json file"() { @@ -92,12 +99,14 @@ class AccountS3Spec extends StorageBaseSpec { s3Service.uploadFile(DEFAULT_BUCKET, INVALID_FILE_BODY, "${S3Service.DEFAULT_ACCOUNT_DIR}/${accountId}.json") when: "PBS processes auction request" - s3StorageAccountPbsService.sendAuctionRequest(bidRequest) + def response = s3StorageAccountPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } def "PBS should throw exception when account is not present in S3 storage and valid account enforced"() { @@ -108,11 +117,13 @@ class AccountS3Spec extends StorageBaseSpec { } when: "PBS processes auction request" - s3StorageAccountPbsService.sendAuctionRequest(bidRequest) + def response = s3StorageAccountPbsService.sendAuctionRequest(bidRequest, SC_UNAUTHORIZED) then: "PBS should reject the entire auction" - def exception = thrown(PrebidServerException) - assert exception.statusCode == UNAUTHORIZED.code() - assert exception.responseBody == "Unauthorized account id: ${accountId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [BAD_INPUT] + it.errorMessage == ["Unauthorized account id: ${accountId}"] + } } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy b/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy index cf5e68bbc90..15e0e83ea50 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/storage/AmpS3Spec.groovy @@ -1,15 +1,17 @@ package org.prebid.server.functional.tests.storage +import org.apache.http.HttpStatus import org.prebid.server.functional.model.db.StoredRequest 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.auction.Site -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.auction.ErrorType import org.prebid.server.functional.service.S3Service import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST +import static org.prebid.server.functional.model.response.BidderErrorCode.GENERIC class AmpS3Spec extends StorageBaseSpec { @@ -63,13 +65,14 @@ class AmpS3Spec extends StorageBaseSpec { s3Service.uploadStoredRequest(DEFAULT_BUCKET, storedRequest, ampRequest.tagId) when: "PBS processes amp request" - s3StoragePbsService.sendAmpRequest(ampRequest) + def response = s3StoragePbsService.sendAmpRequest(ampRequest, SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "No stored request found for id: ${ampRequest.tagId}" + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "No stored request found for id: ${ampRequest.tagId}"] + } } def "PBS should throw exception when trying to take parameters from request where id isn't match with stored request id"() { @@ -88,13 +91,14 @@ class AmpS3Spec extends StorageBaseSpec { s3Service.uploadFile(DEFAULT_BUCKET, INVALID_FILE_BODY, "${S3Service.DEFAULT_REQUEST_DIR}/${ampRequest.tagId}.json") when: "PBS processes amp request" - s3StoragePbsService.sendAmpRequest(ampRequest) + def response = s3StoragePbsService.sendAmpRequest(ampRequest, HttpStatus.SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "Can't parse Json for stored request with id ${ampRequest.tagId}" + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "Can't parse Json for stored request with id ${ampRequest.tagId}"] + } } def "PBS should throw an exception when trying to take parameters from stored request on S3 service that do not exist"() { @@ -104,12 +108,13 @@ class AmpS3Spec extends StorageBaseSpec { } when: "PBS processes amp request" - s3StoragePbsService.sendAmpRequest(ampRequest) + def response = s3StoragePbsService.sendAmpRequest(ampRequest, HttpStatus.SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "No stored request found for id: ${ampRequest.tagId}" + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "No stored request found for id: ${ampRequest.tagId}"] + } } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/storage/AuctionS3Spec.groovy b/src/test/groovy/org/prebid/server/functional/tests/storage/AuctionS3Spec.groovy index 51d39dd5af9..2aea9c135f1 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/storage/AuctionS3Spec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/storage/AuctionS3Spec.groovy @@ -1,16 +1,19 @@ package org.prebid.server.functional.tests.storage +import org.apache.http.HttpStatus import org.prebid.server.functional.model.db.StoredImp import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.Imp import org.prebid.server.functional.model.request.auction.PrebidStoredRequest import org.prebid.server.functional.model.request.auction.SecurityLevel -import org.prebid.server.functional.service.PrebidServerException +import org.prebid.server.functional.model.response.auction.ErrorType +import org.prebid.server.functional.model.response.auction.NoBidResponse import org.prebid.server.functional.service.S3Service import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST +import static org.prebid.server.functional.model.response.BidderErrorCode.GENERIC class AuctionS3Spec extends StorageBaseSpec { @@ -63,13 +66,15 @@ class AuctionS3Spec extends StorageBaseSpec { s3Service.uploadStoredImp(DEFAULT_BUCKET, storedImp, storedRequestId) when: "Requesting PBS auction" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "No stored impression found for id: ${storedRequestId}" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "No stored impression found for id: ${storedRequestId}"] + } } def "PBS should throw exception when trying to populate imp[0].secure from invalid imp stored request on S3 service"() { @@ -86,13 +91,15 @@ class AuctionS3Spec extends StorageBaseSpec { s3Service.uploadFile(DEFAULT_BUCKET, INVALID_FILE_BODY, "${S3Service.DEFAULT_IMPS_DIR}/${storedRequestId}.json" ) when: "Requesting PBS auction" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest, HttpStatus.SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "Can't parse Json for stored request with id ${storedRequestId}" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "Can't parse Json for stored request with id ${storedRequestId}"] + } } def "PBS should throw exception when trying to populate imp[0].secure from unexciting imp stored request on S3 service"() { @@ -106,12 +113,14 @@ class AuctionS3Spec extends StorageBaseSpec { } when: "Requesting PBS auction" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest, HttpStatus.SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Stored request processing failed: " + - "No stored impression found for id: ${storedRequestId}" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + verifyAll(response.ext.errors[ErrorType.PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Stored request processing failed: " + + "No stored impression found for id: ${storedRequestId}"] + } } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/storage/StoredResponseS3Spec.groovy b/src/test/groovy/org/prebid/server/functional/tests/storage/StoredResponseS3Spec.groovy index e07b5b71f2e..ebbf10f7fcd 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/storage/StoredResponseS3Spec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/storage/StoredResponseS3Spec.groovy @@ -4,12 +4,14 @@ import org.prebid.server.functional.model.db.StoredResponse import org.prebid.server.functional.model.request.auction.BidRequest import org.prebid.server.functional.model.request.auction.StoredAuctionResponse import org.prebid.server.functional.model.response.auction.SeatBid -import org.prebid.server.functional.service.PrebidServerException import org.prebid.server.functional.service.S3Service import org.prebid.server.functional.util.PBSUtils import spock.lang.PendingFeature -import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST +import static org.apache.http.HttpStatus.SC_BAD_REQUEST +import static org.prebid.server.functional.model.response.BidderErrorCode.GENERIC +import static org.prebid.server.functional.model.response.auction.ErrorType.PREBID +import static org.prebid.server.functional.model.response.auction.NoBidResponse.UNKNOWN_ERROR class StoredResponseS3Spec extends StorageBaseSpec { @@ -54,13 +56,15 @@ class StoredResponseS3Spec extends StorageBaseSpec { s3Service.uploadStoredResponse(DEFAULT_BUCKET, storedResponse, storedResponseId as String) when: "PBS processes auction request" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Failed to fetch stored auction response for " + - "impId = ${bidRequest.imp[0].id} and storedAuctionResponse id = ${storedResponseId}." + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Failed to fetch stored auction response for " + + "impId = ${bidRequest.imp[0].id} and storedAuctionResponse id = ${storedResponseId}."] + } } def "PBS should throw request format exception when invalid stored auction response defined in S3 storage"() { @@ -73,12 +77,14 @@ class StoredResponseS3Spec extends StorageBaseSpec { s3Service.uploadFile(DEFAULT_BUCKET, INVALID_FILE_BODY, "${S3Service.DEFAULT_RESPONSE_DIR}/${storedResponseId}.json") when: "PBS processes auction request" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest, SC_BAD_REQUEST) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Can't parse Json for stored response with id ${storedResponseId}" + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Can't parse Json for stored response with id ${storedResponseId}"] + } } def "PBS should throw request format exception when stored auction response defined in request but not defined in S3 storage"() { @@ -88,12 +94,14 @@ class StoredResponseS3Spec extends StorageBaseSpec { bidRequest.imp[0].ext.prebid.storedAuctionResponse = new StoredAuctionResponse(id: storedResponseId) when: "PBS processes auction request" - s3StoragePbsService.sendAuctionRequest(bidRequest) + def response = s3StoragePbsService.sendAuctionRequest(bidRequest) then: "PBS should throw request format error" - def exception = thrown(PrebidServerException) - assert exception.statusCode == BAD_REQUEST.code() - assert exception.responseBody == "Invalid request format: Failed to fetch stored auction response for " + - "impId = ${bidRequest.imp[0].id} and storedAuctionResponse id = ${storedResponseId}." + assert response.noBidResponse == UNKNOWN_ERROR + verifyAll(response.ext.errors[PREBID]) { + it.code == [GENERIC] + it.errorMessage == ["Invalid request format: Failed to fetch stored auction response for " + + "impId = ${bidRequest.imp[0].id} and storedAuctionResponse id = ${storedResponseId}."] + } } } diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCaV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCaV1Consent.groovy index 9b256e8b2f8..261c4bd6cb3 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCaV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCaV1Consent.groovy @@ -6,8 +6,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsCaliforniaV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsCaliforniaV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsCaV1Consent extends GppConsent { diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCoV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCoV1Consent.groovy index 2903be57f36..d39705f79f8 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCoV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCoV1Consent.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsColoradoV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsColoradoV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsCoV1Consent extends GppConsent { diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCtV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCtV1Consent.groovy index 5f832b08d1e..b343da6b80a 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCtV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsCtV1Consent.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsConnecticutV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsConnecticutV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsCtV1Consent extends GppConsent { diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsNatV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsNatV1Consent.groovy index eaa1a49c333..9483e132c34 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsNatV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsNatV1Consent.groovy @@ -7,8 +7,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsNationalV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsNationalV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsNatV1Consent extends GppConsent { diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsUtV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsUtV1Consent.groovy index 8b8dde2ad02..43c0a0e896b 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsUtV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsUtV1Consent.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsUtahV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsUtahV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsUtV1Consent extends GppConsent { diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsVaV1Consent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsVaV1Consent.groovy index 596bcbf1da0..197ae4a03fc 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsVaV1Consent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/gpp/v1/UsVaV1Consent.groovy @@ -5,8 +5,8 @@ import org.prebid.server.functional.model.privacy.gpp.MspaMode import org.prebid.server.functional.model.privacy.gpp.Notice import org.prebid.server.functional.model.privacy.gpp.OptOut import org.prebid.server.functional.model.privacy.gpp.UsVirginiaV1ChildSensitiveData -import org.prebid.server.functional.util.privacy.gpp.GppConsent import org.prebid.server.functional.model.privacy.gpp.UsVirginiaV1SensitiveData +import org.prebid.server.functional.util.privacy.gpp.GppConsent class UsVaV1Consent extends GppConsent {