Skip to content

Commit

Permalink
Add web platform tests for max trusted bidding/scoring signals URL le…
Browse files Browse the repository at this point in the history
…ngth.

Add web platform tests for both maxTrustedBiddingSignalsURLLength and
maxTrustedScoringSignalsURLLength by checking if any merged URL length
exceeds any of the signals' URL length limit.

Bug: 324416012
Change-Id: Icf4ea75992307b3a02048eccfb0dbf4bd708a7f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5385994
Commit-Queue: Tianyang Xu <xtlsheep@google.com>
Reviewed-by: mmenke <mmenke@chromium.org>
Reviewed-by: Caleb Raitto <caraitto@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1279285}
  • Loading branch information
xtlsheep authored and chromium-wpt-export-bot committed Mar 27, 2024
1 parent ccd60d5 commit acabb88
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 2 deletions.
2 changes: 2 additions & 0 deletions fledge/tentative/resources/trusted-bidding-signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ def main(request, response):
value = request.GET.first(b"slotSize", b"not-found").decode("ASCII")
elif key == "allSlotsRequestedSizes":
value = request.GET.first(b"allSlotsRequestedSizes", b"not-found").decode("ASCII")
elif key == "url":
value = request.url
responseBody["keys"][key] = value

if "data-version" in interestGroupNames:
Expand Down
2 changes: 2 additions & 0 deletions fledge/tentative/resources/trusted-scoring-signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ def main(request, response):
value = request.GET.first(b"hostname", b"not-found").decode("ASCII")
elif signalsParam == "headers":
value = fledge_http_server_util.headers_to_ascii(request.headers)
elif signalsParam == "url":
value = request.url
if addValue:
if urlList["type"] not in responseBody:
responseBody[urlList["type"]] = {}
Expand Down
156 changes: 155 additions & 1 deletion fledge/tentative/trusted-bidding-signals.https.window.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
// META: variant=?51-55
// META: variant=?56-60
// META: variant=?61-65
// META: variant=?66-last
// META: variant=?66-70
// META: variant=?71-last

"use strict";

Expand Down Expand Up @@ -785,3 +786,156 @@ subsetTest(promise_test, async test => {
auctionConfigOverrides,
uuid);
}, 'all-slots-requested-sizes trustedBiddingSignalsSlotSizeMode in a component auction');

/////////////////////////////////////////////////////////////////////////////
// maxTrustedBiddingSignalsURLLength tests
/////////////////////////////////////////////////////////////////////////////

// Trusted bidding signals can be retrieved when `maxTrustedBiddingSignalsURLLength` is set to 0,
// which means infinite length limit.
// In the following three tests, the generated request URL contains approximately 166 characters.
// The target of the tests is primarily to make sure all the signals are fetched with the full URL.
subsetTest(promise_test, async test => {
const name = 'group';
await runTrustedBiddingSignalsTest(
test,
// Check the URL length is within an approximate range to ensure the URL is not truncated.
` trustedBiddingSignals["interest-group-names"] === '["${name}"]' &&
trustedBiddingSignals["url"].length > 150 &&
trustedBiddingSignals["url"].length < 180 `,
{
name: name,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 0
});
}, 'Trusted bidding signals request works with a URL length limit set to 0.');

// Trusted bidding signals can be retrieved when `maxTrustedBiddingSignalsURLLength` is set to
// a non-zero value smaller than the length of the request URL. It also tests that multiple
// bidding keys from the same interest group will not be separated even the full URL length is
// larger than the limit.
subsetTest(promise_test, async test => {
const name = 'group';
await runTrustedBiddingSignalsTest(
test,
` trustedBiddingSignals["interest-group-names"] === '["${name}"]' &&
trustedBiddingSignals["url"].length > 150 &&
trustedBiddingSignals["url"].length < 180 `,
{
name: name,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 1
});
}, 'Trusted bidding signals request works with a URL length limit smaller than the URL length.');

// Trusted bidding signals can be retrieved when `maxTrustedBiddingSignalsURLLength` is set to
// a value larger than the length of the request URL.
subsetTest(promise_test, async test => {
const name = 'group';
await runTrustedBiddingSignalsTest(
test,
` trustedBiddingSignals["interest-group-names"] === '["${name}"]' &&
trustedBiddingSignals["url"].length < 180 `,
{
name: name,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 1000
});
}, 'Trusted bidding signals request works with a URL length limit larger than the URL length.');

// Test whether an oversized trusted bidding signals request URL, generated from two interest
// groups, will be split into two parts when `maxTrustedBiddingSignalsURLLength` is set to a
// value larger than a single URL length and smaller than the combined URL length. A request
// URL from a single interest group contains about 188 characters, while a request URL from
// two interest groups contains about 216 characters. Note that this test can only verifies
// the fetch status of the winner's trusted bidding signal, which is the second interest
// group. We consider the request to be split if the URL length check passes for the second
// interest group.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const name1 = 'extraordinarilyLongNameGroup1';
const name2 = 'extraordinarilyLongNameGroup2';

await Promise.all(
[ joinInterestGroup(
test, uuid,
{
name: name1,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 200,
biddingLogicURL: createBiddingScriptURL(
{
// Return 0 as bid to force the second interest group to win. This interest group
// is considered as fetching trusted bidding signals by itself if the winner's
// URL length passes the limit check.
generateBid:
`return { bid: 0, render: interestGroup.ads[0].renderURL };`
})
}),
joinInterestGroup(
test, uuid,
{
name: name2,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 200,
biddingLogicURL: createBiddingScriptURL(
{
generateBid:
`if (trustedBiddingSignals["interest-group-names"] !== '["${name2}"]' ||
trustedBiddingSignals["url"].length > 200) {
throw "unexpected trustedBiddingSignals";
}
return { bid: 10, render: interestGroup.ads[0].renderURL };`})
})
]
);
runBasicFledgeTestExpectingWinner(test, uuid);
}, 'Trusted bidding signals splits the request if the combined URL length exceeds the limit of regular value.');

// Test whether an oversized trusted bidding signals request URL, generated from two interest
// groups, will be split into two parts when `maxTrustedBiddingSignalsURLLength` is set to a
// value smaller than a single URL length.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const name1 = 'extraordinaryLongNameGroup1';
const name2 = 'extraordinaryLongNameGroup2';

await Promise.all(
[ joinInterestGroup(
test, uuid,
{
name: name1,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 1,
biddingLogicURL: createBiddingScriptURL(
{
generateBid:
`return { bid: 0, render: interestGroup.ads[0].renderURL };`
})
}),
joinInterestGroup(
test, uuid,
{
name: name2,
trustedBiddingSignalsKeys: ['interest-group-names', 'url'],
trustedBiddingSignalsURL: TRUSTED_BIDDING_SIGNALS_URL,
maxTrustedBiddingSignalsURLLength: 1,
biddingLogicURL: createBiddingScriptURL(
{
generateBid:
`if (trustedBiddingSignals["interest-group-names"] !== '["${name2}"]' ||
trustedBiddingSignals["url"].length > 200) {
throw "unexpected trustedBiddingSignals";
}
return { bid: 10, render: interestGroup.ads[0].renderURL };`})
})
]
);
runBasicFledgeTestExpectingWinner(test, uuid);
}, 'Trusted bidding signals splits the request if the combined URL length exceeds the limit of small value.');
151 changes: 150 additions & 1 deletion fledge/tentative/trusted-scoring-signals.https.window.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
// META: variant=?26-30
// META: variant=?31-35
// META: variant=?36-40
// META: variant=?41-last
// META: variant=?41-45
// META: variant=?45-last

"use strict";

Expand Down Expand Up @@ -510,3 +511,151 @@ subsetTest(promise_test, async test => {
})
});
}, 'Component ads trusted scoring signals.');

/////////////////////////////////////////////////////////////////////////////
// maxTrustedBiddingSignalsURLLength tests
/////////////////////////////////////////////////////////////////////////////

// Trusted scoring signals can be retrieved when `maxTrustedScoringSignalsURLLength` is set to 0.
// In the following three tests, the generated request URL contains approximately 294 characters.
// The target of the tests is primarily to make sure the signals were fetched with the full URL.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const renderURL = createRenderURL(uuid, /*script=*/null, 'url');
const interestGroupOverrides = { ads: [{ renderURL: renderURL }] };
const auctionConfigOverrides = {
trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
maxTrustedScoringSignalsURLLength: 0,
decisionLogicURL:
createDecisionScriptURL(uuid, {
// Check the URL length is within an approximate range to ensure the URL is not truncated.
scoreAd:
`if (trustedScoringSignals.renderURL["${renderURL}"].length < 280 ||
trustedScoringSignals.renderURL["${renderURL}"].length > 300)
throw "error";`
})
};

await joinGroupAndRunBasicFledgeTestExpectingWinner(
test,
{
uuid: uuid,
interestGroupOverrides: interestGroupOverrides,
auctionConfigOverrides: auctionConfigOverrides
});
}, 'Trusted scoring signals request works with a URL length limit set to 0.');

// Trusted scoring signals can be retrieved when `maxTrustedScoringSignalsURLLength` is set to
// a non-zero value smaller than the length of the request URL.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const renderURL = createRenderURL(uuid, /*script=*/null, 'url');
const interestGroupOverrides = { ads: [{ renderURL: renderURL }] };
const auctionConfigOverrides = {
trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
maxTrustedScoringSignalsURLLength: 1,
decisionLogicURL:
createDecisionScriptURL(uuid, {
// Check the URL length is within an approximate range to ensure the URL is not truncated.
scoreAd:
`if (trustedScoringSignals.renderURL["${renderURL}"].length < 280 ||
trustedScoringSignals.renderURL["${renderURL}"].length > 300)
throw "error";`
})
};

await joinGroupAndRunBasicFledgeTestExpectingWinner(
test,
{
uuid: uuid,
interestGroupOverrides: interestGroupOverrides,
auctionConfigOverrides: auctionConfigOverrides
});
}, 'Trusted scoring signals request works with a URL length limit smaller than the URL length.');

// Trusted scoring signals can be retrieved when `maxTrustedScoringSignalsURLLength` is set to
// a value larger than the length of the request URL.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const renderURL = createRenderURL(uuid, /*script=*/null, 'url');
const interestGroupOverrides = { ads: [{ renderURL: renderURL }] };
const auctionConfigOverrides = {
trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
maxTrustedScoringSignalsURLLength: 1000,
decisionLogicURL:
createDecisionScriptURL(uuid, {
scoreAd: `if (trustedScoringSignals.renderURL["${renderURL}"].length > 300) throw "error";`
})
};

await joinGroupAndRunBasicFledgeTestExpectingWinner(
test,
{
uuid: uuid,
interestGroupOverrides: interestGroupOverrides,
auctionConfigOverrides: auctionConfigOverrides
});
}, 'Trusted scoring signals request works with a URL length limit larger than the URL length.');

// Test whether an oversized trusted scoring signals request URL, generated from two interest
// groups, will be split into two parts when `maxTrustedScoringSignalsURLLength` is set to a
// value larger than a single URL length and smaller than the combined URL length. A request
// URL from a single interest group contains about 294 characters, while a request URL from
// two interest groups contains about 466 characters.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const renderURL1 = createRenderURL(uuid, /*script=*/null, 'url,group1');
const renderURL2 = createRenderURL(uuid, /*script=*/null, 'url,group2');
const auctionConfigOverrides = {
trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
maxTrustedScoringSignalsURLLength: 300,
decisionLogicURL:
createDecisionScriptURL(uuid, {
// This will make the auction reject `renderURL2`, and if `renderURL1` passes the URL
// length check, we consider `renderURL2` is fetched by itself in the trusted scoring
// signals request.
scoreAd:
`if (!trustedScoringSignals.renderURL.has("${renderURL1}") ||
trustedScoringSignals.renderURL.has("${renderURL2}") ||
trustedScoringSignals.renderURL["${renderURL1}"].length > 300) {
throw "error";
}`
})
};

await Promise.all(
[ joinInterestGroup(test, uuid, { name: 'group 1', ads: [{ renderURL: renderURL1 }] }),
joinInterestGroup(test, uuid, { name: 'group 2', ads: [{ renderURL: renderURL2 }] }) ]
);

runBasicFledgeTestExpectingWinner(test, uuid, auctionConfigOverrides);
}, 'Trusted scoring signals splits the request if the combined URL length exceeds the limit of regular value.');

// Test whether an oversized trusted scoring signals request URL, generated from two interest
// groups, will be split into two parts when `maxTrustedScoringSignalsURLLength` is set to a
// value smaller than a single URL length.
subsetTest(promise_test, async test => {
const uuid = generateUuid(test);
const renderURL1 = createRenderURL(uuid, /*script=*/null, 'url,group1');
const renderURL2 = createRenderURL(uuid, /*script=*/null, 'url,group2');
const auctionConfigOverrides = {
trustedScoringSignalsURL: TRUSTED_SCORING_SIGNALS_URL,
maxTrustedScoringSignalsURLLength: 1,
decisionLogicURL:
createDecisionScriptURL(uuid, {
scoreAd:
`if (!trustedScoringSignals.renderURL.has("${renderURL1}") ||
trustedScoringSignals.renderURL.has("${renderURL2}") ||
trustedScoringSignals.renderURL["${renderURL1}"].length > 300) {
throw "error";
}`
})
};

await Promise.all(
[ joinInterestGroup(test, uuid, { name: 'group 1', ads: [{ renderURL: renderURL1 }] }),
joinInterestGroup(test, uuid, { name: 'group 2', ads: [{ renderURL: renderURL2 }] }) ]
);

runBasicFledgeTestExpectingWinner(test, uuid, auctionConfigOverrides);
}, 'Trusted scoring signals splits the request if the combined URL length exceeds the limit of small value.');

0 comments on commit acabb88

Please sign in to comment.