tor-browser

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

join-leave-ad-interest-group.https.window.js (20304B)


      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-10
      8 // META: variant=?11-20
      9 // META: variant=?21-30
     10 // META: variant=?31-40
     11 // META: variant=?41-50
     12 // META: variant=?51-60
     13 // META: variant=?61-70
     14 // META: variant=?71-80
     15 // META: variant=?81-last
     16 
     17 "use strict";
     18 
     19 // These tests are focused on joinAdInterestGroup() and leaveAdInterestGroup().
     20 // Most join tests do not run auctions, but instead only check the result of
     21 // the returned promise, since testing that interest groups are actually
     22 // joined, and that each interestGroup field behaves as intended, are covered
     23 // by other tests.
     24 
     25 // Minimal fields needed for a valid interest group. Used in most test cases.
     26 const BASE_INTEREST_GROUP = {
     27  owner: window.location.origin,
     28  name: 'default name',
     29 }
     30 
     31 // Each test case attempts to join and then leave an interest group, checking
     32 // if any exceptions are thrown from either operation.
     33 const SIMPLE_JOIN_LEAVE_TEST_CASES = [
     34  { expectJoinSucces: false,
     35    expectLeaveSucces: false,
     36    interestGroup: null
     37  },
     38  { expectJoinSucces: false,
     39    expectLeaveSucces: false,
     40    interestGroup: {}
     41  },
     42 
     43  // Basic success test case.
     44  { expectJoinSucces: true,
     45    expectLeaveSucces: true,
     46    interestGroup: BASE_INTEREST_GROUP
     47  },
     48 
     49  // "owner" tests
     50  { expectJoinSucces: false,
     51    expectLeaveSucces: false,
     52    interestGroup: { name: 'default name' }
     53  },
     54  { expectJoinSucces: false,
     55    expectLeaveSucces: false,
     56    interestGroup: { ...BASE_INTEREST_GROUP,
     57                     owner: null}
     58  },
     59  { expectJoinSucces: false,
     60    expectLeaveSucces: false,
     61    interestGroup: { ...BASE_INTEREST_GROUP,
     62                     owner: window.location.origin.replace('https', 'http')}
     63  },
     64  { expectJoinSucces: false,
     65    expectLeaveSucces: false,
     66    interestGroup: { ...BASE_INTEREST_GROUP,
     67                     owner: window.location.origin.replace('https', 'wss')}
     68  },
     69  // Cross-origin joins and leaves are not allowed without .well-known
     70  // permissions.
     71  { expectJoinSucces: false,
     72    expectLeaveSucces: false,
     73    interestGroup: { ...BASE_INTEREST_GROUP,
     74                     owner: '{{hosts[][www]}}' }
     75  },
     76 
     77  // "name" tests
     78  { expectJoinSucces: false,
     79    expectLeaveSucces: false,
     80    interestGroup: { owner: window.location.origin }
     81  },
     82  { expectJoinSucces: true,
     83    expectLeaveSucces: true,
     84    interestGroup: { ...BASE_INTEREST_GROUP,
     85                     name: ''}
     86  },
     87 
     88  // "priority" tests
     89  { expectJoinSucces: true,
     90    expectLeaveSucces: true,
     91    interestGroup: { ...BASE_INTEREST_GROUP,
     92                     priority: 1}
     93  },
     94  { expectJoinSucces: true,
     95    expectLeaveSucces: true,
     96    interestGroup: { ...BASE_INTEREST_GROUP,
     97                     priority: 0}
     98  },
     99  { expectJoinSucces: true,
    100    expectLeaveSucces: true,
    101    interestGroup: { ...BASE_INTEREST_GROUP,
    102                     priority: -1.5}
    103  },
    104 
    105  // "priorityVector" tests
    106  { expectJoinSucces: false,
    107    expectLeaveSucces: true,
    108    interestGroup: { ...BASE_INTEREST_GROUP,
    109                     priorityVector: null}
    110  },
    111  { expectJoinSucces: false,
    112    expectLeaveSucces: true,
    113    interestGroup: { ...BASE_INTEREST_GROUP,
    114                     priorityVector: 1}
    115  },
    116  { expectJoinSucces: false,
    117    expectLeaveSucces: true,
    118    interestGroup: { ...BASE_INTEREST_GROUP,
    119                     priorityVector: {a: 'apple'}}
    120  },
    121  { expectJoinSucces: true,
    122    expectLeaveSucces: true,
    123    interestGroup: { ...BASE_INTEREST_GROUP,
    124                     priorityVector: {}}
    125  },
    126  { expectJoinSucces: true,
    127    expectLeaveSucces: true,
    128    interestGroup: { ...BASE_INTEREST_GROUP,
    129                     priorityVector: {a: 1}}
    130  },
    131  { expectJoinSucces: true,
    132    expectLeaveSucces: true,
    133    interestGroup: { ...BASE_INTEREST_GROUP,
    134                     priorityVector: {'a': 1, 'b': -4.5, 'a.b': 0}}
    135  },
    136 
    137  // "prioritySignalsOverrides" tests
    138  { expectJoinSucces: false,
    139    expectLeaveSucces: true,
    140    interestGroup: { ...BASE_INTEREST_GROUP,
    141                     prioritySignalsOverrides: null}
    142  },
    143  { expectJoinSucces: false,
    144    expectLeaveSucces: true,
    145    interestGroup: { ...BASE_INTEREST_GROUP,
    146                     prioritySignalsOverrides: 1}
    147  },
    148  { expectJoinSucces: false,
    149    expectLeaveSucces: true,
    150    interestGroup: { ...BASE_INTEREST_GROUP,
    151                     prioritySignalsOverrides: {a: 'apple'}}
    152  },
    153  { expectJoinSucces: true,
    154    expectLeaveSucces: true,
    155    interestGroup: { ...BASE_INTEREST_GROUP,
    156                     prioritySignalsOverrides: {}}
    157  },
    158  { expectJoinSucces: true,
    159    expectLeaveSucces: true,
    160    interestGroup: { ...BASE_INTEREST_GROUP,
    161                     prioritySignalsOverrides: {a: 1}}
    162  },
    163  { expectJoinSucces: true,
    164    expectLeaveSucces: true,
    165    interestGroup: { ...BASE_INTEREST_GROUP,
    166                     prioritySignalsOverrides: {'a': 1, 'b': -4.5, 'a.b': 0}}
    167  },
    168 
    169  // "enableBiddingSignalsPrioritization" tests
    170  { expectJoinSucces: true,
    171    expectLeaveSucces: true,
    172    interestGroup: { ...BASE_INTEREST_GROUP,
    173                     enableBiddingSignalsPrioritization: true}
    174  },
    175  { expectJoinSucces: true,
    176    expectLeaveSucces: true,
    177    interestGroup: { ...BASE_INTEREST_GROUP,
    178                     enableBiddingSignalsPrioritization: false}
    179  },
    180 
    181  // "biddingLogicURL" tests
    182  { expectJoinSucces: true,
    183    expectLeaveSucces: true,
    184    interestGroup: { ...BASE_INTEREST_GROUP,
    185                     biddingLogicURL: null }
    186  },
    187  { expectJoinSucces: false,
    188    expectLeaveSucces: true,
    189    interestGroup: { ...BASE_INTEREST_GROUP,
    190                     biddingLogicURL: 'https://{{hosts[][www]}}/foo.js' }
    191  },
    192  { expectJoinSucces: false,
    193    expectLeaveSucces: true,
    194    interestGroup: { ...BASE_INTEREST_GROUP,
    195                     biddingLogicURL: 'data:text/javascript,Foo' }
    196  },
    197  { expectJoinSucces: true,
    198    expectLeaveSucces: true,
    199    interestGroup: { ...BASE_INTEREST_GROUP,
    200                     biddingLogicURL: `${window.location.origin}/foo.js`}
    201  },
    202  { expectJoinSucces: true,
    203    expectLeaveSucces: true,
    204    interestGroup: { ...BASE_INTEREST_GROUP,
    205                     biddingLogicURL: 'relative/path' }
    206  },
    207 
    208  // "biddingWasmHelperURL" tests
    209  { expectJoinSucces: true,
    210    expectLeaveSucces: true,
    211    interestGroup: { ...BASE_INTEREST_GROUP,
    212                     biddingWasmHelperURL: null }
    213  },
    214  { expectJoinSucces: false,
    215    expectLeaveSucces: true,
    216    interestGroup: { ...BASE_INTEREST_GROUP,
    217                     biddingWasmHelperURL: 'https://{{hosts[][www]}}/foo.js' }
    218  },
    219  { expectJoinSucces: false,
    220    expectLeaveSucces: true,
    221    interestGroup: { ...BASE_INTEREST_GROUP,
    222                     biddingWasmHelperURL: 'data:application/wasm,Foo' }
    223  },
    224  { expectJoinSucces: true,
    225    expectLeaveSucces: true,
    226    interestGroup: { ...BASE_INTEREST_GROUP,
    227                     biddingWasmHelperURL: `${window.location.origin}/foo.js`}
    228  },
    229  { expectJoinSucces: true,
    230    expectLeaveSucces: true,
    231    interestGroup: { ...BASE_INTEREST_GROUP,
    232                     biddingWasmHelperURL: 'relative/path' }
    233  },
    234 
    235  // "updateURL" tests
    236  { expectJoinSucces: true,
    237    expectLeaveSucces: true,
    238    interestGroup: { ...BASE_INTEREST_GROUP,
    239                     updateURL: null }
    240  },
    241  { expectJoinSucces: false,
    242    expectLeaveSucces: true,
    243    interestGroup: { ...BASE_INTEREST_GROUP,
    244                     updateURL: 'https://{{hosts[][www]}}/foo.js' }
    245  },
    246  { expectJoinSucces: false,
    247    expectLeaveSucces: true,
    248    interestGroup: { ...BASE_INTEREST_GROUP,
    249                     updateURL: 'data:application/wasm,Foo' }
    250  },
    251  { expectJoinSucces: true,
    252    expectLeaveSucces: true,
    253    interestGroup: { ...BASE_INTEREST_GROUP,
    254                     updateURL: `${window.location.origin}/foo.js`}
    255  },
    256  { expectJoinSucces: true,
    257    expectLeaveSucces: true,
    258    interestGroup: { ...BASE_INTEREST_GROUP,
    259                     updateURL: 'relative/path' }
    260  },
    261 
    262  // "executionMode" tests
    263  { expectJoinSucces: true,
    264    expectLeaveSucces: true,
    265    interestGroup: { ...BASE_INTEREST_GROUP,
    266                     executionMode: 'compatibility' }
    267  },
    268  { expectJoinSucces: true,
    269    expectLeaveSucces: true,
    270    interestGroup: { ...BASE_INTEREST_GROUP,
    271                     executionMode: 'groupByOrigin' }
    272  },
    273  { expectJoinSucces: true,
    274    expectLeaveSucces: true,
    275    interestGroup: { ...BASE_INTEREST_GROUP,
    276                     executionMode: 'unknownValuesAreValid' }
    277  },
    278 
    279  // "trustedBiddingSignalsURL" tests
    280  { expectJoinSucces: true,
    281    expectLeaveSucces: true,
    282    interestGroup: { ...BASE_INTEREST_GROUP,
    283                     trustedBiddingSignalsURL: null }
    284  },
    285  { expectJoinSucces: false,
    286    expectLeaveSucces: true,
    287    interestGroup: { ...BASE_INTEREST_GROUP,
    288                     trustedBiddingSignalsURL: 'https://{{hosts[][www]}}/foo.js' }
    289  },
    290  { expectJoinSucces: false,
    291    expectLeaveSucces: true,
    292    interestGroup: { ...BASE_INTEREST_GROUP,
    293                     trustedBiddingSignalsURL: 'data:application/json,{}' }
    294  },
    295  { expectJoinSucces: true,
    296    expectLeaveSucces: true,
    297    interestGroup: { ...BASE_INTEREST_GROUP,
    298                     trustedBiddingSignalsURL: `${window.location.origin}/foo.js`}
    299  },
    300  { expectJoinSucces: true,
    301    expectLeaveSucces: true,
    302    interestGroup: { ...BASE_INTEREST_GROUP,
    303                     trustedBiddingSignalsURL: 'relative/path' }
    304  },
    305 
    306  // "trustedBiddingSignalsKeys" tests
    307  { expectJoinSucces: false,
    308    expectLeaveSucces: true,
    309    interestGroup: { ...BASE_INTEREST_GROUP,
    310                     trustedBiddingSignalsKeys: null }
    311  },
    312  { expectJoinSucces: false,
    313    expectLeaveSucces: true,
    314    interestGroup: { ...BASE_INTEREST_GROUP,
    315                     trustedBiddingSignalsKeys: {}}
    316  },
    317  { expectJoinSucces: true,
    318    expectLeaveSucces: true,
    319    interestGroup: { ...BASE_INTEREST_GROUP,
    320                     trustedBiddingSignalsKeys: []}
    321  },
    322  { expectJoinSucces: true,
    323    expectLeaveSucces: true,
    324    interestGroup: { ...BASE_INTEREST_GROUP,
    325                     trustedBiddingSignalsKeys: ['a', 4, 'Foo']}
    326  },
    327 
    328  // "userBiddingSignals" tests
    329  { expectJoinSucces: true,
    330    expectLeaveSucces: true,
    331    interestGroup: { ...BASE_INTEREST_GROUP,
    332                     userBiddingSignals: null }
    333  },
    334  { expectJoinSucces: true,
    335    expectLeaveSucces: true,
    336    interestGroup: { ...BASE_INTEREST_GROUP,
    337                     userBiddingSignals: 'foo' }
    338  },
    339  { expectJoinSucces: true,
    340    expectLeaveSucces: true,
    341    interestGroup: { ...BASE_INTEREST_GROUP,
    342                     userBiddingSignals: 15 }
    343  },
    344  { expectJoinSucces: true,
    345    expectLeaveSucces: true,
    346    interestGroup: { ...BASE_INTEREST_GROUP,
    347                     userBiddingSignals: [5, 'foo', [-6.4, {a: 'b'}]] }
    348  },
    349  { expectJoinSucces: true,
    350    expectLeaveSucces: true,
    351    interestGroup: { ...BASE_INTEREST_GROUP,
    352                     userBiddingSignals: {a: [5, 'foo', {b: -6.4}] }}
    353  },
    354 
    355  // "ads" tests
    356  { expectJoinSucces: false,
    357    expectLeaveSucces: true,
    358    interestGroup: { ...BASE_INTEREST_GROUP,
    359                     ads: null }
    360  },
    361  { expectJoinSucces: false,
    362    expectLeaveSucces: true,
    363    interestGroup: { ...BASE_INTEREST_GROUP,
    364                     ads: 5 }
    365  },
    366  { expectJoinSucces: false,
    367    expectLeaveSucces: true,
    368    interestGroup: { ...BASE_INTEREST_GROUP,
    369                     ads: {} }
    370  },
    371  { expectJoinSucces: true,
    372    expectLeaveSucces: true,
    373    interestGroup: { ...BASE_INTEREST_GROUP,
    374                     ads: [] }
    375  },
    376  { expectJoinSucces: false,
    377    expectLeaveSucces: true,
    378    interestGroup: { ...BASE_INTEREST_GROUP,
    379                     ads: [{}] }
    380  },
    381  { expectJoinSucces: false,
    382    expectLeaveSucces: true,
    383    interestGroup: { ...BASE_INTEREST_GROUP,
    384                     ads: [{metadata: [{a:'b'}, 'c'], 1:[2,3]}] }
    385  },
    386  { expectJoinSucces: false,
    387    expectLeaveSucces: true,
    388    interestGroup: { ...BASE_INTEREST_GROUP,
    389                     ads: [{renderURL: 'https://somewhere.test/',
    390                            adRenderId: 'thirteenChars' }] }
    391  },
    392 
    393  { expectJoinSucces: true,
    394    expectLeaveSucces: true,
    395    interestGroup: { ...BASE_INTEREST_GROUP,
    396                     ads: [{renderURL: 'https://somewhere.test/'}] }
    397  },
    398 
    399  // "adComponents" tests
    400  { expectJoinSucces: false,
    401    expectLeaveSucces: true,
    402    interestGroup: { ...BASE_INTEREST_GROUP,
    403                     adComponents: null }
    404  },
    405  { expectJoinSucces: false,
    406    expectLeaveSucces: true,
    407    interestGroup: { ...BASE_INTEREST_GROUP,
    408                     adComponents: 5 }
    409  },
    410  { expectJoinSucces: false,
    411    expectLeaveSucces: true,
    412    interestGroup: { ...BASE_INTEREST_GROUP,
    413                     adComponents: [{}] }
    414  },
    415  { expectJoinSucces: false,
    416    expectLeaveSucces: true,
    417    interestGroup: { ...BASE_INTEREST_GROUP,
    418                     adComponents: [{metadata: [{a:'b'}, 'c'], 1:[2,3]}] }
    419  },
    420  { expectJoinSucces: false,
    421    expectLeaveSucces: true,
    422    interestGroup: { ...BASE_INTEREST_GROUP,
    423                     adComponents: [{renderURL: 'https://somewhere.test/',
    424                                     adRenderId: 'More than twelve characters'}] }
    425  },
    426  { expectJoinSucces: true,
    427    expectLeaveSucces: true,
    428    interestGroup: { ...BASE_INTEREST_GROUP,
    429                     adComponents: [{renderURL: 'https://somewhere.test/'}] }
    430  },
    431 
    432  // Miscellaneous tests.
    433  { expectJoinSucces: true,
    434    expectLeaveSucces: true,
    435    interestGroup: { ...BASE_INTEREST_GROUP,
    436                     extra: false,
    437                     fields: {do:'not'},
    438                     matter: 'at',
    439                     all: [3,4,5] }
    440  },
    441 
    442  // Interest group dictionaries must be less than 1 MB (1048576 bytes), so
    443  // test that here by using a large name on an otherwise valid interest group
    444  // dictionary. The first case is the largest name value that still results in
    445  // a valid dictionary, whereas the second test case produces a dictionary
    446  // that's one byte too large.
    447  { expectJoinSucces: true,
    448    expectLeaveSucces: true,
    449    interestGroup: { ...BASE_INTEREST_GROUP,
    450      name: 'a'.repeat(1048516)
    451    },
    452    testCaseName: "Largest possible interest group dictionary",
    453  },
    454  { expectJoinSucces: false,
    455    expectLeaveSucces: true,
    456    interestGroup: { ...BASE_INTEREST_GROUP,
    457      name: 'a'.repeat(1048517)
    458    },
    459    testCaseName: "Oversized interest group dictionary",
    460  },
    461 ];
    462 
    463 for (let testCase of SIMPLE_JOIN_LEAVE_TEST_CASES) {
    464  var test_name = 'Join and leave interest group: ';
    465  if ('testCaseName' in testCase) {
    466    test_name += testCase.testCaseName;
    467  } else {
    468    test_name += JSON.stringify(testCase);
    469  }
    470 
    471  subsetTest(promise_test, (async (testCase) => {
    472    const INTEREST_GROUP_LIFETIME_SECS = 1;
    473 
    474    let join_promise = navigator.joinAdInterestGroup(testCase.interestGroup,
    475                                                     INTEREST_GROUP_LIFETIME_SECS);
    476    assert_true(join_promise instanceof Promise, "join should return a promise");
    477    if (testCase.expectJoinSucces) {
    478      assert_equals(await join_promise, undefined);
    479    } else {
    480      let joinExceptionThrown = false;
    481      try {
    482        await join_promise;
    483      } catch (e) {
    484        joinExceptionThrown = true;
    485      }
    486      assert_true(joinExceptionThrown, 'Exception not thrown on join.');
    487    }
    488 
    489    let leave_promise = navigator.leaveAdInterestGroup(testCase.interestGroup);
    490    assert_true(leave_promise instanceof Promise, "leave should return a promise");
    491    if (testCase.expectLeaveSucces) {
    492      assert_equals(await leave_promise, undefined);
    493    } else {
    494      let leaveExceptionThrown = false;
    495      try {
    496        await leave_promise;
    497      } catch (e) {
    498        leaveExceptionThrown = true;
    499      }
    500      assert_true(leaveExceptionThrown, 'Exception not thrown on leave.');
    501    }
    502  }).bind(undefined, testCase), test_name);
    503 }
    504 
    505 subsetTest(promise_test, async test => {
    506  const uuid = generateUuid(test);
    507 
    508  // Joining an interest group without a bidding script and run an auction.
    509  // There should be no winner.
    510  await joinInterestGroup(test, uuid, { biddingLogicURL: null });
    511  assert_equals(null, await runBasicFledgeAuction(test, uuid),
    512                'Auction unexpectedly had a winner');
    513 
    514  // Joining an interest group with a bidding script and the same owner/name as
    515  // the previously joined interest group, and re-run the auction. There should
    516  // be a winner this time.
    517  await joinInterestGroup(test, uuid);
    518  let config = await runBasicFledgeAuction(test, uuid);
    519  assert_true(config instanceof FencedFrameConfig,
    520              'Wrong value type returned from auction: ' +
    521              config.constructor.name);
    522 
    523  // Re-join the first interest group, and re-run the auction. The interest
    524  // group should be overwritten again, and there should be no winner.
    525  await joinInterestGroup(test, uuid, { biddingLogicURL: null });
    526  assert_equals(null, await runBasicFledgeAuction(test, uuid),
    527                'Auction unexpectedly had a winner');
    528 }, 'Join same interest group overwrites old matching group.');
    529 
    530 subsetTest(promise_test, async test => {
    531  const uuid = generateUuid(test);
    532 
    533  // Join an interest group, run an auction to make sure it was joined.
    534  await joinInterestGroup(test, uuid);
    535  let config = await runBasicFledgeAuction(test, uuid);
    536  assert_true(config instanceof FencedFrameConfig,
    537              'Wrong value type returned from auction: ' +
    538              config.constructor.name);
    539 
    540  // Leave the interest group, re-run the auction. There should be no winner.
    541  await leaveInterestGroup();
    542  assert_equals(null, await runBasicFledgeAuction(test, uuid),
    543                'Auction unexpectedly had a winner');
    544 }, 'Leaving interest group actually leaves interest group.');
    545 
    546 subsetTest(promise_test, async test => {
    547  // This should not throw.
    548  await leaveInterestGroup({ name: 'Never join group' });
    549 }, 'Leave an interest group that was never joined.');
    550 
    551 ///////////////////////////////////////////////////////////////////////////////
    552 // Expiration tests
    553 ///////////////////////////////////////////////////////////////////////////////
    554 
    555 subsetTest(promise_test, async test => {
    556  const uuid = generateUuid(test);
    557 
    558  // Joins the default interest group, with a 0.2 second duration.
    559  await joinInterestGroup(test, uuid, {}, 0.2);
    560 
    561  // Keep on running auctions until interest group duration expires.
    562  // Unfortunately, there's no duration that's guaranteed to be long enough to
    563  // be be able to win an auction once, but short enough to prevent this test
    564  // from running too long, so can't check the interest group won at least one
    565  // auction.
    566  while (await runBasicFledgeAuction(test, uuid) !== null);
    567 }, 'Interest group duration.');
    568 
    569 subsetTest(promise_test, async test => {
    570  const uuid = generateUuid(test);
    571 
    572  // Join interest group with a duration of -600. The interest group should
    573  // immediately expire, and not be allowed to participate in auctions.
    574  await joinInterestGroup(test, uuid, {}, -600);
    575  assert_true(await runBasicFledgeAuction(test, uuid) === null);
    576 }, 'Interest group duration of -600.');
    577 
    578 subsetTest(promise_test, async test => {
    579  const uuid = generateUuid(test);
    580 
    581  // Join a long-lived interest group.
    582  await joinInterestGroup(test, uuid, {}, 600);
    583 
    584  // Make sure interest group with a non-default timeout was joined.
    585  assert_true(await runBasicFledgeAuction(test, uuid) !== null);
    586 
    587  // Re-join interest group with a duration value of 0.2 seconds.
    588  await joinInterestGroup(test, uuid, {}, 0.2);
    589 
    590  // Keep on running auctions until interest group expires.
    591  while (await runBasicFledgeAuction(test, uuid) !== null);
    592 }, 'Interest group test with overwritten duration.');
    593 
    594 subsetTest(promise_test, async test => {
    595  const uuid = generateUuid(test);
    596 
    597  // Join a long-lived interest group.
    598  await joinInterestGroup(test, uuid, {}, 600);
    599 
    600  // Re-join interest group with a duration value of 0.2 seconds. The new
    601  // duration should take precedence, and the interest group should immediately
    602  // expire.
    603  await joinInterestGroup(test, uuid, {}, -600);
    604  assert_true(await runBasicFledgeAuction(test, uuid) === null);
    605 }, 'Interest group test with overwritten duration of -600.');