Skip to content

Commit

Permalink
chore(swingset): remove non-XS metering tests (injected Node shim)
Browse files Browse the repository at this point in the history
We no longer care about injected (Node.js) -based metering: XS is the only
platform where we can reasonably+efficiently meter code. This removes the
unit tests which exercised injected metering, as well as the grandchild
Compartment -based escape we found and fixed.

The tests are modernized slightly: using `controller.kpResolution` instead of
appending strings to testLog.

This is a cleanup/refactoring in preparation for #3308, but is limited to
unit tests, and does not change any code behavior.
  • Loading branch information
warner committed Jul 22, 2021
1 parent 5704f80 commit 5a82a3a
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 388 deletions.
6 changes: 0 additions & 6 deletions packages/SwingSet/test/metering/grandchild.js

This file was deleted.

15 changes: 0 additions & 15 deletions packages/SwingSet/test/metering/metered-dynamic-vat.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { assert } from '@agoric/assert';
import { importBundle } from '@agoric/import-bundle';
import { makePromiseKit } from '@agoric/promise-kit';
import { Far } from '@agoric/marshal';
import { meterMe } from './metered-code.js';

export function buildRootObject(_dynamicVatPowers) {
let grandchildNS;

return Far('root', {
never() {
return makePromiseKit().promise;
Expand All @@ -21,16 +17,5 @@ export function buildRootObject(_dynamicVatPowers) {
meterMe([], how);
return -1;
},

async load(bundle) {
const require = harden(() => 0);
grandchildNS = await importBundle(bundle, {
endowments: { console, assert, require },
});
},

async meterThem(explode) {
grandchildNS.meterThem(explode);
},
});
}
118 changes: 48 additions & 70 deletions packages/SwingSet/test/metering/test-dynamic-vat-metered.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
/* global require */
// TODO Remove babel-standalone preinitialization
// https://github.com/endojs/endo/issues/768
import '@agoric/babel-standalone';
import '@agoric/install-metering-and-ses';
/* global __dirname */
// eslint-disable-next-line import/order
import { test } from '../../tools/prepare-test-env-ava.js';

// eslint-disable-next-line import/order
import path from 'path';
import bundleSource from '@agoric/bundle-source';
import test from 'ava';
import { provideHostStorage } from '../../src/hostStorage.js';
import { buildKernelBundles, buildVatController } from '../../src/index.js';
import makeNextLog from '../make-nextlog.js';

function capdata(body, slots = []) {
return harden({ body, slots });
Expand All @@ -22,10 +21,10 @@ async function prepare() {
// we'll give this bundle to the loader vat, which will use it to create a
// new (metered) dynamic vat
const dynamicVatBundle = await bundleSource(
require.resolve('./metered-dynamic-vat.js'),
path.join(__dirname, 'metered-dynamic-vat.js'),
);
const bootstrapBundle = await bundleSource(
require.resolve('./vat-load-dynamic.js'),
path.join(__dirname, 'vat-load-dynamic.js'),
);
return { kernelBundles, dynamicVatBundle, bootstrapBundle };
}
Expand All @@ -34,7 +33,17 @@ test.before(async t => {
t.context.data = await prepare();
});

async function runOneTest(t, explosion, managerType) {
function kpidRejected(t, c, kpid, message) {
t.is(c.kpStatus(kpid), 'rejected');
const resCapdata = c.kpResolution(kpid);
t.deepEqual(resCapdata.slots, []);
const body = JSON.parse(resCapdata.body);
delete body.errorId;
t.deepEqual(body, { '@qclass': 'error', name: 'Error', message });
}

async function overflowCrank(t, explosion) {
const managerType = 'xs-worker';
const { kernelBundles, dynamicVatBundle, bootstrapBundle } = t.context.data;
const config = {
bootstrap: 'bootstrap',
Expand All @@ -51,19 +60,17 @@ async function runOneTest(t, explosion, managerType) {
kernelBundles,
});
c.pinVatRoot('bootstrap');
const nextLog = makeNextLog(c);

// let the vatAdminService get wired up before we create any new vats
await c.run();

// 'createVat' will import the bundle
c.queueToVatRoot(
'bootstrap',
'createVat',
capargs([dynamicVatBundle, { managerType }]),
);
const cvargs = capargs([dynamicVatBundle, { managerType }], []);
const kp2 = c.queueToVatRoot('bootstrap', 'createVat', cvargs);
await c.run();
t.deepEqual(nextLog(), ['created'], 'first create');
const res2 = c.kpResolution(kp2);
t.is(JSON.parse(res2.body)[0], 'created', res2.body);
const doneKPID = res2.slots[0];

// extract the vatID for the newly-created dynamic vat
const dynamicVatIDs = JSON.parse(kvStore.get('vat.dynamicIDs'));
Expand All @@ -79,80 +86,51 @@ async function runOneTest(t, explosion, managerType) {
const neverKPID = neverArgs.slots[0];

// First, send a message to the dynamic vat that runs normally
c.queueToVatRoot('bootstrap', 'run', capargs([]));
const kp3 = c.queueToVatRoot('bootstrap', 'run', capargs([]));
await c.run();
t.is(JSON.parse(kvStore.get('vat.dynamicIDs')).length, 1);
t.is(kvStore.get(`${root}.owner`), vatID);
t.true(Array.from(kvStore.getKeys(`${vatID}`, `${vatID}/`)).length > 0);
// neverKPID should still be unresolved
t.is(kvStore.get(`${neverKPID}.state`), 'unresolved');

t.deepEqual(nextLog(), ['did run'], 'first run ok');

// Now send a message that makes the dynamic vat exhaust its meter. The
// message result promise should be rejected, and the control facet should
// report the vat's demise. Remnants of the killed vat should be gone
// from the kernel state store.
c.queueToVatRoot('bootstrap', 'explode', capargs([explosion]));
// neverP and doneP should still be unresolved
t.is(c.kpStatus(neverKPID), 'unresolved');
t.is(c.kpStatus(doneKPID), 'unresolved');
t.deepEqual(c.kpResolution(kp3), capargs(42));

// Now send a message that makes the dynamic vat exhaust its per-crank
// meter. The message result promise should be rejected, and the control
// facet should report the vat's demise. Remnants of the killed vat should
// be gone from the kernel state store.
const kp4 = c.queueToVatRoot('bootstrap', 'explode', capargs([explosion]));
await c.run();
kpidRejected(t, c, kp4, 'vat terminated');
t.is(JSON.parse(kvStore.get('vat.dynamicIDs')).length, 0);
t.is(kvStore.get(`${root}.owner`), undefined);
t.is(Array.from(kvStore.getKeys(`${vatID}`, `${vatID}/`)).length, 0);
// neverKPID should be rejected
t.is(kvStore.get(`${neverKPID}.state`), 'rejected');
t.is(
kvStore.get(`${neverKPID}.data.body`),
JSON.stringify({
'@qclass': 'error',
name: 'Error',
message: 'vat terminated',
}),
);
// TODO: the rejection shouldn't reveal the reason, maybe use this instead:
// t.is(kvStore.get(`${neverKPID}.data.body`),
// JSON.stringify('vat terminated'));
// neverP should be rejected, without revealing details
kpidRejected(t, c, neverKPID, 'vat terminated');

// but doneP gets more details
const expected = {
allocate: 'Allocate meter exceeded',
compute: 'Compute meter exceeded',
stack: 'Stack meter exceeded',
};

t.deepEqual(
nextLog(),
[
'did explode: Error: vat terminated',
`terminated: Error: ${expected[explosion]}`,
],
'first boom',
);
kpidRejected(t, c, doneKPID, expected[explosion]);

// the dead vat should stay dead
c.queueToVatRoot('bootstrap', 'run', capargs([]));
const kp5 = c.queueToVatRoot('bootstrap', 'run', capargs([]));
await c.run();
t.deepEqual(nextLog(), ['run exploded: Error: vat terminated'], 'stay dead');
kpidRejected(t, c, kp5, 'vat terminated');
}

test('local vat allocate overflow', t => {
return runOneTest(t, 'allocate', 'local');
});

test('local vat compute overflow', t => {
return runOneTest(t, 'compute', 'local');
});

test('local vat stack overflow', t => {
return runOneTest(t, 'stack', 'local');
});

test('xsnap vat allocate overflow', t => {
return runOneTest(t, 'allocate', 'xs-worker');
test('exceed allocate', t => {
return overflowCrank(t, 'allocate');
});

test('xsnap vat compute overflow', t => {
return runOneTest(t, 'compute', 'xs-worker');
test('exceed per-crank compute', t => {
return overflowCrank(t, 'compute');
});

test('xsnap vat stack overflow', t => {
return runOneTest(t, 'stack', 'xs-worker');
test('exceed stack', t => {
return overflowCrank(t, 'stack');
});
87 changes: 0 additions & 87 deletions packages/SwingSet/test/metering/test-dynamic-vat-subcompartment.js

This file was deleted.

Loading

0 comments on commit 5a82a3a

Please sign in to comment.