@@ -14,14 +14,17 @@ import org.prebid.server.functional.model.response.auction.Adm
1414import org.prebid.server.functional.model.response.auction.BidResponse
1515import org.prebid.server.functional.util.PBSUtils
1616
17+ import static org.prebid.server.functional.model.response.auction.ErrorType.CACHE
1718import static org.prebid.server.functional.model.response.auction.MediaType.BANNER
1819import static org.prebid.server.functional.model.response.auction.MediaType.VIDEO
20+ import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer
1921
2022class CacheSpec extends BaseSpec {
2123
2224 private static final String PBS_API_HEADER = ' x-pbc-api-key'
2325 private static final Integer MAX_DATACENTER_REGION_LENGTH = 4
2426 private static final Integer DEFAULT_UUID_LENGTH = 36
27+ private static final Integer TARGETING_PARAM_NAME_MAX_LENGTH = 20
2528
2629 private static final String XML_CREATIVE_SIZE_ACCOUNT_METRIC = " account.%s.prebid_cache.creative_size.xml"
2730 private static final String JSON_CREATIVE_SIZE_ACCOUNT_METRIC = " account.%s.prebid_cache.creative_size.json"
@@ -33,6 +36,12 @@ class CacheSpec extends BaseSpec {
3336 private static final String JSON_CREATIVE_SIZE_GLOBAL_METRIC = " prebid_cache.creative_size.json"
3437 private static final String CACHE_REQUEST_OK_GLOBAL_METRIC = " prebid_cache.requests.ok"
3538
39+ private static final String CACHE_PATH = " /${ PBSUtils.randomString} " . toString()
40+ private static final String CACHE_HOST = " ${ PBSUtils.randomString} :${ PBSUtils.getRandomNumber(0, 65535)} " . toString()
41+ private static final String INTERNAL_CACHE_PATH = ' /cache'
42+ private static final String HTTP_SCHEME = ' http'
43+ private static final String HTTPS_SCHEME = ' https'
44+
3645 def " PBS should update prebid_cache.creative_size.xml metric when xml creative is received" () {
3746 given : " Current value of metric prebid_cache.requests.ok"
3847 def initialValue = getCurrentMetricValue(defaultPbsService, CACHE_REQUEST_OK_GLOBAL_METRIC )
@@ -492,4 +501,145 @@ class CacheSpec extends BaseSpec {
492501 PBSUtils . getRandomCase(" inline " ) | " ${ PBSUtils.getRandomCase(" impression ")} $PBSUtils . randomNumber "
493502 " inline ${ PBSUtils.getRandomString()} " | " ImpreSSion "
494503 }
504+
505+ def " PBS shouldn't cache bids when targeting is specified and config cache is invalid" () {
506+ given : " Pbs config with cache"
507+ def INVALID_PREBID_CACHE_CONFIG = [" cache.path" : CACHE_PATH ,
508+ " cache.scheme" : HTTP_SCHEME ,
509+ " cache.host" : CACHE_HOST ]
510+ def pbsService = pbsServiceFactory. getService(INVALID_PREBID_CACHE_CONFIG )
511+
512+ and : " Default BidRequest with cache, targeting"
513+ def bidRequest = BidRequest . defaultBidRequest. tap {
514+ it. enableCache()
515+ }
516+
517+ when : " PBS processes auction request"
518+ def bidResponse = pbsService. sendAuctionRequest(bidRequest)
519+
520+ then : " Response should contain error"
521+ assert bidResponse. ext?. errors[CACHE ]* . code == [999 ]
522+ assert bidResponse. ext?. errors[CACHE ]* . message[0 ] == (" Failed to resolve '${ CACHE_HOST.tokenize(":")[0]} ' [A(1)]" )
523+
524+ and : " Bid response targeting should contain value"
525+ assert bidResponse. seatbid[0 ]. bid[0 ]. ext. prebid. targeting. findAll { it. key. startsWith(" hb_cache" ) }. isEmpty()
526+
527+ and : " PBS shouldn't call PBC"
528+ assert prebidCache. getRequestCount(bidRequest. imp[0 ]. id) == 0
529+
530+ cleanup : " Stop and remove pbs container"
531+ pbsServiceFactory. removeContainer(INVALID_PREBID_CACHE_CONFIG )
532+ }
533+
534+ def " PBS should cache bids and emit error when targeting is specified and config cache is valid and internal is invalid" () {
535+ given : " Pbs config with cache"
536+ def INVALID_PREBID_CACHE_CONFIG = [" cache.internal.path" : CACHE_PATH ,
537+ " cache.internal.scheme" : HTTP_SCHEME ,
538+ " cache.internal.host" : CACHE_HOST ]
539+ def pbsService = pbsServiceFactory. getService(INVALID_PREBID_CACHE_CONFIG )
540+
541+ and : " Default BidRequest with cache, targeting"
542+ def bidRequest = BidRequest . defaultBidRequest. tap {
543+ it. enableCache()
544+ }
545+
546+ when : " PBS processes auction request"
547+ def bidResponse = pbsService. sendAuctionRequest(bidRequest)
548+
549+ then : " PBS should call PBC"
550+ assert prebidCache. getRequestCount(bidRequest. imp[0 ]. id) == 0
551+
552+ and : " Seat bid shouldn't be discarded"
553+ assert ! bidResponse. seatbid. isEmpty()
554+
555+ and : " Bid response targeting should contain value"
556+ assert bidResponse. seatbid[0 ]. bid[0 ]. ext. prebid. targeting. findAll { it. key. startsWith(" hb_cache" ) }. isEmpty()
557+
558+ and : " Debug should contain http call with empty response body"
559+ def cacheCall = bidResponse. ext. debug. httpcalls[' cache' ][0 ]
560+ assert cacheCall. responseBody == null
561+ assert cacheCall. uri == " ${ HTTP_SCHEME} ://${ networkServiceContainer.hostAndPort + INTERNAL_CACHE_PATH} "
562+
563+ then : " Response should contain error"
564+ assert bidResponse. ext?. errors[CACHE ]* . code == [999 ]
565+ assert bidResponse. ext?. errors[CACHE ]* . message[0 ] == (" Failed to resolve '${ CACHE_HOST.tokenize(":")[0]} ' [A(1)]" )
566+
567+ cleanup : " Stop and remove pbs container"
568+ pbsServiceFactory. removeContainer(INVALID_PREBID_CACHE_CONFIG )
569+ }
570+
571+ def " PBS should cache bids when targeting is specified and config cache is invalid and internal cache config valid" () {
572+ given : " Pbs config with cache"
573+ def INVALID_PREBID_CACHE_CONFIG = [" cache.path" : CACHE_PATH ,
574+ " cache.scheme" : HTTPS_SCHEME ,
575+ " cache.host" : CACHE_HOST ,]
576+ def VALID_INTERNAL_CACHE_CONFIG = [" cache.internal.scheme" : HTTP_SCHEME ,
577+ " cache.internal.host" : " $networkServiceContainer . hostAndPort " . toString(),
578+ " cache.internal.path" : INTERNAL_CACHE_PATH ,]
579+ def pbsService = pbsServiceFactory. getService(INVALID_PREBID_CACHE_CONFIG + VALID_INTERNAL_CACHE_CONFIG )
580+
581+ and : " Default BidRequest with cache, targeting"
582+ def bidRequest = BidRequest . defaultBidRequest. tap {
583+ it. enableCache()
584+ }
585+
586+ when : " PBS processes auction request"
587+ def bidResponse = pbsService. sendAuctionRequest(bidRequest)
588+
589+ then : " PBS shouldn't call PBC"
590+ assert prebidCache. getRequestCount(bidRequest. imp[0 ]. id) == 1
591+
592+ and : " Bid response targeting should contain value"
593+ verifyAll (bidResponse?. seatbid[0 ]?. bid[0 ]?. ext?. prebid?. targeting as Map ) {
594+ it. get(" hb_cache_id" )
595+ it. get(" hb_cache_id_generic" )
596+ it. get(" hb_cache_path" ) == CACHE_PATH
597+ it. get(" hb_cache_host" ) == CACHE_HOST
598+ it. get(" hb_cache_path_generic" . substring(0 , TARGETING_PARAM_NAME_MAX_LENGTH )) == CACHE_PATH
599+ it. get(" hb_cache_host_generic" . substring(0 , TARGETING_PARAM_NAME_MAX_LENGTH )) == CACHE_HOST
600+ }
601+
602+ and : " Debug should contain http call"
603+ assert bidResponse. ext. debug. httpcalls[' cache' ][0 ]. uri ==
604+ " ${ HTTPS_SCHEME} ://${ CACHE_HOST + CACHE_PATH} "
605+
606+ cleanup : " Stop and remove pbs container"
607+ pbsServiceFactory. removeContainer(INVALID_PREBID_CACHE_CONFIG + VALID_INTERNAL_CACHE_CONFIG )
608+ }
609+
610+ def " PBS should cache bids when targeting is specified and config cache and internal cache config valid" () {
611+ given : " Pbs config with cache"
612+ def VALID_INTERNAL_CACHE_CONFIG = [" cache.internal.scheme" : HTTP_SCHEME ,
613+ " cache.internal.host" : " $networkServiceContainer . hostAndPort " . toString(),
614+ " cache.internal.path" : INTERNAL_CACHE_PATH ]
615+ def pbsService = pbsServiceFactory. getService(VALID_INTERNAL_CACHE_CONFIG )
616+
617+ and : " Default BidRequest with cache, targeting"
618+ def bidRequest = BidRequest . defaultBidRequest. tap {
619+ it. enableCache()
620+ }
621+
622+ when : " PBS processes auction request"
623+ def bidResponse = pbsService. sendAuctionRequest(bidRequest)
624+
625+ then : " PBS should call PBC"
626+ assert prebidCache. getRequestCount(bidRequest. imp[0 ]. id) == 1
627+
628+ and : " Bid response targeting should contain value"
629+ verifyAll (bidResponse. seatbid[0 ]. bid[0 ]. ext. prebid. targeting) {
630+ it. get(" hb_cache_id" )
631+ it. get(" hb_cache_id_generic" )
632+ it. get(" hb_cache_path" ) == INTERNAL_CACHE_PATH
633+ it. get(" hb_cache_host" ) == networkServiceContainer. hostAndPort. toString()
634+ it. get(" hb_cache_path_generic" . substring(0 , TARGETING_PARAM_NAME_MAX_LENGTH )) == INTERNAL_CACHE_PATH
635+ it. get(" hb_cache_host_generic" . substring(0 , TARGETING_PARAM_NAME_MAX_LENGTH )) == networkServiceContainer. hostAndPort. toString()
636+ }
637+
638+ and : " Debug should contain http call"
639+ assert bidResponse. ext. debug. httpcalls[' cache' ][0 ]. uri ==
640+ " ${ HTTP_SCHEME} ://${ networkServiceContainer.hostAndPort + INTERNAL_CACHE_PATH} "
641+
642+ cleanup : " Stop and remove pbs container"
643+ pbsServiceFactory. removeContainer(VALID_INTERNAL_CACHE_CONFIG )
644+ }
495645}
0 commit comments