From 4ac71e69521206dd88f5da4ea12371701f020ed8 Mon Sep 17 00:00:00 2001 From: Matt Menke Date: Mon, 14 Aug 2023 17:20:47 +0000 Subject: [PATCH] Bug 1847834 [wpt PR 41389] - [FLEDGE]: Add trustedScoringSignalsUrl WPT tests., a=testonly Automatic update from web-platform-tests [FLEDGE]: Add trustedScoringSignalsUrl WPT tests. This doesn't test the prioritization vector or componentRenderUrl fields, which we'll add tests for when we test those specific features. Bug: 1425952 Change-Id: Ida3ce4d22dfe52a72cabfaeda90e77845142ef79 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4762089 Reviewed-by: Maks Orlovich Commit-Queue: Matt Menke Cr-Commit-Position: refs/heads/main@{#1181551} -- wpt-commits: 7a48bbd4ed7425a3981f607d0f4ed2b7d9069b63 wpt-pr: 41389 --- testing/web-platform/tests/fledge/tentative/TODO | 3 +- .../fledge/tentative/resources/fledge-util.js | 26 +- .../tentative/resources/trusted-scoring-signals.py | 127 +++++++ .../trusted-scoring-signals.https.sub.window.js | 409 +++++++++++++++++++++ 4 files changed, 553 insertions(+), 12 deletions(-) create mode 100644 testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py create mode 100644 testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.sub.window.js diff --git a/testing/web-platform/tests/fledge/tentative/TODO b/testing/web-platform/tests/fledge/tentative/TODO index 96654d2c592e..fc2c296762ce 100644 --- a/testing/web-platform/tests/fledge/tentative/TODO +++ b/testing/web-platform/tests/fledge/tentative/TODO @@ -18,8 +18,7 @@ Need tests for (likely not a complete list): loading URNs in fencedframes in other frames, loading component ad URNs in fenced frames of other frames, etc) * adAuctionConfig passed to reportResult(). -* trusted scoring signals. -* Component ads. +* Component ads (including scoring signals fetches). * Component auctions. * browserSignals fields in scoring/bidding methods. * In reporting methods, browserSignals fields: dataVersion, topLevelSeller, diff --git a/testing/web-platform/tests/fledge/tentative/resources/fledge-util.js b/testing/web-platform/tests/fledge/tentative/resources/fledge-util.js index 7fef79c85e80..f941d2285d2d 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/fledge-util.js +++ b/testing/web-platform/tests/fledge/tentative/resources/fledge-util.js @@ -6,12 +6,15 @@ const BASE_PATH = (new URL(BASE_URL)).pathname; const DEFAULT_INTEREST_GROUP_NAME = 'default name'; -// Unlike other URLs, the trustedBiddingSignalsUrl can't have a query string -// that's set by tests, since FLEDGE controls it entirely, so tests that -// exercise it use a fixed URL string. Special keys and interest group names -// control the response. +// Unlike other URLs, trusted signals URLs can't have query strings +// that are set by tests, since FLEDGE controls it entirely, so tests that +// exercise them use a fixed URL string. Note that FLEDGE adds query +// params when requesting these URLs, and the python scripts use these +// to construct the response. const TRUSTED_BIDDING_SIGNALS_URL = `${BASE_URL}resources/trusted-bidding-signals.py`; +const TRUSTED_SCORING_SIGNALS_URL = + `${BASE_URL}resources/trusted-scoring-signals.py`; // Creates a URL that will be sent to the URL request tracker script. // `uuid` is used to identify the stash shard to use. @@ -159,11 +162,14 @@ function createDecisionScriptUrl(uuid, params = {}) { // Creates a renderUrl for an ad that runs the passed in "script". "uuid" has // no effect, beyond making the URL distinct between tests, and being verified // by the decision logic script before accepting a bid. "uuid" is expected to -// be last. -function createRenderUrl(uuid, script) { +// be last. "signalsParams" also has no effect, but is used by +// trusted-scoring-signals.py to affect the response. +function createRenderUrl(uuid, script, signalsParams) { let url = new URL(`${BASE_URL}resources/fenced-frame.sub.py`); if (script) url.searchParams.append('script', script); + if (signalsParams) + url.searchParams.append('signalsParams', signalsParams); url.searchParams.append('uuid', uuid); return url.toString(); } @@ -245,10 +251,10 @@ async function runBasicFledgeAuctionAndNavigate(test, uuid, } // Joins an interest group and runs an auction, expecting a winner to be -// returned. "testConfig" can optionally modify the interest group or +// returned. "testConfig" can optionally modify the uuid, interest group or // auctionConfig. async function runBasicFledgeTestExpectingWinner(test, testConfig = {}) { - const uuid = generateUuid(test); + const uuid = testConfig.uuid ? testConfig.uuid : generateUuid(test); await joinInterestGroup(test, uuid, testConfig.interestGroupOverrides); let config = await runBasicFledgeAuction( test, uuid, testConfig.auctionConfigOverrides); @@ -257,10 +263,10 @@ async function runBasicFledgeTestExpectingWinner(test, testConfig = {}) { } // Joins an interest group and runs an auction, expecting no winner to be -// returned. "testConfig" can optionally modify the interest group or +// returned. "testConfig" can optionally modify the uuid, interest group or // auctionConfig. async function runBasicFledgeTestExpectingNoWinner(test, testConfig = {}) { - const uuid = generateUuid(test); + const uuid = testConfig.uuid ? testConfig.uuid : generateUuid(test); await joinInterestGroup(test, uuid, testConfig.interestGroupOverrides); let result = await runBasicFledgeAuction( test, uuid, testConfig.auctionConfigOverrides); diff --git a/testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py b/testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py new file mode 100644 index 000000000000..6036d2ef4d12 --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py @@ -0,0 +1,127 @@ +import json +from urllib.parse import unquote_plus, urlparse + +# Script to generate trusted scoring signals. The responses depends on the +# query strings in the ads Urls - some result in entire response failures, +# others affect only their own value. Each renderUrl potentially has a +# signalsParam, which is a comma-delimited list of instructions that can +# each affect either the value associated with the renderUrl, or the +# response as a whole. +def main(request, response): + hostname = None + renderUrls = None + adComponentRenderUrls = None + + # Manually parse query params. Can't use request.GET because it unescapes as well as splitting, + # and commas mean very different things from escaped commas. + for param in request.url_parts.query.split("&"): + pair = param.split("=", 1) + if len(pair) != 2: + return fail(response, "Bad query parameter: " + param) + # Browsers should escape query params consistently. + if "%20" in pair[1]: + return fail(response, "Query parameter should escape using '+': " + param) + + # Hostname can't be empty. The empty string can be a key or interest group name, though. + if pair[0] == "hostname" and hostname == None and len(pair[1]) > 0: + hostname = pair[1] + continue + if pair[0] == "renderUrls" and renderUrls == None: + renderUrls = list(map(unquote_plus, pair[1].split(","))) + continue + if pair[0] == "adComponentRenderUrls" and adComponentRenderUrls == None: + adComponentRenderUrls = list(map(unquote_plus, pair[1].split(","))) + continue + return fail(response, "Unexpected query parameter: " + param) + + # "hostname" and "renderUrls" are mandatory. + if not hostname: + return fail(response, "hostname missing") + if not renderUrls: + return fail(response, "renderUrls missing") + + response.status = (200, b"OK") + + # The JSON representation of this is used as the response body. + responseBody = {"renderUrls": {}} + + # Set when certain special keys are observed, used in place of the JSON + # representation of `responseBody`, when set. + body = None + + contentType = "application/json" + adAuctionAllowed = "true" + dataVersion = None + if renderUrls: + for renderUrl in renderUrls: + value = "default value" + + signalsParams = None + for param in urlparse(renderUrl).query.split("&"): + pair = param.split("=", 1) + if len(pair) != 2: + continue + if pair[0] == "signalsParams": + if signalsParams != None: + return fail(response, "renderUrl has multiple signalsParams: " + renderUrl) + signalsParams = pair[1] + if signalsParams != None: + signalsParams = unquote_plus(signalsParams) + for signalsParam in signalsParams.split(","): + if signalsParam == "close-connection": + # Close connection without writing anything, to simulate a + # network error. The write call is needed to avoid writing the + # default headers. + response.writer.write("") + response.close_connection = True + return + elif signalsParam.startswith("replace-body:"): + # Replace entire response body. Continue to run through other + # renderUrls, to allow them to modify request headers. + body = signalsParam.split(':', 1)[1] + elif signalsParam.startswith("data-version:"): + dataVersion = signalsParam.split(':', 1)[1] + elif signalsParam == "http-error": + response.status = (404, b"Not found") + elif signalsParam == "no-content-type": + contentType = None + elif signalsParam == "wrong-content-type": + contentType = 'text/plain' + elif signalsParam == "bad-ad-auction-allowed": + adAuctionAllowed = "sometimes" + elif signalsParam == "ad-auction-not-allowed": + adAuctionAllowed = "false" + elif signalsParam == "no-ad-auction-allow": + adAuctionAllowed = None + elif signalsParam == "no-value": + continue + elif signalsParam == "null-value": + value = None + elif signalsParam == "num-value": + value = 1 + elif signalsParam == "string-value": + value = "1" + elif signalsParam == "array-value": + value = [1, "foo", None] + elif signalsParam == "object-value": + value = {"a":"b", "c":["d"]} + elif signalsParam == "hostname": + value = request.GET.first(b"hostname", b"not-found").decode("ASCII") + if value != None: + responseBody["renderUrls"][renderUrl] = value + + if contentType: + response.headers.set("Content-Type", contentType) + if adAuctionAllowed: + response.headers.set("Ad-Auction-Allowed", adAuctionAllowed) + if dataVersion: + response.headers.set("Data-Version", dataVersion) + + if body != None: + return body + return json.dumps(responseBody) + +def fail(response, body): + response.status = (400, "Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + return body diff --git a/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.sub.window.js b/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.sub.window.js new file mode 100644 index 000000000000..660ad0477bcf --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.sub.window.js @@ -0,0 +1,409 @@ +// META: script=/resources/testdriver.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.js +// META: timeout=long + +"use strict"; + +// These tests focus on trustedScoringSignals: Requesting them, handling network +// errors, handling the renderURLs portion of the response, passing renderURLs +// to worklet scripts, and handling the Data-Version header. + +// Helper for trusted scoring signals tests. Runs an auction with +// TRUSTED_SCORING_SIGNALS_URL and a single interest group, failing the test +// if there's no winner. "scoreAdCheck" is an expression that should be true +// when evaluated in scoreAd(). "renderURL" can be used to control the response +// given for TRUSTED_SCORING_SIGNALS_URL. +async function runTrustedScoringSignalsTest(test, uuid, renderURL, scoreAdCheck) { + const auctionConfigOverrides = { + trustedScoringSignalsUrl: TRUSTED_SCORING_SIGNALS_URL, + decisionLogicUrl: + createDecisionScriptUrl(uuid, { + scoreAd: `if (!(${scoreAdCheck})) throw "error";` })}; + await runBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {ads: [{renderUrl: renderURL}]}, + auctionConfigOverrides: auctionConfigOverrides + }); +} + +// Much like runTrustedScoringSignalsTest, but runs auctions through reporting +// as well, and evaluates `check` both in scodeAd() and reportResult(). Also +// makes sure browserSignals.dataVersion is undefined in generateBid() and +// reportWin(). +async function runTrustedScoringSignalsDataVersionTest( + test, uuid, renderURL, check) { + const interestGroupOverrides = { + biddingLogicUrl : + createBiddingScriptUrl({ + generateBid: + `if (browserSignals.dataVersion !== undefined) + throw "Bad browserSignals.dataVersion"`, + reportWin: + `if (browserSignals.dataVersion !== undefined) + sendReportTo('${createSellerReportUrl(uuid, 'error')}'); + else + sendReportTo('${createSellerReportUrl(uuid)}');` }), + ads: [{renderUrl: renderURL}]}; + await joinInterestGroup(test, uuid, interestGroupOverrides); + + const auctionConfigOverrides = { + decisionLogicUrl: createDecisionScriptUrl( + uuid, + { scoreAd: + `if (!(${check})) return false;`, + reportResult: + `if (!(${check})) + sendReportTo('${createSellerReportUrl(uuid, 'error')}') + sendReportTo('${createSellerReportUrl(uuid)}')`, + }), + trustedScoringSignalsUrl: TRUSTED_SCORING_SIGNALS_URL + } + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + await waitForObservedRequests( + uuid, [createBidderReportUrl(uuid), createSellerReportUrl(uuid)]); +} + +// Creates a render URL that, when sent to the trusted-scoring-signals.py, +// results in a trusted scoring signals response with the provided response +// body. +function createScoringSignalsRenderUrlWithBody(uuid, responseBody) { + return createRenderUrl(uuid, /*script=*/null, + /*signalsParam=*/`replace-body:${responseBody}`); +} + +///////////////////////////////////////////////////////////////////////////// +// Tests where no renderURL value is received for the passed in renderURL. +///////////////////////////////////////////////////////////////////////////// + +promise_test(async test => { + const uuid = generateUuid(test); + const decsionLogicScriptUrl = createDecisionScriptUrl( + uuid, + { scoreAd: 'if (trustedScoringSignals !== null) throw "error";'}); + await runBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + auctionConfigOverrides: { decisionLogicUrl: decsionLogicScriptUrl } + }); +}, 'No trustedScoringSignalsUrl.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'close-connection'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'trustedScoringSignals === null'); +}, 'Trusted scoring signals closes the connection without sending anything.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'http-error'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response is HTTP 404 error.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'no-content-type'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response has no content-type.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'wrong-content-type'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response has wrong content-type.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'ad-auction-not-allowed'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response does not allow FLEDGE.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'bad-ad-auction-allowed'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response has wrong Ad-Auction-Allowed header.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'no-ad-auction-allow'); + await runTrustedScoringSignalsTest( test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response has no Ad-Auction-Allowed header.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/''); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response has no body.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'Not JSON'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response is not JSON.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'[]'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response is a JSON array.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'{JSON_keys_need_quotes: 1}'); + await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); +}, 'Trusted scoring signals response is invalid JSON object.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'{}'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === null`); +}, 'Trusted scoring signals response has no renderUrl object.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'{"renderUrls":{}}'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === null`); +}, 'Trusted scoring signals response has no renderUrls.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createScoringSignalsRenderUrlWithBody( + uuid, /*responseBody=*/'{"renderUrls":{"https://wrong-url.test": 5}}'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === null && + trustedScoringSignals["https://wrong-url.test/"] === undefined`); +}, 'Trusted scoring signals response has renderURL not in response.'); + +///////////////////////////////////////////////////////////////////////////// +// Tests where renderURL value is received for the passed in renderURL. +///////////////////////////////////////////////////////////////////////////// + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'null-value'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === null`); +}, 'Trusted scoring signals response has null value for renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'num-value'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === 1`); +}, 'Trusted scoring signals response has a number value for renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, + /*signalsParam=*/'string-value'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === "1"`); +}, 'Trusted scoring signals response has a string value for renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'array-value'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `JSON.stringify(trustedScoringSignals.renderURL["${renderURL}"]) === '[1,"foo",null]'`); +}, 'Trusted scoring signals response has an array value for renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'object-value'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `Object.keys(trustedScoringSignals.renderURL["${renderURL}"]).length === 2 && + trustedScoringSignals.renderURL["${renderURL}"]["a"] === "b" && + JSON.stringify(trustedScoringSignals.renderURL["${renderURL}"]["c"]) === '["d"]'`); +}, 'Trusted scoring signals response has an object value for renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'+%20 \x00?,3#&'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === "default value"`); +}, 'Trusted scoring signals with escaped renderURL.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'hostname'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + `trustedScoringSignals.renderURL["${renderURL}"] === "${window.location.hostname}"`); +}, 'Trusted scoring signals receives hostname field.'); + +// Joins two interest groups and makes sure the scoring signals for one are never leaked +// to the seller script when scoring the other. +// +// There's no guarantee in this test that a single request to the server will be made with +// render URLs from two different IGs, though that's the case this is trying to test - +// browsers are not required to support batching, and even if they do, joining any two +// particular requests may be racy. +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL1 = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'num-value'); + const renderURL2 = createRenderUrl(uuid, /*script=*/null, /*signalsParam=*/'string-value'); + await joinInterestGroup(test, uuid, {ads: [{renderUrl: renderURL1}], name: '1'}); + await joinInterestGroup(test, uuid, {ads: [{renderUrl: renderURL2}], name: '2'}); + let auctionConfigOverrides = { trustedScoringSignalsUrl: TRUSTED_SCORING_SIGNALS_URL }; + + // scoreAd() only accepts the first IG's bid, validating its trustedScoringSignals. + auctionConfigOverrides.decisionLogicUrl = + createDecisionScriptUrl(uuid, { + scoreAd: `if (browserSignals.renderURL === "${renderURL1}" && + trustedScoringSignals.renderURL["${renderURL1}"] !== 1 || + trustedScoringSignals.renderURL["${renderURL2}"] !== undefined) + return;` }); + let config = await runBasicFledgeAuction( + test, uuid, auctionConfigOverrides); + assert_true(config instanceof FencedFrameConfig, + `Wrong value type returned from first auction: ${config.constructor.type}`); + + // scoreAd() only accepts the second IG's bid, validating its trustedScoringSignals. + auctionConfigOverrides.decisionLogicUrl = + createDecisionScriptUrl(uuid, { + scoreAd: `if (browserSignals.renderURL === "${renderURL2}" && + trustedScoringSignals.renderURL["${renderURL1}"] !== undefined || + trustedScoringSignals.renderURL["${renderURL2}"] !== '1') + return;` }); + config = await runBasicFledgeAuction( + test, uuid, auctionConfigOverrides); + assert_true(config instanceof FencedFrameConfig, + `Wrong value type returned from second auction: ${config.constructor.type}`); +}, 'Trusted scoring signals multiple renderURLs.'); + +///////////////////////////////////////////////////////////////////////////// +// Data-Version tests +///////////////////////////////////////////////////////////////////////////// + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has no data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:3'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === 3'); +}, 'Trusted scoring signals response has valid data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:0'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === 0'); +}, 'Trusted scoring signals response has min data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:4294967295'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === 4294967295'); +}, 'Trusted scoring signals response has max data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:4294967296'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has too large data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:03'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has data-version with leading 0.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:-1'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has negative data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:1.3'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has decimal in data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:2 2'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has space in data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:0x4'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has space hax data-version.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:3,replace-body:'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has data-version and empty body.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:3,replace-body:[]'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has data-version and JSON array body.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:3,replace-body:{} {}'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === undefined'); +}, 'Trusted scoring signals response has data-version and double JSON object body.'); + +promise_test(async test => { + const uuid = generateUuid(test); + const renderURL = createRenderUrl(uuid, /*script=*/null, 'data-version:3,replace-body:{}'); + await runTrustedScoringSignalsTest( + test, uuid, renderURL, + 'browserSignals.dataVersion === 3'); +}, 'Trusted scoring signals response has data-version and no renderURLs.'); -- 2.11.4.GIT