tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

currency.https.window.js (34240B)


      1 // META: script=/resources/testdriver.js
      2 // META: script=/resources/testdriver-vendor.js
      3 // META: script=/common/utils.js
      4 // META: script=resources/fledge-util.sub.js
      5 // META: script=/common/subset-tests.js
      6 // META: timeout=long
      7 // META: variant=?1-4
      8 // META: variant=?5-8
      9 // META: variant=?9-12
     10 // META: variant=?13-16
     11 // META: variant=?17-20
     12 // META: variant=?21-24
     13 // META: variant=?25-28
     14 // META: variant=?29-32
     15 // META: variant=?33-last
     16 
     17 'use strict';
     18 
     19 const ORIGIN = window.location.origin;
     20 
     21 // The tests in this file focus on calls to runAdAuction involving currency
     22 // handling.
     23 
     24 // Joins an interest group that bids 9USD on window.location.origin, and one
     25 // that bids 10CAD on OTHER_ORIGIN1, each with a reportWin() report.
     26 async function joinTwoCurrencyGroups(test, uuid) {
     27  const reportWinURL = createBidderReportURL(uuid, 'USD');
     28  const biddingURL = createBiddingScriptURL(
     29      {bidCurrency: 'USD', reportWin: `sendReportTo('${reportWinURL}')`});
     30  await joinInterestGroup(test, uuid, {biddingLogicURL: biddingURL});
     31 
     32  const otherReportWinURL = createBidderReportURL(uuid, 'CAD', OTHER_ORIGIN1);
     33  const otherBiddingURL = createBiddingScriptURL({
     34    origin: OTHER_ORIGIN1,
     35    bid: 10,
     36    bidCurrency: 'CAD',
     37    reportWin: `sendReportTo('${otherReportWinURL}')`
     38  });
     39  await joinCrossOriginInterestGroup(
     40      test, uuid, OTHER_ORIGIN1, {biddingLogicURL: otherBiddingURL});
     41 }
     42 
     43 function createBiddingScriptURLWithCurrency(uuid, currency) {
     44  return createBiddingScriptURL({
     45    bidCurrency: currency,
     46    allowComponentAuction: true,
     47    reportWin: `
     48        sendReportTo('${createBidderReportURL(uuid, /*id=*/ '')}' +
     49                     browserSignals.bid + browserSignals.bidCurrency);`,
     50  });
     51 }
     52 
     53 // Creates a component-auction eligible bidding script returning a bid `bid` in
     54 // currency `currency`. It provides a reporting handler that logs bid and
     55 // highestScoringOtherBid along with their currencies.
     56 function createBiddingScriptURLForHighestScoringOther(uuid, bid, currency) {
     57  return createBiddingScriptURL({
     58    bid: bid,
     59    bidCurrency: currency,
     60    allowComponentAuction: true,
     61    generateBid: `
     62      forDebuggingOnly.reportAdAuctionWin(
     63          '${createBidderReportURL(uuid, /*id=*/ 'dbg_')}' +
     64          '\${winningBid}\${winningBidCurrency}_' +
     65          '\${highestScoringOtherBid}\${highestScoringOtherBidCurrency}');`,
     66    reportWin: `
     67        sendReportTo(
     68            '${createBidderReportURL(uuid, /*id=*/ '')}' +
     69            browserSignals.bid + browserSignals.bidCurrency +
     70            '_' + browserSignals.highestScoringOtherBid +
     71            browserSignals.highestScoringOtherBidCurrency);`,
     72  });
     73 }
     74 
     75 function createDecisionURLExpectCurrency(uuid, currencyInScore) {
     76  return createDecisionScriptURL(uuid, {
     77    scoreAd: `
     78            if (browserSignals.bidCurrency !== '${currencyInScore}')
     79              throw 'Wrong currency';`,
     80    reportResult: `
     81          sendReportTo('${createSellerReportURL(uuid, /*id=*/ '')}' +
     82                         browserSignals.bid + browserSignals.bidCurrency);`,
     83  });
     84 }
     85 
     86 // Creates a component-auction seller script, which by default just scores
     87 // bid * 2, but the `conversion` argument can be used to customize bid
     88 // modification and currenct conversion.
     89 //
     90 // The script provides a reporting handler that logs bid and
     91 // highestScoringOtherBid along with their currencies as well as `suffix`.
     92 function createDecisionURLForHighestScoringOther(
     93    uuid, conversion = '', suffix = '') {
     94  return createDecisionScriptURL(uuid, {
     95    scoreAd: `
     96      forDebuggingOnly.reportAdAuctionWin(
     97          '${createSellerReportURL(uuid, /*id=*/ 'dbg_')}' + '${suffix}' +
     98          '\${winningBid}\${winningBidCurrency}_' +
     99          '\${highestScoringOtherBid}\${highestScoringOtherBidCurrency}');
    100      let converted = undefined;
    101      let modified = undefined;
    102      let modifiedCurrency = undefined;
    103      ${conversion}
    104      return {desirability: 2 * bid,
    105              incomingBidInSellerCurrency: converted,
    106              bid: modified,
    107              bidCurrency: modifiedCurrency,
    108              allowComponentAuction: true};
    109    `,
    110    reportResult: `
    111        sendReportTo(
    112            '${createSellerReportURL(uuid, /*id=*/ '')}' + '${suffix}' +
    113            browserSignals.bid + browserSignals.bidCurrency +
    114            '_' + browserSignals.highestScoringOtherBid +
    115            browserSignals.highestScoringOtherBidCurrency);`,
    116  });
    117 }
    118 
    119 // Joins groups for 9USD and 10USD, with reporting including
    120 // highestScoringOtherBid.
    121 async function joinTwoGroupsForHighestScoringOther(test, uuid) {
    122  await joinInterestGroup(test, uuid, {
    123    name: 'group-9USD',
    124    biddingLogicURL:
    125        createBiddingScriptURLForHighestScoringOther(uuid, /*bid=*/ 9, 'USD')
    126  });
    127  await joinInterestGroup(test, uuid, {
    128    name: 'group-10USD',
    129    biddingLogicURL:
    130        createBiddingScriptURLForHighestScoringOther(uuid, /*bid=*/ 10, 'USD')
    131  });
    132 }
    133 
    134 async function runCurrencyComponentAuction(test, uuid, params = {}) {
    135  let auctionConfigOverrides = {
    136    interestGroupBuyers: [],
    137    decisionLogicURL: createDecisionScriptURL(uuid, {
    138      reportResult: `
    139        sendReportTo('${createSellerReportURL(uuid, 'top_')}' +
    140                     browserSignals.bid + browserSignals.bidCurrency)`,
    141      ...params.topLevelSellerScriptParamsOverride
    142    }),
    143    componentAuctions: [{
    144      seller: ORIGIN,
    145      decisionLogicURL: createDecisionScriptURL(uuid, {
    146        reportResult: `
    147          sendReportTo('${createSellerReportURL(uuid, 'component_')}' +
    148                       browserSignals.bid + browserSignals.bidCurrency)`,
    149        ...params.componentSellerScriptParamsOverride
    150      }),
    151      interestGroupBuyers: [ORIGIN],
    152      ...params.componentAuctionConfigOverrides
    153    }],
    154    ...params.topLevelAuctionConfigOverrides
    155  };
    156  return await runBasicFledgeAuction(test, uuid, auctionConfigOverrides);
    157 }
    158 
    159 // Runs a component auction with reporting scripts that report bid and
    160 // highestScoringOtherBid, along with their currencies.
    161 //
    162 // Customization points in `params` are:
    163 // componentAuctionConfigOverrides, topLevelAuctionConfigOverrides:
    164 // edit auctionConfig for given auction level.
    165 //
    166 // topLevelConversion and componentConversion:
    167 // Permit customizing how the scoring function does currency conversiona and
    168 // bid modification. See createDecisionURLForHighestScoringOther().
    169 async function runCurrencyComponentAuctionForHighestScoringOther(
    170    test, uuid, params = {}) {
    171  let auctionConfigOverrides = {
    172    interestGroupBuyers: [],
    173    decisionLogicURL: createDecisionURLForHighestScoringOther(
    174        uuid, params.topLevelConversion || '', 'top_'),
    175    componentAuctions: [{
    176      seller: ORIGIN,
    177      decisionLogicURL: createDecisionURLForHighestScoringOther(
    178          uuid, params.componentConversion || '', 'component_'),
    179      interestGroupBuyers: [ORIGIN],
    180      ...params.componentAuctionConfigOverrides
    181    }],
    182    ...params.topLevelAuctionConfigOverrides
    183  };
    184  return await runBasicFledgeAuction(test, uuid, auctionConfigOverrides);
    185 }
    186 
    187 subsetTest(promise_test, async test => {
    188  const uuid = generateUuid(test);
    189  await joinInterestGroup(
    190      test, uuid,
    191      {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'usd'})});
    192  await runBasicFledgeTestExpectingNoWinner(test, uuid);
    193 }, 'Returning bid with invalid currency.');
    194 
    195 subsetTest(promise_test, async test => {
    196  const uuid = generateUuid(test);
    197  await joinInterestGroup(
    198      test, uuid,
    199      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    200  await runBasicFledgeAuctionAndNavigate(
    201      test, uuid,
    202      {decisionLogicURL: createDecisionURLExpectCurrency(uuid, 'USD')});
    203  await waitForObservedRequests(uuid, [
    204    createSellerReportURL(uuid, '9???'), createBidderReportURL(uuid, '9???')
    205  ]);
    206 }, 'Returning bid with currency, configuration w/o currency.');
    207 
    208 subsetTest(promise_test, async test => {
    209  const uuid = generateUuid(test);
    210  await joinInterestGroup(
    211      test, uuid,
    212      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, undefined)});
    213  await runBasicFledgeAuctionAndNavigate(test, uuid, {
    214    perBuyerCurrencies: {'*': 'USD'},
    215    decisionLogicURL: createDecisionURLExpectCurrency(uuid, '???')
    216  });
    217  await waitForObservedRequests(uuid, [
    218    createSellerReportURL(uuid, '9USD'), createBidderReportURL(uuid, '9USD')
    219  ]);
    220 }, 'Returning bid w/o currency, configuration w/currency.');
    221 
    222 subsetTest(promise_test, async test => {
    223  const uuid = generateUuid(test);
    224  await joinInterestGroup(
    225      test, uuid,
    226      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    227  await runBasicFledgeAuctionAndNavigate(test, uuid, {
    228    perBuyerCurrencies: {'*': 'USD'},
    229    decisionLogicURL: createDecisionURLExpectCurrency(uuid, 'USD')
    230  });
    231  await waitForObservedRequests(uuid, [
    232    createSellerReportURL(uuid, '9USD'), createBidderReportURL(uuid, '9USD')
    233  ]);
    234 }, 'Returning bid w/currency, configuration w/matching currency.');
    235 
    236 subsetTest(promise_test, async test => {
    237  const uuid = generateUuid(test);
    238  await joinInterestGroup(
    239      test, uuid,
    240      {biddingLogicURL: createBiddingScriptURL({bidCurrency: 'USD'})});
    241  await runBasicFledgeTestExpectingNoWinner(
    242      test, uuid, {perBuyerCurrencies: {'*': 'CAD'}});
    243 }, 'Returning bid w/currency, configuration w/different currency.');
    244 
    245 subsetTest(promise_test, async test => {
    246  const uuid = generateUuid(test);
    247  await joinTwoCurrencyGroups(test, uuid);
    248  let auctionConfigOverrides = {
    249    interestGroupBuyers: [ORIGIN, OTHER_ORIGIN1],
    250    perBuyerCurrencies: {}
    251  };
    252  auctionConfigOverrides.perBuyerCurrencies['*'] = 'USD';
    253  auctionConfigOverrides.perBuyerCurrencies[OTHER_ORIGIN1] = 'CAD';
    254  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
    255 
    256  // Since the scoring script doesn't actually look at the currencies,
    257  // We expect 10CAD to win because 10 > 9
    258  await waitForObservedRequests(uuid, [
    259    createBidderReportURL(uuid, 'CAD', OTHER_ORIGIN1),
    260    createSellerReportURL(uuid)
    261  ]);
    262 }, 'Different currencies for different origins, all match.');
    263 
    264 subsetTest(promise_test, async test => {
    265  const uuid = generateUuid(test);
    266  await joinTwoCurrencyGroups(test, uuid);
    267  let auctionConfigOverrides = {
    268    interestGroupBuyers: [ORIGIN, OTHER_ORIGIN1],
    269    perBuyerCurrencies: {}
    270  };
    271  auctionConfigOverrides.perBuyerCurrencies[ORIGIN] = 'USD';
    272  auctionConfigOverrides.perBuyerCurrencies[OTHER_ORIGIN1] = 'EUR';
    273  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
    274 
    275  // Since the configuration for CAD script expects EUR only the USD bid goes
    276  // through.
    277  await waitForObservedRequests(
    278      uuid, [createBidderReportURL(uuid, 'USD'), createSellerReportURL(uuid)]);
    279 }, 'Different currencies for different origins, USD one matches.');
    280 
    281 subsetTest(promise_test, async test => {
    282  const uuid = generateUuid(test);
    283  await joinTwoCurrencyGroups(test, uuid);
    284  let auctionConfigOverrides = {
    285    interestGroupBuyers: [ORIGIN, OTHER_ORIGIN1],
    286    perBuyerCurrencies: {}
    287  };
    288  auctionConfigOverrides.perBuyerCurrencies['*'] = 'EUR';
    289 }, 'Different currencies for different origins, none match.');
    290 
    291 subsetTest(promise_test, async test => {
    292  const uuid = generateUuid(test);
    293  await joinInterestGroup(
    294      test, uuid,
    295      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    296  let config = await runCurrencyComponentAuction(test, uuid, {
    297    topLevelSellerScriptParamsOverride: {
    298      scoreAd: `
    299              if (browserSignals.bidCurrency !== 'USD')
    300                throw 'Wrong currency';`
    301    }
    302  });
    303  expectSuccess(config);
    304  createAndNavigateFencedFrame(test, config);
    305  // While scoring sees the original currency tag, reporting currency tags are
    306  // config-based.
    307  await waitForObservedRequests(uuid, [
    308    createSellerReportURL(uuid, 'top_9???'),
    309    createSellerReportURL(uuid, 'component_9???'),
    310    createBidderReportURL(uuid, '9???')
    311  ]);
    312 }, 'Multi-seller auction --- no currency restriction.');
    313 
    314 
    315 subsetTest(promise_test, async test => {
    316  const uuid = generateUuid(test);
    317  await joinInterestGroup(
    318      test, uuid,
    319      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    320  let config = await runCurrencyComponentAuction(test, uuid, {
    321    componentAuctionConfigOverrides: {sellerCurrency: 'USD'},
    322    topLevelSellerScriptParamsOverride: {
    323      scoreAd: `
    324                if (browserSignals.bidCurrency !== 'USD')
    325                  throw 'Wrong currency';`
    326    }
    327  });
    328  expectSuccess(config);
    329  createAndNavigateFencedFrame(test, config);
    330  // Because component's sellerCurrency is USD, the bid it makes is seen to be
    331  // in dollars by top-level reporting. That doesn't affect reporting in its
    332  // own auction.
    333  await waitForObservedRequests(uuid, [
    334    createSellerReportURL(uuid, 'top_9USD'),
    335    createSellerReportURL(uuid, 'component_9???'),
    336    createBidderReportURL(uuid, '9???')
    337  ]);
    338 }, 'Multi-seller auction --- component sellerCurrency matches bid.');
    339 
    340 subsetTest(promise_test, async test => {
    341  const uuid = generateUuid(test);
    342  await joinInterestGroup(
    343      test, uuid,
    344      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    345  let config = await runCurrencyComponentAuction(test, uuid, {
    346    componentAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    347    componentSellerScriptParamsOverride: {
    348      scoreAd: `
    349        return {desirability: 2 * bid, allowComponentAuction: true,
    350                 bid: 1.5 * bid, bidCurrency: 'EUR'}
    351      `
    352    },
    353    topLevelSellerScriptParamsOverride: {
    354      scoreAd: `
    355                if (browserSignals.bidCurrency !== 'EUR')
    356                  throw 'Wrong currency';`
    357    }
    358  });
    359  expectSuccess(config);
    360  createAndNavigateFencedFrame(test, config);
    361  // Because component's sellerCurrency is USD, the bid it makes is seen to be
    362  // in dollars by top-level reporting. That doesn't affect reporting in its
    363  // own auction.
    364  await waitForObservedRequests(uuid, [
    365    createSellerReportURL(uuid, 'top_13.5EUR'),
    366    createSellerReportURL(uuid, 'component_9???'),
    367    createBidderReportURL(uuid, '9???')
    368  ]);
    369 }, 'Multi-seller auction --- component scoreAd modifies bid into its sellerCurrency.');
    370 
    371 subsetTest(promise_test, async test => {
    372  const uuid = generateUuid(test);
    373  await joinInterestGroup(
    374      test, uuid,
    375      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    376  let config = await runCurrencyComponentAuction(test, uuid, {
    377    componentAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    378    componentSellerScriptParamsOverride: {
    379      scoreAd: `
    380        return {desirability: 2 * bid, allowComponentAuction: true,
    381                 bid: 1.5 * bid}
    382      `
    383    },
    384    topLevelSellerScriptParamsOverride: {
    385      scoreAd: `
    386                // scoreAd sees what's actually passed in.
    387                if (browserSignals.bidCurrency !== '???')
    388                  throw 'Wrong currency';`
    389    }
    390  });
    391  expectSuccess(config);
    392  createAndNavigateFencedFrame(test, config);
    393  await waitForObservedRequests(uuid, [
    394    createSellerReportURL(uuid, 'top_13.5EUR'),
    395    createSellerReportURL(uuid, 'component_9???'),
    396    createBidderReportURL(uuid, '9???')
    397  ]);
    398 }, 'Multi-seller auction --- component scoreAd modifies bid, no explicit currency.');
    399 
    400 subsetTest(promise_test, async test => {
    401  const uuid = generateUuid(test);
    402  await joinInterestGroup(
    403      test, uuid,
    404      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    405  let config = await runCurrencyComponentAuction(test, uuid, {
    406    componentAuctionConfigOverrides:
    407        {sellerCurrency: 'EUR', perBuyerCurrencies: {'*': 'USD'}},
    408    componentSellerScriptParamsOverride: {
    409      scoreAd: `
    410        return {desirability: 2 * bid, allowComponentAuction: true,
    411                 bid: 1.5 * bid}
    412      `
    413    },
    414    topLevelSellerScriptParamsOverride: {
    415      scoreAd: `
    416                // scoreAd sees what's actually passed in.
    417                if (browserSignals.bidCurrency !== '???')
    418                  throw 'Wrong currency';`
    419    }
    420  });
    421  expectSuccess(config);
    422  createAndNavigateFencedFrame(test, config);
    423  await waitForObservedRequests(uuid, [
    424    createSellerReportURL(uuid, 'top_13.5EUR'),
    425    createSellerReportURL(uuid, 'component_9USD'),
    426    createBidderReportURL(uuid, '9USD')
    427  ]);
    428 }, 'Multi-seller auction --- component scoreAd modifies bid, bidder has bidCurrency.');
    429 
    430 subsetTest(promise_test, async test => {
    431  const uuid = generateUuid(test);
    432  await joinInterestGroup(
    433      test, uuid,
    434      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    435  let config = await runCurrencyComponentAuction(test, uuid, {
    436    componentAuctionConfigOverrides: {perBuyerCurrencies: {'*': 'USD'}},
    437    componentSellerScriptParamsOverride: {
    438      scoreAd: `
    439        return {desirability: 2 * bid, allowComponentAuction: true,
    440                 bid: 1.5 * bid}
    441      `
    442    },
    443    topLevelSellerScriptParamsOverride: {
    444      scoreAd: `
    445                // scoreAd sees what's actually passed in.
    446                if (browserSignals.bidCurrency !== '???')
    447                  throw 'Wrong currency';`
    448    }
    449  });
    450  expectSuccess(config);
    451  createAndNavigateFencedFrame(test, config);
    452  await waitForObservedRequests(uuid, [
    453    createSellerReportURL(uuid, 'top_13.5???'),
    454    createSellerReportURL(uuid, 'component_9USD'),
    455    createBidderReportURL(uuid, '9USD')
    456  ]);
    457 }, 'Multi-seller auction --- only bidder currency specified.');
    458 
    459 subsetTest(promise_test, async test => {
    460  const uuid = generateUuid(test);
    461  await joinInterestGroup(
    462      test, uuid,
    463      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    464  let config = await runCurrencyComponentAuction(test, uuid, {
    465    componentAuctionConfigOverrides: {perBuyerCurrencies: {'*': 'USD'}},
    466    componentSellerScriptParamsOverride: {
    467      scoreAd: `
    468        return {desirability: 2 * bid, allowComponentAuction: true,
    469                 bid: 1.5 * bid, bidCurrency: 'CAD'}
    470      `
    471    },
    472    topLevelSellerScriptParamsOverride: {
    473      scoreAd: `
    474                // scoreAd sees what's actually passed in.
    475                if (browserSignals.bidCurrency !== 'CAD')
    476                  throw 'Wrong currency';`
    477    }
    478  });
    479  expectSuccess(config);
    480  createAndNavigateFencedFrame(test, config);
    481  await waitForObservedRequests(uuid, [
    482    createSellerReportURL(uuid, 'top_13.5???'),
    483    createSellerReportURL(uuid, 'component_9USD'),
    484    createBidderReportURL(uuid, '9USD')
    485  ]);
    486 }, 'Multi-seller auction --- only bidder currency in config, component uses explicit currency.');
    487 
    488 subsetTest(promise_test, async test => {
    489  const uuid = generateUuid(test);
    490  await joinInterestGroup(test, uuid, {
    491    biddingLogicURL:
    492        createBiddingScriptURLWithCurrency(uuid, /*bidCurrency=*/ undefined)
    493  });
    494  let config = await runCurrencyComponentAuction(test, uuid, {
    495    componentAuctionConfigOverrides: {sellerCurrency: 'CAD'},
    496    componentSellerScriptParamsOverride: {
    497      scoreAd: `
    498        return {desirability: 2 * bid, allowComponentAuction: true,
    499                 incomingBidInSellerCurrency: 12345}
    500      `
    501    },
    502    topLevelSellerScriptParamsOverride: {
    503      scoreAd: `
    504                // scoreAd sees what's actually passed in.
    505                if (bid !== 9)
    506                  throw 'Wrong bid';
    507                if (browserSignals.bidCurrency !== '???')
    508                  throw 'Wrong currency';`
    509    }
    510  });
    511  expectSuccess(config);
    512  createAndNavigateFencedFrame(test, config);
    513  await waitForObservedRequests(uuid, [
    514    createSellerReportURL(uuid, 'top_9CAD'),
    515    createSellerReportURL(uuid, 'component_9???'),
    516    createBidderReportURL(uuid, '9???')
    517  ]);
    518 }, 'Multi-seller auction --- incomingBidInSellerCurrency does not go to top-level; component sellerCurrency does.');
    519 
    520 subsetTest(promise_test, async test => {
    521  const uuid = generateUuid(test);
    522  await joinInterestGroup(
    523      test, uuid,
    524      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    525  let result = await runCurrencyComponentAuction(test, uuid, {
    526    componentAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    527    componentSellerScriptParamsOverride: {
    528      scoreAd: `
    529        return {desirability: 2 * bid, allowComponentAuction: true,
    530                 bid: 1.5 * bid, bidCurrency: 'CAD'}
    531      `
    532    }
    533  });
    534  expectNoWinner(result);
    535 }, 'Multi-seller auction --- component scoreAd modifies bid to wrong currency.');
    536 
    537 subsetTest(promise_test, async test => {
    538  const uuid = generateUuid(test);
    539  await joinInterestGroup(
    540      test, uuid,
    541      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    542  let topLevelConfigOverride = {perBuyerCurrencies: {}};
    543  topLevelConfigOverride.perBuyerCurrencies[ORIGIN] = 'USD';
    544  let config = await runCurrencyComponentAuction(test, uuid, {
    545    topLevelAuctionConfigOverrides: topLevelConfigOverride,
    546    topLevelSellerScriptParamsOverride: {
    547      scoreAd: `
    548              if (browserSignals.bidCurrency !== 'USD')
    549                throw 'Wrong currency';`
    550    }
    551  });
    552  expectSuccess(config);
    553  createAndNavigateFencedFrame(test, config);
    554  // Because component is constrained by perBuyerCurrencies for it on top-level
    555  // to USD, the bid it makes is seen to be in dollars by top-level reporting.
    556  // That doesn't affect reporting in its own auction.
    557  await waitForObservedRequests(uuid, [
    558    createSellerReportURL(uuid, 'top_9USD'),
    559    createSellerReportURL(uuid, 'component_9???'),
    560    createBidderReportURL(uuid, '9???')
    561  ]);
    562 }, 'Multi-seller auction --- top-level perBuyerCurrencies matches bid.');
    563 
    564 subsetTest(promise_test, async test => {
    565  const uuid = generateUuid(test);
    566  await joinInterestGroup(
    567      test, uuid,
    568      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    569  let topLevelConfigOverride = {perBuyerCurrencies: {}};
    570  topLevelConfigOverride.perBuyerCurrencies[ORIGIN] = 'USD';
    571  let config = await runCurrencyComponentAuction(test, uuid, {
    572    componentAuctionConfigOverrides: {sellerCurrency: 'USD'},
    573    topLevelAuctionConfigOverrides: topLevelConfigOverride,
    574    topLevelSellerScriptParamsOverride: {
    575      scoreAd: `
    576              if (browserSignals.bidCurrency !== 'USD')
    577                throw 'Wrong currency';`
    578    }
    579  });
    580  expectSuccess(config);
    581  createAndNavigateFencedFrame(test, config);
    582  // Because component is constrained by perBuyerCurrencies for it on top-level
    583  // to USD, the bid it makes is seen to be in dollars by top-level reporting.
    584  // That doesn't affect reporting in its own auction.
    585  await waitForObservedRequests(uuid, [
    586    createSellerReportURL(uuid, 'top_9USD'),
    587    createSellerReportURL(uuid, 'component_9???'),
    588    createBidderReportURL(uuid, '9???')
    589  ]);
    590 }, 'Multi-seller auction --- consistent sellerConfig and top-level perBuyerCurrencies.');
    591 
    592 subsetTest(promise_test, async test => {
    593  const uuid = generateUuid(test);
    594  await joinInterestGroup(
    595      test, uuid,
    596      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    597  let topLevelConfigOverride = {perBuyerCurrencies: {}};
    598  topLevelConfigOverride.perBuyerCurrencies[ORIGIN] = 'EUR';
    599  let result = await runCurrencyComponentAuction(test, uuid, {
    600    componentAuctionConfigOverrides: {sellerCurrency: 'USD'},
    601    topLevelAuctionConfigOverrides: topLevelConfigOverride,
    602    topLevelSellerScriptParamsOverride: {
    603      scoreAd: `
    604              if (browserSignals.bidCurrency !== 'USD')
    605                throw 'Wrong currency';`
    606    }
    607  });
    608  expectNoWinner(result);
    609 }, 'Multi-seller auction --- inconsistent sellerConfig and top-level perBuyerCurrencies.');
    610 
    611 subsetTest(promise_test, async test => {
    612  const uuid = generateUuid(test);
    613  await joinInterestGroup(
    614      test, uuid,
    615      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    616  let topLevelConfigOverride = {perBuyerCurrencies: {}};
    617  topLevelConfigOverride.perBuyerCurrencies[ORIGIN] = 'EUR';
    618 
    619  let result = await runCurrencyComponentAuction(
    620      test, uuid, {componentAuctionConfigOverrides: topLevelConfigOverride});
    621  expectNoWinner(result);
    622 }, 'Multi-seller auction --- top-level perBuyerCurrencies different from bid.');
    623 
    624 subsetTest(promise_test, async test => {
    625  const uuid = generateUuid(test);
    626  await joinInterestGroup(
    627      test, uuid,
    628      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    629  let result = await runCurrencyComponentAuction(
    630      test, uuid, {componentAuctionConfigOverrides: {sellerCurrency: 'EUR'}});
    631  expectNoWinner(result);
    632 }, 'Multi-seller auction --- component sellerCurrency different from bid.');
    633 
    634 subsetTest(promise_test, async test => {
    635  const uuid = generateUuid(test);
    636  await joinInterestGroup(test, uuid);
    637  await runBasicFledgeTestExpectingNoWinner(test, uuid, {
    638    decisionLogicURL: createDecisionScriptURL(uuid, {
    639      scoreAd: `
    640          return {desirability: 2 * bid,
    641                  incomingBidInSellerCurrency: 5* bid}
    642        `
    643    })
    644  });
    645 }, 'Trying to use incomingBidInSellerCurrency w/o sellerCurrency set.');
    646 
    647 subsetTest(promise_test, async test => {
    648  const uuid = generateUuid(test);
    649  await joinInterestGroup(test, uuid);
    650  await runBasicFledgeTestExpectingWinner(test, uuid, {
    651    decisionLogicURL: createDecisionScriptURL(uuid, {
    652      scoreAd: `
    653          return {desirability: 2 * bid,
    654                  incomingBidInSellerCurrency: 5* bid}
    655        `,
    656    }),
    657    sellerCurrency: 'USD'
    658  });
    659 }, 'Trying to use incomingBidInSellerCurrency w/sellerCurrency set.');
    660 
    661 subsetTest(promise_test, async test => {
    662  const uuid = generateUuid(test);
    663  await joinInterestGroup(
    664      test, uuid,
    665      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    666  await runBasicFledgeTestExpectingNoWinner(test, uuid, {
    667    decisionLogicURL: createDecisionScriptURL(uuid, {
    668      scoreAd: `
    669          return {desirability: 2 * bid,
    670                  incomingBidInSellerCurrency: 5* bid}
    671        `
    672    }),
    673    sellerCurrency: 'USD'
    674  });
    675 }, 'Trying to use incomingBidInSellerCurrency to change bid already in that currency.');
    676 
    677 subsetTest(promise_test, async test => {
    678  const uuid = generateUuid(test);
    679  await joinInterestGroup(
    680      test, uuid,
    681      {biddingLogicURL: createBiddingScriptURLWithCurrency(uuid, 'USD')});
    682  await runBasicFledgeTestExpectingWinner(test, uuid, {
    683    decisionLogicURL: createDecisionScriptURL(uuid, {
    684      scoreAd: `
    685          return {desirability: 2 * bid,
    686                  incomingBidInSellerCurrency: bid}
    687        `
    688    }),
    689    sellerCurrency: 'USD'
    690  });
    691 }, 'incomingBidInSellerCurrency repeating value of bid already in that currency is OK.');
    692 
    693 subsetTest(promise_test, async test => {
    694  const uuid = generateUuid(test);
    695  await joinTwoGroupsForHighestScoringOther(test, uuid);
    696  await runBasicFledgeAuctionAndNavigate(
    697      test, uuid,
    698      {decisionLogicURL: createDecisionURLForHighestScoringOther(uuid)});
    699  await waitForObservedRequests(uuid, [
    700    createSellerReportURL(uuid, '10???_9???'),
    701    createBidderReportURL(uuid, '10???_9???'),
    702    // w/o sellerCurrency set, forDebuggingOnly reports original values and ???
    703    // as tags.
    704    createSellerReportURL(uuid, 'dbg_10???_9???'),
    705    createBidderReportURL(uuid, 'dbg_10???_9???')
    706  ]);
    707 }, 'Converted currency use with no sellerCurrency set.');
    708 
    709 subsetTest(promise_test, async test => {
    710  const uuid = generateUuid(test);
    711  await joinTwoGroupsForHighestScoringOther(test, uuid);
    712  await runBasicFledgeAuctionAndNavigate(test, uuid, {
    713    decisionLogicURL: createDecisionURLForHighestScoringOther(uuid),
    714    sellerCurrency: 'USD'
    715  });
    716  await waitForObservedRequests(uuid, [
    717    createSellerReportURL(uuid, '10???_9USD'),
    718    createBidderReportURL(uuid, '10???_9USD'),
    719    // w/sellerCurrency set, forDebuggingOnly reports converted bids +
    720    // sellerCurrency.
    721    createSellerReportURL(uuid, 'dbg_10USD_9USD'),
    722    createBidderReportURL(uuid, 'dbg_10USD_9USD')
    723  ]);
    724 }, 'Converted currency use with sellerCurrency set matching.');
    725 
    726 subsetTest(promise_test, async test => {
    727  const uuid = generateUuid(test);
    728  await joinTwoGroupsForHighestScoringOther(test, uuid);
    729  await runBasicFledgeAuctionAndNavigate(test, uuid, {
    730    decisionLogicURL: createDecisionURLForHighestScoringOther(uuid),
    731    sellerCurrency: 'EUR'
    732  });
    733  await waitForObservedRequests(uuid, [
    734    createSellerReportURL(uuid, '10???_0EUR'),
    735    createBidderReportURL(uuid, '10???_0EUR'),
    736    // sellerCurrency set, and no bid available in it: get 0s.
    737    createSellerReportURL(uuid, 'dbg_0EUR_0EUR'),
    738    createBidderReportURL(uuid, 'dbg_0EUR_0EUR')
    739  ]);
    740 }, 'Converted currency use with sellerCurrency different, no conversion.');
    741 
    742 subsetTest(promise_test, async test => {
    743  const uuid = generateUuid(test);
    744  await joinTwoGroupsForHighestScoringOther(test, uuid);
    745  await runBasicFledgeAuctionAndNavigate(test, uuid, {
    746    decisionLogicURL:
    747        createDecisionURLForHighestScoringOther(uuid, 'converted = 3 * bid'),
    748    sellerCurrency: 'EUR'
    749  });
    750  await waitForObservedRequests(uuid, [
    751    createSellerReportURL(uuid, '10???_27EUR'),
    752    createBidderReportURL(uuid, '10???_27EUR'),
    753    // sellerCurrency set, converted bids.
    754    createSellerReportURL(uuid, 'dbg_30EUR_27EUR'),
    755    createBidderReportURL(uuid, 'dbg_30EUR_27EUR')
    756  ]);
    757 }, 'Converted currency use with sellerCurrency different, conversion.');
    758 
    759 subsetTest(promise_test, async test => {
    760  const uuid = generateUuid(test);
    761  await joinTwoGroupsForHighestScoringOther(test, uuid);
    762  let result =
    763      await runCurrencyComponentAuctionForHighestScoringOther(test, uuid, {
    764        componentConversion: `
    765          modified = bid + 1;
    766          modifiedCurrency = 'EUR';`,
    767        componentAuctionConfigOverrides: {sellerCurrency: 'EUR'}
    768      });
    769  expectSuccess(result);
    770  createAndNavigateFencedFrame(test, result);
    771  await waitForObservedRequests(uuid, [
    772    createSellerReportURL(uuid, 'top_11EUR_0???'),
    773    createSellerReportURL(uuid, 'component_10???_0EUR'),
    774    createBidderReportURL(uuid, '10???_0EUR'),
    775    // forDebuggingOnly info w/sellerCurrency set relies on conversion;
    776    // but sellerCurrency is on component auction only.
    777    createBidderReportURL(uuid, 'dbg_0EUR_0EUR'),
    778    createSellerReportURL(uuid, 'dbg_component_0EUR_0EUR'),
    779    createSellerReportURL(uuid, 'dbg_top_11???_0???'),
    780  ]);
    781 }, 'Modified bid does not act in place of incomingBidInSellerCurrency.');
    782 
    783 subsetTest(promise_test, async test => {
    784  const uuid = generateUuid(test);
    785  await joinTwoGroupsForHighestScoringOther(test, uuid);
    786  let result =
    787      await runCurrencyComponentAuctionForHighestScoringOther(test, uuid, {
    788        componentConversion: `
    789          modified = bid + 1;
    790          modifiedCurrency = 'EUR';
    791          converted = bid - 1;`,
    792        componentAuctionConfigOverrides: {sellerCurrency: 'EUR'}
    793      });
    794  expectSuccess(result);
    795  createAndNavigateFencedFrame(test, result);
    796  await waitForObservedRequests(uuid, [
    797    createSellerReportURL(uuid, 'top_11EUR_0???'),
    798    createSellerReportURL(uuid, 'component_10???_8EUR'),
    799    createBidderReportURL(uuid, '10???_8EUR'),
    800    // Debug at component shows converted; top-level has no sellerCurrency,
    801    // so shows modified.
    802    createBidderReportURL(uuid, 'dbg_9EUR_8EUR'),
    803    createSellerReportURL(uuid, 'dbg_component_9EUR_8EUR'),
    804    createSellerReportURL(uuid, 'dbg_top_11???_0???'),
    805  ]);
    806 }, 'Both modified bid and incomingBidInSellerCurrency.');
    807 
    808 subsetTest(promise_test, async test => {
    809  const uuid = generateUuid(test);
    810  await joinTwoGroupsForHighestScoringOther(test, uuid);
    811  let result =
    812      await runCurrencyComponentAuctionForHighestScoringOther(test, uuid, {
    813        componentConversion: `
    814          modified = bid + 1;
    815          modifiedCurrency = 'CAD';`,
    816        topLevelAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    817        topLevelConversion: `converted = 3 * bid;`,
    818      });
    819  expectSuccess(result);
    820  createAndNavigateFencedFrame(test, result);
    821  await waitForObservedRequests(uuid, [
    822    createSellerReportURL(uuid, 'top_11???_0???'),
    823    createSellerReportURL(uuid, 'component_10???_9???'),
    824    createBidderReportURL(uuid, '10???_9???'),
    825    // No sellerCurrency at component; debug at top-level shows the result of
    826    // conversion.
    827    createBidderReportURL(uuid, 'dbg_10???_9???'),
    828    createSellerReportURL(uuid, 'dbg_component_10???_9???'),
    829    createSellerReportURL(uuid, 'dbg_top_33EUR_0???'),
    830  ]);
    831 }, 'incomingBidInSellerCurrency at top-level trying to convert is OK.');
    832 
    833 subsetTest(promise_test, async test => {
    834  const uuid = generateUuid(test);
    835  await joinTwoGroupsForHighestScoringOther(test, uuid);
    836  let result =
    837      await runCurrencyComponentAuctionForHighestScoringOther(test, uuid, {
    838        componentConversion: `
    839          modified = bid + 1;
    840          modifiedCurrency = 'EUR';`,
    841        topLevelAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    842        topLevelConversion: `converted = 3 * bid;`,
    843      });
    844  // Tried to change a bid that was already in EUR.
    845  expectNoWinner(result);
    846 }, 'incomingBidInSellerCurrency at top-level trying to change bid is not OK.');
    847 
    848 subsetTest(promise_test, async test => {
    849  const uuid = generateUuid(test);
    850  await joinTwoGroupsForHighestScoringOther(test, uuid);
    851  let result =
    852      await runCurrencyComponentAuctionForHighestScoringOther(test, uuid, {
    853        componentConversion: `
    854          modified = bid + 1;
    855          modifiedCurrency = 'EUR';`,
    856        topLevelAuctionConfigOverrides: {sellerCurrency: 'EUR'},
    857        topLevelConversion: `converted = bid;`,
    858      });
    859  // Changing the bid to itself when it was already in right currency is OK.
    860  expectSuccess(result);
    861  createAndNavigateFencedFrame(test, result);
    862  await waitForObservedRequests(uuid, [
    863    createSellerReportURL(uuid, 'top_11???_0???'),
    864    createSellerReportURL(uuid, 'component_10???_9???'),
    865    createBidderReportURL(uuid, '10???_9???'),
    866    // No sellerCurrency at component; debug at top-level shows the result of
    867    // no-op conversion.
    868    createBidderReportURL(uuid, 'dbg_10???_9???'),
    869    createSellerReportURL(uuid, 'dbg_component_10???_9???'),
    870    createSellerReportURL(uuid, 'dbg_top_11EUR_0???'),
    871  ]);
    872 }, 'incomingBidInSellerCurrency at top-level doing a no-op conversion OK.');
    873 
    874 // TODO: PrivateAggregation. It follows the same rules as
    875 // highestScoringOtherBid, but is actually visible at top-level.