Skip to content

Commit

Permalink
test baggage (#9659)
Browse files Browse the repository at this point in the history
incidental

## Description
Adds a way to test contract baggage, to detect changes.


### Security Considerations
Uses the `setTestJig` to expose baggage. Safe by design.

### Scaling Considerations
none

### Documentation Considerations
Could be useful at some point

### Testing Considerations
CI

### Upgrade Considerations
none
  • Loading branch information
mergify[bot] authored Jul 8, 2024
2 parents d60c4df + fbe4414 commit a4a571e
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 4 deletions.
37 changes: 37 additions & 0 deletions packages/internal/src/testing-utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// @ts-check
/**
* @file note this cannot be called test-utils.js due to
* https://github.com/Agoric/agoric-sdk/issues/7503
*/
/* global setImmediate */
/** @import {MapStore} from '@agoric/store'; */

/**
* A workaround for some issues with fake time in tests.
Expand All @@ -14,3 +16,38 @@
export const eventLoopIteration = async () =>
new Promise(resolve => setImmediate(resolve));
harden(eventLoopIteration);

/** @type {(value: any) => string} */
const stringOrTag = value => {
if (typeof value === 'string') {
return value;
} else if (typeof value === 'object' && Symbol.toStringTag in value) {
return value[Symbol.toStringTag];
}
return String(value);
};
/**
* @param {MapStore} store
* @returns {object} tree of the contents of the storeÂ
*/
export const inspectMapStore = store => {
/** @type {Record<string, unknown>} */
const obj = {};
for (const key of store.keys()) {
const value = store.get(key);
const hasKeys = typeof value === 'object' && 'keys' in value;
const index = stringOrTag(key);
if (hasKeys && 'get' in value) {
obj[index] = inspectMapStore(value);
} else if (hasKeys) {
obj[index] = Array.from(value.keys());
} else {
obj[index] =
value instanceof Object && Symbol.toStringTag in value
? value[Symbol.toStringTag]
: value;
}
}
return obj;
};
harden(inspectMapStore);
4 changes: 4 additions & 0 deletions packages/orchestration/src/utils/start-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export const provideOrchestration = (
remotePowers,
marshaller,
) => {
zcf.setTestJig(() => ({
baggage,
}));

const zone = makeDurableZone(baggage);
const { agoricNames, timerService } = remotePowers;

Expand Down
28 changes: 28 additions & 0 deletions packages/orchestration/test/examples/sendAnywhere.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { E } from '@endo/far';
import path from 'path';
import { mustMatch } from '@endo/patterns';
import { makeIssuerKit } from '@agoric/ertp';
import { inspectMapStore } from '@agoric/internal/src/testing-utils.js';
import { CosmosChainInfo, IBCConnectionInfo } from '../../src/cosmos-api.js';
import { commonSetup } from '../supports.js';
import { SingleAmountRecord } from '../../src/examples/sendAnywhere.contract.js';
Expand Down Expand Up @@ -214,3 +215,30 @@ test('send using arbitrary chain info', async t => {
});
}
});

test('baggage', async t => {
const {
bootstrap,
commonPrivateArgs,
brands: { ist },
utils: { inspectLocalBridge, pourPayment },
} = await commonSetup(t);

let contractBaggage;
const setJig = ({ baggage }) => {
contractBaggage = baggage;
};
const { bundleAndInstall, zoe } = await setUpZoeForTest({
setJig,
});

await E(zoe).startInstance(
await bundleAndInstall(contractFile),
{ Stable: ist.issuer },
{},
commonPrivateArgs,
);

const tree = inspectMapStore(contractBaggage);
t.snapshot(tree, 'contract baggage after start');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Snapshot report for `test/examples/sendAnywhere.test.ts`

The actual snapshot is saved in `sendAnywhere.test.ts.snap`.

Generated by [AVA](https://avajs.dev).

## baggage

> contract baggage after start
{
'Durable Publish Kit_kindHandle': 'Alleged: kind',
'Local Orchestration Account Kit_kindHandle': 'Alleged: kind',
LocalChainFacade_kindHandle: 'Alleged: kind',
Orchestrator_kindHandle: 'Alleged: kind',
Recorder_kindHandle: 'Alleged: kind',
RemoteChainFacade_kindHandle: 'Alleged: kind',
ResumableAgoricNamesHack_kindHandle: 'Alleged: kind',
'Send CF_kindHandle': 'Alleged: kind',
'Send CF_singleton': 'Alleged: Send CF',
'Send PF_kindHandle': 'Alleged: kind',
'Send PF_singleton': 'Alleged: Send PF',
'Staking Account Holder_kindHandle': 'Alleged: kind',
asyncFlow: {
AdminAsyncFlow_kindHandle: 'Alleged: kind',
AdminAsyncFlow_singleton: 'Alleged: AdminAsyncFlow',
Bijection_kindHandle: 'Alleged: kind',
FunctionUnwrapper_kindHandle: 'Alleged: kind',
FunctionUnwrapper_singleton: 'Alleged: FunctionUnwrapper',
LogStore_kindHandle: 'Alleged: kind',
StateUnwrapper_kindHandle: 'Alleged: kind',
asyncFuncEagerWakers: [],
asyncFuncFailures: {},
flowForOutcomeVow: {},
unwrapMap: 'Alleged: weakMapStore',
},
sendIt: {
asyncFlow_kindHandle: 'Alleged: kind',
endowments: {
1: {
contractState_kindHandle: 'Alleged: kind',
contractState_singleton: 'Alleged: contractState',
},
},
},
vbankAssetsByBrand: {},
vows: {
PromiseWatcher_kindHandle: 'Alleged: kind',
VowInternalsKit_kindHandle: 'Alleged: kind',
WatchUtils_kindHandle: 'Alleged: kind',
},
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Snapshot report for `test/examples/unbondExample.test.ts`

The actual snapshot is saved in `unbondExample.test.ts.snap`.

Generated by [AVA](https://avajs.dev).

## start

> contract baggage after start
{
'Durable Publish Kit_kindHandle': 'Alleged: kind',
LSTTia: {
asyncFlow_kindHandle: 'Alleged: kind',
},
'Local Orchestration Account Kit_kindHandle': 'Alleged: kind',
LocalChainFacade_kindHandle: 'Alleged: kind',
Orchestrator_kindHandle: 'Alleged: kind',
Recorder_kindHandle: 'Alleged: kind',
RemoteChainFacade_kindHandle: 'Alleged: kind',
'Staking Account Holder_kindHandle': 'Alleged: kind',
asyncFlow: {
AdminAsyncFlow_kindHandle: 'Alleged: kind',
AdminAsyncFlow_singleton: 'Alleged: AdminAsyncFlow',
Bijection_kindHandle: 'Alleged: kind',
FunctionUnwrapper_kindHandle: 'Alleged: kind',
FunctionUnwrapper_singleton: 'Alleged: FunctionUnwrapper',
LogStore_kindHandle: 'Alleged: kind',
StateUnwrapper_kindHandle: 'Alleged: kind',
asyncFuncEagerWakers: [],
asyncFuncFailures: {},
flowForOutcomeVow: {},
unwrapMap: 'Alleged: weakMapStore',
},
vows: {
PromiseWatcher_kindHandle: 'Alleged: kind',
VowInternalsKit_kindHandle: 'Alleged: kind',
WatchUtils_kindHandle: 'Alleged: kind',
},
}
Binary file not shown.
11 changes: 10 additions & 1 deletion packages/orchestration/test/examples/unbondExample.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js';
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js';
import { E } from '@endo/far';
import path from 'path';
import { inspectMapStore } from '@agoric/internal/src/testing-utils.js';
import { commonSetup } from '../supports.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);
Expand All @@ -17,7 +18,12 @@ test('start', async t => {
commonPrivateArgs,
} = await commonSetup(t);

const { zoe, bundleAndInstall } = await setUpZoeForTest();
let contractBaggage;
const { zoe, bundleAndInstall } = await setUpZoeForTest({
setJig: ({ baggage }) => {
contractBaggage = baggage;
},
});
const installation: Installation<StartFn> =
await bundleAndInstall(contractFile);

Expand All @@ -43,4 +49,7 @@ test('start', async t => {
);
const result = await E(userSeat).getOfferResult();
t.is(result, undefined);

const tree = inspectMapStore(contractBaggage);
t.snapshot(tree, 'contract baggage after start');
});
4 changes: 4 additions & 0 deletions packages/zoe/src/contracts/valueVow.contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ harden(meta);
* @param {Baggage} baggage
*/
export const start = (zcf, _privateArgs, baggage) => {
zcf.setTestJig(() => ({
baggage,
}));

const zone = makeDurableZone(baggage);

const vowTools = prepareVowTools(zone);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Snapshot report for `test/unitTests/contracts/valueVow.test.js`

The actual snapshot is saved in `valueVow.test.js.snap`.

Generated by [AVA](https://avajs.dev).

## baggage

> contract baggage after start
{
PromiseWatcher_kindHandle: 'Alleged: kind',
VowInternalsKit_kindHandle: 'Alleged: kind',
WatchUtils_kindHandle: 'Alleged: kind',
publicFacet_kindHandle: 'Alleged: kind',
publicFacet_singleton: 'Alleged: publicFacet',
vowResolver: {
resolver: Object @Alleged: VowInternalsKit resolver {},
vow: Object @Vow {
payload: {
vowV0: Object @Alleged: VowInternalsKit vowV0 {},
},
},
},
}
Binary file not shown.
27 changes: 24 additions & 3 deletions packages/zoe/test/unitTests/contracts/valueVow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { heapVowTools } from '@agoric/vow/vat.js';

import { unsafeMakeBundleCache } from '@agoric/swingset-vat/tools/bundleTool.js';
import { E } from '@endo/eventual-send';
import { makeZoeForTest } from '../../../tools/setup-zoe.js';
import { inspectMapStore } from '@agoric/internal/src/testing-utils.js';
import { makeZoeForTest, setUpZoeForTest } from '../../../tools/setup-zoe.js';

/**
* @import {start as startValueVow} from '../../../src/contracts/valueVow.contract.js';
Expand All @@ -15,7 +16,7 @@ import { makeZoeForTest } from '../../../tools/setup-zoe.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);

const contractRoot = `${dirname}/../../../src/contracts/valueVow.contract.js`;
const contractFile = `${dirname}/../../../src/contracts/valueVow.contract.js`;

/** @type {import('ava').TestFn<{ installation: Installation<typeof startValueVow>, zoe: ReturnType<typeof makeZoeForTest> }>} */
const test = anyTest;
Expand All @@ -24,7 +25,7 @@ test.before(async t => {
const bundleCache = await unsafeMakeBundleCache('bundles');
const zoe = makeZoeForTest();
const installation = await E(zoe).install(
await bundleCache.load(contractRoot),
await bundleCache.load(contractFile),
);

t.context = {
Expand Down Expand Up @@ -58,3 +59,23 @@ test('invitations', async t => {

t.is(await heapVowTools.asPromise(vow), 'hello');
});

test('baggage', async t => {
/** @type {import('@agoric/swingset-liveslots').Baggage} */
let contractBaggage;
const setJig = ({ baggage }) => {
contractBaggage = baggage;
};
const { bundleAndInstall, zoe } = await setUpZoeForTest({
setJig,
});

await E(zoe).startInstance(
/** @type {Installation<startValueVow>} */
(await bundleAndInstall(contractFile)),
);

// @ts-expect-error setJig may not have been called
const tree = inspectMapStore(contractBaggage);
t.snapshot(tree, 'contract baggage after start');
});

0 comments on commit a4a571e

Please sign in to comment.