Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strict liveslots test env with upgrade tools #10126

Merged
merged 11 commits into from
Sep 25, 2024
19 changes: 19 additions & 0 deletions packages/SwingSet/tools/prepare-strict-test-env-ava.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Like prepare-strict-test-env but also sets up ses-ava and provides
* the ses-ava `test` function to be used as if it is the ava
* `test` function.
*/

import '@agoric/swingset-liveslots/tools/prepare-strict-test-env.js';

import { wrapTest } from '@endo/ses-ava';
import rawTest from 'ava';

export * from '@agoric/swingset-liveslots/tools/prepare-strict-test-env.js';

export const test = wrapTest(rawTest);

// Does not import from a module because we're testing the global env
/* global globalThis */
export const VatData = globalThis.VatData;
assert(VatData);
3 changes: 1 addition & 2 deletions packages/async-flow/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@
"@endo/promise-kit": "^1.1.5"
},
"devDependencies": {
"@agoric/swingset-liveslots": "^0.10.2",
"@agoric/swingset-vat": "^0.32.2",
"@agoric/zone": "^0.2.2",
"@endo/env-options": "^1.1.6",
"@endo/ses-ava": "^1.2.5",
"ava": "^5.3.0",
"tsd": "^0.31.1"
},
Expand Down
22 changes: 2 additions & 20 deletions packages/async-flow/test/prepare-test-env-ava.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
import '@agoric/swingset-liveslots/tools/prepare-test-env.js';
import { wrapTest } from '@endo/ses-ava';
import rawTest from 'ava';
import '@agoric/swingset-vat/tools/prepare-strict-test-env-ava.js';

import { environmentOptionsListHas } from '@endo/env-options';
import { reincarnate } from '@agoric/swingset-liveslots/tools/setup-vat-data.js';

export const test = wrapTest(rawTest);

/** @type {ReturnType<typeof reincarnate>} */
let incarnation;

export const annihilate = () => {
incarnation = reincarnate({ relaxDurabilityRules: false });
};

export const getBaggage = () => {
return incarnation.fakeVomKit.cm.provideBaggage();
};

export const nextLife = () => {
incarnation = reincarnate(incarnation);
};
export * from '@agoric/swingset-vat/tools/prepare-strict-test-env-ava.js';

export const asyncFlowVerbose = () => {
// TODO figure out how we really want to control this.
Expand Down
70 changes: 70 additions & 0 deletions packages/swingset-liveslots/test/exo-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { provideLazy as provide } from '@agoric/store';

// Partially duplicates @agoric/vat-data to avoid circular dependencies.
export const makeExoUtils = VatData => {
const { defineDurableKind, makeKindHandle, watchPromise } = VatData;

const provideKindHandle = (baggage, kindName) =>
provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName));

const emptyRecord = harden({});
const initEmpty = () => emptyRecord;

const defineDurableExoClass = (
kindHandle,
interfaceGuard,
init,
methods,
options,
) =>
defineDurableKind(kindHandle, init, methods, {
...options,
thisfulMethods: true,
interfaceGuard,
});

const prepareExoClass = (
baggage,
kindName,
interfaceGuard,
init,
methods,
options = undefined,
) =>
defineDurableExoClass(
provideKindHandle(baggage, kindName),
interfaceGuard,
init,
methods,
options,
);

const prepareExo = (
baggage,
kindName,
interfaceGuard,
methods,
options = undefined,
) => {
const makeSingleton = prepareExoClass(
baggage,
kindName,
interfaceGuard,
initEmpty,
methods,
options,
);
return provide(baggage, `the_${kindName}`, () => makeSingleton());
};

return {
defineDurableKind,
makeKindHandle,
watchPromise,

provideKindHandle,
defineDurableExoClass,
prepareExoClass,
prepareExo,
};
};
72 changes: 2 additions & 70 deletions packages/swingset-liveslots/test/handled-promises.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,87 +2,19 @@ import test from 'ava';

import { Fail } from '@endo/errors';
import { Far } from '@endo/marshal';
import { M, provideLazy as provide } from '@agoric/store';
import { M } from '@agoric/store';
import { makePromiseKit } from '@endo/promise-kit';
// Disabled to avoid circular dependencies.
// import { makeStoreUtils } from '@agoric/vat-data/src/vat-data-bindings.js';
// import { makeExoUtils } from '@agoric/vat-data/src/exo-utils.js';
import { kslot, kser } from '@agoric/kmarshal';
import { setupTestLiveslots } from './liveslots-helpers.js';
import { makeResolve, makeReject } from './util.js';
import { makeExoUtils } from './exo-utils.js';

// eslint-disable-next-line no-unused-vars
const compareEntriesByKey = ([ka], [kb]) => (ka < kb ? -1 : 1);

// Paritally duplicates @agoric/vat-data to avoid circular dependencies.
const makeExoUtils = VatData => {
const { defineDurableKind, makeKindHandle, watchPromise } = VatData;

const provideKindHandle = (baggage, kindName) =>
provide(baggage, `${kindName}_kindHandle`, () => makeKindHandle(kindName));

const emptyRecord = harden({});
const initEmpty = () => emptyRecord;

const defineDurableExoClass = (
kindHandle,
interfaceGuard,
init,
methods,
options,
) =>
defineDurableKind(kindHandle, init, methods, {
...options,
thisfulMethods: true,
interfaceGuard,
});

const prepareExoClass = (
baggage,
kindName,
interfaceGuard,
init,
methods,
options = undefined,
) =>
defineDurableExoClass(
provideKindHandle(baggage, kindName),
interfaceGuard,
init,
methods,
options,
);

const prepareExo = (
baggage,
kindName,
interfaceGuard,
methods,
options = undefined,
) => {
const makeSingleton = prepareExoClass(
baggage,
kindName,
interfaceGuard,
initEmpty,
methods,
options,
);
return provide(baggage, `the_${kindName}`, () => makeSingleton());
};

return {
defineDurableKind,
makeKindHandle,
watchPromise,

provideKindHandle,
defineDurableExoClass,
prepareExoClass,
prepareExo,
};
};

// cf. packages/SwingSet/test/vat-durable-promise-watcher.js
const buildPromiseWatcherRootObject = (vatPowers, vatParameters, baggage) => {
const { VatData } = vatPowers;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* global globalThis */
// eslint-disable-next-line import/order
import { annihilate, startLife } from '../tools/prepare-strict-test-env.js';

import test from 'ava';

import { makeUpgradeDisconnection } from '@agoric/internal/src/upgrade-api.js';
import { makeExoUtils } from './exo-utils.js';

test.serial('kind redefinition enforced', async t => {
annihilate();

const { prepareExoClass } = makeExoUtils(globalThis.VatData);

await startLife(async baggage => {
const makeTestExo = prepareExoClass(
baggage,
'TestExo',
undefined,
() => ({}),
{
foo() {
return 'bar';
},
},
);

baggage.init('testExo', makeTestExo());
});

await t.throwsAsync(
async () =>
startLife(async () => {
// Not redefining the kind here
}),
{ message: 'defineDurableKind not called for tags: [TestExo]' },
);

await startLife(async baggage => {
prepareExoClass(baggage, 'TestExo', undefined, () => ({}), {
foo() {
return 'baz';
},
});

t.is(baggage.get('testExo').foo(), 'baz');
});
});

test.serial('decided promise rejected', async t => {
annihilate();

const { prepareExo } = makeExoUtils(globalThis.VatData);
const { watchPromise } = globalThis.VatData;

t.plan(1);

await startLife(async baggage => {
const watcher = prepareExo(
baggage,
'DurablePromiseTestWatcher',
undefined,
{
onFulfilled(value) {
t.fail(
`First incarnation watcher onFulfilled triggered with value ${value}`,
);
},
onRejected(reason) {
t.fail(
`First incarnation watcher onRejected triggered with reason ${reason}`,
);
},
},
);

const never = harden(new Promise(() => {}));

watchPromise(never, watcher);
});

await startLife(async baggage => {
prepareExo(baggage, 'DurablePromiseTestWatcher', undefined, {
onFulfilled(value) {
t.fail(
`Second incarnation watcher onFulfilled triggered with value ${value}`,
);
},
onRejected(reason) {
t.deepEqual(reason, makeUpgradeDisconnection('vat upgraded', 1));
},
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ test('multifaceted virtual objects', t => {

flushStateCache();
t.deepEqual(log.splice(0), [
`get kindIDID => undefined`,
`get idCounters => undefined`,
`get kindIDID => undefined`,
`set kindIDID 1`,
`set vom.vkind.2.descriptor {"kindID":"2","tag":"multithing"}`,
`set vom.${kid}/1 ${multiThingVal('foo', 1)}`,
Expand Down Expand Up @@ -203,8 +203,8 @@ test('virtual object operations', t => {
// t3-0: 'thing-3' 200 0
const thing4 = makeThing('thing-4', 300); // [t4-0* t3-0* t2-0* t1-0*]
// t4-0: 'thing-4' 300 0
t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `get idCounters => undefined`);
t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `set kindIDID 1`);
t.is(log.shift(), `set vom.vkind.2.descriptor {"kindID":"2","tag":"thing"}`);
t.is(log.shift(), `set vom.vkind.3.descriptor {"kindID":"3","tag":"zot"}`);
Expand Down Expand Up @@ -468,8 +468,8 @@ test('symbol named methods', t => {
// t1-0: 'thing-1' 0 0
const thing2 = makeThing('thing-2', 100); // [t1-0* t2-0*]
// t2-0: 'thing-2' 100 0
t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `get idCounters => undefined`);
t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `set kindIDID 1`);
t.is(
log.shift(),
Expand Down Expand Up @@ -649,8 +649,8 @@ test('virtual object gc', t => {
},
});

t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `get idCounters => undefined`);
t.is(log.shift(), `get kindIDID => undefined`);
t.is(log.shift(), `set kindIDID 1`);
const skit = [
'storeKindIDTable',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff) {
VirtualObjectAwareWeakSet,
flushStateCache,
canBeDurable,
insistAllDurableKindsReconnected,
} = makeVirtualObjectManager(
fakeStuff.syscall,
vrm,
Expand All @@ -43,6 +44,7 @@ export function makeFakeVirtualObjectManager(vrm, fakeStuff) {
defineDurableKindMulti,
makeKindHandle,
canBeDurable,
insistAllDurableKindsReconnected,
VirtualObjectAwareWeakMap,
VirtualObjectAwareWeakSet,
};
Expand Down
Loading
Loading