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..9e54f4ce7e6 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 @@ -34,6 +34,7 @@ class VendorListResponse { List features List specialFeatures String policyUrl + ZonedDateTime deletedDate Overflow overflow String cookieMaxAgeSeconds Boolean usesCookies @@ -41,9 +42,9 @@ class VendorListResponse { Boolean usesNonCookieAccess Boolean deviceStorageDisclosureUrl - static Vendor getDefaultVendor(int id) { + static Vendor getDefaultVendor(int vendorId) { new Vendor().tap { - it.id = id + it.id = vendorId it.name = PBSUtils.randomString it.purposes = [1, 3, 4, 5] it.legIntPurposes = [2, 7, 10] diff --git a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/VendorList.groovy b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/VendorList.groovy index 343a118f53a..9e079f0bc02 100644 --- a/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/VendorList.groovy +++ b/src/test/groovy/org/prebid/server/functional/testcontainers/scaffolding/VendorList.groovy @@ -4,7 +4,7 @@ import org.mockserver.matchers.TimeToLive import org.mockserver.matchers.Times import org.mockserver.model.Delay import org.mockserver.model.HttpRequest -import org.mockserver.model.HttpResponse +import org.prebid.server.functional.util.privacy.TcfConsent import org.testcontainers.containers.MockServerContainer import static org.mockserver.model.HttpRequest.request @@ -20,10 +20,13 @@ import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVers class VendorList extends NetworkScaffolding { - private static final String VENDOR_LIST_ENDPOINT = "/v{TCF_POLICY}/vendor-list.json" + private static final String ENDPOINT_TEMPLATE = "/v{TCF_POLICY}/{FILE_NAME}" - VendorList(MockServerContainer mockServerContainer) { - super(mockServerContainer, VENDOR_LIST_ENDPOINT) + private final String fileName + + VendorList(MockServerContainer mockServerContainer, String fileName = "vendor-list.json") { + super(mockServerContainer, ENDPOINT_TEMPLATE.replace("{FILE_NAME}", fileName)) + this.fileName = fileName } @Override @@ -33,29 +36,39 @@ class VendorList extends NetworkScaffolding { @Override protected HttpRequest getRequest() { - request().withPath(VENDOR_LIST_ENDPOINT) + request().withPath(endpoint) } @Override void reset() { - TcfPolicyVersion.values().each { version -> super.reset("/v${version.vendorListVersion}/vendor-list.json") } + TcfPolicyVersion.values().each { + super.reset("/v${it.vendorListVersion}/${fileName}") + } } void setResponse(TcfPolicyVersion tcfPolicyVersion = TCF_POLICY_V2, Delay delay = null, - Map vendors = [(GENERIC_VENDOR_ID): Vendor.getDefaultVendor(GENERIC_VENDOR_ID)]) { + Map vendors = [(GENERIC_VENDOR_ID): Vendor.getDefaultVendor(GENERIC_VENDOR_ID)], + vendorListVersion = TcfConsent.VENDOR_LIST_VERSION) { + def prepareEndpoint = endpoint.replace("{TCF_POLICY}", tcfPolicyVersion.vendorListVersion.toString()) def prepareEncodeResponseBody = encode(defaultVendorListResponse.tap { it.tcfPolicyVersion = tcfPolicyVersion.vendorListVersion it.vendors = vendors + it.vendorListVersion = vendorListVersion it.gvlSpecificationVersion = tcfPolicyVersion >= TcfPolicyVersion.TCF_POLICY_V4 ? V3 : V2 }) - mockServerClient.when(request().withPath(prepareEndpoint), Times.unlimited(), TimeToLive.unlimited(), -10) - .respond { request -> - request.withPath(endpoint) - ? response().withStatusCode(OK_200.code()).withDelay(delay).withBody(prepareEncodeResponseBody) - : HttpResponse.notFoundResponse() - } + def mockResponse = response() + .withStatusCode(OK_200.code()) + .withBody(prepareEncodeResponseBody) + + if (delay != null) { + mockResponse.withDelay(delay) + } + + mockServerClient + .when(request().withPath(prepareEndpoint), Times.unlimited(), TimeToLive.unlimited(), -10) + .respond(mockResponse) } } 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 d92bec507cc..a0557a55202 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 @@ -8,10 +8,8 @@ import org.prebid.server.functional.model.config.AccountDsaConfig import org.prebid.server.functional.model.config.AccountGdprConfig import org.prebid.server.functional.model.config.AccountGppConfig import org.prebid.server.functional.model.config.AccountPrivacyConfig -import org.prebid.server.functional.model.config.Purpose import org.prebid.server.functional.model.db.Account import org.prebid.server.functional.model.mock.services.vendorlist.VendorListResponse -import org.prebid.server.functional.model.privacy.EnforcementRequirement import org.prebid.server.functional.model.privacy.gpp.GppDataActivity import org.prebid.server.functional.model.privacy.gpp.UsCaliforniaV1ChildSensitiveData import org.prebid.server.functional.model.privacy.gpp.UsCaliforniaV1SensitiveData @@ -55,12 +53,9 @@ import org.prebid.server.functional.util.privacy.gpp.v1.UsVaV1Consent 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.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 @@ -74,10 +69,6 @@ import static org.prebid.server.functional.model.request.auction.TraceLevel.VERB import static org.prebid.server.functional.model.response.cookiesync.UserSyncInfo.Type.REDIRECT import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer import static org.prebid.server.functional.util.privacy.TcfConsent.GENERIC_VENDOR_ID -import static org.prebid.server.functional.util.privacy.TcfConsent.PurposeId.BASIC_ADS -import static org.prebid.server.functional.util.privacy.TcfConsent.RestrictionType.REQUIRE_CONSENT -import static org.prebid.server.functional.util.privacy.TcfConsent.RestrictionType.REQUIRE_LEGITIMATE_INTEREST -import static org.prebid.server.functional.util.privacy.TcfConsent.RestrictionType.UNDEFINED import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVersion.TCF_POLICY_V2 import static org.prebid.server.functional.util.privacy.model.State.ALABAMA @@ -90,7 +81,7 @@ abstract class PrivacyBaseSpec extends BaseSpec { "adapters.${GENERIC.value}.ortb-version" : "2.6"] private static final Map OPENX_CONFIG = ["adaptrs.${OPENX.value}.enabled" : "true", "adapters.${OPENX.value}.usersync.cookie-family-name": OPENX.value, - "adapters.${OPENX}.ortb-version" : "2.6", + "adapters.${OPENX.value}.ortb-version" : "2.6", "adapters.${OPENX.value}.endpoint" : "$networkServiceContainer.rootUri/auction".toString(), "adapters.${OPENX.value}.enabled" : 'true'] protected static final Map GDPR_VENDOR_LIST_CONFIG = ["gdpr.vendorlist.v2.http-endpoint-template": "$networkServiceContainer.rootUri/v2/vendor-list.json".toString(), diff --git a/src/test/groovy/org/prebid/server/functional/tests/privacy/gdpr/GdprAuctionSpec.groovy b/src/test/groovy/org/prebid/server/functional/tests/privacy/gdpr/GdprAuctionSpec.groovy index d90bf8da9ac..68942f587ee 100644 --- a/src/test/groovy/org/prebid/server/functional/tests/privacy/gdpr/GdprAuctionSpec.groovy +++ b/src/test/groovy/org/prebid/server/functional/tests/privacy/gdpr/GdprAuctionSpec.groovy @@ -7,28 +7,35 @@ import org.prebid.server.functional.model.config.AccountMetricsConfig import org.prebid.server.functional.model.config.AccountMetricsVerbosityLevel import org.prebid.server.functional.model.config.PurposeConfig import org.prebid.server.functional.model.config.PurposeEnforcement +import org.prebid.server.functional.model.mock.services.vendorlist.VendorListResponse import org.prebid.server.functional.model.pricefloors.Country +import org.prebid.server.functional.model.privacy.EnforcementRequirement 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.auction.ErrorType +import org.prebid.server.functional.model.response.auction.NoBidResponse +import org.prebid.server.functional.service.PrebidServerService +import org.prebid.server.functional.testcontainers.scaffolding.VendorList import org.prebid.server.functional.tests.privacy.PrivacyBaseSpec import org.prebid.server.functional.util.PBSUtils import org.prebid.server.functional.util.privacy.BogusConsent import org.prebid.server.functional.util.privacy.TcfConsent +import org.prebid.server.functional.util.privacy.TcfUtils import org.prebid.server.functional.util.privacy.VendorListConsent import spock.lang.PendingFeature import java.time.Instant +import java.time.ZonedDateTime 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 import static org.prebid.server.functional.model.config.Purpose.P4 +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.GvlSpecificationVersion.V3 import static org.prebid.server.functional.model.pricefloors.Country.BULGARIA @@ -46,15 +53,33 @@ import static org.prebid.server.functional.model.request.auction.PublicCountryIp import static org.prebid.server.functional.model.request.auction.TraceLevel.BASIC import static org.prebid.server.functional.model.request.auction.TraceLevel.VERBOSE import static org.prebid.server.functional.model.response.auction.BidRejectionReason.REQUEST_BLOCKED_PRIVACY +import static org.prebid.server.functional.testcontainers.Dependencies.getNetworkServiceContainer import static org.prebid.server.functional.util.privacy.TcfConsent.GENERIC_VENDOR_ID import static org.prebid.server.functional.util.privacy.TcfConsent.PurposeId.BASIC_ADS import static org.prebid.server.functional.util.privacy.TcfConsent.PurposeId.DEVICE_ACCESS +import static org.prebid.server.functional.util.privacy.TcfConsent.RestrictionType.REQUIRE_CONSENT +import static org.prebid.server.functional.util.privacy.TcfConsent.RestrictionType.UNDEFINED import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVersion.TCF_POLICY_V2 import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVersion.TCF_POLICY_V4 import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVersion.TCF_POLICY_V5 class GdprAuctionSpec extends PrivacyBaseSpec { + private static final String LIVE_GVL_FILE_NAME = "live-gvl-vendor-list.json" + private static final VENDOR_LIST_VERSION = PBSUtils.getRandomNumber(2, 4094) + private static final Map REFRESH_LIVE_VENDOR_LIST_CONFIG = GENERAL_PRIVACY_CONFIG + + ["gdpr.vendorlist.live-gvl-url": "$networkServiceContainer.rootUri/v3/$LIVE_GVL_FILE_NAME".toString()] + private static final VendorList liveVendorListResponse = new VendorList(networkServiceContainer, LIVE_GVL_FILE_NAME) + + def setup() { + vendorListResponse.setResponse() + liveVendorListResponse.reset() + } + + def cleanup() { + vendorListResponse.reset() + } + @PendingFeature def "PBS should add debug log for auction request when valid gdpr was passed"() { given: "Default gdpr BidRequest" @@ -1116,4 +1141,271 @@ class GdprAuctionSpec extends PrivacyBaseSpec { assert metrics["adapter.${GENERIC.value}.requests.buyeruid_scrubbed"] == 1 assert metrics["account.${account.uuid}.adapter.${GENERIC.value}.requests.buyeruid_scrubbed"] == 1 } + + def "PBS should treated GVL record as valid when it's don't marked as deleted for GVL file"() { + given: "Vendor list response with not passed delete date for bidder" + def vendorList = VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID).tap { + deletedDate = gvlDeletedDate + } + downloadGvtList(VENDOR_LIST_VERSION, [(GENERIC_VENDOR_ID): vendorList]) + + and: "PBS with proper warmed GVL config" + def pbsWithLiveGvlSetup = pbsServiceFactory.getService(REFRESH_LIVE_VENDOR_LIST_CONFIG) + warmupGvtList(pbsWithLiveGvlSetup, VENDOR_LIST_VERSION) + + and: "Valid tcf full enforcement requirments" + def requirement = new EnforcementRequirement(purpose: P2, + restrictionType: [REQUIRE_CONSENT, UNDEFINED], + vendorIdGvl: GENERIC_VENDOR_ID, + enforcePurpose: FULL, + vendorConsentBitField: GENERIC_VENDOR_ID, + enforceVendor: true, + disclosedVendorsId: [GENERIC_VENDOR_ID], + vendorListVersion: VENDOR_LIST_VERSION) + + and: "Tcf consent setup" + def tcfConsent = TcfUtils.getConsentString(requirement) + + and: "Bid request with tcf consent string" + def bidRequest = getGdprBidRequest(tcfConsent) + + and: "Account with tcf config" + def accountGdprConfig = new AccountGdprConfig(purposes: TcfUtils.getPurposeConfigsForPersonalizedAds(requirement)) + def account = getAccountWithGdpr(bidRequest.accountId, accountGdprConfig) + accountDao.save(account) + + and: "Flush metric" + flushMetrics(pbsWithLiveGvlSetup) + + when: "PBS processes auction request" + def response = pbsWithLiveGvlSetup.sendAuctionRequest(bidRequest) + + then: "Response should contain seatBid" + assert response.seatbid.bid.flatten().size() == 1 + + "Response shouldn't contain any nrb, errors and warnings" + assert verifyAll(response) { + !it.noBidResponse + !it.ext.warnings + !it.ext.errors + } + + and: "Bidder request should be valid" + assert bidder.getBidderRequests(bidRequest.id) + + and: "Disallowed metrics shouldn't be updated" + def metrics = pbsWithLiveGvlSetup.sendCollectedMetricsRequest() + assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(bidRequest, FETCH_BIDS)] == 0 + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(REFRESH_LIVE_VENDOR_LIST_CONFIG) + + where: + gvlDeletedDate << [null, ZonedDateTime.now().plusYears(1)] + } + + def "PBS should treated GVL record as invalid when it's marked as deleted for GVL file"() { + given: "Vendor list response with passed delete date for bidder" + def vendorList = VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID).tap { + deletedDate = ZonedDateTime.now().minusSeconds(1) + } + downloadGvtList(VENDOR_LIST_VERSION, [(GENERIC_VENDOR_ID): vendorList]) + + and: "PBS with proper warmed GVL config" + def pbsWithLiveGvlSetup = pbsServiceFactory.getService(REFRESH_LIVE_VENDOR_LIST_CONFIG) + warmupGvtList(pbsWithLiveGvlSetup, VENDOR_LIST_VERSION) + + and: "Valid tcf full enforcement requirments" + def requirement = new EnforcementRequirement(purpose: P2, + restrictionType: [REQUIRE_CONSENT, UNDEFINED], + vendorIdGvl: GENERIC_VENDOR_ID, + enforcePurpose: FULL, + vendorConsentBitField: GENERIC_VENDOR_ID, + enforceVendor: true, + disclosedVendorsId: [GENERIC_VENDOR_ID], + vendorListVersion: VENDOR_LIST_VERSION) + + and: "Tcf consent setup" + def tcfConsent = TcfUtils.getConsentString(requirement) + + and: "Bid request with tcf consent string" + def bidRequest = getGdprBidRequest(tcfConsent) + + and: "Account with tcf config" + def accountGdprConfig = new AccountGdprConfig(purposes: TcfUtils.getPurposeConfigsForPersonalizedAds(requirement)) + def account = getAccountWithGdpr(bidRequest.accountId, accountGdprConfig) + accountDao.save(account) + + and: "Flush metric" + flushMetrics(pbsWithLiveGvlSetup) + + when: "PBS processes auction request" + def response = pbsWithLiveGvlSetup.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain any seatBids, errors and warnings" + assert verifyAll(response) { + !it.seatbid.size() + !it.ext.warnings + !it.ext.errors + } + + and: "Response should include nbr" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + + and: "PBS should cansel request" + assert !bidder.getBidderRequests(bidRequest.id) + + and: "Disallowed metrics should be updated" + def metrics = pbsWithLiveGvlSetup.sendCollectedMetricsRequest() + assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(bidRequest, FETCH_BIDS)] == 1 + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(REFRESH_LIVE_VENDOR_LIST_CONFIG) + } + + def "PBS should treated GVL record as invalid when it's marked as deleted for newer GVL file"() { + given: "Newer Vendor list response with passed delete date for bidder" + def vendorList = VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID).tap { + deletedDate = ZonedDateTime.now().minusSeconds(1) + } + downloadGvtList(VENDOR_LIST_VERSION, [(GENERIC_VENDOR_ID): vendorList]) + + and: "PBS with proper warmed older GVL config" + def pbsWithLiveGvlSetup = pbsServiceFactory.getService(REFRESH_LIVE_VENDOR_LIST_CONFIG) + warmupGvtList(pbsWithLiveGvlSetup, VENDOR_LIST_VERSION - 1) + + and: "Valid tcf full enforcement requirments for older gvl list" + def requirement = new EnforcementRequirement(purpose: P2, + restrictionType: [REQUIRE_CONSENT, UNDEFINED], + vendorIdGvl: GENERIC_VENDOR_ID, + enforcePurpose: FULL, + vendorConsentBitField: GENERIC_VENDOR_ID, + enforceVendor: true, + disclosedVendorsId: [GENERIC_VENDOR_ID], + vendorListVersion: VENDOR_LIST_VERSION - 1) + + and: "Tcf consent setup" + def tcfConsent = TcfUtils.getConsentString(requirement) + + and: "Bid request with tcf consent string" + def bidRequest = getGdprBidRequest(tcfConsent) + + and: "Account with tcf config" + def accountGdprConfig = new AccountGdprConfig(purposes: TcfUtils.getPurposeConfigsForPersonalizedAds(requirement)) + def account = getAccountWithGdpr(bidRequest.accountId, accountGdprConfig) + accountDao.save(account) + + and: "Flush metric" + flushMetrics(pbsWithLiveGvlSetup) + + when: "PBS processes auction request" + def response = pbsWithLiveGvlSetup.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain any seatBids, errors and warnings" + assert verifyAll(response) { + !it.seatbid.size() + !it.ext.warnings + !it.ext.errors + } + + and: "Response should include nbr" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + + and: "PBS should cansel request" + assert !bidder.getBidderRequests(bidRequest.id) + + and: "Disallowed metrics should be updated" + def metrics = pbsWithLiveGvlSetup.sendCollectedMetricsRequest() + assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(bidRequest, FETCH_BIDS)] == 1 + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(REFRESH_LIVE_VENDOR_LIST_CONFIG) + } + + def "PBS should treated GVL record as invalid when it's marked as deleted for older GVL file"() { + given: "Old vendor list response with passed delete date for bidder" + def olderVendorList = VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID).tap { + deletedDate = ZonedDateTime.now().minusSeconds(1) + } + downloadGvtList(VENDOR_LIST_VERSION - 1, [(GENERIC_VENDOR_ID): olderVendorList]) + + and: "PBS with a high-frequency live GVL refresh config" + def config = REFRESH_LIVE_VENDOR_LIST_CONFIG + ['gdpr.vendorlist.live-gvl-refresh-period-ms': '1000'] + def pbsWithLiveGvlSetup = pbsServiceFactory.getService(config) + + and: "Newer vendor list where the bidder is not deleted yet" + def newerVendorList = VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID).tap { + deletedDate = ZonedDateTime.now().plusYears(1) + } + downloadGvtList(VENDOR_LIST_VERSION, [(GENERIC_VENDOR_ID): newerVendorList]) + + and: "GVL list is warmed up for PBS" + warmupGvtList(pbsWithLiveGvlSetup, VENDOR_LIST_VERSION) + + and: "Valid tcf full enforcement requirments for older GVL list" + def requirement = new EnforcementRequirement(purpose: P2, + restrictionType: [REQUIRE_CONSENT, UNDEFINED], + vendorIdGvl: GENERIC_VENDOR_ID, + enforcePurpose: FULL, + vendorConsentBitField: GENERIC_VENDOR_ID, + enforceVendor: true, + disclosedVendorsId: [GENERIC_VENDOR_ID], + vendorListVersion: VENDOR_LIST_VERSION) + + and: "Tcf consent setup" + def tcfConsent = TcfUtils.getConsentString(requirement) + + and: "Bid request with tcf consent string" + def bidRequest = getGdprBidRequest(tcfConsent) + + and: "Account with tcf config" + def accountGdprConfig = new AccountGdprConfig(purposes: TcfUtils.getPurposeConfigsForPersonalizedAds(requirement)) + def account = getAccountWithGdpr(bidRequest.accountId, accountGdprConfig) + accountDao.save(account) + + and: "Flush metric" + flushMetrics(pbsWithLiveGvlSetup) + + when: "PBS processes auction request" + def response = pbsWithLiveGvlSetup.sendAuctionRequest(bidRequest) + + then: "Response shouldn't contain any seatBids, errors and warnings" + assert verifyAll(response) { + !it.seatbid.size() + !it.ext.warnings + !it.ext.errors + } + + and: "Response should include nbr" + assert response.noBidResponse == NoBidResponse.UNKNOWN_ERROR + + and: "PBS should cansel request" + assert !bidder.getBidderRequests(bidRequest.id) + + and: "Disallowed metrics should be updated" + def metrics = pbsWithLiveGvlSetup.sendCollectedMetricsRequest() + assert metrics[TEMPLATE_ADAPTER_DISALLOWED_COUNT.getValue(bidRequest, FETCH_BIDS)] == 1 + + cleanup: "Stop and remove pbs container" + pbsServiceFactory.removeContainer(config) + } + + private static void downloadGvtList( + Integer vendorListVersion = VENDOR_LIST_VERSION, + Map vendors = [(GENERIC_VENDOR_ID): VendorListResponse.Vendor.getDefaultVendor(GENERIC_VENDOR_ID)], + TcfConsent.TcfPolicyVersion tcfPolicyVersion = TCF_POLICY_V5) { + + liveVendorListResponse.reset() + liveVendorListResponse.setResponse(tcfPolicyVersion, null, vendors, vendorListVersion) + } + + private static void warmupGvtList(PrebidServerService pbsService, Integer vendorListVersion = VENDOR_LIST_VERSION) { + def simpleTcfString = new TcfConsent.Builder() + .setDisclosedVendors([GENERIC_VENDOR_ID]) + .setVendorListVersion(vendorListVersion) + .build() + def bidRequest = getGdprBidRequest(simpleTcfString) + pbsService.sendAuctionRequest(bidRequest) + + } } diff --git a/src/test/groovy/org/prebid/server/functional/util/privacy/TcfConsent.groovy b/src/test/groovy/org/prebid/server/functional/util/privacy/TcfConsent.groovy index 56953549575..7a64c22b3df 100644 --- a/src/test/groovy/org/prebid/server/functional/util/privacy/TcfConsent.groovy +++ b/src/test/groovy/org/prebid/server/functional/util/privacy/TcfConsent.groovy @@ -12,9 +12,9 @@ import static org.prebid.server.functional.util.privacy.TcfConsent.TcfPolicyVers class TcfConsent implements ConsentString { - public static final Integer RUBICON_VENDOR_ID = PBSUtils.getRandomNumber(0, 65534) - public static final Integer GENERIC_VENDOR_ID = PBSUtils.getRandomNumber(0, 65534) - public static final Integer VENDOR_LIST_VERSION = PBSUtils.getRandomNumber(0, 4095) + public static final Integer RUBICON_VENDOR_ID = PBSUtils.getRandomNumber(1, 65534) + public static final Integer GENERIC_VENDOR_ID = PBSUtils.getRandomNumber(1, 65534) + public static final Integer VENDOR_LIST_VERSION = PBSUtils.getRandomNumber(1, 4095) private final TCStringEncoder.Builder tcStringEncoder