diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:27 +0000 |
commit | 40a355a42d4a9444dc753c04c6608dade2f06a23 (patch) | |
tree | 871fc667d2de662f171103ce5ec067014ef85e61 /testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js | |
parent | Adding upstream version 124.0.1. (diff) | |
download | firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip |
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js')
-rw-r--r-- | testing/web-platform/tests/fledge/tentative/generate-bid-browser-signals.https.window.js | 946 |
1 files changed, 946 insertions, 0 deletions
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.'); |