diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy
index 8dc9831e3fa..984ef6409b2 100644
--- a/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy
+++ b/src/test/groovy/org/prebid/server/functional/model/config/AccountAuctionConfig.groovy
@@ -22,6 +22,7 @@ class AccountAuctionConfig {
Boolean debugAllow
AccountBidValidationConfig bidValidations
AccountEventsConfig events
+ AccountCacheConfig cache
AccountPriceFloorsConfig priceFloors
Targeting targeting
PaaFormat paaformat
diff --git a/src/test/groovy/org/prebid/server/functional/model/config/AccountCacheConfig.groovy b/src/test/groovy/org/prebid/server/functional/model/config/AccountCacheConfig.groovy
new file mode 100644
index 00000000000..121e32f03cd
--- /dev/null
+++ b/src/test/groovy/org/prebid/server/functional/model/config/AccountCacheConfig.groovy
@@ -0,0 +1,9 @@
+package org.prebid.server.functional.model.config
+
+import groovy.transform.ToString
+
+@ToString(includeNames = true, ignoreNulls = true)
+class AccountCacheConfig {
+
+ Boolean enabled
+}
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 e145e5a972f..2aec80a7e0a 100644
--- a/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy
+++ b/src/test/groovy/org/prebid/server/functional/tests/CacheSpec.groovy
@@ -1,6 +1,7 @@
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
@@ -14,6 +15,8 @@ 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.AccountStatus.ACTIVE
+import static org.prebid.server.functional.model.bidder.BidderName.GENERIC
import static org.prebid.server.functional.model.response.auction.MediaType.BANNER
import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO
@@ -42,6 +45,9 @@ class CacheSpec extends BaseSpec {
def creative = encodeXml(Vast.getDefaultVastModel(PBSUtils.randomString))
def request = VtrackRequest.getDefaultVtrackRequest(creative)
+ and: "Flush metrics"
+ flushMetrics(defaultPbsService)
+
when: "PBS processes vtrack request"
defaultPbsService.sendVtrackRequest(request, accountId)
@@ -468,6 +474,9 @@ class CacheSpec extends BaseSpec {
"<${impression}> <![CDATA[ ]]> ${impression}>${wrapper}>"
def request = VtrackRequest.getDefaultVtrackRequest(creative)
+ and: "Flush metrics"
+ flushMetrics(defaultPbsService)
+
when: "PBS processes vtrack request"
defaultPbsService.sendVtrackRequest(request, accountId)
@@ -492,4 +501,130 @@ class CacheSpec extends BaseSpec {
PBSUtils.getRandomCase(" inline ") | " ${PBSUtils.getRandomCase(" impression ")} $PBSUtils.randomNumber "
" inline ${PBSUtils.getRandomString()} " | " ImpreSSion "
}
+
+ 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)
+
+ and: "Default BidRequest with cache, targeting"
+ def bidRequest = BidRequest.getDefaultVideoRequest().tap {
+ it.enableCache()
+ }
+
+ and: "Account in the DB"
+ def accountConfig = new AccountConfig(status: ACTIVE, auction: accountAuctionConfig)
+ def account = new Account(uuid: bidRequest.accountId, config: accountConfig)
+ accountDao.save(account)
+
+ and: "Default bid response"
+ def presetBidResponse = BidResponse.getDefaultBidResponse(bidRequest)
+ bidder.setResponse(bidRequest.id, presetBidResponse)
+
+ and: "Flush metrics"
+ flushMetrics(defaultPbsService)
+
+ when: "PBS processes auction request"
+ def response = defaultPbsService.sendAuctionRequest(bidRequest)
+
+ then: "PBS should call PBC"
+ assert prebidCache.getRequestCount(bidRequest.imp[0].id) == 1
+
+ and: "PBS response targeting contains bidder specific keys"
+ def targetingKeyMap = response.seatbid?.first()?.bid?.first()?.ext?.prebid?.targeting
+ assert targetingKeyMap.containsKey('hb_cache_id')
+ assert targetingKeyMap.containsKey("hb_cache_id_${GENERIC}".toString())
+ assert targetingKeyMap.containsKey('hb_uuid')
+ assert targetingKeyMap.containsKey("hb_uuid_${GENERIC}".toString())
+
+ 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
+
+ where:
+ accountAuctionConfig << [
+ new AccountAuctionConfig(),
+ new AccountAuctionConfig(cache: new AccountCacheConfig()),
+ new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: null)),
+ new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: true))
+ ]
+ }
+
+ 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"
+ def bidRequest = BidRequest.getDefaultVideoRequest().tap {
+ it.enableCache()
+ }
+
+ and: "Account with cache config"
+ def accountAuctionConfig = new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: false))
+ def accountConfig = new AccountConfig(status: ACTIVE, auction: accountAuctionConfig)
+ def account = new Account(uuid: bidRequest.accountId, config: accountConfig)
+ accountDao.save(account)
+
+ and: "Default bid response"
+ def presetBidResponse = BidResponse.getDefaultBidResponse(bidRequest)
+ bidder.setResponse(bidRequest.id, presetBidResponse)
+
+ and: "Flush metrics"
+ flushMetrics(defaultPbsService)
+
+ when: "PBS processes auction request"
+ def response = defaultPbsService.sendAuctionRequest(bidRequest)
+
+ then: "PBS shouldn't call PBC"
+ assert !prebidCache.getRequestCount(bidRequest.imp[0].id)
+
+ and: "PBS response targeting shouldn't contains bidder specific keys"
+ def targetingKeyMap = response.seatbid?.first()?.bid?.first()?.ext?.prebid?.targeting
+ assert !targetingKeyMap.containsKey('hb_cache_id')
+ 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/module/responsecorrenction/ResponseCorrectionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy
index b4cbdd3fb88..2426a3fd316 100644
--- a/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy
+++ b/src/test/groovy/org/prebid/server/functional/tests/module/responsecorrenction/ResponseCorrectionSpec.groovy
@@ -1,5 +1,7 @@
package org.prebid.server.functional.tests.module.responsecorrenction
+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.AccountHooksConfiguration
import org.prebid.server.functional.model.config.AppVideoHtml
@@ -576,6 +578,61 @@ class ResponseCorrectionSpec extends ModuleBaseSpec {
assert !response.ext.warnings
}
+ def "PBS should modify response when requested video impression respond with invalid adm VAST keyword and disabled cache config"() {
+ given: "Start up time"
+ def start = Instant.now()
+
+ and: "Default bid request with APP and Video imp"
+ def bidRequest = getDefaultVideoRequest(APP)
+
+ and: "Set bidder response"
+ def bidResponse = BidResponse.getDefaultBidResponse(bidRequest).tap {
+ seatbid[0].bid[0].setAdm(PBSUtils.getRandomCase(admValue))
+ }
+ bidder.setResponse(bidRequest.id, bidResponse)
+
+ and: "Save account with enabled response correction module"
+ def accountWithResponseCorrectionModule = accountConfigWithResponseCorrectionModule(bidRequest).tap {
+ config.auction = new AccountAuctionConfig(cache: new AccountCacheConfig(enabled: false))
+ }
+ accountDao.save(accountWithResponseCorrectionModule)
+
+ when: "PBS processes auction request"
+ def response = pbsServiceWithResponseCorrectionModule.sendAuctionRequest(bidRequest)
+
+ then: "PBS should emit log"
+ def logsByTime = pbsServiceWithResponseCorrectionModule.getLogsByTime(start)
+ def bidId = bidResponse.seatbid[0].bid[0].id
+ def responseCorrection = getLogsByText(logsByTime, bidId)
+ assert responseCorrection.size() == 1
+ assert responseCorrection.any {
+ it.contains("Bid $bidId of bidder generic: changing media type to banner" as String)
+ }
+
+ and: "Response should contain seatBid"
+ assert response.seatbid.size() == 1
+
+ and: "Response should contain single seatBid with proper media type"
+ assert response.seatbid.bid.ext.prebid.type.flatten() == [BANNER]
+
+ and: "Response should contain single seatBid with proper meta media type"
+ assert response.seatbid.bid.ext.prebid.meta.mediaType.flatten() == [VIDEO.value]
+
+ and: "Response shouldn't contain errors"
+ assert !response.ext.errors
+
+ and: "Response shouldn't contain warnings"
+ assert !response.ext.warnings
+
+ where:
+ admValue << [
+ "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST${PBSUtils.randomString}",
+ "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST",
+ "<${' ' * PBSUtils.getRandomNumber(0, OPTIMAL_MAX_LENGTH)}VAST>",
+ "<${PBSUtils.randomString}VAST${' ' * PBSUtils.getRandomNumber(1, OPTIMAL_MAX_LENGTH)}"
+ ]
+ }
+
private static Account accountConfigWithResponseCorrectionModule(BidRequest bidRequest, Boolean enabledResponseCorrection = true, Boolean enabledAppVideoHtml = true) {
def modulesConfig = new PbsModulesConfig(pbResponseCorrection: new PbResponseCorrection(
enabled: enabledResponseCorrection, appVideoHtml: new AppVideoHtml(enabled: enabledAppVideoHtml)))