diff --git a/src/test/groovy/org/prebid/server/functional/model/response/vtrack/TransferValue.groovy b/src/test/groovy/org/prebid/server/functional/model/response/vtrack/TransferValue.groovy new file mode 100644 index 00000000000..1a7f24177dd --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/model/response/vtrack/TransferValue.groovy @@ -0,0 +1,22 @@ +package org.prebid.server.functional.model.response.vtrack + +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString +import org.prebid.server.functional.util.PBSUtils + +@ToString(includeNames = true, ignoreNulls = true) +@EqualsAndHashCode +class TransferValue { + + String adm + Integer width + Integer height + + static final TransferValue getTransferValue(){ + return new TransferValue().tap { + adm = PBSUtils.randomString + width = 300 + height = 250 + } + } +} 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 b9c173baa54..45a1138cf71 100644 --- a/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy +++ b/src/test/groovy/org/prebid/server/functional/service/PrebidServerService.groovy @@ -28,6 +28,7 @@ import org.prebid.server.functional.model.response.getuids.GetuidResponse import org.prebid.server.functional.model.response.infobidders.BidderInfoResponse import org.prebid.server.functional.model.response.setuid.SetuidResponse import org.prebid.server.functional.model.response.status.StatusResponse +import org.prebid.server.functional.model.response.vtrack.TransferValue import org.prebid.server.functional.testcontainers.container.PrebidServerContainer import org.prebid.server.functional.util.ObjectMapperWrapper import org.prebid.server.functional.util.PBSUtils @@ -73,7 +74,7 @@ class PrebidServerService implements ObjectMapperWrapper { authenticationScheme.password = pbsContainer.ADMIN_ENDPOINT_PASSWORD this.pbsContainer = pbsContainer requestSpecification = new RequestSpecBuilder().setBaseUri(pbsContainer.rootUri) - .build() + .build() adminRequestSpecification = buildAndGetRequestSpecification(pbsContainer.adminRootUri, authenticationScheme) prometheusRequestSpecification = buildAndGetRequestSpecification(pbsContainer.prometheusRootUri, authenticationScheme) } @@ -198,7 +199,7 @@ class PrebidServerService implements ObjectMapperWrapper { def uidsCookieAsEncodedJson = Base64.urlEncoder.encodeToString(uidsCookieAsJson.bytes) def response = given(requestSpecification).cookie(UIDS_COOKIE_NAME, uidsCookieAsEncodedJson) - .get(GET_UIDS_ENDPOINT) + .get(GET_UIDS_ENDPOINT) checkResponseStatusCode(response) decode(response.body.asString(), GetuidResponse) @@ -206,22 +207,31 @@ class PrebidServerService implements ObjectMapperWrapper { byte[] sendEventRequest(EventRequest eventRequest, Map headers = [:]) { def response = given(requestSpecification).headers(headers) - .queryParams(toMap(eventRequest)) - .get(EVENT_ENDPOINT) + .queryParams(toMap(eventRequest)) + .get(EVENT_ENDPOINT) checkResponseStatusCode(response) response.body.asByteArray() } - PrebidCacheResponse sendVtrackRequest(VtrackRequest request, String account) { + PrebidCacheResponse sendPostVtrackRequest(VtrackRequest request, String account) { def response = given(requestSpecification).queryParam("a", account) - .body(request) - .post(VTRACK_ENDPOINT) + .body(request) + .post(VTRACK_ENDPOINT) checkResponseStatusCode(response) decode(response.body.asString(), PrebidCacheResponse) } + TransferValue sendGetVtrackRequest(Map parameters) { + def response = given(requestSpecification) + .queryParams(parameters) + .get(VTRACK_ENDPOINT) + + checkResponseStatusCode(response) + decode(response.body.asString(), TransferValue) + } + StatusResponse sendStatusRequest() { def response = given(requestSpecification).get(STATUS_ENDPOINT) @@ -267,7 +277,7 @@ class PrebidServerService implements ObjectMapperWrapper { String sendLoggingHttpInteractionRequest(HttpInteractionRequest httpInteractionRequest) { def response = given(adminRequestSpecification).queryParams(toMap(httpInteractionRequest)) - .get(HTTP_INTERACTION_ENDPOINT) + .get(HTTP_INTERACTION_ENDPOINT) checkResponseStatusCode(response) response.body().asString() @@ -296,8 +306,8 @@ class PrebidServerService implements ObjectMapperWrapper { def payload = encode(bidRequest) given(requestSpecification).headers(headers) - .body(payload) - .post(AUCTION_ENDPOINT) + .body(payload) + .post(AUCTION_ENDPOINT) } private Response postCookieSync(CookieSyncRequest cookieSyncRequest, @@ -388,7 +398,7 @@ class PrebidServerService implements ObjectMapperWrapper { throw new IllegalArgumentException("The end time of the test is less than the start time") } def formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") - .withZone(ZoneId.from(UTC)) + .withZone(ZoneId.from(UTC)) def logs = Arrays.asList(pbsContainer.logs.split("\n")) def filteredLogs = [] @@ -441,7 +451,7 @@ class PrebidServerService implements ObjectMapperWrapper { private static RequestSpecification buildAndGetRequestSpecification(String uri, AuthenticationScheme authScheme) { new RequestSpecBuilder().setBaseUri(uri) - .setAuth(authScheme) - .build() + .setAuth(authScheme) + .build() } } diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/NetworkScaffolding.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/NetworkScaffolding.groovy index 7eea7536dfb..8ac5ad41483 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/NetworkScaffolding.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/NetworkScaffolding.groovy @@ -37,17 +37,17 @@ abstract class NetworkScaffolding implements ObjectMapperWrapper { int getRequestCount(HttpRequest httpRequest) { mockServerClient.retrieveRecordedRequests(httpRequest) - .size() + .size() } int getRequestCount(String value) { mockServerClient.retrieveRecordedRequests(getRequest(value)) - .size() + .size() } int getRequestCount() { mockServerClient.retrieveRecordedRequests(request) - .size() + .size() } void setResponse(HttpRequest httpRequest, @@ -56,8 +56,8 @@ abstract class NetworkScaffolding implements ObjectMapperWrapper { Times times = Times.exactly(1)) { def mockResponse = encode(responseModel) mockServerClient.when(httpRequest, times) - .respond(response().withStatusCode(statusCode.code()) - .withBody(mockResponse, APPLICATION_JSON)) + .respond(response().withStatusCode(statusCode.code()) + .withBody(mockResponse, APPLICATION_JSON)) } void setResponse(String value, @@ -73,9 +73,9 @@ abstract class NetworkScaffolding implements ObjectMapperWrapper { def responseHeaders = headers.collect { new Header(it.key, it.value) } def mockResponse = encode(responseModel) mockServerClient.when(getRequest(value), Times.unlimited()) - .respond(response().withStatusCode(statusCode.code()) - .withBody(mockResponse, APPLICATION_JSON) - .withHeaders(responseHeaders)) + .respond(response().withStatusCode(statusCode.code()) + .withBody(mockResponse, APPLICATION_JSON) + .withHeaders(responseHeaders)) } void setResponse(String value, @@ -86,39 +86,39 @@ abstract class NetworkScaffolding implements ObjectMapperWrapper { def responseHeaders = headers.collect { new Header(it.key, it.value) } def mockResponse = encode(responseModel) mockServerClient.when(getRequest(value), Times.unlimited()) - .respond(response().withStatusCode(statusCode.code()) - .withBody(mockResponse, APPLICATION_JSON) - .withHeaders(responseHeaders) - .withDelay(TimeUnit.MILLISECONDS, responseDelay)) + .respond(response().withStatusCode(statusCode.code()) + .withBody(mockResponse, APPLICATION_JSON) + .withHeaders(responseHeaders) + .withDelay(TimeUnit.MILLISECONDS, responseDelay)) } void setResponse(String value, String mockResponse) { mockServerClient.when(getRequest(value), Times.exactly(1)) - .respond(response().withStatusCode(OK_200.code()) - .withBody(mockResponse, APPLICATION_JSON)) + .respond(response().withStatusCode(OK_200.code()) + .withBody(mockResponse, APPLICATION_JSON)) } void setResponse(ResponseModel responseModel) { def mockResponse = encode(responseModel) mockServerClient.when(request().withPath(endpoint)) - .respond(response().withStatusCode(OK_200.code()) - .withBody(mockResponse, APPLICATION_JSON)) + .respond(response().withStatusCode(OK_200.code()) + .withBody(mockResponse, APPLICATION_JSON)) } void setResponse(String value, HttpStatusCode httpStatusCode) { mockServerClient.when(getRequest(value), Times.exactly(1)) - .respond(response().withStatusCode(httpStatusCode.code())) + .respond(response().withStatusCode(httpStatusCode.code())) } void setResponse(String value, HttpStatusCode httpStatusCode, String errorText) { mockServerClient.when(getRequest(value), Times.exactly(1)) - .respond(response().withStatusCode(httpStatusCode.code()) - .withBody(errorText, APPLICATION_JSON)) + .respond(response().withStatusCode(httpStatusCode.code()) + .withBody(errorText, APPLICATION_JSON)) } void setResponseWithTimeout(String value, int timeoutSec = 5) { mockServerClient.when(getRequest(value), Times.exactly(1)) - .respond(response().withDelay(SECONDS, timeoutSec)) + .respond(response().withDelay(SECONDS, timeoutSec)) } protected def getRequestAndResponse() { @@ -130,14 +130,19 @@ abstract class NetworkScaffolding implements ObjectMapperWrapper { .collect { it.body.toString() } } + String getRecordedRequestsQueryParameters(HttpRequest httpRequest) { + mockServerClient.retrieveRecordedRequests(httpRequest) + .collect { it -> it.queryStringParameters.multimap.toString()} + } + List getRecordedRequestsBody(String value) { mockServerClient.retrieveRecordedRequests(getRequest(value)) - .collect { it.body.toString() } + .collect { it.body.toString() } } List getRecordedRequestsBody() { mockServerClient.retrieveRecordedRequests(request) - .collect { it.body.toString() } + .collect { it.body.toString() } } Map> getLastRecordedRequestHeaders(HttpRequest httpRequest) { diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/PrebidCache.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/PrebidCache.groovy index 224f7c8b228..66ce54a9531 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/PrebidCache.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/PrebidCache.groovy @@ -7,12 +7,15 @@ import org.mockserver.model.HttpResponse import org.prebid.server.functional.model.mock.services.prebidcache.response.CacheObject import org.prebid.server.functional.model.mock.services.prebidcache.response.PrebidCacheResponse import org.prebid.server.functional.model.request.cache.BidCacheRequest +import org.prebid.server.functional.model.response.vtrack.TransferValue +import org.prebid.server.functional.util.PBSUtils import org.testcontainers.containers.MockServerContainer import java.util.stream.Stream import static org.mockserver.model.HttpRequest.request import static org.mockserver.model.HttpResponse.response +import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500 import static org.mockserver.model.HttpStatusCode.OK_200 import static org.mockserver.model.JsonPathBody.jsonPath @@ -24,6 +27,11 @@ class PrebidCache extends NetworkScaffolding { super(mockServerContainer, CACHE_ENDPOINT) } + String getVTracGetRequestParams() { + getRecordedRequestsQueryParameters(request().withMethod("GET") + .withPath(CACHE_ENDPOINT)) + } + void setXmlCacheResponse(String payload, PrebidCacheResponse prebidCacheResponse) { setResponse(getXmlCacheRequest(payload), prebidCacheResponse) } @@ -43,8 +51,8 @@ class PrebidCache extends NetworkScaffolding { @Override protected HttpRequest getRequest(String impId) { request().withMethod("POST") - .withPath(CACHE_ENDPOINT) - .withBody(jsonPath("\$.puts[?(@.value.impid == '$impId')]")) + .withPath(CACHE_ENDPOINT) + .withBody(jsonPath("\$.puts[?(@.value.impid == '$impId')]")) } List getRecordedRequests(String impId) { @@ -59,21 +67,52 @@ class PrebidCache extends NetworkScaffolding { @Override HttpRequest getRequest() { request().withMethod("POST") - .withPath(CACHE_ENDPOINT) + .withPath(CACHE_ENDPOINT) } @Override void setResponse() { - mockServerClient.when(request().withPath(endpoint), Times.unlimited(), TimeToLive.unlimited(), -10) - .respond{request -> request.withPath(endpoint) - ? response().withStatusCode(OK_200.code()).withBody(getBodyByRequest(request)) - : HttpResponse.notFoundResponse()} + mockServerClient.when(request() + .withMethod("POST") + .withPath(endpoint), Times.unlimited(), TimeToLive.unlimited(), -10) + .respond { request -> + request.withPath(endpoint) + ? response().withStatusCode(OK_200.code()).withBody(getBodyByRequest(request)) + : HttpResponse.notFoundResponse() + } + } + + void setGetResponse(TransferValue vTrackResponse) { + mockServerClient.when(request() + .withMethod("GET") + .withPath(endpoint), Times.unlimited(), TimeToLive.unlimited(), -10) + .respond { request -> + request.withPath(endpoint) + ? response().withStatusCode(OK_200.code()).withBody(encode(vTrackResponse)) + : HttpResponse.notFoundResponse() + } + } + + void setInvalidPostResponse() { + mockServerClient.when(request() + .withMethod("POST") + .withPath(endpoint), Times.unlimited(), TimeToLive.unlimited(), -10) + .respond { response().withStatusCode(INTERNAL_SERVER_ERROR_500.code()) } + } + + void setInvalidGetResponse(String uuid, String errorMessage = PBSUtils.randomString) { + mockServerClient.when(request() + .withMethod("GET") + .withPath(endpoint) + .withQueryStringParameter("uuid", uuid), Times.unlimited(), TimeToLive.unlimited(), -10) + .respond { response().withBody(errorMessage).withStatusCode(INTERNAL_SERVER_ERROR_500.code()) } + } private static HttpRequest getXmlCacheRequest(String payload) { request().withMethod("POST") - .withPath(CACHE_ENDPOINT) - .withBody(jsonPath("\$.puts[?(@.value =~/^.*$payload.*\$/)]")) + .withPath(CACHE_ENDPOINT) + .withBody(jsonPath("\$.puts[?(@.value =~/^.*$payload.*\$/)]")) } private String getBodyByRequest(HttpRequest request) { 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 0db60125603..495650fe6e4 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/BidderParamsSpec.groovy @@ -140,7 +140,7 @@ class BidderParamsSpec extends BaseSpec { accountDao.save(account) when: "PBS processes vtrack request" - pbsService.sendVtrackRequest(request, accountId.toString()) + pbsService.sendPostVtrackRequest(request, accountId.toString()) then: "vast xml is modified" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) @@ -172,7 +172,7 @@ class BidderParamsSpec extends BaseSpec { accountDao.save(account) when: "PBS processes vtrack request" - pbsService.sendVtrackRequest(request, accountId.toString()) + pbsService.sendPostVtrackRequest(request, accountId.toString()) then: "vast xml is not modified" def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) 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 b745ae53a1f..d77f9601abc 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy @@ -3,14 +3,11 @@ package org.prebid.server.functional.tests import org.prebid.server.functional.model.config.AccountAuctionConfig import org.prebid.server.functional.model.config.AccountCacheConfig import org.prebid.server.functional.model.config.AccountConfig -import org.prebid.server.functional.model.config.AccountEventsConfig import org.prebid.server.functional.model.db.Account 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.request.vtrack.VtrackRequest -import org.prebid.server.functional.model.request.vtrack.xml.Vast 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 @@ -29,15 +26,18 @@ class CacheSpec extends BaseSpec { private static final Integer DEFAULT_UUID_LENGTH = 36 private static final Integer TARGETING_PARAM_NAME_MAX_LENGTH = 20 - private static final String XML_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.xml" - private static final String JSON_CREATIVE_SIZE_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_size.json" - private static final String XML_CREATIVE_TTL_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_ttl.xml" - private static final String JSON_CREATIVE_TTL_ACCOUNT_METRIC = "account.%s.prebid_cache.creative_ttl.json" - private static final String CACHE_REQUEST_OK_ACCOUNT_METRIC = "account.%s.prebid_cache.requests.ok" + private static final String ACCOUNT_JSON_CREATIVE_SIZE_METRIC = "account.%s.prebid_cache.creative_size.json" + private static final String ACCOUNT_XML_CREATIVE_SIZE_METRIC = "account.%s.prebid_cache.creative_size.xml" + private static final String ACCOUNT_XML_CREATIVE_TTL_METRIC = "account.%s.prebid_cache.creative_ttl.xml" + private static final String ACCOUNT_JSON_CREATIVE_TTL_METRIC = "account.%s.prebid_cache.creative_ttl.json" + + private static final String ACCOUNT_REQUEST_OK_METRIC = "account.%s.prebid_cache.requests.ok" + private static final String REQUEST_OK_METRIC = "prebid_cache.requests.ok" - private static final String XML_CREATIVE_SIZE_GLOBAL_METRIC = "prebid_cache.creative_size.xml" private static final String JSON_CREATIVE_SIZE_GLOBAL_METRIC = "prebid_cache.creative_size.json" - private static final String CACHE_REQUEST_OK_GLOBAL_METRIC = "prebid_cache.requests.ok" + private static final String XML_CREATIVE_SIZE_GLOBAL_METRIC = "prebid_cache.creative_size.xml" + private static final String XML_CREATIVE_TTL_METRIC = "prebid_cache.creative_ttl.xml" + private static final String JSON_CREATIVE_TTL_METRIC = "prebid_cache.creative_ttl.json" private static final String CACHE_PATH = "/${PBSUtils.randomString}".toString() private static final String CACHE_HOST = "${PBSUtils.randomString}:${PBSUtils.getRandomNumber(0, 65535)}".toString() @@ -45,39 +45,49 @@ class CacheSpec extends BaseSpec { private static final String HTTP_SCHEME = 'http' private static final String HTTPS_SCHEME = 'https' - def "PBS should update prebid_cache.creative_size.xml metric when xml creative is received"() { + def "PBS should update prebid_cache.creative_size.json metric when json creative is received"() { given: "Current value of metric prebid_cache.requests.ok" - def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) + def initialValue = getCurrentMetricValue(defaultPbsService, REQUEST_OK_METRIC) - and: "Default VtrackRequest" - def accountId = PBSUtils.randomNumber.toString() - def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString)) - def request = VtrackRequest.getDefaultVtrackRequest(creative) + and: "Default BidRequest with cache, targeting" + def bidRequest = BidRequest.defaultBidRequest.tap { + it.enableCache() + } - and: "Flush metrics" - flushMetrics(defaultPbsService) + and: "Default basic bid with banner creative" + def asset = new Asset(id: PBSUtils.randomNumber) + def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap { + seatbid[0].bid[0].adm = new Adm(assets: [asset]) + } + + and: "Set bidder response" + bidder.setResponse(bidRequest.id, bidResponse) - when: "PBS processes vtrack request" - defaultPbsService.sendVtrackRequest(request, accountId) + when: "PBS processes auction request" + defaultPbsService.sendAuctionRequest(bidRequest) - then: "prebid_cache.creative_size.xml metric should be updated" + then: "prebid_cache.creative_size.json should be update" + def adm = bidResponse.seatbid[0].bid[0].getAdm() + def creativeSize = adm.bytes.length + + and: "prebid_cache.creative_size.json metric should be updated" def metrics = defaultPbsService.sendCollectedMetricsRequest() - def creativeSize = creative.bytes.length - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == initialValue + 1 - assert metrics[XML_CREATIVE_SIZE_GLOBAL_METRIC] == creativeSize + assert metrics[REQUEST_OK_METRIC] == initialValue + 1 + assert metrics[JSON_CREATIVE_SIZE_GLOBAL_METRIC] == creativeSize - and: "account..prebid_cache.creative_size.xml should be updated" - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(accountId)] == 1 - assert metrics[XML_CREATIVE_SIZE_ACCOUNT_METRIC.formatted(accountId)] == creativeSize + and: "account..prebid_cache.creative_size.json should be update" + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_SIZE_METRIC.formatted(bidRequest.accountId)] == creativeSize } - def "PBS should update prebid_cache.creative_size.json metric when json creative is received"() { + def "PBS should update prebid_cache.creative_size.xml metric when video bid and xml creative is received"() { given: "Current value of metric prebid_cache.requests.ok" - def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) + def initialValue = getCurrentMetricValue(defaultPbsService, REQUEST_OK_METRIC) and: "Default BidRequest with cache, targeting" - def bidRequest = BidRequest.defaultBidRequest.tap { + def bidRequest = BidRequest.defaultVideoRequest.tap { it.enableCache() + it.ext.prebid.targeting = new Targeting() } and: "Default basic bid with banner creative" @@ -98,12 +108,12 @@ class CacheSpec extends BaseSpec { and: "prebid_cache.creative_size.json metric should be updated" def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == initialValue + 1 - assert metrics[JSON_CREATIVE_SIZE_GLOBAL_METRIC] == creativeSize + assert metrics[REQUEST_OK_METRIC] == initialValue + 1 + assert metrics[XML_CREATIVE_SIZE_GLOBAL_METRIC] == creativeSize and: "account..prebid_cache.creative_size.json should be update" - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 - assert metrics[JSON_CREATIVE_SIZE_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == creativeSize + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_XML_CREATIVE_SIZE_METRIC.formatted(bidRequest.accountId)] == creativeSize } def "PBS should cache bids when targeting is specified"() { @@ -204,8 +214,8 @@ class CacheSpec extends BaseSpec { and: "PBS should include metrics for request" def metrics = pbsService.sendCollectedMetricsRequest() - assert metrics[JSON_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -244,11 +254,15 @@ class CacheSpec extends BaseSpec { and: "PBS cache key should have length equal to default UUID" assert cacheKey.length() == DEFAULT_UUID_LENGTH - and: "PBS should include metrics for request" + and: "PBS should include metrics for account" def metrics = pbsService.sendCollectedMetricsRequest() - assert metrics[JSON_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == videoHostTtl - assert metrics[XML_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == videoHostTtl - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == videoHostTtl + assert metrics[ACCOUNT_XML_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == videoHostTtl + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 + + and: "PBS should include metrics prebid_cache_creative.{xml,json}.creative.ttl for general" + assert metrics[JSON_CREATIVE_TTL_METRIC] == videoHostTtl + assert metrics[XML_CREATIVE_TTL_METRIC] == videoHostTtl cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -284,8 +298,8 @@ class CacheSpec extends BaseSpec { and: "PBS should include metrics for request" def metrics = pbsService.sendCollectedMetricsRequest() - assert metrics[JSON_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -320,8 +334,8 @@ class CacheSpec extends BaseSpec { and: "PBS should include metrics for request" def metrics = pbsService.sendCollectedMetricsRequest() - assert metrics[JSON_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -354,8 +368,8 @@ class CacheSpec extends BaseSpec { and: "PBS should include metrics for request" def metrics = pbsService.sendCollectedMetricsRequest() - assert metrics[JSON_CREATIVE_TTL_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[ACCOUNT_JSON_CREATIVE_TTL_METRIC.formatted(bidRequest.accountId)] == bannerHostTtl + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 cleanup: "Stop and remove pbs container" pbsServiceFactory.removeContainer(pbsConfig) @@ -470,55 +484,6 @@ class CacheSpec extends BaseSpec { true | VIDEO } - def "PBS should update prebid_cache.creative_size.xml metric and adding tracking xml when xml creative contain #wrapper and impression are valid xml value"() { - given: "Current value of metric prebid_cache.requests.ok" - def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) - - and: "Create and save enabled events config in account" - def accountId = PBSUtils.randomNumber.toString() - def account = new Account().tap { - uuid = accountId - config = new AccountConfig().tap { - auction = new AccountAuctionConfig(events: new AccountEventsConfig(enabled: true)) - } - } - accountDao.save(account) - - and: "Vtrack request with custom tags" - def payload = PBSUtils.randomString - def creative = "<${wrapper}>prebid.org wrapper" + - "<![CDATA[//${payload}]]>" + - "<${impression}> <![CDATA[ ]]> " - def request = VtrackRequest.getDefaultVtrackRequest(creative) - - and: "Flush metrics" - flushMetrics(defaultPbsService) - - when: "PBS processes vtrack request" - defaultPbsService.sendVtrackRequest(request, accountId) - - then: "Vast xml is modified" - def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) - assert prebidCacheRequest.size() == 1 - assert prebidCacheRequest[0].contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") - - and: "prebid_cache.creative_size.xml metric should be updated" - def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == initialValue + 1 - - and: "account..prebid_cache.creative_size.xml should be updated" - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(accountId) as String] == 1 - - where: - wrapper | impression - " wrapper " | " impression " - PBSUtils.getRandomCase(" wrapper ") | PBSUtils.getRandomCase(" impression ") - " wraPPer ${PBSUtils.getRandomString()} " | " imPreSSion ${PBSUtils.getRandomString()}" - " inLine " | " ImpreSSion $PBSUtils.randomNumber" - PBSUtils.getRandomCase(" inline ") | " ${PBSUtils.getRandomCase(" impression ")} $PBSUtils.randomNumber " - " inline ${PBSUtils.getRandomString()} " | " ImpreSSion " - } - def "PBS shouldn't cache bids when targeting is specified and config cache is invalid"() { given: "Pbs config with cache" def INVALID_PREBID_CACHE_CONFIG = ["cache.path" : CACHE_PATH, @@ -607,7 +572,7 @@ class CacheSpec extends BaseSpec { assert prebidCache.getRequestCount(bidRequest.imp[0].id) == 1 and: "Bid response targeting should contain value" - verifyAll (bidResponse?.seatbid[0]?.bid[0]?.ext?.prebid?.targeting as Map) { + verifyAll(bidResponse?.seatbid[0]?.bid[0]?.ext?.prebid?.targeting as Map) { it.get("hb_cache_id") it.get("hb_cache_id_generic") it.get("hb_cache_path") == CACHE_PATH @@ -643,7 +608,7 @@ class CacheSpec extends BaseSpec { assert prebidCache.getRequestCount(bidRequest.imp[0].id) == 1 and: "Bid response targeting should contain value" - verifyAll (bidResponse.seatbid[0].bid[0].ext.prebid.targeting) { + verifyAll(bidResponse.seatbid[0].bid[0].ext.prebid.targeting) { it.get("hb_cache_id") it.get("hb_cache_id_generic") it.get("hb_cache_path") == INTERNAL_CACHE_PATH @@ -662,7 +627,7 @@ class CacheSpec extends BaseSpec { def "PBS should cache bids and add targeting values when account cache config #accountAuctionConfig"() { given: "Current value of metric prebid_cache.requests.ok" - def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) + def initialValue = getCurrentMetricValue(defaultPbsService, REQUEST_OK_METRIC) and: "Default BidRequest with cache, targeting" def bidRequest = BidRequest.getDefaultVideoRequest().tap { @@ -696,8 +661,8 @@ class CacheSpec extends BaseSpec { and: "Metrics should be updated" def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == initialValue + 1 - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] == 1 + assert metrics[REQUEST_OK_METRIC] == initialValue + 1 + assert metrics[ACCOUNT_REQUEST_OK_METRIC.formatted(bidRequest.accountId)] == 1 where: accountAuctionConfig << [ @@ -709,10 +674,7 @@ class CacheSpec extends BaseSpec { } def "PBS shouldn't cache bids and add targeting values when account cache config disabled"() { - given: "Current value of metric prebid_cache.requests.ok" - def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) - - and: "Default BidRequest with cache, targeting" + given: "Default BidRequest with cache, targeting" def bidRequest = BidRequest.getDefaultVideoRequest().tap { it.enableCache() } @@ -742,47 +704,5 @@ class CacheSpec extends BaseSpec { assert !targetingKeyMap.containsKey("hb_cache_id_${GENERIC}".toString()) assert !targetingKeyMap.containsKey('hb_uuid') assert !targetingKeyMap.containsKey("hb_uuid_${GENERIC}".toString()) - - and: "Metrics shouldn't be updated" - def metrics = defaultPbsService.sendCollectedMetricsRequest() - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == initialValue - assert !metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(bidRequest.accountId)] - } - - def "PBS should update prebid_cache.creative_size.xml metric when account cache config #enabledCacheConcfig"() { - given: "Current value of metric prebid_cache.requests.ok" - def okInitialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC) - - and: "Default VtrackRequest" - def accountId = PBSUtils.randomNumber.toString() - def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString)) - def request = VtrackRequest.getDefaultVtrackRequest(creative) - - and: "Create and save enabled events config in account" - def account = new Account().tap { - it.uuid = accountId - it.config = new AccountConfig().tap { - it.auction = new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: enabledCacheConcfig)) - } - } - accountDao.save(account) - - and: "Flush metrics" - flushMetrics(defaultPbsService) - - when: "PBS processes vtrack request" - defaultPbsService.sendVtrackRequest(request, accountId) - - then: "prebid_cache.creative_size.xml metric should be updated" - def metrics = defaultPbsService.sendCollectedMetricsRequest() - def creativeSize = creative.bytes.length - assert metrics[CACHE_REQUEST_OK_GLOBAL_METRIC] == okInitialValue + 1 - - and: "account..prebid_cache.creative_size.xml should be updated" - assert metrics[CACHE_REQUEST_OK_ACCOUNT_METRIC.formatted(accountId)] == 1 - assert metrics[XML_CREATIVE_SIZE_ACCOUNT_METRIC.formatted(accountId)] == creativeSize - - where: - enabledCacheConcfig << [null, false, true] } } diff --git a/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy new file mode 100644 index 00000000000..e96fc519fe5 --- /dev/null +++ b/src/test/groovy/org/prebid/server/functional/tests/CacheVtrackSpec.groovy @@ -0,0 +1,388 @@ +package org.prebid.server.functional.tests + +import org.prebid.server.functional.model.config.AccountAuctionConfig +import org.prebid.server.functional.model.config.AccountCacheConfig +import org.prebid.server.functional.model.config.AccountConfig +import org.prebid.server.functional.model.config.AccountEventsConfig +import org.prebid.server.functional.model.db.Account +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.vtrack.TransferValue +import org.prebid.server.functional.service.PrebidServerException +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 io.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR +import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer + +class CacheVtrackSpec extends BaseSpec { + + private static final String ACCOUNT_VTRACK_XML_CREATIVE_SIZE_METRIC = "account.%s.prebid_cache.vtrack.creative_size.xml" + private static final String ACCOUNT_VTRACK_CREATIVE_TTL_XML_METRIC = "account.%s.prebid_cache.vtrack.creative_ttl.xml" + private static final String ACCOUNT_VTRACK_WRITE_ERR_METRIC = "account.%s.prebid_cache.vtrack.write.err" + private static final String ACCOUNT_VTRACK_WRITE_OK_METRIC = "account.%s.prebid_cache.vtrack.write.ok" + + private static final String VTRACK_XML_CREATIVE_SIZE_METRIC = "prebid_cache.vtrack.creative_size.xml" + private static final String VTRACK_XML_CREATIVE_TTL_METRIC = "prebid_cache.vtrack.creative_ttl.xml" + private static final String VTRACK_WRITE_OK_METRIC = "prebid_cache.vtrack.write.ok" + private static final String VTRACK_WRITE_ERROR_METRIC = "prebid_cache.vtrack.write.err" + private static final String VTRACK_READ_OK_METRIC = "prebid_cache.vtrack.read.ok" + private static final String VTRACK_READ_ERROR_METRIC = "prebid_cache.vtrack.read.err" + + private static final String CACHE_ENDPOINT = "/cache" + private static final String CACHE_PATH = "/${PBSUtils.randomString}".toString() + private static final String CACHE_HOST = "${PBSUtils.randomString}:${PBSUtils.getRandomNumber(0, 65535)}".toString() + private static final String HTTP_SCHEME = 'http' + + private static final Map INVALID_PREBID_CACHE_CONFIG = ["cache.path" : CACHE_PATH, + "cache.scheme": HTTP_SCHEME, + "cache.host" : CACHE_HOST] + private static final Map VALID_INTERNAL_CACHE = ["cache.internal.scheme": HTTP_SCHEME, + "cache.internal.host" : "$networkServiceContainer.hostAndPort".toString(), + "cache.internal.path" : CACHE_ENDPOINT] + private static PrebidServerService pbsServiceWithInternalCache + + def setupSpec() { + pbsServiceWithInternalCache = pbsServiceFactory.getService(VALID_INTERNAL_CACHE + INVALID_PREBID_CACHE_CONFIG) + } + + def cleanupSpec() { + pbsServiceFactory.removeContainer(VALID_INTERNAL_CACHE + INVALID_PREBID_CACHE_CONFIG) + } + + void cleanup() { + prebidCache.reset() + } + + def "PBS should return 400 status code when get vtrack request without uuid"() { + when: "PBS processes get vtrack request" + defaultPbsService.sendGetVtrackRequest(["uuid": null]) + + then: "Request should fail with an error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == BAD_REQUEST.code() + assert exception.responseBody == "'uuid' is a required query parameter and can't be empty" + } + + def "PBS should return 200 status code when get vtrack request contain uuid"() { + given: "Clean up and set up successful response" + def responseBody = TransferValue.getTransferValue() + prebidCache.setGetResponse(responseBody) + + when: "PBS processes get vtrack request" + def response = defaultPbsService.sendGetVtrackRequest(["uuid": UUID.randomUUID().toString()]) + + then: "Response should contain response from pbc" + assert response == responseBody + + then: "Metrics should contain ok metric" + def metricsRequest = defaultPbsService.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_OK_METRIC] == 1 + } + + def "PBS should return status code that came from pbc when get vtrack request and response from pbc invalid"() { + given: "Random uuid" + def uuid = UUID.randomUUID().toString() + + and: "Cache set up invalid response" + def randomErrorMessage = PBSUtils.randomString + prebidCache.setInvalidGetResponse(uuid, randomErrorMessage) + + when: "PBS processes get vtrack request" + defaultPbsService.sendGetVtrackRequest(["uuid": uuid]) + + then: "Request should fail with an error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == INTERNAL_SERVER_ERROR.code() + assert exception.responseBody == "Error occurred while sending request to cache: Cannot parse response: $randomErrorMessage" + + and: "Metrics should contain error metric" + def metricsRequest = defaultPbsService.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_ERROR_METRIC] == 1 + } + + def "PBS should return 200 status code and body when get vtrack request with uuid and ch"() { + given: "Current value of metric prebid_cache.vtrack.read.ok" + def initialValue = getCurrentMetricValue(defaultPbsService, VTRACK_READ_OK_METRIC) + + and: "Random uuid and cache host" + def uuid = UUID.randomUUID().toString() + def cacheHost = PBSUtils.randomString + + and: "Set up response body" + def responseBody = TransferValue.getTransferValue() + prebidCache.setGetResponse(responseBody) + + when: "PBS processes get vtrack request" + def response = defaultPbsService.sendGetVtrackRequest(["uuid": uuid, "ch": cacheHost]) + + then: "Response should contain response from pbc" + assert response == responseBody + + and: "Metrics should contain ok metrics" + def metricsRequest = defaultPbsService.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_OK_METRIC] == initialValue + 1 + } + + def "PBS should return 200 status code and body when internal cache configured and get vtrack request with uuid and ch"() { + given: "Current value of metric prebid_cache.vtrack.read.ok" + def initialValue = getCurrentMetricValue(pbsServiceWithInternalCache, VTRACK_READ_OK_METRIC) + + and: "Flush metric" + flushMetrics(pbsServiceWithInternalCache) + + and: "Random uuid and cache host" + def uuid = UUID.randomUUID().toString() + def cacheHost = PBSUtils.randomString + + and: "Mock set up successful response" + def responseBody = TransferValue.getTransferValue() + prebidCache.setGetResponse(responseBody) + + when: "PBS processes get vtrack request" + def response = pbsServiceWithInternalCache.sendGetVtrackRequest(["uuid": uuid, "ch": cacheHost]) + + then: "Response should contain response from pbc" + assert response == responseBody + + and: "Metrics should contain ok metrics" + def metricsRequest = pbsServiceWithInternalCache.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_OK_METRIC] == initialValue + 1 + + and: "Verify parameters that came to external cache services" + def requestParams = prebidCache.getVTracGetRequestParams() + assert requestParams == "[{ch=[$cacheHost], uuid=[$uuid]}]" + } + + def "PBS should return 200 status code when internal cache and get vtrack request contain uuid"() { + given: "Current value of metric prebid_cache.vtrack.read.ok" + def initialValue = getCurrentMetricValue(pbsServiceWithInternalCache, VTRACK_READ_OK_METRIC) + + and: "Random uuid" + def uuid = UUID.randomUUID().toString() + + and: "Set up response body" + def responseBody = TransferValue.getTransferValue() + prebidCache.setGetResponse(responseBody) + + and: "Flush metric" + flushMetrics(pbsServiceWithInternalCache) + + when: "PBS processes get vtrack request" + def response = pbsServiceWithInternalCache.sendGetVtrackRequest(["uuid": uuid]) + + then: "Response should contain response from pbc" + assert response == responseBody + + and: "Metrics should contain ok metrics" + def metricsRequest = pbsServiceWithInternalCache.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_OK_METRIC] == initialValue + 1 + + and: "Verify parameters that came to external cache services" + def requestParams = prebidCache.getVTracGetRequestParams() + assert requestParams == "[{uuid=[$uuid]}]" + } + + def "PBS should return status code that came from pbc when internal cache and get vtrack request and response from pbc invalid"() { + given: "Random uuid" + def uuid = UUID.randomUUID().toString() + + and: "Cache set up invalid response" + def randomErrorMessage = PBSUtils.randomString + prebidCache.setInvalidGetResponse(uuid, randomErrorMessage) + + and: "Flush metric" + flushMetrics(pbsServiceWithInternalCache) + + when: "PBS processes get vtrack request" + pbsServiceWithInternalCache.sendGetVtrackRequest(["uuid": uuid]) + + then: "Request should fail with an error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == INTERNAL_SERVER_ERROR.code() + assert exception.responseBody == "Error occurred while sending request to cache: Cannot parse response: $randomErrorMessage" + + and: "Metrics should contain error metric" + def metricsRequest = pbsServiceWithInternalCache.sendCollectedMetricsRequest() + assert metricsRequest[VTRACK_READ_ERROR_METRIC] == 1 + + and: "Verify parameters that came to external cache services" + def requestParams = prebidCache.getVTracGetRequestParams() + assert requestParams == "[{uuid=[$uuid]}]" + } + + def "PBS should return 400 status code when internal cache and get vtrack request without uuid"() { + when: "PBS processes get vtrack request" + pbsServiceWithInternalCache.sendGetVtrackRequest(["uuid": null]) + + then: "Request should fail with an error" + def exception = thrown(PrebidServerException) + assert exception.statusCode == BAD_REQUEST.code() + assert exception.responseBody == "'uuid' is a required query parameter and can't be empty" + } + + def "PBS should update prebid_cache.creative_size.xml metric when xml creative is received"() { + given: "Current value of metric prebid_cache.requests.ok" + def initialValue = getCurrentMetricValue(defaultPbsService, VTRACK_WRITE_OK_METRIC) + + and: "Cache set up response" + prebidCache.setResponse() + + and: "Default VtrackRequest" + def accountId = PBSUtils.randomNumber.toString() + def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString)) + def request = VtrackRequest.getDefaultVtrackRequest(creative) + + and: "Flush metrics" + flushMetrics(defaultPbsService) + + when: "PBS processes vtrack request" + defaultPbsService.sendPostVtrackRequest(request, accountId) + + then: "prebid_cache.vtrack.creative_size.xml metric should be updated" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + def creativeSize = creative.bytes.length + assert metrics[VTRACK_WRITE_OK_METRIC] == initialValue + 1 + assert metrics[VTRACK_XML_CREATIVE_SIZE_METRIC] == creativeSize + + and: "account..prebid_cache.creative_size.xml should be updated" + assert metrics[ACCOUNT_VTRACK_WRITE_OK_METRIC.formatted(accountId)] == 1 + assert metrics[ACCOUNT_VTRACK_XML_CREATIVE_SIZE_METRIC.formatted(accountId)] == creativeSize + } + + def "PBS should update prebid_cache.creative_size.xml metric and adding tracking xml when xml creative contain #wrapper and impression are valid xml value"() { + given: "Current value of metric prebid_cache.vtrack.write.ok" + def initialOkVTrackValue = getCurrentMetricValue(defaultPbsService, VTRACK_WRITE_OK_METRIC) + + and: "Create and save enabled events config in account" + def accountId = PBSUtils.randomNumber.toString() + def account = new Account().tap { + uuid = accountId + config = new AccountConfig().tap { + auction = new AccountAuctionConfig(events: new AccountEventsConfig(enabled: true)) + } + } + accountDao.save(account) + + and: "Set up prebid cache" + prebidCache.setResponse() + + and: "Vtrack request with custom tags" + def payload = PBSUtils.randomString + def creative = "<${wrapper}>prebid.org wrapper" + + "<![CDATA[//${payload}]]>" + + "<${impression}> <![CDATA[ ]]> " + def request = VtrackRequest.getDefaultVtrackRequest(creative) + + and: "Flush metrics" + flushMetrics(defaultPbsService) + + when: "PBS processes vtrack request" + defaultPbsService.sendPostVtrackRequest(request, accountId) + + then: "Vast xml is modified" + def prebidCacheRequest = prebidCache.getXmlRecordedRequestsBody(payload) + assert prebidCacheRequest.size() == 1 + assert prebidCacheRequest[0].contains("/event?t=imp&b=${request.puts[0].bidid}&a=$accountId&bidder=${request.puts[0].bidder}") + + and: "prebid_cache.creative_size.xml metric should be updated" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + def ttlSeconds = request.puts[0].ttlseconds + assert metrics[VTRACK_WRITE_OK_METRIC] == initialOkVTrackValue + 1 + assert metrics[VTRACK_XML_CREATIVE_TTL_METRIC] == ttlSeconds + + and: "account..prebid_cache.vtrack.creative_size.xml should be updated" + assert metrics[ACCOUNT_VTRACK_WRITE_OK_METRIC.formatted(accountId) as String] == 1 + assert metrics[ACCOUNT_VTRACK_CREATIVE_TTL_XML_METRIC.formatted(accountId) as String] == ttlSeconds + + where: + wrapper | impression + " wrapper " | " impression " + PBSUtils.getRandomCase(" wrapper ") | PBSUtils.getRandomCase(" impression ") + " wraPPer ${PBSUtils.getRandomString()} " | " imPreSSion ${PBSUtils.getRandomString()}" + " inLine " | " ImpreSSion $PBSUtils.randomNumber" + PBSUtils.getRandomCase(" inline ") | " ${PBSUtils.getRandomCase(" impression ")} $PBSUtils.randomNumber " + " inline ${PBSUtils.getRandomString()} " | " ImpreSSion " + } + + def "PBS should update prebid_cache.creative_size.xml metric when account cache config #enabledCacheConcfig"() { + given: "Current value of metric prebid_cache.requests.ok" + def okInitialValue = getCurrentMetricValue(defaultPbsService, VTRACK_WRITE_OK_METRIC) + + and: "Default VtrackRequest" + def accountId = PBSUtils.randomNumber.toString() + def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString)) + def request = VtrackRequest.getDefaultVtrackRequest(creative) + + and: "Create and save enabled events config in account" + def account = new Account().tap { + it.uuid = accountId + it.config = new AccountConfig().tap { + it.auction = new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: enabledCacheConcfig)) + } + } + accountDao.save(account) + + and: "Flush metrics" + flushMetrics(defaultPbsService) + + and: "Set up prebid cache" + prebidCache.setResponse() + + when: "PBS processes vtrack request" + defaultPbsService.sendPostVtrackRequest(request, accountId) + + then: "prebid_cache.creative_size.xml metric should be updated" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + def creativeSize = creative.bytes.length + assert metrics[VTRACK_WRITE_OK_METRIC] == okInitialValue + 1 + + and: "account..prebid_cache.creative_size.xml should be updated" + assert metrics[ACCOUNT_VTRACK_WRITE_OK_METRIC.formatted(accountId)] == 1 + assert metrics[ACCOUNT_VTRACK_XML_CREATIVE_SIZE_METRIC.formatted(accountId)] == creativeSize + + where: + enabledCacheConcfig << [null, false, true] + } + + def "PBS should failed cache and update prebid_cache.vtrack.write.err metric when cache service respond with invalid status code"() { + given: "Current value of metric prebid_cache.requests.ok" + def okInitialValue = getCurrentMetricValue(defaultPbsService, VTRACK_WRITE_ERROR_METRIC) + + and: "Default VtrackRequest" + def accountId = PBSUtils.randomNumber.toString() + def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString)) + def request = VtrackRequest.getDefaultVtrackRequest(creative) + + and: "Create and save enabled events config in account" + def account = new Account().tap { + it.uuid = accountId + it.config = new AccountConfig().tap { + it.auction = new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: true)) + } + } + accountDao.save(account) + + and: "Flush metrics" + flushMetrics(defaultPbsService) + + and: "Reset cache and set up invalid response" + prebidCache.setInvalidPostResponse() + + when: "PBS processes vtrack request" + defaultPbsService.sendPostVtrackRequest(request, accountId) + + then: "PBS throws an exception" + def exception = thrown(PrebidServerException) + assert exception.statusCode == 500 + assert exception.responseBody.contains("Error occurred while sending request to cache: HTTP status code 500") + + then: "prebid_cache.vtrack.write.err metric should be updated" + def metrics = defaultPbsService.sendCollectedMetricsRequest() + assert metrics[VTRACK_WRITE_ERROR_METRIC] == okInitialValue + 1 + + and: "account..prebid_cache.vtrack.write.err should be updated" + assert metrics[ACCOUNT_VTRACK_WRITE_ERR_METRIC.formatted(accountId)] == 1 + } +} diff --git a/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy index 01f60ac2808..b70715e721b 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/HttpSettingsSpec.groovy @@ -271,7 +271,7 @@ class HttpSettingsSpec extends BaseSpec { httpSettings.setResponse(accountId, httpSettingsResponse) when: "PBS processes vtrack request" - def response = prebidServerService.sendVtrackRequest(request, accountId) + def response = prebidServerService.sendPostVtrackRequest(request, accountId) then: "Response should contain uid" assert response.responses[0]?.uuid diff --git a/src/test/groovy/org/prebid/server/functional/tests/SmokeSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/SmokeSpec.groovy index c7cceae6d01..daa27b260fa 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/SmokeSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/SmokeSpec.groovy @@ -98,7 +98,7 @@ class SmokeSpec extends BaseSpec { def accountId = PBSUtils.randomNumber.toString() when: "PBS processes vtrack request" - def response = defaultPbsService.sendVtrackRequest(request, accountId) + def response = defaultPbsService.sendPostVtrackRequest(request, accountId) then: "Response should contain uid" assert response.responses[0]?.uuid