From ad0df91027ebe6ade220c99053bd2ff598478f9a Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 10 Sep 2024 13:27:59 -0700 Subject: [PATCH 1/2] Revert "test: temporarily remove addAssets test" This reverts commit 9e15cb4fbd2eedc488ed8a3a3cebb046a72dd69c. --- .../test/bootstrapTests/addAssets.test.ts | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 packages/boot/test/bootstrapTests/addAssets.test.ts diff --git a/packages/boot/test/bootstrapTests/addAssets.test.ts b/packages/boot/test/bootstrapTests/addAssets.test.ts new file mode 100644 index 00000000000..c472e47ddac --- /dev/null +++ b/packages/boot/test/bootstrapTests/addAssets.test.ts @@ -0,0 +1,169 @@ +import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; + +import type { TestFn } from 'ava'; + +import { TimeMath } from '@agoric/time'; +import { + LiquidationTestContext, + makeLiquidationTestContext, +} from '../../tools/liquidation.js'; +import { makeProposalExtractor } from '../../tools/supports.js'; + +const test = anyTest as TestFn< + LiquidationTestContext & { + getCollateralProposal: ( + name: string, + id: string, + ) => Awaited>>; + } +>; + +const auctioneerPath = 'published.auction'; + +test.before(async t => { + const context = await makeLiquidationTestContext(t); + const proposal = await context.buildProposal( + '@agoric/builders/scripts/inter-protocol/add-STARS.js', + ); + + const getCollateralProposal = (name, id) => { + // stringify, modify and parse because modifying a deep copy was fragile. + const proposalJSON = JSON.stringify(proposal); + const proposalMod = proposalJSON + .replaceAll('STARS', name) + .replaceAll('ibc/987C17B1', `ibc/987C17B1${id}`); + return JSON.parse(proposalMod); + }; + t.context = { + ...context, + getCollateralProposal, + }; +}); + +test.after.always(t => { + // This will fail if a subset of tests are run. It detects that three + // collaterals were added to the auction after ATOM. + t.like(t.context.readLatest(`${auctioneerPath}.book3`), { + currentPriceLevel: null, + }); + return t.context.shutdown && t.context.shutdown(); +}); + +test('addAsset to quiescent auction', async t => { + const { advanceTimeTo, evalProposal, readLatest } = t.context; + + await evalProposal(t.context.getCollateralProposal('COMETS', 'A')); + + const { EV } = t.context.runUtils; + + const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); + const schedules = await EV(auctioneerKit.creatorFacet).getSchedule(); + const { liveAuctionSchedule, nextAuctionSchedule } = schedules; + const nextEndTime = liveAuctionSchedule + ? liveAuctionSchedule.endTime + : nextAuctionSchedule!.endTime; + const fiveMinutes = harden({ + relValue: 5n * 60n, + timerBrand: nextEndTime.timerBrand, + }); + const nextQuiescentTime = TimeMath.addAbsRel(nextEndTime, fiveMinutes); + await advanceTimeTo(nextQuiescentTime); + + t.like(readLatest(`${auctioneerPath}.book1`), { + currentPriceLevel: null, + }); +}); + +test('addAsset to active auction', async t => { + const { advanceTimeTo, readLatest } = t.context; + const { EV } = t.context.runUtils; + + t.like(readLatest(`${auctioneerPath}.book0`), { startPrice: null }); + + const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); + const schedules = await EV(auctioneerKit.creatorFacet).getSchedule(); + const { nextAuctionSchedule } = schedules; + assert(nextAuctionSchedule); + const nextStartTime = nextAuctionSchedule.startTime; + const fiveMinutes = harden({ + relValue: 5n * 60n, + timerBrand: nextStartTime.timerBrand, + }); + const futureBusyTime = TimeMath.addAbsRel(nextStartTime, fiveMinutes); + + await advanceTimeTo(futureBusyTime); + + t.log('launching proposal'); + + const proposal = t.context.getCollateralProposal('PLANETS', 'B'); + const bridgeMessage = { + type: 'CORE_EVAL', + evals: proposal.evals, + }; + t.log({ bridgeMessage }); + + const coreEvalBridgeHandler = await EV.vat('bootstrap').consumeItem( + 'coreEvalBridgeHandler', + ); + // XXX races with the following lines + void EV(coreEvalBridgeHandler).fromBridge(bridgeMessage); + + const nextEndTime = nextAuctionSchedule!.endTime; + const afterEndTime = TimeMath.addAbsRel(nextEndTime, fiveMinutes); + await advanceTimeTo(afterEndTime); + t.log('proposal executed'); + + const schedulesAfter = await EV(auctioneerKit.creatorFacet).getSchedule(); + // TimeMath.compareAbs() can't handle brands processed by kmarshall + t.truthy( + schedules.nextAuctionSchedule!.endTime.absValue < + schedulesAfter.nextAuctionSchedule!.endTime.absValue, + ); + + t.like(readLatest(`${auctioneerPath}.book1`), { currentPriceLevel: null }); +}); + +test('addAsset to auction starting soon', async t => { + const { advanceTimeTo, readLatest } = t.context; + const { EV } = t.context.runUtils; + + const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); + const schedules = await EV(auctioneerKit.creatorFacet).getSchedule(); + const { nextAuctionSchedule } = schedules; + assert(nextAuctionSchedule); + const nextStartTime = nextAuctionSchedule.startTime; + const fiveMinutes = harden({ + relValue: 5n * 60n, + timerBrand: nextStartTime.timerBrand, + }); + const tooCloseTime = TimeMath.subtractAbsRel(nextStartTime, fiveMinutes); + + await advanceTimeTo(tooCloseTime); + + const proposal = t.context.getCollateralProposal('MOONS', 'C'); + t.log('launching proposal'); + const bridgeMessage = { + type: 'CORE_EVAL', + evals: proposal.evals, + }; + t.log({ bridgeMessage }); + + const coreEvalBridgeHandler = await EV.vat('bootstrap').consumeItem( + 'coreEvalBridgeHandler', + ); + // XXX races with the following lines + void EV(coreEvalBridgeHandler).fromBridge(bridgeMessage); + + const nextEndTime = nextAuctionSchedule.endTime; + const afterEndTime = TimeMath.addAbsRel(nextEndTime, fiveMinutes); + await advanceTimeTo(afterEndTime); + + t.log('proposal executed'); + + const schedulesAfter = await EV(auctioneerKit.creatorFacet).getSchedule(); + t.truthy( + schedules.nextAuctionSchedule!.endTime.absValue < + schedulesAfter.nextAuctionSchedule!.endTime.absValue, + ); + t.like(readLatest(`${auctioneerPath}.book1`), { currentPriceLevel: null }); +}); From 5ad5ebc25f6c4ed225e70b2a4253aa896dbab105 Mon Sep 17 00:00:00 2001 From: Turadg Aleahmad Date: Tue, 10 Sep 2024 13:59:38 -0700 Subject: [PATCH 2/2] test: sequential addAssets --- .../test/bootstrapTests/addAssets.test.ts | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/packages/boot/test/bootstrapTests/addAssets.test.ts b/packages/boot/test/bootstrapTests/addAssets.test.ts index c472e47ddac..90190890b22 100644 --- a/packages/boot/test/bootstrapTests/addAssets.test.ts +++ b/packages/boot/test/bootstrapTests/addAssets.test.ts @@ -1,3 +1,7 @@ +/** + * @file tests of adding an asset to the vaultFactory. + * Checks that auctions update correctly. + */ import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; import type { TestFn } from 'ava'; @@ -15,6 +19,7 @@ const test = anyTest as TestFn< name: string, id: string, ) => Awaited>>; + getNumAuctionBooks: () => number; } >; @@ -34,23 +39,28 @@ test.before(async t => { .replaceAll('ibc/987C17B1', `ibc/987C17B1${id}`); return JSON.parse(proposalMod); }; + + const getNumAuctionBooks = () => + Array.from(context.storage.data.keys()).filter(k => + k.startsWith(`${auctioneerPath}.book`), + ).length; + t.context = { ...context, getCollateralProposal, + getNumAuctionBooks, }; }); test.after.always(t => { - // This will fail if a subset of tests are run. It detects that three - // collaterals were added to the auction after ATOM. - t.like(t.context.readLatest(`${auctioneerPath}.book3`), { - currentPriceLevel: null, - }); return t.context.shutdown && t.context.shutdown(); }); -test('addAsset to quiescent auction', async t => { - const { advanceTimeTo, evalProposal, readLatest } = t.context; +test.serial('addAsset to quiescent auction', async t => { + const { advanceTimeTo, evalProposal, getNumAuctionBooks, readLatest } = + t.context; + + const booksBefore = getNumAuctionBooks(); await evalProposal(t.context.getCollateralProposal('COMETS', 'A')); @@ -69,16 +79,31 @@ test('addAsset to quiescent auction', async t => { const nextQuiescentTime = TimeMath.addAbsRel(nextEndTime, fiveMinutes); await advanceTimeTo(nextQuiescentTime); - t.like(readLatest(`${auctioneerPath}.book1`), { - currentPriceLevel: null, - }); + const booksAfter = getNumAuctionBooks(); + t.is(booksAfter, booksBefore + 1); + + t.like( + readLatest(`${auctioneerPath}.book${booksAfter - 1}`), + { + currentPriceLevel: null, + }, + 'quiescent', + ); }); -test('addAsset to active auction', async t => { - const { advanceTimeTo, readLatest } = t.context; +test.serial('addAsset to active auction', async t => { + const { advanceTimeTo, getNumAuctionBooks, readLatest } = t.context; const { EV } = t.context.runUtils; - t.like(readLatest(`${auctioneerPath}.book0`), { startPrice: null }); + const booksBefore = getNumAuctionBooks(); + + t.like( + readLatest(`${auctioneerPath}.book${booksBefore - 1}`), + { + startPrice: null, + }, + 'active', + ); const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); const schedules = await EV(auctioneerKit.creatorFacet).getSchedule(); @@ -120,12 +145,14 @@ test('addAsset to active auction', async t => { schedulesAfter.nextAuctionSchedule!.endTime.absValue, ); - t.like(readLatest(`${auctioneerPath}.book1`), { currentPriceLevel: null }); + const booksAfter = getNumAuctionBooks(); + t.is(booksAfter, booksBefore + 1); }); -test('addAsset to auction starting soon', async t => { - const { advanceTimeTo, readLatest } = t.context; +test.serial('addAsset to auction starting soon', async t => { + const { advanceTimeTo, getNumAuctionBooks } = t.context; const { EV } = t.context.runUtils; + const booksBefore = getNumAuctionBooks(); const auctioneerKit = await EV.vat('bootstrap').consumeItem('auctioneerKit'); const schedules = await EV(auctioneerKit.creatorFacet).getSchedule(); @@ -165,5 +192,7 @@ test('addAsset to auction starting soon', async t => { schedules.nextAuctionSchedule!.endTime.absValue < schedulesAfter.nextAuctionSchedule!.endTime.absValue, ); - t.like(readLatest(`${auctioneerPath}.book1`), { currentPriceLevel: null }); + + const booksAfter = getNumAuctionBooks(); + t.is(booksAfter, booksBefore + 1); });