From 9f74d5ac5963eaff3d8bd07ed738754197a94507 Mon Sep 17 00:00:00 2001 From: Matt Menke Date: Thu, 15 Feb 2024 11:59:10 -0800 Subject: [PATCH] [Protected Audiences] Add some generateBid browserSignals tests. These include a basic all-fields test, and joinCount tests. Still need tests for bidCount and prevWinsMs. Bug: 40261114 Change-Id: I5ceebca3e26bba6083c5d4e9631ff94e69e634e9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5285076 Reviewed-by: Maks Orlovich Commit-Queue: mmenke Cr-Commit-Position: refs/heads/main@{#1261242} --- ...nerate-bid-browser-signals.https.window.js | 147 ++++++++++++++++++ .../generate-bid-recency.https.window.js | 34 ---- fledge/tentative/resources/fledge-util.sub.js | 16 +- 3 files changed, 161 insertions(+), 36 deletions(-) create mode 100644 fledge/tentative/generate-bid-browser-signals.https.window.js delete mode 100644 fledge/tentative/generate-bid-recency.https.window.js diff --git a/fledge/tentative/generate-bid-browser-signals.https.window.js b/fledge/tentative/generate-bid-browser-signals.https.window.js new file mode 100644 index 00000000000000..3ab8bbf51f6baf --- /dev/null +++ b/fledge/tentative/generate-bid-browser-signals.https.window.js @@ -0,0 +1,147 @@ +// 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;" + +// 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.'); diff --git a/fledge/tentative/generate-bid-recency.https.window.js b/fledge/tentative/generate-bid-recency.https.window.js deleted file mode 100644 index a8ab5f97484c72..00000000000000 --- a/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/fledge/tentative/resources/fledge-util.sub.js b/fledge/tentative/resources/fledge-util.sub.js index 212531e3f78dbf..4fc77933634aa2 100644 --- a/fledge/tentative/resources/fledge-util.sub.js +++ b/fledge/tentative/resources/fledge-util.sub.js @@ -605,11 +605,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) {