diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
commit | 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch) | |
tree | a4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /testing/web-platform/tests/fledge | |
parent | Adding debian version 124.0.1-1. (diff) | |
download | firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip |
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/fledge')
22 files changed, 1563 insertions, 206 deletions
diff --git a/testing/web-platform/tests/fledge/tentative/additional-bids.https.window.js b/testing/web-platform/tests/fledge/tentative/additional-bids.https.window.js new file mode 100644 index 0000000000..0e1d22c261 --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/additional-bids.https.window.js @@ -0,0 +1,146 @@ +// META: script=/resources/testdriver.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.sub.js +// META: script=/common/subset-tests.js +// META: timeout=long +// META: variant=?1-last + +"use strict;" + +// This file contains tests for additional bids and negative targeting. +// +// TODO: +// - test that an negatively targeted additional bid is suppressed. +// - test that an incorrectly signed additional bid is not negative targeted. +// - test that an missing-signature additional bid is not negative targeted. +// - test that an additional bid with some correct signatures can be negative. +// negative targeted for those negative interest groups whose signatures +// match. +// - test an additional bid with multiple negative interest groups. +// - test that multiple negative interest groups with mismatched joining origins +// is not negative targeted. +// - test that additional bids can be fetched using an iframe navigation. +// - test that additional bids are not fetched using an iframe navigation for +// which the `adAuctionHeaders=true` attribute is not specified. +// - test that additional bids are not fetched using a Fetch request for which +// `adAuctionHeaders: true` is not specified. +// - test that an additional bid with an incorrect auction nonce is not used +// included in an auction. Same for seller and top-level seller. +// - test that correctly formatted additional bids are included in an auction +// when fetched alongside malformed additional bid headers by a Fetch +// request. +// - test that correctly formatted additional bids are included in an auction +// when fetched alongside malformed additional bid headers by an iframe +// navigation. +// - test that reportWin is not used for reporting an additional bid win. +// - test that additional bids can *not* be fetched from iframe subresource +// requests. +// - test that an auction nonce can only be used once, and a second auction +// trying to reuse an auction immediately fails. +// - test that an auction nonce must be created in the same window/tab as the +// call to runAdAuction. +// - test reportAdditionalBidWin with each of no metadata, null metadata, and +// an object metadata. +// - test that an auction running in one tab can't see an additional bid loaded +// in a new tab. +// - test that two auctions running with different nonces only get the +// additional bids fetched with their auction nonce. +// - test that two auctions running with different nonces only get the +// additional bids fetched with their auction nonce, when both additional +// bids are retrieved with one fetch. +// - test that a multiseller auction with two component auctions can direct +// additional bids to the correct component auctions. +// - test that two auctions running with different nonces only get the +// additional bids fetched with their auction nonce. +// - test that two auctions running with different nonces only get the +// additional bids fetched with their auction nonce, when both additional +// bids are retrieved with one fetch. +// - test that an additional bid can compete against an interest group bid and +// lose. +// - test that an additional bid can compete against an interest group bid and +// win. +// - test that a malformed additional bid causes that one additional bid to be +// ignored, but the rest of the auction (and other additional bids, even +// from the same fetch) continue on. +// - test (in join-leave-ad-interest-group.https.window.js) that an IG that +// provides `additionalBidKey` fails if the key fails to decode, or if +// that IG also provides `ads`, or if it provides `updateURL`. +// - test that an IG update cannot cause a regular interest group (one that +// does not provide `additionalBidKey`) to become a negative interest +// group (one that does provide `additionalBidKey`). +// - test (in auction-config-passed-to-worklets.https.window.js) that a +// multi-seller auction fails if the top-level auction provides +// a value for `additionalBids`. +// - test (in auction-config-passed-to-worklets.https.window.js) that an auction +// fails if it provides `additionalBids` but not `auctionNonce`, or if it +// provides `additionalBids` but not `interestGroupBuyers`. + +// The auction is run with the seller being the same as the document origin. +// The request to fetch additional bids must be issued to the seller's origin +// for ad auction headers interception to associate it with this auction. +const SINGLE_SELLER_AUCTION_SELLER = window.location.origin; + +// Single-seller auction with a single buyer who places a single additional +// bid. As the only bid, this wins. +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const auctionNonce = await navigator.createAuctionNonce(); + const seller = SINGLE_SELLER_AUCTION_SELLER; + + const buyer = OTHER_ORIGIN1; + const additionalBid = createAdditionalBid( + uuid, auctionNonce, seller, buyer, 'horses', 1.99); + + await runAdditionalBidTest( + test, uuid, [buyer], auctionNonce, + fetchAdditionalBids(seller, [additionalBid]), + /*highestScoringOtherBid=*/0, + /*winningAdditionalBidId=*/'horses'); +}, 'single valid additional bid'); + +// Single-seller auction with a two buyers competing with additional bids. +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const auctionNonce = await navigator.createAuctionNonce(); + const seller = SINGLE_SELLER_AUCTION_SELLER; + + const buyer1 = OTHER_ORIGIN1; + const additionalBid1 = createAdditionalBid( + uuid, auctionNonce, seller, buyer1, 'horses', 1.99); + + const buyer2 = OTHER_ORIGIN2; + const additionalBid2 = createAdditionalBid( + uuid, auctionNonce, seller, buyer2, 'planes', 2.99); + + await runAdditionalBidTest( + test, uuid, [buyer1, buyer2], auctionNonce, + fetchAdditionalBids(seller, [additionalBid1, additionalBid2]), + /*highestScoringOtherBid=*/1.99, + /*winningAdditionalBidId=*/'planes'); +}, 'two valid additional bids'); + +// Same as the test above, except that this uses two Fetch requests instead of +// one to retrieve the additional bids. +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const auctionNonce = await navigator.createAuctionNonce(); + const seller = SINGLE_SELLER_AUCTION_SELLER; + + const buyer1 = OTHER_ORIGIN1; + const additionalBid1 = createAdditionalBid( + uuid, auctionNonce, seller, buyer1, 'horses', 1.99); + + const buyer2 = OTHER_ORIGIN2; + const additionalBid2 = createAdditionalBid( + uuid, auctionNonce, seller, buyer2, 'planes', 2.99); + + + await runAdditionalBidTest( + test, uuid, [buyer1, buyer2], auctionNonce, + Promise.all([ + fetchAdditionalBids(seller, [additionalBid1]), + fetchAdditionalBids(seller, [additionalBid2]) + ]), + /*highestScoringOtherBid=*/1.99, + /*winningAdditionalBidId=*/'planes'); +}, 'two valid additional bids from two distinct Fetch requests'); diff --git a/testing/web-platform/tests/fledge/tentative/auction-config.https.window.js b/testing/web-platform/tests/fledge/tentative/auction-config.https.window.js index 3b5814b5d4..8fbdc95dfc 100644 --- a/testing/web-platform/tests/fledge/tentative/auction-config.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/auction-config.https.window.js @@ -390,3 +390,80 @@ makeTest({ [{width: '100', height: '100'}, {width: '200furlongs', height: '200'}]} }); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // The renderURL / report URLs for the first/second iterations of the auction. + let renderURL = createRenderURL(uuid); + let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/ 1); + let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/ 2); + let bidderDebugReportURL = + createBidderReportURL(uuid, /*id=*/ 'forDebuggingOnly'); + let sellerReportURL1 = createSellerReportURL(uuid, /*id=*/ 1); + let sellerReportURL2 = createSellerReportURL(uuid, /*id=*/ 2); + let sellerDebugReportURL = + createSellerReportURL(uuid, /*id=*/ 'forDebuggingOnly'); + + // reportWin() sends "bidderReportURL1" if + // browserSignals.forDebuggingOnlyInCooldownOrLockout is true, + // "bidderReportURL2" otherwise. + await joinInterestGroup(test, uuid, { + ads: [{renderURL: renderURL}], + biddingLogicURL: createBiddingScriptURL({ + generateBid: ` + forDebuggingOnly.reportAdAuctionWin('${bidderDebugReportURL}'); + if (!browserSignals.hasOwnProperty( + 'forDebuggingOnlyInCooldownOrLockout')) { + throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals"; + } + let bid = browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2; + return {bid: bid, render: '${renderURL}'};`, + reportWin: ` + if (browserSignals.bid == 1) + sendReportTo('${bidderReportURL1}'); + if (browserSignals.bid == 2) + sendReportTo('${bidderReportURL2}');` + + }) + }); + + // reportResult() sends "sellerReportURL1" if + // browserSignals.forDebuggingOnlyInCooldownOrLockout in scoreAd() is true, + // "sellerReportURL2" otherwise. + const auctionConfigOverrides = { + decisionLogicURL: createDecisionScriptURL(uuid, { + scoreAd: ` + forDebuggingOnly.reportAdAuctionWin('${sellerDebugReportURL}'); + if (!browserSignals.hasOwnProperty( + 'forDebuggingOnlyInCooldownOrLockout')) { + throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals"; + } + let desirability = + browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2; + return {desirability: desirability};`, + reportResult: ` + if (browserSignals.desirability == 1) + sendReportTo('${sellerReportURL1}'); + if (browserSignals.desirability == 2) + sendReportTo('${sellerReportURL2}');` + }) + }; + + // In the first auction, browserSignals.forDebuggingOnlyInCooldownOrLockout in + // generateBid() and scoreAd() should both be false. After the auction, + // lockout and cooldowns should be updated. + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + await waitForObservedRequestsIgnoreDebugOnlyReports( + uuid, [bidderReportURL2, sellerReportURL2]); + + // In the second auction, browserSignals.forDebuggingOnlyInCooldownOrLockout + // in generateBid() and scoreAd() should both be true, since both the buyer + // and seller called forDebuggingOnly API in the first auction, so they are in + // cooldowns at least (and also in lockout if a debug report is allowed to be + // sent). + await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides); + await waitForObservedRequestsIgnoreDebugOnlyReports( + uuid, + [bidderReportURL2, sellerReportURL2, bidderReportURL1, sellerReportURL1]); +}, `forDebuggingOnly lockout and cooldowns updating in one auction, read in another's.`); diff --git a/testing/web-platform/tests/fledge/tentative/component-auction.https.window.js b/testing/web-platform/tests/fledge/tentative/component-auction.https.window.js index 63771d42b8..c70532024c 100644 --- a/testing/web-platform/tests/fledge/tentative/component-auction.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/component-auction.https.window.js @@ -671,7 +671,7 @@ subsetTest(promise_test, async test => { browserSignals.prevWinsMs[0][1].renderURL === "${renderURL1}") { return {bid: 1, allowComponentAuction: true, render: "${renderURL2}"}; } - throw "Unexpected biddingSignals: " + JSON.stringify(browserSignals);`, + throw "Unexpected browserSignals: " + JSON.stringify(browserSignals);`, reportWin: `if (browserSignals.renderURL === "${renderURL1}") sendReportTo("${bidderReportURL1}"); diff --git a/testing/web-platform/tests/fledge/tentative/cross-origin.https.window.js b/testing/web-platform/tests/fledge/tentative/cross-origin.https.window.js index 788558e5cf..a8cf93049f 100644 --- a/testing/web-platform/tests/fledge/tentative/cross-origin.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/cross-origin.https.window.js @@ -356,8 +356,8 @@ subsetTest(promise_test, async test => { throw "Wrong origin: " + interestGroup.owner; if (!interestGroup.biddingLogicURL.startsWith("${bidderOrigin}")) throw "Wrong origin: " + interestGroup.biddingLogicURL; - if (interestGroup.ads[0].renderUrl != "${renderURL}") - throw "Wrong renderURL: " + interestGroup.ads[0].renderUrl; + if (interestGroup.ads[0].renderURL != "${renderURL}") + throw "Wrong renderURL: " + interestGroup.ads[0].renderURL; if (browserSignals.seller !== "${sellerOrigin}") throw "Wrong origin: " + browserSignals.seller;`, reportWin: `if (browserSignals.topWindowHostname !== "${document.location.hostname}") diff --git a/testing/web-platform/tests/fledge/tentative/direct-from-seller-signals.https.window.js b/testing/web-platform/tests/fledge/tentative/direct-from-seller-signals.https.window.js index 339bc32ee5..d0c0e550c4 100644 --- a/testing/web-platform/tests/fledge/tentative/direct-from-seller-signals.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/direct-from-seller-signals.https.window.js @@ -22,7 +22,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/ null, /*expectedAuctionSignals=*/ null, /*expectedPerBuyerSignals=*/ null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -38,7 +38,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/1', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -55,7 +55,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, 'auctionSignals/2', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -72,7 +72,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, /*expectedAuctionSignals=*/null, 'perBuyerSignals/3'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -89,7 +89,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -106,7 +106,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/1', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -119,7 +119,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, 'auctionSignals/2', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -137,7 +137,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -216,7 +216,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/5', 'auctionSignals/5', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -233,7 +233,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/5', 'auctionSignals/5', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -250,7 +250,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -295,7 +295,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -312,7 +312,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -329,7 +329,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -347,7 +347,7 @@ subsetTest(promise_test, async test => { await fetchDirectFromSellerSignals({ 'Buyer-Origin': window.location.origin }); await runReportTest( test, uuid, codeToInsert, - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -366,7 +366,7 @@ subsetTest(promise_test, async test => { await fetchDirectFromSellerSignals({ 'Buyer-Origin': window.location.origin }, OTHER_ORIGIN1); await runReportTest( test, uuid, codeToInsert, - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -386,7 +386,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid, '1', OTHER_ORIGIN1)], // renderURLOverride null, @@ -406,7 +406,7 @@ subsetTest(promise_test, async test => { test_instance, "${uuid}", directFromSellerSignalsValidatorCode( "${uuid}", 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL("${uuid}"), createBidderReportURL("${uuid}")], // renderURLOverride null, @@ -425,7 +425,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( "${uuid}", 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL("${uuid}"), createBidderReportURL("${uuid}")], // renderURLOverride null, @@ -447,7 +447,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( "${uuid}", 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL("${uuid}"), createBidderReportURL("${uuid}")], // renderURLOverride null, @@ -467,7 +467,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals/4', 'auctionSignals/4', 'perBuyerSignals/4'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -484,7 +484,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sellerSignals', 'auctionSignals', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -511,7 +511,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'altSellerSignals/1', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -532,7 +532,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'altV2SellerSignals/1', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -551,7 +551,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, /*expectedSellerSignals=*/null, 'auctionSignals/2', /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -569,7 +569,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'firstSellerSignals/1', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -587,7 +587,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'nonDupSellerSignals/2', /*expectedAuctionSignals=*/null, /*expectedPerBuyerSignals=*/null), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, @@ -606,7 +606,7 @@ subsetTest(promise_test, async test => { directFromSellerSignalsValidatorCode( uuid, 'sameSellerSignals', 'sameAuctionSignals', 'samePerBuyerSignals'), - // expectedReportUrls + // expectedReportURLs [createSellerReportURL(uuid), createBidderReportURL(uuid)], // renderURLOverride null, diff --git a/testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js b/testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js new file mode 100644 index 0000000000..8687e3f296 --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js @@ -0,0 +1,946 @@ +// META: script=/resources/testdriver.js +// META: script=/common/utils.js +// META: script=resources/fledge-util.sub.js +// META: script=/common/subset-tests.js +// META: timeout=long +// META: variant=?1-4 +// META: variant=?5-8 +// META: variant=?9-12 +// META: variant=?13-16 +// META: variant=?17-20 +// META: variant=?21-24 +// META: variant=?25-28 +// META: variant=?29-last + +"use strict;" + +// These tests focus on the browserSignals argument passed to generateBid(). +// Note that "topLevelSeller" is covered by component auction tests, +// "dataVersion" by trusted signals tests, and cross-origin +// "topWindowHostname" and "seller" are covered by cross origin tests. +// +// Some of these tests use the "uuid" for interest group name, to avoid +// joins/bids from previous tests that failed to clean up after themselves +// from affecting results. + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let expectedBrowserSignals = { + "topWindowHostname": window.location.hostname, + "seller": window.location.origin, + "adComponentsLimit": 40, + "joinCount": 1, + "bidCount": 0, + "prevWinsMs": [] + } + let biddingLogicURL = createBiddingScriptURL( + { generateBid: + `let expectedBrowserSignals = ${JSON.stringify(expectedBrowserSignals)}; + + // Can't check this value exactly. + expectedBrowserSignals.recency = browserSignals.recency; + + // This value may be affected by other recently run tests. + expectedBrowserSignals.forDebuggingOnlyInCooldownOrLockout = + browserSignals.forDebuggingOnlyInCooldownOrLockout; + + // Remove deprecated field, if present. + delete browserSignals.prevWins; + + if (!deepEquals(browserSignals, expectedBrowserSignals)) + throw "Unexpected browserSignals: " + JSON.stringify(browserSignals);` + }); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: biddingLogicURL}}); +}, 'Only expected fields present.'); + +// Creates a bidding script URL that expects the "joinCount" to be +// "expectedJoinCount". +function createJoinCountBiddingScriptURL(expectedJoinCount) { + return createBiddingScriptURL( + { generateBid: + `if (browserSignals.joinCount !== ${expectedJoinCount}) + throw "Unexpected joinCount: " + browserSignals.joinCount;` + }); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(1)}}); + + // Joining again, even with a different script URL, should increase the join count. + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(2)}}); +}, 'browserSignals.joinCount same joining page.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(1)}}); + + // Attempt to re-join the same interest group from a different top-level origin. + // The join count should still be persisted. + await joinCrossOriginInterestGroupInTopLevelWindow( + test, uuid, OTHER_ORIGIN1, window.location.origin, + { name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(2)}); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.joinCount different top-level joining origin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(1)}}); + + // Leaving interest group should clear join count. + await leaveInterestGroup({name: uuid}); + + // Check that join count was cleared. + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: {name: uuid, + biddingLogicURL: createJoinCountBiddingScriptURL(1)}}); +}, 'browserSignals.joinCount leave and rejoin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + await runReportTest( + test, uuid, + { generateBid: + `if (browserSignals.recency === undefined) + throw new Error("Missing recency in browserSignals.") + + if (browserSignals.recency < 0) + throw new Error("Recency is a negative value.") + + if (browserSignals.recency > 30000) + throw new Error("Recency is over 30 seconds threshold.") + + if (browserSignals.recency % 100 !== 0) + throw new Error("Recency is not rounded to multiple of 100 milliseconds.") + + return {'bid': 9, + 'render': interestGroup.ads[0].renderURL};`, + reportWin: + `sendReportTo('${createBidderReportURL(uuid)}');` + }, + // expectedReportURLs + [createBidderReportURL(uuid)] + ); +}, 'Check recency in generateBid() is below a certain threshold and rounded ' + + 'to multiple of 100 milliseconds.'); + +// Creates a bidding script URL that expects the "bidCount" to be +// "expectedBidCount". +function createBidCountBiddingScriptURL(expectedBidCount) { + return createBiddingScriptURL( + { generateBid: + `if (browserSignals.bidCount !== ${expectedBidCount}) + throw "Unexpected bidCount: " + browserSignals.bidCount;` + }); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Running an auction should not increment "bidCount". + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0)}); + + // These auctions would have no winner if the "bidCount" were incremented. + await runBasicFledgeAuction(test, uuid); + await runBasicFledgeAuction(test, uuid); +}, 'browserSignals.bidCount not incremented when ad not used.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0) }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Wait for the navigation to trigger reports. "bidCount" should be updated before + // any reports are sent. + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Wait for the navigation to trigger reports. "bidCount" should be updated before + // any reports are sent. + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(2) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented when ad used.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Join an interest group and run an auction and navigate to the winning ad, + // increasing the bid count to 1. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0)}); + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Wait for the navigation to trigger reports. "bidCount" should be updated before + // any reports are sent. + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinCrossOriginInterestGroupInTopLevelWindow( + test, uuid, OTHER_ORIGIN1, window.location.origin, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount persists across re-join from other top-level origin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Join an interest group and run an auction and navigate to the winning ad, + // increasing the bid count to 1. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0) }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + // Leaving interest group should clear "bidCount". + await leaveInterestGroup({name: uuid}); + + // Check that bid count was cleared. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0)}); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount leave and rejoin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0)} ); + + // Run two auctions at once, without any navigations. + // "bidCount" should be 0 for both auctions. + let fencedFrameConfigs = + await Promise.all([runBasicFledgeTestExpectingWinner(test, uuid), + runBasicFledgeTestExpectingWinner(test, uuid)]); + + // Start navigating to both auction winners. + createAndNavigateFencedFrame(test, fencedFrameConfigs[0]); + createAndNavigateFencedFrame(test, fencedFrameConfigs[1]); + + // Wait for navigations to have sent reports (and thus to have updated + // bid counts). + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + // Check that "bidCount" has increased by 2. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(2) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount two auctions at once.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use a tracker URL for the ad. It won't be successfully loaded, due to missing + // the fenced frame header, but it should be fetched twice. + let trackedRenderURL = + createTrackerURL(window.location.origin, uuid, 'track_get', /*id=*/'ad'); + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0), + ads: [{ renderURL: trackedRenderURL }] + }); + + let fencedFrameConfig = await runBasicFledgeTestExpectingWinner(test, uuid); + + // Start navigating two frames to the winning ad. + createAndNavigateFencedFrame(test, fencedFrameConfig); + createAndNavigateFencedFrame(test, fencedFrameConfig); + + // Wait for both navigations to have requested ads (and thus to have updated + // bid counts). + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + trackedRenderURL, + trackedRenderURL]); + + // Check that "bidCount" has increased by only 1. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented once when winning ad used twice.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let bidderReportURL = createBidderReportURL(uuid, /*id=*/'winner'); + + // Join an interest group named "uuid", which will bid 0.1, losing the first auction. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { bid: 0.1, reportWin: `sendReportTo('${createBidderReportURL(uuid, /*id=*/'loser')}')` }) + }); + + // Join an interest group with the default name, which will bid 1 and win the first + // auction, sending a bidder report. + await joinInterestGroup( + test, uuid, + { biddingLogicURL: createBiddingScriptURL( + { bid: 1, reportWin: `sendReportTo('${bidderReportURL}')` }) + }); + + // Run an auction that both bidders participate in. Despite the first interest group + // losing, its "bidCount" should be incremented. + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Make sure the right bidder won. + await waitForObservedRequests(uuid, [bidderReportURL, createSellerReportURL(uuid)]); + + // Leave the second interest group (which has the default name). + await leaveInterestGroup(); + + // Re-join the first interest group, with a bidding script that checks its "bidCount". + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) + }); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented when another interest group wins.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use default interest group, other than using a unique name. It will make a bid. + await joinInterestGroup(test, uuid, { name: uuid }); + // Run auction with seller that rejects all bids. + await runBasicFledgeTestExpectingNoWinner( + test, uuid, + { decisionLogicURL: createDecisionScriptURL(uuid, {scoreAd: `return 0;`})}); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented when seller rejects bid.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use default interest group, other than using a unique name. It will make a bid. + await joinInterestGroup(test, uuid, { name: uuid }); + // Run auction with seller that always throws. + await runBasicFledgeTestExpectingNoWinner( + test, uuid, + { decisionLogicURL: createDecisionScriptURL(uuid, {scoreAd: `throw "a fit";`})}); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented when seller throws.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Interest group that does not bid. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { generateBid: 'return;' }) + }); + await runBasicFledgeTestExpectingNoWinner(test, uuid); + + // Check that "bidCount" was not incremented. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount not incremented when no bid.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let bidderReportURL = createBidderReportURL(uuid, /*id=*/'winner'); + + // Interest group that does not bid. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { generateBid: 'return;' }) + }); + + // Join an interest group with the default name, which will bid 1 and win the first + // auction, sending a bidder report. + await joinInterestGroup( + test, uuid, + { biddingLogicURL: createBiddingScriptURL( + { bid: 1, reportWin: `sendReportTo('${bidderReportURL}')` }) + }); + + // Run an auction that both bidders participate in, and make sure the right bidder won. + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [bidderReportURL, createSellerReportURL(uuid)]); + + // Leave the second interest group (which has the default name). + await leaveInterestGroup(); + + // Re-join the first interest group, with a bidding script that checks its "bidCount". + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(0) + }); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount not incremented when no bid and another interest group wins.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let bidderReportURL = createBidderReportURL(uuid, /*id=*/'winner'); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { bid: 42, reportWin: `sendReportTo('${createBidderReportURL(uuid, /*id=*/'loser')}')` }) + }); + + // Join an interest group with the default name, which will bid 1 and win the first + // auction, sending a bidder report. + await joinInterestGroup( + test, uuid, + { biddingLogicURL: createBiddingScriptURL( + { bid: 1, reportWin: `sendReportTo('${bidderReportURL}')` }) + }); + + // Run an auction that both bidders participate in. The scoreAd script rejects the + // first interest group's bid. + await runBasicFledgeAuctionAndNavigate( + test, uuid, + { decisionLogicURL: createDecisionScriptURL( + uuid, + { scoreAd: `if (bid === 42) return -1;`})}); + // Make sure the second interest group won. + await waitForObservedRequests(uuid, [bidderReportURL]); + + // Leave the second interest group (which has the default name). + await leaveInterestGroup(); + + // Re-join the first interest group, with a bidding script that checks its "bidCount". + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBidCountBiddingScriptURL(1) + }); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.bidCount incremented when makes largest bid, but seller rejects the bid.'); + +// Creates a bidding script URL that expects "prevWinsMs" to be +// "expectedPrevWinsMs". All times in "expectedPrevWinsMs" must be 0. +// +// "adIndex" is the index of the ad to use in the bid. +function createPrevWinsMsBiddingScriptURL(expectedPrevWinsMs, adIndex = 0) { + return createBiddingScriptURL( + { generateBid: + `for (let i = 0; i < browserSignals.prevWinsMs.length; i++) { + // Check age is in a reasonable range. + if (browserSignals.prevWinsMs[i][0] < 0 || + browserSignals.prevWinsMs[i][0] > 30000) { + throw "Unexpected prevWinsMs time: " + JSON.stringify(browserSignals.prevWinsMs); + } + + // Set age to 0. + browserSignals.prevWinsMs[i][0] = 0; + + // Remove obsolete field, if present. + delete browserSignals.prevWinsMs[i][1].render_url; + } + if (!deepEquals(browserSignals.prevWinsMs, ${JSON.stringify(expectedPrevWinsMs)})) + throw "Unexpected prevWinsMs: " + JSON.stringify(browserSignals.prevWinsMs); + + return { + bid: 1, + render: interestGroup.ads[${adIndex}].renderURL + };` + }); +} + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Running an auction should not increment "prevWinsMs". + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([])}); + + // These auctions would have no winner if the "prevWinsMs" were incremented. + await runBasicFledgeAuction(test, uuid); + await runBasicFledgeAuction(test, uuid); +}, 'browserSignals.prevWinsMs not affected when ad not used.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Wait for the navigation to trigger reports. "prevWinsMs" should be updated before + // any reports are sent. + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: createRenderURL(uuid)}]]) }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + // Wait for the navigation to trigger reports. "prevWinsMs" should be updated before + // any reports are sent. + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [ [0, {renderURL: createRenderURL(uuid)}], + [0, {renderURL: createRenderURL(uuid)}]]) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs, no metadata.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const ads = [ {renderURL: createRenderURL(uuid, 0), metadata: null}, + {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}, + {renderURL: createRenderURL(uuid, 2)} ]; + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([], /*adIndex=*/0), + ads: ads }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: createRenderURL(uuid, 0), metadata: null}]], + /*adIndex=*/1), + ads: ads }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [ [0, {renderURL: createRenderURL(uuid, 0), metadata: null}], + [0, {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}] ], + /*adIndex=*/2), + ads: ads }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [ [0, {renderURL: createRenderURL(uuid, 0), metadata: null}], + [0, {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}], + [0, {renderURL: createRenderURL(uuid, 2)}] ]), + ads: ads }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs, with metadata.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + const ads = [ {renderURL: createRenderURL(uuid, 0), metadata: null}, + {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}, + {renderURL: createRenderURL(uuid, 2)} ]; + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]), + ads: [{renderURL: createRenderURL(uuid, 0), metadata: null}] }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: createRenderURL(uuid, 0), metadata: null}]]), + ads: [{renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}] }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [ [0, {renderURL: createRenderURL(uuid, 0), metadata: null}], + [0, {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}] ]), + ads: [{renderURL: createRenderURL(uuid, 2)}] }); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [ [0, {renderURL: createRenderURL(uuid, 0), metadata: null}], + [0, {renderURL: createRenderURL(uuid, 1), metadata: ['1', 2, {3: 4}]}], + [0, {renderURL: createRenderURL(uuid, 2)}] ]) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs, different set of ads for each bid.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Join an interest group and run an auction and navigate to the winning ad, + // which should be logged in "prevWinsMs". + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([])}); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + await joinCrossOriginInterestGroupInTopLevelWindow( + test, uuid, OTHER_ORIGIN1, window.location.origin, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: createRenderURL(uuid)}]]) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs persists across re-join from other top-level origin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Join an interest group and run an auction and navigate to the winning ad, + // which should be logged in "prevWinsMs". + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([])}); + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [createSellerReportURL(uuid)]); + + // Leaving interest group should clear "prevWinsMs". + await leaveInterestGroup({name: uuid}); + + // Check that bid count was cleared. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([])}); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs leave and rejoin.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + + // Run two auctions at once, without any navigations. + // "prevWinsMs" should be empty for both auctions. + let fencedFrameConfigs = + await Promise.all([runBasicFledgeTestExpectingWinner(test, uuid), + runBasicFledgeTestExpectingWinner(test, uuid)]); + + // Start navigating to both auction winners. + createAndNavigateFencedFrame(test, fencedFrameConfigs[0]); + createAndNavigateFencedFrame(test, fencedFrameConfigs[1]); + + // Wait for navigations to have sent reports (and thus to have updated + // "prevWinsMs"). + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + createSellerReportURL(uuid)]); + + // Check that "prevWinsMs" has two URLs. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: createRenderURL(uuid)}], + [0, {renderURL: createRenderURL(uuid)}]]) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs two auctions at once.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use a tracker URL for the ad. It won't be successfully loaded, due to missing + // the fenced frame header, but it should be fetched twice. + let trackedRenderURL = + createTrackerURL(window.location.origin, uuid, 'track_get', /*id=*/'ad'); + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]), + ads: [{ renderURL: trackedRenderURL }] + }); + + let fencedFrameConfig = await runBasicFledgeTestExpectingWinner(test, uuid); + + // Start navigating two frames to the winning ad. + createAndNavigateFencedFrame(test, fencedFrameConfig); + createAndNavigateFencedFrame(test, fencedFrameConfig); + + // Wait for both navigations to have requested ads (and thus to have updated + // "prevWinsMs"). + await waitForObservedRequests(uuid, [createSellerReportURL(uuid), + trackedRenderURL, + trackedRenderURL]); + + // Check that "prevWins" has only a single win. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL( + [[0, {renderURL: trackedRenderURL}]]) }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs has only one win when winning ad used twice.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let bidderReportURL = createBidderReportURL(uuid, /*id=*/'winner'); + + // Join an interest group named "uuid", which will bid 0.1, losing the first auction. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { bid: 0.1, reportWin: `sendReportTo('${createBidderReportURL(uuid, /*id=*/'loser')}')` }) + }); + + // Join an interest group with the default name, which will bid 1 and win the first + // auction, sending a bidder report. + await joinInterestGroup( + test, uuid, + { biddingLogicURL: createBiddingScriptURL( + { bid: 1, reportWin: `sendReportTo('${bidderReportURL}')` }) + }); + + // Run an auction that both bidders participate in, and make sure the right bidder won. + await runBasicFledgeAuctionAndNavigate(test, uuid); + await waitForObservedRequests(uuid, [bidderReportURL, createSellerReportURL(uuid)]); + + // Leave the second interest group (which has the default name). + await leaveInterestGroup(); + + // Re-join the first interest group, with a bidding script that expects prevWinsMs to + // be empty. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs not updated when another interest group wins.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use default interest group, other than using a unique name. It will make a bid. + await joinInterestGroup(test, uuid, { name: uuid }); + // Run auction with seller that rejects all bids. + await runBasicFledgeTestExpectingNoWinner( + test, uuid, + { decisionLogicURL: createDecisionScriptURL(uuid, {scoreAd: `return 0;`})}); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs not updated when seller rejects bid.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Use default interest group, other than using a unique name. It will make a bid. + await joinInterestGroup(test, uuid, { name: uuid }); + // Run auction with seller that always throws. + await runBasicFledgeTestExpectingNoWinner( + test, uuid, + { decisionLogicURL: createDecisionScriptURL(uuid, {scoreAd: `throw "a fit";`})}); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs not updated when seller throws.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Interest group that does not bid. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { generateBid: 'return;' }) + }); + await runBasicFledgeTestExpectingNoWinner(test, uuid); + + // Check that "prevWinsMs" was not modified. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs not updated when no bid.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + let bidderReportURL = createBidderReportURL(uuid, /*id=*/'winner'); + + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createBiddingScriptURL( + { bid: 42, reportWin: `sendReportTo('${createBidderReportURL(uuid, /*id=*/'loser')}')` }) + }); + + // Join an interest group with the default name, which will bid 1 and win the first + // auction, sending a bidder report. + await joinInterestGroup( + test, uuid, + { biddingLogicURL: createBiddingScriptURL( + { bid: 1, reportWin: `sendReportTo('${bidderReportURL}')` }) + }); + + // Run an auction that both bidders participate in. The scoreAd script returns a low + // score for the first interest group's bid. + await runBasicFledgeAuctionAndNavigate( + test, uuid, + { decisionLogicURL: createDecisionScriptURL( + uuid, + { scoreAd: `if (bid === 42) return 0.1;`})}); + // Make sure the second interest group won. + await waitForObservedRequests(uuid, [bidderReportURL]); + + // Leave the second interest group (which has the default name). + await leaveInterestGroup(); + + // Re-join the first interest group, with a bidding script that expects prevWinsMs to + // be empty. + await joinInterestGroup( + test, uuid, + { name: uuid, + biddingLogicURL: createPrevWinsMsBiddingScriptURL([]) + }); + + await runBasicFledgeTestExpectingWinner(test, uuid); +}, 'browserSignals.prevWinsMs not updated when makes largest bid, but another interest group wins.'); + +subsetTest(promise_test, async test => { + const uuid = generateUuid(test); + + // Join an interest group with a WASM helper that exposes a single "increment" method, + // and make sure that method can be invoked and behaves as expected. + await joinGroupAndRunBasicFledgeTestExpectingWinner( + test, + { uuid: uuid, + interestGroupOverrides: { + biddingWasmHelperURL: `${RESOURCE_PATH}wasm-helper.py`, + biddingLogicURL: createBiddingScriptURL( + { generateBid: + `if (!browserSignals.wasmHelper) + throw "No WASM helper"; + + let instance = new WebAssembly.Instance(browserSignals.wasmHelper); + if (!instance) + throw "Couldn't create WASM Instance"; + + if (!deepEquals(Object.keys(instance.exports), ["increment"])) + throw "Unexpected exports: " + JSON.stringify(instance.exports); + + if (instance.exports.increment(1) != 2) + throw "Unexpected increment result: " + instance.exports.increment(1);` }) + } + }); +}, 'browserSignals.wasmHelper.'); diff --git a/testing/web-platform/tests/fledge/tentative/generate-bid-recency.https.window.js b/testing/web-platform/tests/fledge/tentative/generate-bid-recency.https.window.js deleted file mode 100644 index 07da463a2d..0000000000 --- a/testing/web-platform/tests/fledge/tentative/generate-bid-recency.https.window.js +++ /dev/null @@ -1,34 +0,0 @@ -// META: script=/resources/testdriver.js -// META: script=/common/utils.js -// META: script=resources/fledge-util.sub.js -// META: timeout=long - -"use strict;" - -promise_test(async test => { - const uuid = generateUuid(test); - await runReportTest( - test, uuid, - { generateBid: - `if (browserSignals.recency === undefined) - throw new Error("Missing recency in browserSignals.") - - if (browserSignals.recency < 0) - throw new Error("Recency is a negative value.") - - if (browserSignals.recency > 30000) - throw new Error("Recency is over 30 seconds threshold.") - - if (browserSignals.recency % 100 !== 0) - throw new Error("Recency is not rounded to multiple of 100 milliseconds.") - - return {'bid': 9, - 'render': interestGroup.ads[0].renderURL};`, - reportWin: - `sendReportTo('${createBidderReportURL(uuid)}');` - }, - // expectedReportUrls - [createBidderReportURL(uuid)] - ); -}, 'Check recency in generateBid() is below a certain threshold and rounded ' + - 'to multiple of 100 milliseconds.'); diff --git a/testing/web-platform/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js b/testing/web-platform/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js index b5dfe025bf..02148ef36b 100644 --- a/testing/web-platform/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/join-leave-ad-interest-group.https.window.js @@ -231,31 +231,31 @@ const SIMPLE_JOIN_LEAVE_TEST_CASES = [ biddingWasmHelperURL: 'relative/path' } }, - // "dailyUpdateUrl" tests + // "updateURL" tests { expectJoinSucces: true, expectLeaveSucces: true, interestGroup: { ...BASE_INTEREST_GROUP, - dailyUpdateUrl: null } + updateURL: null } }, { expectJoinSucces: false, expectLeaveSucces: true, interestGroup: { ...BASE_INTEREST_GROUP, - dailyUpdateUrl: 'https://{{hosts[][www]}}/foo.js' } + updateURL: 'https://{{hosts[][www]}}/foo.js' } }, { expectJoinSucces: false, expectLeaveSucces: true, interestGroup: { ...BASE_INTEREST_GROUP, - dailyUpdateUrl: 'data:application/wasm,Foo' } + updateURL: 'data:application/wasm,Foo' } }, { expectJoinSucces: true, expectLeaveSucces: true, interestGroup: { ...BASE_INTEREST_GROUP, - dailyUpdateUrl: `${window.location.origin}/foo.js`} + updateURL: `${window.location.origin}/foo.js`} }, { expectJoinSucces: true, expectLeaveSucces: true, interestGroup: { ...BASE_INTEREST_GROUP, - dailyUpdateUrl: 'relative/path' } + updateURL: 'relative/path' } }, // "executionMode" tests diff --git a/testing/web-platform/tests/fledge/tentative/kanon-status-below-threshold.https.window.js b/testing/web-platform/tests/fledge/tentative/kanon-status-below-threshold.https.window.js index 4eac4a8e91..787283d687 100644 --- a/testing/web-platform/tests/fledge/tentative/kanon-status-below-threshold.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/kanon-status-below-threshold.https.window.js @@ -13,7 +13,7 @@ subsetTest(promise_test, async test => { `browserSignals.kAnonStatus === "belowThreshold"`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)]); }, 'Check kAnonStatus is "belowThreshold" when FledgeConsiderKAnonymity' + diff --git a/testing/web-platform/tests/fledge/tentative/kanon-status-not-calculated.https.window.js b/testing/web-platform/tests/fledge/tentative/kanon-status-not-calculated.https.window.js index a3ac19bd85..4a750cd352 100644 --- a/testing/web-platform/tests/fledge/tentative/kanon-status-not-calculated.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/kanon-status-not-calculated.https.window.js @@ -13,7 +13,7 @@ subsetTest(promise_test, async test => { `browserSignals.kAnonStatus === "notCalculated"`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)]); }, 'Check kAnonStatus is "notCalculated" when FledgeConsiderKAnonymity' + diff --git a/testing/web-platform/tests/fledge/tentative/register-ad-beacon.https.window.js b/testing/web-platform/tests/fledge/tentative/register-ad-beacon.https.window.js index 19fab2ac1b..3643e44662 100644 --- a/testing/web-platform/tests/fledge/tentative/register-ad-beacon.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/register-ad-beacon.https.window.js @@ -17,9 +17,9 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon: '${createSellerBeaconURL(uuid)}'});`, reportWin: '' }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: `], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -39,9 +39,9 @@ subsetTest(promise_test, async test => { reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createBidderBeaconURL(uuid)}, body: `], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -60,9 +60,9 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon: '${createSellerBeaconURL(uuid)}'});`, reportWin: '' }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: body`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -81,9 +81,9 @@ subsetTest(promise_test, async test => { '', reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createBidderBeaconURL(uuid)}, body: body`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -102,10 +102,10 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon: '${createSellerBeaconURL(uuid)}'});`, reportWin: '' }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: body1`, `${createSellerBeaconURL(uuid)}, body: body2`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -129,10 +129,10 @@ subsetTest(promise_test, async test => { '', reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createBidderBeaconURL(uuid)}, body: body1`, `${createBidderBeaconURL(uuid)}, body: body2`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -157,10 +157,10 @@ subsetTest(promise_test, async test => { beacon2: '${createSellerBeaconURL(uuid, '2')}'});`, reportWin: '' }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid, '1')}, body: body1`, `${createSellerBeaconURL(uuid, '2')}, body: body2`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -186,10 +186,10 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon1: '${createBidderBeaconURL(uuid, '1')}', beacon2: '${createBidderBeaconURL(uuid, '2')}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createBidderBeaconURL(uuid, '1')}, body: body1`, `${createBidderBeaconURL(uuid, '2')}, body: body2`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -213,10 +213,10 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon: '${createSellerBeaconURL(uuid)}'});`, reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: body`, `${createBidderBeaconURL(uuid)}, body: body`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -235,10 +235,10 @@ subsetTest(promise_test, async test => { `registerAdBeacon({beacon: '${createSellerBeaconURL(uuid)}'});`, reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: body1`, `${createBidderBeaconURL(uuid)}, body: body2`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -268,9 +268,9 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createBidderBeaconURL(uuid)}, body: body`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ @@ -293,9 +293,9 @@ subsetTest(promise_test, async test => { `sendReportTo('${createBidderReportURL(uuid)}'); registerAdBeacon({beacon: '${createBidderBeaconURL(uuid)}'}); registerAdBeacon({beacon1: '${createBidderBeaconURL(uuid)}'});` }, - // expectedReportUrls: + // expectedReportURLs: [`${createSellerBeaconURL(uuid)}, body: body`], - // renderUrlOverride: + // renderURLOverride: createRenderURL( uuid, `window.fence.reportEvent({ diff --git a/testing/web-platform/tests/fledge/tentative/reporting-arguments.https.window.js b/testing/web-platform/tests/fledge/tentative/reporting-arguments.https.window.js index f26a969328..c7c7120240 100644 --- a/testing/web-platform/tests/fledge/tentative/reporting-arguments.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/reporting-arguments.https.window.js @@ -46,7 +46,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === 45', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid), createBidderReportURL(uuid)] ); }, 'Seller passes number to bidder.'); @@ -62,7 +62,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === "foo"', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid), createBidderReportURL(uuid)] ); }, 'Seller passes string to bidder.'); @@ -78,7 +78,7 @@ subsetTest(promise_test, async test => { 'JSON.stringify(sellerSignals) === "[3,1,2]"', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid), createBidderReportURL(uuid)] ); }, 'Seller passes array to bidder.'); @@ -94,7 +94,7 @@ subsetTest(promise_test, async test => { `JSON.stringify(sellerSignals) === '{"a":4,"b":["c",null,{}]}'`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid), createBidderReportURL(uuid)] ); }, 'Seller passes object to bidder.'); diff --git a/testing/web-platform/tests/fledge/tentative/resources/additional-bids.py b/testing/web-platform/tests/fledge/tentative/resources/additional-bids.py new file mode 100644 index 0000000000..060606b41d --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/resources/additional-bids.py @@ -0,0 +1,59 @@ +"""Endpoint to return additional bids in the appropriate response header. + +Additional bids are returned using the "Ad-Auction-Additional-Bid" response +header, as described at +https://github.com/WICG/turtledove/blob/main/FLEDGE.md#63-http-response-headers. + +This script generates one of "Ad-Auction-Additional-Bid" response header for +each additional bid provided in a url-encoded `additionalBids` query parameter. + +All requests to this endpoint requires a "Sec-Ad-Auction-Fetch" request header +with a value of b"?1"; this entrypoint otherwise returns a 400 response. +""" +import json +import base64 + +import fledge.tentative.resources.fledge_http_server_util as fledge_http_server_util + + +class BadRequestError(Exception): + pass + + +def main(request, response): + try: + if fledge_http_server_util.handle_cors_headers_and_preflight(request, response): + return + + # Verify that Sec-Ad-Auction-Fetch is present + if (request.headers.get("Sec-Ad-Auction-Fetch", default=b"").decode("utf-8") != "?1"): + raise BadRequestError("Sec-Ad-Auction-Fetch missing or unexpected value; expected '?1'") + + # Return each signed additional bid in its own header + additional_bids = request.GET.get(b"additionalBids", default=b"").decode("utf-8") + if not additional_bids: + raise BadRequestError("Missing 'additionalBids' parameter") + for additional_bid in json.loads(additional_bids): + additional_bid_string = json.dumps(additional_bid) + auction_nonce = additional_bid.get("auctionNonce", None) + if not auction_nonce: + raise BadRequestError("Additional bid missing required 'auctionNonce' field") + signed_additional_bid = json.dumps({ + "bid": additional_bid_string, + "signatures": [] + }) + additional_bid_header_value = (auction_nonce.encode("utf-8") + b":" + + base64.b64encode(signed_additional_bid.encode("utf-8"))) + response.headers.append(b"Ad-Auction-Additional-Bid", additional_bid_header_value) + + response.status = (200, b"OK") + response.headers.set(b"Content-Type", b"text/plain") + + except BadRequestError as error: + response.status = (400, b"Bad Request") + response.headers.set(b"Content-Type", b"text/plain") + response.content = str(error) + + except Exception as exception: + response.status = (500, b"Internal Server Error") + response.content = str(exception) diff --git a/testing/web-platform/tests/fledge/tentative/resources/bidding-logic.sub.py b/testing/web-platform/tests/fledge/tentative/resources/bidding-logic.sub.py index 707e37f36b..e17f2c2c75 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/bidding-logic.sub.py +++ b/testing/web-platform/tests/fledge/tentative/resources/bidding-logic.sub.py @@ -1,71 +1,83 @@ from pathlib import Path +from fledge.tentative.resources import fledge_http_server_util + # General bidding logic script. Depending on query parameters, it can -# simulate a variety of network errors, and its generateBid() and -# reportWin() functions can have arbitrary Javascript code injected -# in them. generateBid() will by default return a bid of 9 for the +# simulate a variety of network errors, and its generateBid(), reportWin(), +# and reportAdditionalBidWin() functions can have arbitrary Javascript code +# injected in them. generateBid() will by default return a bid of 9 for the # first ad. def main(request, response): - error = request.GET.first(b"error", None) + if fledge_http_server_util.handle_cors_headers_and_preflight(request, response): + return + + error = request.GET.first(b"error", None) - if error == b"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 + if error == b"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 - if error == b"http-error": - response.status = (404, b"OK") - else: - response.status = (200, b"OK") + if error == b"http-error": + response.status = (404, b"OK") + else: + response.status = (200, b"OK") - if error == b"wrong-content-type": - response.headers.set(b"Content-Type", b"application/json") - elif error != b"no-content-type": - response.headers.set(b"Content-Type", b"application/javascript") + if error == b"wrong-content-type": + response.headers.set(b"Content-Type", b"application/json") + elif error != b"no-content-type": + response.headers.set(b"Content-Type", b"application/javascript") - if error == b"bad-allow-fledge": - response.headers.set(b"Ad-Auction-Allowed", b"sometimes") - elif error == b"fledge-not-allowed": - response.headers.set(b"Ad-Auction-Allowed", b"false") - elif error != b"no-allow-fledge": - response.headers.set(b"Ad-Auction-Allowed", b"true") + if error == b"bad-allow-fledge": + response.headers.set(b"Ad-Auction-Allowed", b"sometimes") + elif error == b"fledge-not-allowed": + response.headers.set(b"Ad-Auction-Allowed", b"false") + elif error != b"no-allow-fledge": + response.headers.set(b"Ad-Auction-Allowed", b"true") - if error == b"no-body": - return b'' + if error == b"no-body": + return b'' - body = (Path(__file__).parent.resolve() / 'worklet-helpers.js').read_text().encode("ASCII") - if error != b"no-generateBid": - # Use bid query param if present. Otherwise, use a bid of 9. - bid = (request.GET.first(b"bid", None) or b"9").decode("ASCII") + body = (Path(__file__).parent.resolve() / 'worklet-helpers.js').read_text().encode("ASCII") + if error != b"no-generateBid": + # Use bid query param if present. Otherwise, use a bid of 9. + bid = (request.GET.first(b"bid", None) or b"9").decode("ASCII") - bidCurrency = "" - bidCurrencyParam = request.GET.first(b"bidCurrency", None) - if bidCurrencyParam != None: - bidCurrency = "bidCurrency: '" + bidCurrencyParam.decode("ASCII") + "'," + bidCurrency = "" + bidCurrencyParam = request.GET.first(b"bidCurrency", None) + if bidCurrencyParam != None: + bidCurrency = "bidCurrency: '" + bidCurrencyParam.decode("ASCII") + "'," - allowComponentAuction = "" - allowComponentAuctionParam = request.GET.first(b"allowComponentAuction", None) - if allowComponentAuctionParam != None: - allowComponentAuction = f"allowComponentAuction: {allowComponentAuctionParam.decode('ASCII')}," + allowComponentAuction = "" + allowComponentAuctionParam = request.GET.first(b"allowComponentAuction", None) + if allowComponentAuctionParam != None: + allowComponentAuction = f"allowComponentAuction: {allowComponentAuctionParam.decode('ASCII')}," - body += f""" - function generateBid(interestGroup, auctionSignals, perBuyerSignals, - trustedBiddingSignals, browserSignals, - directFromSellerSignals) {{ - {{{{GET[generateBid]}}}}; - return {{ - bid: {bid}, - {bidCurrency} - {allowComponentAuction} - render: interestGroup.ads[0].renderURL - }}; - }}""".encode() - if error != b"no-reportWin": - body += b""" - function reportWin(auctionSignals, perBuyerSignals, sellerSignals, - browserSignals, directFromSellerSignals) { - {{GET[reportWin]}}; - }""" - return body + body += f""" + function generateBid(interestGroup, auctionSignals, perBuyerSignals, + trustedBiddingSignals, browserSignals, + directFromSellerSignals) {{ + {{{{GET[generateBid]}}}}; + return {{ + bid: {bid}, + {bidCurrency} + {allowComponentAuction} + render: interestGroup.ads[0].renderURL + }}; + }}""".encode() + if error != b"no-reportWin": + body += b""" + function reportWin(auctionSignals, perBuyerSignals, sellerSignals, + browserSignals, directFromSellerSignals) { + {{GET[reportWin]}}; + }""" + if error != b"no-reportAdditionalBidWin": + body += b""" + function reportAdditionalBidWin(auctionSignals, perBuyerSignals, + sellerSignals, browserSignals, + directFromSellerSignals) { + {{GET[reportAdditionalBidWin]}}; + }""" + return body diff --git a/testing/web-platform/tests/fledge/tentative/resources/decision-logic.sub.py b/testing/web-platform/tests/fledge/tentative/resources/decision-logic.sub.py index 78d459e3f9..3a23f98162 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/decision-logic.sub.py +++ b/testing/web-platform/tests/fledge/tentative/resources/decision-logic.sub.py @@ -43,8 +43,8 @@ def main(request, response): // Don't bid on interest group with the wrong uuid. This is to prevent // left over interest groups from other tests from affecting auction // results. - if (!browserSignals.renderUrl.endsWith('uuid={{GET[uuid]}}') && - !browserSignals.renderUrl.includes('uuid={{GET[uuid]}}&')) { + if (!browserSignals.renderURL.endsWith('uuid={{GET[uuid]}}') && + !browserSignals.renderURL.includes('uuid={{GET[uuid]}}&')) { return 0; } diff --git a/testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js b/testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js index 69573d4998..5819357e29 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js +++ b/testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js @@ -33,7 +33,7 @@ const OTHER_ORIGIN7 = 'https://{{hosts[alt][www]}}:{{ports[https][1]}}'; // on behavior of the script; it only serves to make the URL unique. // `id` will always be the last query parameter. function createTrackerURL(origin, uuid, dispatch, id = null) { - let url = new URL(`${origin}${BASE_PATH}resources/request-tracker.py`); + let url = new URL(`${origin}${RESOURCE_PATH}request-tracker.py`); let search = `uuid=${uuid}&dispatch=${dispatch}`; if (id) search += `&id=${id}`; @@ -59,6 +59,10 @@ function createSellerReportURL(uuid, id = '1', origin = window.location.origin) return createTrackerURL(origin, uuid, `track_get`, `seller_report_${id}`); } +function createHighestScoringOtherBidReportURL(uuid, highestScoringOtherBid) { + return createSellerReportURL(uuid) + '&highestScoringOtherBid=' + Math.round(highestScoringOtherBid); +} + // Much like above ReportURL methods, except designed for beacons, which // are expected to be POSTs. function createBidderBeaconURL(uuid, id = '1', origin = window.location.origin) { @@ -69,7 +73,7 @@ function createSellerBeaconURL(uuid, id = '1', origin = window.location.origin) } function createDirectFromSellerSignalsURL(origin = window.location.origin) { - let url = new URL(`${origin}${BASE_PATH}resources/direct-from-seller-signals.py`); + let url = new URL(`${origin}${RESOURCE_PATH}direct-from-seller-signals.py`); return url.toString(); } @@ -80,7 +84,7 @@ function generateUuid(test) { let uuid = token(); test.add_cleanup(async () => { let response = await fetch(createCleanupURL(uuid), - {credentials: 'omit', mode: 'cors'}); + { credentials: 'omit', mode: 'cors' }); assert_equals(await response.text(), 'cleanup complete', `Sever state cleanup failed`); }); @@ -94,7 +98,7 @@ async function fetchTrackedData(uuid) { let trackedRequestsURL = createTrackerURL(window.location.origin, uuid, 'tracked_data'); let response = await fetch(trackedRequestsURL, - {credentials: 'omit', mode: 'cors'}); + { credentials: 'omit', mode: 'cors' }); let trackedData = await response.json(); // Fail on fetch error. @@ -118,23 +122,29 @@ async function fetchTrackedData(uuid) { // Elements of `expectedRequests` should either be URLs, in the case of GET // requests, or "<URL>, body: <body>" in the case of POST requests. // +// `filter` will be applied to the array of tracked requests. +// // If any other strings are received from the tracking script, or the tracker // script reports an error, fails the test. -async function waitForObservedRequests(uuid, expectedRequests) { +async function waitForObservedRequests(uuid, expectedRequests, filter) { // Sort array for easier comparison, as observed request order does not // matter, and replace UUID to print consistent errors on failure. - expectedRequests = expectedRequests.sort().map((url) => url.replace(uuid, '<uuid>')); + expectedRequests = expectedRequests.map((url) => url.replace(uuid, '<uuid>')).sort(); while (true) { let trackedData = await fetchTrackedData(uuid); // Clean up "trackedRequests" in same manner as "expectedRequests". - let trackedRequests = trackedData.trackedRequests.sort().map( - (url) => url.replace(uuid, '<uuid>')); + let trackedRequests = trackedData.trackedRequests.map( + (url) => url.replace(uuid, '<uuid>')).sort(); + + if (filter) { + trackedRequests = trackedRequests.filter(filter); + } // If expected number of requests have been observed, compare with list of // all expected requests and exit. - if (trackedRequests.length == expectedRequests.length) { + if (trackedRequests.length >= expectedRequests.length) { assert_array_equals(trackedRequests, expectedRequests); break; } @@ -148,6 +158,16 @@ async function waitForObservedRequests(uuid, expectedRequests) { } } + +// Similar to waitForObservedRequests, but ignore forDebuggingOnly reports. +async function waitForObservedRequestsIgnoreDebugOnlyReports( + uuid, expectedRequests) { + return waitForObservedRequests( + uuid, + expectedRequests, + request => !request.includes('forDebuggingOnly')); +} + // Creates a bidding script with the provided code in the method bodies. The // bidding script's generateBid() method will return a bid of 9 for the first // ad, after the passed in code in the "generateBid" input argument has been @@ -163,6 +183,8 @@ function createBiddingScriptURL(params = {}) { url.searchParams.append('generateBid', params.generateBid); if (params.reportWin != null) url.searchParams.append('reportWin', params.reportWin); + if (params.reportAdditionalBidWin != null) + url.searchParams.append('reportAdditionalBidWin', params.reportAdditionalBidWin); if (params.error != null) url.searchParams.append('error', params.error); if (params.bid != null) @@ -254,7 +276,7 @@ async function joinInterestGroup(test, uuid, interestGroupOverrides = {}, await navigator.joinAdInterestGroup(interestGroup, durationSeconds); test.add_cleanup( - async () => {await navigator.leaveAdInterestGroup(interestGroup)}); + async () => { await navigator.leaveAdInterestGroup(interestGroup) }); } // Similar to joinInterestGroup, but leaves the interest group instead. @@ -465,6 +487,24 @@ async function runReportTest(test, uuid, codeToInsert, expectedReportURLs, await waitForObservedRequests(uuid, expectedReportURLs); } +async function runAdditionalBidTest(test, uuid, buyers, auctionNonce, + additionalBidsPromise, + highestScoringOtherBid, + winningAdditionalBidId) { + await runBasicFledgeAuctionAndNavigate( + test, uuid, + { interestGroupBuyers: buyers, + auctionNonce: auctionNonce, + additionalBids: additionalBidsPromise, + decisionLogicURL: createDecisionScriptURL( + uuid, + { reportResult: `sendReportTo("${createSellerReportURL(uuid)}&highestScoringOtherBid=" + Math.round(browserSignals.highestScoringOtherBid));` })}); + + await waitForObservedRequests( + uuid, [createHighestScoringOtherBidReportURL(uuid, highestScoringOtherBid), + createBidderReportURL(uuid, winningAdditionalBidId)]); +} + // Runs "script" in "child_window" via an eval call. The "child_window" must // have been created by calling "createFrame()" below. "param" is passed to the // context "script" is run in, so can be used to pass objects that @@ -504,7 +544,7 @@ async function runInFrame(test, child_window, script, param) { // iframe or closes the window. async function createFrame(test, origin, is_iframe = true, permissions = null) { const frameUuid = generateUuid(test); - const frameUrl = + const frameURL = `${origin}${RESOURCE_PATH}subordinate-frame.sub.html?uuid=${frameUuid}`; let promise = new Promise(function(resolve, reject) { function WaitForMessage(event) { @@ -523,7 +563,7 @@ async function createFrame(test, origin, is_iframe = true, permissions = null) { let iframe = document.createElement('iframe'); if (permissions) iframe.allow = permissions; - iframe.src = frameUrl; + iframe.src = frameURL; document.body.appendChild(iframe); test.add_cleanup(async () => { @@ -535,7 +575,7 @@ async function createFrame(test, origin, is_iframe = true, permissions = null) { return iframe.contentWindow; } - let child_window = window.open(frameUrl); + let child_window = window.open(frameURL); test.add_cleanup(async () => { await runInFrame(test, child_window, "await test_instance.do_cleanup();"); child_window.close(); @@ -576,11 +616,23 @@ async function joinInterestGroupInTopLevelWindow( let interestGroup = JSON.stringify( createInterestGroupForOrigin(uuid, origin, interestGroupOverrides)); - let topLeveWindow = await createTopLevelWindow(test, origin); - await runInFrame(test, topLeveWindow, + let topLevelWindow = await createTopLevelWindow(test, origin); + await runInFrame(test, topLevelWindow, `await joinInterestGroup(test_instance, "${uuid}", ${interestGroup})`); } +// Opens a top-level window and calls joinCrossOriginInterestGroup() in it. +async function joinCrossOriginInterestGroupInTopLevelWindow( + test, uuid, windowOrigin, interestGroupOrigin, interestGroupOverrides = {}) { + let interestGroup = JSON.stringify( + createInterestGroupForOrigin(uuid, interestGroupOrigin, interestGroupOverrides)); + + let topLevelWindow = await createTopLevelWindow(test, windowOrigin); + await runInFrame(test, topLevelWindow, + `await joinCrossOriginInterestGroup( + test_instance, "${uuid}", "${interestGroupOrigin}", ${interestGroup})`); +} + // Fetch directFromSellerSignals from seller and check header // 'Ad-Auction-Signals' is hidden from documents. async function fetchDirectFromSellerSignals(headers_content, origin) { @@ -643,3 +695,46 @@ function directFromSellerSignalsValidatorCode(uuid, expectedSellerSignals, `sendReportTo("${createBidderReportURL(uuid)}");`, }; } + +// Creates an additional bid with the given parameters. This additional bid +// specifies a biddingLogicURL that provides an implementation of +// reportAdditionalBidWin that triggers a sendReportTo() to the bidder report +// URL of the winning additional bid. Additional bids are described in more +// detail at +// https://github.com/WICG/turtledove/blob/main/FLEDGE.md#6-additional-bids. +function createAdditionalBid(uuid, auctionNonce, seller, buyer, interestGroupName, bidAmount, + additionalBidOverrides = {}) { + return { + interestGroup: { + name: interestGroupName, + biddingLogicURL: createBiddingScriptURL( + { + origin: buyer, + reportAdditionalBidWin: `sendReportTo("${createBidderReportURL(uuid, interestGroupName)}");` + }), + owner: buyer + }, + bid: { + ad: ['metadata'], + bid: bidAmount, + render: createRenderURL(uuid) + }, + auctionNonce: auctionNonce, + seller: seller, + ...additionalBidOverrides + } +} + +// Fetch some number of additional bid from a seller and verify that the +// 'Ad-Auction-Additional-Bid' header is not visible in this JavaScript context. +// The `additionalBids` parameter is a list of additional bids. +async function fetchAdditionalBids(seller, additionalBids) { + const url = new URL(`${seller}${RESOURCE_PATH}additional-bids.py`); + url.searchParams.append('additionalBids', JSON.stringify(additionalBids)); + const response = await fetch(url.href, {adAuctionHeaders: true}); + + assert_equals(response.status, 200, 'Failed to fetch additional bid: ' + await response.text()); + assert_false( + response.headers.has('Ad-Auction-Additional-Bid'), + 'Header "Ad-Auction-Additional-Bid" should not be available in JavaScript context.'); +} diff --git a/testing/web-platform/tests/fledge/tentative/resources/permissions.py b/testing/web-platform/tests/fledge/tentative/resources/permissions.py new file mode 100644 index 0000000000..eed93c4275 --- /dev/null +++ b/testing/web-platform/tests/fledge/tentative/resources/permissions.py @@ -0,0 +1,54 @@ +"""Methods for the interest group cross-origin permissions endpoint.""" +import json +import re + +from fledge.tentative.resources import fledge_http_server_util + +SUBDOMAIN_WWW = 'www' +SUBDOMAIN_WWW1 = 'www1' +SUBDOMAIN_WWW2 = 'www2' +SUBDOMAIN_FRENCH = 'élève'.encode('idna').decode() +SUBDOMAIN_JAPANESE = '天気の良い日'.encode('idna').decode() +ALL_SUBDOMAINS = [SUBDOMAIN_WWW, SUBDOMAIN_WWW1, SUBDOMAIN_WWW2, + SUBDOMAIN_FRENCH, SUBDOMAIN_JAPANESE] + +def get_permissions(request, response): + """Returns JSON object containing interest group cross-origin permissions. + + The structure returned is described in more detail at + https://github.com/WICG/turtledove/blob/main/FLEDGE.md#13-permission-delegation. + This correctly handles requests issued in CORS mode. + + This .well-known is fetched at the origin of the interest group's owner, and + specifies as a URL parameter the origin of frame that's attempting to join or + leave that interest group. + + This is implemented such that the origin of the frame is ignored altogether, + and the determination of which operations are allowed depends strictly on the + origin of the interest group owner, and specifically on the subdomain of the + origin of the interest group owner. wptserve serves each of its two domains + at both the raw domain and each of five subdomains. + + - www: disallows both join and leave + - www1: allows join, but not leave + - www2: allows leave, but not join + - 天気の良い日 / élève: allow both join and leave + - anything else (including no subdomain): returns a 404 + """ + if fledge_http_server_util.handle_cors_headers_and_preflight(request, response): + return + + first_domain_label = re.search(r"[^.]*", request.url_parts.netloc).group(0) + if first_domain_label not in ALL_SUBDOMAINS: + response.status = (404, b"Not Found") + response.content = "Not Found" + return + + response.status = (200, b"OK") + response.headers.set(b"Content-Type", b"application/json") + response.content = json.dumps({ + "joinAdInterestGroup": first_domain_label in [ + SUBDOMAIN_WWW1, SUBDOMAIN_FRENCH, SUBDOMAIN_JAPANESE], + "leaveAdInterestGroup": first_domain_label in [ + SUBDOMAIN_WWW2, SUBDOMAIN_FRENCH, SUBDOMAIN_JAPANESE], + }) diff --git a/testing/web-platform/tests/fledge/tentative/resources/request-tracker.py b/testing/web-platform/tests/fledge/tentative/resources/request-tracker.py index c449d2ab02..3514741f63 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/request-tracker.py +++ b/testing/web-platform/tests/fledge/tentative/resources/request-tracker.py @@ -110,4 +110,6 @@ def simple_response(request, response, status_code, status_message, body, content_type=b"text/plain"): response.status = (status_code, status_message) response.headers.set(b"Content-Type", content_type) + # Force refetch on reuse, so multiple requests to tracked URLs are all visible. + response.headers.set(b"Cache-control", b"no-store") return body 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 index 80488a5d6a..eccef5e762 100644 --- a/testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py +++ b/testing/web-platform/tests/fledge/tentative/resources/trusted-scoring-signals.py @@ -15,7 +15,7 @@ def main(request, response): renderUrls = None adComponentRenderURLs = None # List of {type: <render URL type>, urls: <render URL list>} pairs, where <render URL type> is - # one of the two render URL dictionary keys used in the response ("renderUrls" or + # one of the two render URL dictionary keys used in the response ("renderURLs" or # "adComponentRenderURLs"). May be of length 1 or 2, depending on whether there # are any component URLs. urlLists = [] @@ -36,7 +36,7 @@ def main(request, response): continue if pair[0] == "renderUrls" and renderUrls == None: renderUrls = list(map(unquote_plus, pair[1].split(","))) - urlLists.append({"type":"renderUrls", "urls":renderUrls}) + urlLists.append({"type":"renderURLs", "urls":renderUrls}) continue if pair[0] == "adComponentRenderUrls" and adComponentRenderURLs == None: adComponentRenderURLs = list(map(unquote_plus, pair[1].split(","))) diff --git a/testing/web-platform/tests/fledge/tentative/round-a-value.https.window.js b/testing/web-platform/tests/fledge/tentative/round-a-value.https.window.js index 5bccd4ab07..90523e2256 100644 --- a/testing/web-platform/tests/fledge/tentative/round-a-value.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/round-a-value.https.window.js @@ -18,7 +18,7 @@ promise_test(async test => { `browserSignals.adCost === 1.9921875 || browserSignals.adCost === 1.984375`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Check adCost is stochastically rounded with 8 bit mantissa and exponent.'); @@ -35,7 +35,7 @@ promise_test(async test => { `browserSignals.bid === 1.9921875 || browserSignals.bid === 1.984375`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Check bid is stochastically rounded with 8 bit mantissa and exponent.'); @@ -52,7 +52,7 @@ promise_test(async test => { `browserSignals.desirability === 1.9921875 || browserSignals.desirability === 1.984375`, reportResult: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Check desirability is stochastically rounded with 8 bit mantissa and exponent.'); @@ -70,7 +70,7 @@ promise_test(async test => { `browserSignals.highestScoringOtherBid === 1.9921875 || browserSignals.highestScoringOtherBid === 1.984375`, reportResult: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Check highestScoringOtherBid is stochastically rounded with 8 bit mantissa and exponent.'); @@ -87,7 +87,7 @@ promise_test(async test => { `browserSignals.adCost === 2`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Value is ignored as a non-valid floating-point number.'); @@ -104,7 +104,7 @@ promise_test(async test => { `browserSignals.adCost === 0`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Value is rounded to 0 if value is greater than 0 and its exponent is less than -128.'); @@ -121,7 +121,7 @@ promise_test(async test => { `browserSignals.adCost === -0`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Value is rounded to -0 if value is greater than 0 and its exponent is less than -128.'); @@ -138,7 +138,7 @@ promise_test(async test => { `browserSignals.adCost === Infinity`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Value is rounded to Infinity if value is greater than 0 and its exponent is greater than 127.'); @@ -155,7 +155,7 @@ promise_test(async test => { `browserSignals.adCost === -Infinity`, reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls + // expectedReportURLs [createBidderReportURL(uuid)] ); }, 'Value is rounded to -Infinity if value is less than 0 and its exponent is greater than 127.'); diff --git a/testing/web-platform/tests/fledge/tentative/send-report-to.https.window.js b/testing/web-platform/tests/fledge/tentative/send-report-to.https.window.js index 65a2520420..e3cf0a95f1 100644 --- a/testing/web-platform/tests/fledge/tentative/send-report-to.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/send-report-to.https.window.js @@ -18,7 +18,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid), createBidderReportURL(uuid)] ); }, 'Both send reports, seller passes nothing to bidder.'); @@ -31,7 +31,7 @@ subsetTest(promise_test, async test => { `sendReportTo('${createSellerReportURL(uuid)}');`, reportWin: '' }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid)] ); }, 'Only seller sends a report'); @@ -44,7 +44,7 @@ subsetTest(promise_test, async test => { `sendReportTo('${createSellerReportURL(uuid)}');`, reportWin: 'throw new Error("Very serious exception")' }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid)] ); }, 'Only seller sends a report, bidder throws an exception'); @@ -55,7 +55,7 @@ subsetTest(promise_test, async test => { test, uuid, { reportResult: `sendReportTo('${createSellerReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid)] ); }, 'Only seller sends a report, bidder has no reportWin() method'); @@ -70,7 +70,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)] ); }, 'Only bidder sends a report'); @@ -85,7 +85,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === "foo"', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)] ); }, 'Only bidder sends a report, seller passes a message to bidder'); @@ -100,7 +100,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)] ); }, 'Only bidder sends a report, seller throws an exception'); @@ -113,7 +113,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)] ); }, 'Only bidder sends a report, seller has no reportResult() method'); @@ -130,7 +130,7 @@ subsetTest(promise_test, async test => { 'sellerSignals === null', reportWin: `sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createBidderReportURL(uuid)] ); }, 'Seller calls sendReportTo() twice, which throws an exception.'); @@ -144,7 +144,7 @@ subsetTest(promise_test, async test => { reportWin: `sendReportTo('${createBidderReportURL(uuid)}'); sendReportTo('${createBidderReportURL(uuid)}');` }, - // expectedReportUrls: + // expectedReportURLs: [createSellerReportURL(uuid)] ); // Seller reports may be sent before bidder reports, since reportWin() diff --git a/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.window.js b/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.window.js index 67ae3577e4..4de5cfc0f3 100644 --- a/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.window.js +++ b/testing/web-platform/tests/fledge/tentative/trusted-scoring-signals.https.window.js @@ -82,7 +82,7 @@ async function runTrustedScoringSignalsDataVersionTest( // 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) { +function createScoringSignalsRenderURLWithBody(uuid, responseBody) { return createRenderURL(uuid, /*script=*/null, /*signalsParam=*/`replace-body:${responseBody}`); } @@ -93,13 +93,13 @@ function createScoringSignalsRenderUrlWithBody(uuid, responseBody) { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const decisionLogicScriptUrl = createDecisionScriptURL( + const decisionLogicScriptURL = createDecisionScriptURL( uuid, { scoreAd: 'if (trustedScoringSignals !== null) throw "error";' }); await joinGroupAndRunBasicFledgeTestExpectingWinner( test, { uuid: uuid, - auctionConfigOverrides: { decisionLogicURL: decisionLogicScriptUrl } + auctionConfigOverrides: { decisionLogicURL: decisionLogicScriptURL } }); }, 'No trustedScoringSignalsURL.'); @@ -149,35 +149,35 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + const renderURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/''); await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); }, 'Trusted scoring signals response has no body.'); subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + const renderURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/'Not JSON'); await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); }, 'Trusted scoring signals response is not JSON.'); subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + const renderURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/'[]'); await runTrustedScoringSignalsTest(test, uuid, renderURL, 'trustedScoringSignals === null'); }, 'Trusted scoring signals response is a JSON array.'); subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + 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.'); subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + const renderURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/'{}'); await runTrustedScoringSignalsTest( test, uuid, renderURL, @@ -444,7 +444,7 @@ subsetTest(promise_test, async test => { const renderURL = createRenderURL(uuid, /*script=*/null, /*signalsParam=*/'num-value'); // This should not be sent. If it is, it will take precedence over the "num-value" parameter // from "renderURL", resulting in the "renderURL" having a null "trustedScoringSignals" value. - const componentURL = createScoringSignalsRenderUrlWithBody( + const componentURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/'{}'); await runTrustedScoringSignalsTest( test, uuid, renderURL, @@ -456,7 +456,7 @@ subsetTest(promise_test, async test => { subsetTest(promise_test, async test => { const uuid = generateUuid(test); - const renderURL = createScoringSignalsRenderUrlWithBody( + const renderURL = createScoringSignalsRenderURLWithBody( uuid, /*responseBody=*/'{}'); const componentURL = createRenderURL(uuid, /*script=*/null); await runTrustedScoringSignalsTest( |