diff options
Diffstat (limited to 'testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js')
-rw-r--r-- | testing/web-platform/tests/fledge/tentative/resources/fledge-util.sub.js | 125 |
1 files changed, 110 insertions, 15 deletions
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.'); +} |