Field trial testing config for sampling debug reports.
Enable FledgeSampleDebugReports in field trial config. Add a WPT to test browserSignals.forDebuggingOnlyInCooldownOrLockout is set to true in generatedBid() and scoreAd() after an earlier auction made them under lockout or cooldown.
Bug: b/310944302
Change-Id: Ibb8129d1c61acfbda6fb2967404de89612c20c0d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5285079
Reviewed-by: Russ Hamilton <behamilton@google.com>
Commit-Queue: Qingxin Wu <qingxinwu@google.com>
Cr-Commit-Position: refs/heads/main@{#1259861}
diff --git a/fledge/tentative/auction-config.https.window.js b/fledge/tentative/auction-config.https.window.js
index 3b5814b..8fbdc95 100644
--- a/fledge/tentative/auction-config.https.window.js
+++ b/fledge/tentative/auction-config.https.window.js
@@ -390,3 +390,80 @@
[{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/fledge/tentative/component-auction.https.window.js b/fledge/tentative/component-auction.https.window.js
index 63771d4..c705320 100644
--- a/fledge/tentative/component-auction.https.window.js
+++ b/fledge/tentative/component-auction.https.window.js
@@ -671,7 +671,7 @@
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/fledge/tentative/resources/fledge-util.sub.js b/fledge/tentative/resources/fledge-util.sub.js
index 69573d4..f64e97a 100644
--- a/fledge/tentative/resources/fledge-util.sub.js
+++ b/fledge/tentative/resources/fledge-util.sub.js
@@ -148,6 +148,35 @@
}
}
+
+// Similar to waitForObservedRequests, but ignore forDebuggingOnly reports.
+async function waitForObservedRequestsIgnoreDebugOnlyReports(
+ uuid, expectedRequests) {
+ // 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>'));
+
+ while (true) {
+ let numTrackedRequest = 0;
+ let trackedData = await fetchTrackedData(uuid);
+
+ // Clean up "trackedRequests" in same manner as "expectedRequests".
+ let trackedRequests = trackedData.trackedRequests.sort().map(
+ (url) => url.replace(uuid, '<uuid>'));
+
+ for (const trackedRequest of trackedRequests) {
+ // Ignore forDebuggingOnly reports, since their appearance is random.
+ if (!trackedRequest.includes('forDebuggingOnly')) {
+ assert_in_array(trackedRequest, expectedRequests);
+ numTrackedRequest++;
+ }
+ }
+
+ if (numTrackedRequest == expectedRequests.length) break;
+ }
+}
+
// 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