tor-browser

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

auction-config.https.window.js (22199B)


      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-5
      8 // META: variant=?6-10
      9 // META: variant=?11-15
     10 // META: variant=?16-20
     11 // META: variant=?21-25
     12 // META: variant=?26-30
     13 // META: variant=?31-35
     14 // META: variant=?36-40
     15 // META: variant=?40-45
     16 // META: variant=?46-50
     17 // META: variant=?51-55
     18 // META: variant=?56-60
     19 // META: variant=?61-65
     20 // META: variant=?66-last
     21 
     22 "use strict";
     23 
     24 // The tests in this file focus on calls to runAdAuction with various
     25 // auctionConfigs.
     26 
     27 // We handle promise rejections ourselves.
     28 setup({ allow_uncaught_exception: true });
     29 
     30 // Helper for when we expect it to happen.
     31 const interceptUnhandledRejection = () => {
     32  let invokePromiseResolved;
     33  let eventHandler = event => {
     34    event.preventDefault();
     35    invokePromiseResolved(event.reason);
     36  }
     37  window.addEventListener("unhandledrejection", eventHandler, {once: true});
     38  return new Promise((resolved) => {
     39    invokePromiseResolved = resolved;
     40  });
     41 }
     42 
     43 // Helper for when we expect it to not happen. This relies on the event
     44 // dispatching being sync.
     45 const unexpectedUnhandledRejection = () => {
     46  let o = { sawError : false }
     47  window.addEventListener("unhandledrejection", event => {
     48    o.sawError = true;
     49  }, {once: true});
     50  return o;
     51 }
     52 
     53 const makeTest = ({
     54  // Test name
     55  name,
     56  // Expectation function (EXPECT_NULL, etc.)
     57  expect,
     58  // Overrides to the auction config.
     59  auctionConfigOverrides = {},
     60  // Expectation for a promise error.
     61  expectPromiseError,
     62 }) => {
     63  subsetTest(promise_test, async test => {
     64    let waitPromiseError, dontExpectPromiseError;
     65    if (expectPromiseError) {
     66      waitPromiseError = interceptUnhandledRejection();
     67    } else {
     68      dontExpectPromiseError = unexpectedUnhandledRejection();
     69    }
     70 
     71    const uuid = generateUuid(test);
     72    // Join an interest group so the auction actually runs.
     73    await joinInterestGroup(test, uuid);
     74    let auctionResult;
     75    try {
     76      auctionResult = await runBasicFledgeAuction(test, uuid, auctionConfigOverrides);
     77    } catch (e) {
     78      auctionResult = e;
     79    }
     80    expect(auctionResult);
     81 
     82    if (expectPromiseError) {
     83      expectPromiseError(await waitPromiseError);
     84    } else {
     85      assert_false(dontExpectPromiseError.sawError,
     86                   "Should not see a promise error");
     87    }
     88  }, name);
     89 };
     90 
     91 // Expect an unsuccessful auction (yielding null).
     92 const EXPECT_NO_WINNER = auctionResult => {
     93  assert_equals(auctionResult, null, 'Auction unexpected had a winner');
     94 };
     95 
     96 // Expect a winner (FencedFrameConfig).
     97 const EXPECT_WINNER =
     98    auctionResult => {
     99      assert_true(
    100          auctionResult instanceof FencedFrameConfig,
    101          'Auction did not return expected FencedFrameConfig');
    102    }
    103 
    104 // Expect an exception of the given type.
    105 const EXPECT_EXCEPTION = exceptionType => auctionResult => {
    106  assert_not_equals(auctionResult, null, "got null instead of expected error");
    107  assert_true(auctionResult instanceof Error, "did not get expected error: " + auctionResult);
    108  assert_throws_js(exceptionType, () => { throw auctionResult; });
    109 };
    110 
    111 const EXPECT_PROMISE_ERROR = auctionResult => {
    112  assert_not_equals(auctionResult, null, "got null instead of expected error");
    113  assert_true(auctionResult instanceof TypeError,
    114              "did not get expected error type: " + auctionResult);
    115 }
    116 
    117 makeTest({
    118  name: 'deprecatedRenderURLReplacements without end bracket is invalid.',
    119  expect: EXPECT_PROMISE_ERROR,
    120  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    121  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'${No_End_Bracket': 'SSP'}}
    122 });
    123 
    124 makeTest({
    125  name: 'deprecatedRenderURLReplacements without percents and brackets.',
    126  expect: EXPECT_PROMISE_ERROR,
    127  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    128  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'No_Wrapper': 'SSP'}}
    129 });
    130 
    131 makeTest({
    132  name: 'deprecatedRenderURLReplacements without dollar sign.',
    133  expect: EXPECT_PROMISE_ERROR,
    134  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    135  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'{No_Dollar_Sign}': 'SSP'}}
    136 });
    137 
    138 makeTest({
    139  name: 'deprecatedRenderURLReplacements without start bracket is invalid.',
    140  expect: EXPECT_PROMISE_ERROR,
    141  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    142  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'$No_Start_Bracket}': 'SSP'}}
    143 });
    144 
    145 makeTest({
    146  name: 'deprecatedRenderURLReplacements mix and match is invalid.',
    147  expect: EXPECT_PROMISE_ERROR,
    148  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    149  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'${Bracket_And_Percent%%': 'SSP'}}
    150 });
    151 
    152 makeTest({
    153  name: 'deprecatedRenderURLReplacements missing start percent is invalid.',
    154  expect: EXPECT_PROMISE_ERROR,
    155  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    156  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%Missing_Start_Percents%%': 'SSP'}}
    157 });
    158 
    159 makeTest({
    160  name: 'deprecatedRenderURLReplacements single percents is invalid.',
    161  expect: EXPECT_PROMISE_ERROR,
    162  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    163  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%Single_Percents%': 'SSP'}}
    164 });
    165 
    166 makeTest({
    167  name: 'deprecatedRenderURLReplacements without end percents is invalid.',
    168  expect: EXPECT_PROMISE_ERROR,
    169  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    170  auctionConfigOverrides: {deprecatedRenderURLReplacements: {'%%No_End_Percents': 'SSP'}}
    171 });
    172 
    173 makeTest({
    174  name: 'sellerRealTimeReportingConfig has default local reporting type',
    175  expect:  EXPECT_WINNER,
    176  auctionConfigOverrides: {sellerRealTimeReportingConfig:
    177                            {type: 'default-local-reporting'}}
    178 });
    179 
    180 makeTest({
    181  name: 'sellerRealTimeReportingConfig has no type',
    182  expect: EXPECT_EXCEPTION(TypeError),
    183  auctionConfigOverrides: {sellerRealTimeReportingConfig:
    184                            {notType: 'default-local-reporting'}}
    185 });
    186 
    187 makeTest({
    188  name: 'sellerRealTimeReportingConfig has unknown type',
    189  expect:  EXPECT_WINNER,
    190  auctionConfigOverrides: {sellerRealTimeReportingConfig: {type: 'unknown type'}}
    191 });
    192 
    193 makeTest({
    194  name: 'perBuyerRealTimeReportingConfig',
    195  expect: EXPECT_WINNER,
    196  auctionConfigOverrides: {perBuyerRealTimeReportingConfig:
    197                            {'https://example.com': {type: 'default-local-reporting'}}}
    198 });
    199 
    200 makeTest({
    201  name: 'perBuyerRealTimeReportingConfig has invalid buyer',
    202  expect: EXPECT_EXCEPTION(TypeError),
    203  auctionConfigOverrides: {perBuyerRealTimeReportingConfig:
    204                            {'http://example.com': {type: 'default-local-reporting'}}}
    205 });
    206 
    207 makeTest({
    208  name: 'perBuyerRealTimeReportingConfig has no type',
    209  expect: EXPECT_EXCEPTION(TypeError),
    210  auctionConfigOverrides: {perBuyerRealTimeReportingConfig:
    211                            {'https://example.com': {notType: 'default-local-reporting'}}}
    212 });
    213 
    214 makeTest({
    215  name: 'perBuyerRealTimeReportingConfig has unknown type',
    216  expect: EXPECT_WINNER,
    217  auctionConfigOverrides: {perBuyerRealTimeReportingConfig:
    218                            {'https://example.com': {type: 'unknown type'}}}
    219 });
    220 
    221 makeTest({
    222  name: 'perBuyerRealTimeReportingConfig has no entry',
    223  expect: EXPECT_WINNER,
    224  auctionConfigOverrides: {perBuyerRealTimeReportingConfig: {}}
    225 });
    226 
    227 makeTest({
    228  name: 'no buyers => no winners',
    229  expect: EXPECT_NO_WINNER,
    230  auctionConfigOverrides: {interestGroupBuyers: []},
    231 });
    232 
    233 makeTest({
    234  name: 'seller is not an https URL',
    235  expect: EXPECT_EXCEPTION(TypeError),
    236  auctionConfigOverrides: {seller: "ftp://not-https"},
    237 });
    238 
    239 makeTest({
    240  name: 'decisionLogicURL is invalid',
    241  expect: EXPECT_EXCEPTION(TypeError),
    242  auctionConfigOverrides: { decisionLogicURL: "https://foo:99999999999" },
    243 });
    244 
    245 makeTest({
    246  name: 'decisionLogicURL is cross-origin with seller',
    247  expect: EXPECT_EXCEPTION(TypeError),
    248  auctionConfigOverrides: { decisionLogicURL: "https://example.com" },
    249 });
    250 
    251 makeTest({
    252  name: 'trustedScoringSignalsURL is invalid',
    253  expect: EXPECT_EXCEPTION(TypeError),
    254  auctionConfigOverrides: { trustedScoringSignalsURL: "https://foo:99999999999" },
    255 });
    256 
    257 makeTest({
    258  name: 'valid trustedScoringSignalsURL',
    259  expect: EXPECT_WINNER,
    260  auctionConfigOverrides:
    261      {trustedScoringSignalsURL: window.location.origin + '/resource.json'}
    262 });
    263 
    264 makeTest({
    265  name: 'trustedScoringSignalsURL should not have a fragment',
    266  expect: EXPECT_EXCEPTION(TypeError),
    267  auctionConfigOverrides:
    268      {trustedScoringSignalsURL: window.location.origin + '/resource.json#foo'}
    269 });
    270 
    271 makeTest({
    272  name: 'trustedScoringSignalsURL with an empty fragment is not OK',
    273  expect: EXPECT_EXCEPTION(TypeError),
    274  auctionConfigOverrides:
    275      {trustedScoringSignalsURL: window.location.origin + '/resource.json#'}
    276 });
    277 
    278 makeTest({
    279  name: 'trustedScoringSignalsURL should not have a query',
    280  expect: EXPECT_EXCEPTION(TypeError),
    281  auctionConfigOverrides:
    282      {trustedScoringSignalsURL: window.location.origin + '/resource.json?foo'}
    283 });
    284 
    285 makeTest({
    286  name: 'trustedScoringSignalsURL with an empty query is not OK',
    287  expect: EXPECT_EXCEPTION(TypeError),
    288  auctionConfigOverrides:
    289      {trustedScoringSignalsURL: window.location.origin + '/resource.json?'}
    290 });
    291 
    292 makeTest({
    293  name: 'trustedScoringSignalsURL should not have embedded credentials',
    294  expect: EXPECT_EXCEPTION(TypeError),
    295  auctionConfigOverrides: {
    296    trustedScoringSignalsURL: (window.location.origin + '/resource.json')
    297                                  .replace('https://', 'https://user:pass@')
    298  }
    299 });
    300 
    301 // Cross-origin trustedScoringSignalsURL is fine, but it needs extra
    302 // headers to actually make it work. The auction here doesn't actually
    303 // care if the signals don't load.
    304 makeTest({
    305  name: 'trustedScoringSignalsURL is cross-origin with seller',
    306  expect: EXPECT_WINNER,
    307  auctionConfigOverrides: { trustedScoringSignalsURL: "https://example.com" },
    308 });
    309 
    310 makeTest({
    311  name: 'interestGroupBuyer is invalid',
    312  expect: EXPECT_EXCEPTION(TypeError),
    313  auctionConfigOverrides: { interestGroupBuyers: ["https://foo:99999999999"] },
    314 });
    315 
    316 makeTest({
    317  name: 'interestGroupBuyer is not https',
    318  expect: EXPECT_EXCEPTION(TypeError),
    319  auctionConfigOverrides: { interestGroupBuyers: ["http://example.com"] },
    320 });
    321 
    322 makeTest({
    323  name: 'only one interestGroupBuyer is invalid',
    324  expect: EXPECT_EXCEPTION(TypeError),
    325  auctionConfigOverrides: {
    326    interestGroupBuyers: ["https://example.com", "https://foo:99999999999"],
    327  },
    328 });
    329 
    330 makeTest({
    331  name: 'only one interestGroupBuyer is not https',
    332  expect: EXPECT_EXCEPTION(TypeError),
    333  auctionConfigOverrides: {
    334    interestGroupBuyers: ["https://example.com", "http://example.com"],
    335  },
    336 });
    337 
    338 makeTest({
    339  name: 'auctionSignals is invalid as JSON',
    340  expect: EXPECT_PROMISE_ERROR,
    341  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    342  auctionConfigOverrides: { auctionSignals: { sig: BigInt(13) } },
    343 });
    344 
    345 makeTest({
    346  name: 'sellerSignals is invalid as JSON',
    347  expect: EXPECT_PROMISE_ERROR,
    348  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    349  auctionConfigOverrides: { sellerSignals: { sig: BigInt(13) } },
    350 });
    351 
    352 makeTest({
    353  name: 'perBuyerSignals has invalid URL in a key',
    354  expect: EXPECT_PROMISE_ERROR,
    355  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    356  auctionConfigOverrides: { perBuyerSignals: { "https://foo:99999999999" : {} }},
    357 });
    358 
    359 makeTest({
    360  name: 'perBuyerSignals value is invalid as JSON',
    361  expect: EXPECT_PROMISE_ERROR,
    362  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    363  auctionConfigOverrides: {
    364    perBuyerSignals: { "https://example.com" : { sig: BigInt(1) },
    365  }},
    366 });
    367 
    368 makeTest({
    369  name: 'perBuyerGroupLimits has invalid URL in a key',
    370  expect: EXPECT_EXCEPTION(TypeError),
    371  auctionConfigOverrides: { perBuyerGroupLimits: { "https://foo:99999999999" : 5 }},
    372 });
    373 
    374 makeTest({
    375  name: 'perBuyerExperimentGroupIds has invalid URL in a key',
    376  expect: EXPECT_EXCEPTION(TypeError),
    377  auctionConfigOverrides: { perBuyerExperimentGroupIds: { "https://foo:99999999999" : 11 }},
    378 });
    379 
    380 makeTest({
    381  name: 'perBuyerPrioritySignals has invalid URL in a key',
    382  expect: EXPECT_EXCEPTION(TypeError),
    383  auctionConfigOverrides: {
    384    perBuyerPrioritySignals: { "https://foo:99999999999" : { sig: 2.5} },
    385  },
    386 });
    387 
    388 makeTest({
    389  name: 'perBuyerPrioritySignals has a value with a key with prefix "browserSignals"',
    390  expect: EXPECT_EXCEPTION(TypeError),
    391  auctionConfigOverrides: {
    392    perBuyerPrioritySignals: { "https://example.com" : { "browserSignals.foo" : true } },
    393  },
    394 });
    395 
    396 makeTest({
    397  name: 'component auctions are not allowed within component auctions',
    398  expect: EXPECT_EXCEPTION(TypeError),
    399  auctionConfigOverrides: {
    400    interestGroupBuyers: undefined,
    401    componentAuctions: [
    402      {
    403        seller: window.location.origin,
    404        decisionLogicURL: window.location.origin,
    405        interestGroupBuyers: undefined,
    406        componentAuctions: [
    407          {
    408            seller: window.location.origin,
    409            decisionLogicURL: window.location.origin,
    410          }
    411        ],
    412      },
    413    ],
    414  },
    415 });
    416 
    417 makeTest({
    418  name: 'component auctions are not allowed with interestGroupBuyers',
    419  expect: EXPECT_EXCEPTION(TypeError),
    420  auctionConfigOverrides: {
    421    interestGroupBuyers: ["https://example.com"],
    422    componentAuctions: [
    423      {
    424        seller: window.location.origin,
    425        decisionLogicURL: window.location.origin,
    426        interestGroupBuyers: [],
    427      },
    428    ],
    429  },
    430 });
    431 
    432 makeTest({
    433  name: 'perBuyerCurrencies with invalid currency',
    434  expect: EXPECT_PROMISE_ERROR,
    435  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    436  auctionConfigOverrides: {perBuyerCurrencies: {'*': 'Dollars'}}
    437 });
    438 
    439 makeTest({
    440  name: 'perBuyerCurrencies with invalid currency map key',
    441  expect: EXPECT_PROMISE_ERROR,
    442  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    443  auctionConfigOverrides: {perBuyerCurrencies: {'example': 'USD'}}
    444 });
    445 
    446 makeTest({
    447  name: 'perBuyerCurrencies with non-https currency map key',
    448  expect: EXPECT_PROMISE_ERROR,
    449  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    450  auctionConfigOverrides: {perBuyerCurrencies: {'http://example.org/': 'USD'}}
    451 });
    452 
    453 makeTest({
    454  name: 'perBuyerCurrencies not convertible to dictionary',
    455  expect: EXPECT_PROMISE_ERROR,
    456  expectPromiseError: EXPECT_EXCEPTION(TypeError),
    457  auctionConfigOverrides: {perBuyerCurrencies: 123}
    458 });
    459 
    460 makeTest({
    461  name: 'requestedSize has no width',
    462  expect: EXPECT_EXCEPTION(TypeError),
    463  auctionConfigOverrides: {requestedSize: {height: '100'}}
    464 });
    465 
    466 makeTest({
    467  name: 'requestedSize has no height',
    468  expect: EXPECT_EXCEPTION(TypeError),
    469  auctionConfigOverrides: {requestedSize: {width: '100'}}
    470 });
    471 
    472 makeTest({
    473  name: 'requestedSize width not a number',
    474  expect: EXPECT_EXCEPTION(TypeError),
    475  auctionConfigOverrides: {requestedSize: {width: '10 0', height: '100'}}
    476 });
    477 
    478 makeTest({
    479  name: 'requestedSize height not a number',
    480  expect: EXPECT_EXCEPTION(TypeError),
    481  auctionConfigOverrides: {requestedSize: {width: '100', height: '10 0'}}
    482 });
    483 
    484 makeTest({
    485  name: 'requestedSize 0',
    486  expect: EXPECT_EXCEPTION(TypeError),
    487  auctionConfigOverrides: {requestedSize: {width: '0', height: '100'}}
    488 });
    489 
    490 makeTest({
    491  name: 'requestedSize space before units',
    492  expect: EXPECT_EXCEPTION(TypeError),
    493  auctionConfigOverrides: {requestedSize: {width: '100 px', height: '100'}}
    494 });
    495 
    496 makeTest({
    497  name: 'requestedSize leading 0',
    498  expect: EXPECT_EXCEPTION(TypeError),
    499  auctionConfigOverrides: {requestedSize: {width: '0100', height: '100'}}
    500 });
    501 
    502 makeTest({
    503  name: 'requestedSize invalid unit type',
    504  expect: EXPECT_EXCEPTION(TypeError),
    505  auctionConfigOverrides: {requestedSize: {width: '100furlongs', height: '100'}}
    506 });
    507 
    508 makeTest({
    509  name: 'requestedSize hexideximal',
    510  expect: EXPECT_EXCEPTION(TypeError),
    511  auctionConfigOverrides: {requestedSize: {width: '0x100', height: '100'}}
    512 });
    513 
    514 makeTest({
    515  name: 'Empty allSlotsRequestedSizes',
    516  expect: EXPECT_EXCEPTION(TypeError),
    517  auctionConfigOverrides: {allSlotsRequestedSizes: []}
    518 });
    519 
    520 makeTest({
    521  name: 'allSlotsRequestedSizes without matching value in requestedSize',
    522  expect: EXPECT_EXCEPTION(TypeError),
    523  auctionConfigOverrides: {requestedSize:
    524                             {width: '100', height: '100'},
    525                           allSlotsRequestedSizes:
    526                            [{width: '100', height: '101'}]}
    527 });
    528 
    529 makeTest({
    530  name: 'allSlotsRequestedSizes has duplicate values',
    531  expect: EXPECT_EXCEPTION(TypeError),
    532  auctionConfigOverrides: {allSlotsRequestedSizes:
    533                            [{width: '100', height: '100'},
    534                             {width: '100', height: '100'}]}
    535 });
    536 
    537 makeTest({
    538  name: 'allSlotsRequestedSizes has invalid value',
    539  expect: EXPECT_EXCEPTION(TypeError),
    540  auctionConfigOverrides: {allSlotsRequestedSizes:
    541                            [{width: '100', height: '100'},
    542                             {width: '200furlongs', height: '200'}]}
    543 });
    544 
    545 subsetTest(promise_test, async test => {
    546  const uuid = generateUuid(test);
    547 
    548  // The renderURL / report URLs for the first/second iterations of the auction.
    549  let renderURL = createRenderURL(uuid);
    550  let bidderReportURL1 = createBidderReportURL(uuid, /*id=*/ 1);
    551  let bidderReportURL2 = createBidderReportURL(uuid, /*id=*/ 2);
    552  let bidderDebugReportURL =
    553      createBidderReportURL(uuid, /*id=*/ 'forDebuggingOnly');
    554  let sellerReportURL1 = createSellerReportURL(uuid, /*id=*/ 1);
    555  let sellerReportURL2 = createSellerReportURL(uuid, /*id=*/ 2);
    556  let sellerDebugReportURL =
    557      createSellerReportURL(uuid, /*id=*/ 'forDebuggingOnly');
    558 
    559  // reportWin() sends "bidderReportURL1" if
    560  // browserSignals.forDebuggingOnlyInCooldownOrLockout is true,
    561  // "bidderReportURL2" otherwise.
    562  await joinInterestGroup(test, uuid, {
    563    ads: [{renderURL: renderURL}],
    564    biddingLogicURL: createBiddingScriptURL({
    565      generateBid: `
    566        forDebuggingOnly.reportAdAuctionWin('${bidderDebugReportURL}');
    567        if (!browserSignals.hasOwnProperty(
    568          'forDebuggingOnlyInCooldownOrLockout')) {
    569          throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals";
    570        }
    571        let bid = browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2;
    572        return {bid: bid, render: '${renderURL}'};`,
    573      reportWin: `
    574        if (browserSignals.bid === 1)
    575          sendReportTo('${bidderReportURL1}');
    576        if (browserSignals.bid === 2)
    577          sendReportTo('${bidderReportURL2}');`
    578 
    579    })
    580  });
    581 
    582  // reportResult() sends "sellerReportURL1" if
    583  // browserSignals.forDebuggingOnlyInCooldownOrLockout in scoreAd() is true,
    584  // "sellerReportURL2" otherwise.
    585  const auctionConfigOverrides = {
    586    decisionLogicURL: createDecisionScriptURL(uuid, {
    587      scoreAd: `
    588        forDebuggingOnly.reportAdAuctionWin('${sellerDebugReportURL}');
    589        if (!browserSignals.hasOwnProperty(
    590          'forDebuggingOnlyInCooldownOrLockout')) {
    591          throw "Missing forDebuggingOnlyInCooldownOrLockout in browserSignals";
    592        }
    593        let desirability =
    594            browserSignals.forDebuggingOnlyInCooldownOrLockout ? 1 : 2;
    595        return {desirability: desirability};`,
    596      reportResult: `
    597        if (browserSignals.desirability === 1)
    598          sendReportTo('${sellerReportURL1}');
    599        if (browserSignals.desirability === 2)
    600          sendReportTo('${sellerReportURL2}');`
    601    })
    602  };
    603 
    604  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
    605  // TODO(crbug.com/337186761) this causes the test being flaky.
    606  // Note: In the first auction,
    607  // browserSignals.forDebuggingOnlyInCooldownOrLockout in generateBid() and
    608  // scoreAd() should both be false. But due to currently there's no way to
    609  // clean up the lockout/cooldown DB tables after a test, so a rerun of this
    610  // test will break this, and other tests that writes to these tables may also
    611  // affect this test. So we cannot reliably check the signals being false.
    612  // await waitForObservedRequestsIgnoreDebugOnlyReports(
    613  //     uuid, [bidderReportURL2, sellerReportURL2]);
    614 
    615  // In the second auction, browserSignals.forDebuggingOnlyInCooldownOrLockout
    616  // in generateBid() and scoreAd() should both be true, since both the buyer
    617  // and seller called forDebuggingOnly API in the first auction, so they are in
    618  // cooldowns at least (and also in lockout if a debug report is allowed to be
    619  // sent).
    620  await runBasicFledgeAuctionAndNavigate(test, uuid, auctionConfigOverrides);
    621  await waitForObservedRequestsIgnoreDebugOnlyReports(
    622    uuid,
    623    [bidderReportURL2, sellerReportURL2, bidderReportURL1, sellerReportURL1]);
    624 }, `forDebuggingOnly lockout and cooldowns updating in one auction, read in another's.`);
    625 
    626 makeTest({
    627  name: 'deprecatedRenderURLReplacements nullability',
    628  expect: EXPECT_WINNER,
    629  auctionConfigOverrides: {deprecatedRenderURLReplacements: null}
    630 });
    631 
    632 makeTest({
    633  name: 'deprecatedRenderURLReplacements nullability 2',
    634  expect: EXPECT_WINNER,
    635  auctionConfigOverrides:
    636      {deprecatedRenderURLReplacements: Promise.resolve(undefined)}
    637 });
    638 
    639 makeTest({
    640  name: 'perBuyerSignals nullability',
    641  expect: EXPECT_WINNER,
    642  auctionConfigOverrides: {perBuyerSignals: null},
    643 });
    644 
    645 makeTest({
    646  name: 'perBuyerSignals nullability 2',
    647  expect: EXPECT_WINNER,
    648  auctionConfigOverrides: {perBuyerSignals: Promise.resolve(undefined)},
    649 });
    650 
    651 makeTest({
    652  name: 'perBuyerTimeouts nullability',
    653  expect: EXPECT_WINNER,
    654  auctionConfigOverrides: {perBuyerTimeouts: null},
    655 });
    656 
    657 makeTest({
    658  name: 'perBuyerTimeouts nullability 2',
    659  expect: EXPECT_WINNER,
    660  auctionConfigOverrides: {perBuyerTimeouts: Promise.resolve(undefined)},
    661 });
    662 
    663 makeTest({
    664  name: 'perBuyerCumulativeTimeouts nullability',
    665  expect: EXPECT_WINNER,
    666  auctionConfigOverrides: {perBuyerCumulativeTimeouts: null},
    667 });
    668 
    669 makeTest({
    670  name: 'perBuyerCumulativeTimeouts nullability 2',
    671  expect: EXPECT_WINNER,
    672  auctionConfigOverrides:
    673      {perBuyerCumulativeTimeouts: Promise.resolve(undefined)},
    674 });
    675 
    676 makeTest({
    677  name: 'perBuyerCurrencies nullability',
    678  expect: EXPECT_WINNER,
    679  auctionConfigOverrides: {perBuyerCurrencies: null},
    680 });
    681 
    682 makeTest({
    683  name: 'perBuyerCurrencies nullability 2',
    684  expect: EXPECT_WINNER,
    685  auctionConfigOverrides: {perBuyerCurrencies: Promise.resolve(undefined)},
    686 });