Skip to content

Commit

Permalink
feat: provide scaffolding for testing scenario3's home objects
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed May 9, 2020
1 parent fb36a40 commit 84752e2
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/cosmic-swingset/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ scenario2-run-client:
# then run: make scenario3-setup FAKE_CHAIN_DELAY=0
scenario3-setup:
rm -rf t3
bin/ag-solo init t3 --egresses=fake
bin/ag-solo init t3 --egresses=fake --webport=$(BASE_PORT)
@echo 'Execute `make scenario3-run` to run the client and simulated chain'

# This runs both the client and the fake chain.
Expand Down
2 changes: 1 addition & 1 deletion packages/cosmic-swingset/lib/ag-solo/fake-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export async function connectToFakeChain(basedir, GCI, role, delay, inbound) {
const argv = [`--role=${role}`, bootAddress];
const stateDBdir = path.join(basedir, `fake-chain-${GCI}-state`);
function doOutboundBridge(dstID, obj) {
console.error('received', dstID, obj);
// console.error('received', dstID, obj);
return 'IBC and bridge device not used on fake-chain';
}
function flushChainSends(replay) {
Expand Down
4 changes: 2 additions & 2 deletions packages/cosmic-swingset/lib/ag-solo/vats/ibc.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ EOF
.catch(rethrowUnlessMissing);
return rchandler.promise;
},
async onListen(_port, localAddr, _listenHandler) {
console.warn('IBC onListen', localAddr);
async onListen(_port, _localAddr, _listenHandler) {
// console.warn('IBC onListen', localAddr);
},
async onListenRemove(_port, localAddr, _listenHandler) {
console.warn('IBC onListenRemove', localAddr);
Expand Down
106 changes: 106 additions & 0 deletions packages/cosmic-swingset/test/captp-fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { spawn } from 'child_process';
import WebSocket from 'ws';
import { makeCapTP, E, HandledPromise } from '@agoric/captp';

const PORT = 8000;

// Ensure we're all using the same HandledPromise.
export { E };

export function makeFixture() {
let expectedToExit = false;
let buf = '';
const cp = spawn(
'make',
['scenario3-setup', 'scenario3-run', `BASE_PORT=${PORT}`],
{
cwd: `${__dirname}/..`,
env: { ...process.env, PORT },
stdio: ['ignore', 'pipe', 'pipe'],
detached: true,
},
);

cp.stdout.on('data', chunk => (buf += chunk.toString('utf-8')));
cp.stderr.on('data', chunk => {
const msg = chunk.toString('utf-8');
if (!msg.match(/^make: \*\*\*.*99/)) {
// Write chunks that don't describe the exit status.
process.stderr.write(chunk);
}
});

/** @type {WebSocket} */
let ws;
function connect() {
process.stdout.write('# connecting');
function tryConnect(resolve, reject) {
process.stdout.write('.');

/** @type {() => void} */
let abortCapTP;
ws = new WebSocket(`ws://localhost:${PORT}/private/captp`, {
origin: `http://localhost:${PORT}`,
});
ws.on('open', () => {
process.stdout.write('\n');
// Create a CapTP connection.
const { abort, dispatch, getBootstrap } = makeCapTP(
'test fixture',
obj => ws.send(JSON.stringify(obj)),
);
abortCapTP = abort;
ws.on('message', data => {
dispatch(JSON.parse(data));
});
const homeP = getBootstrap();
// Wait until the chain bundle is loaded, then take a new copy
// since the chain objects have been added to bootstrap.
E.G(homeP).LOADING.then(_ => resolve(getBootstrap()), reject);
});
ws.on('error', () => {
if (abortCapTP) {
abortCapTP();
abortCapTP = undefined;
} else {
// We didn't connect yet, so retry.
setTimeout(tryConnect, 1000, resolve, reject);
}
});
ws.on('close', () => {
if (abortCapTP) {
abortCapTP();
}
ws = undefined;
});
}

return new HandledPromise((resolve, reject) => {
cp.addListener('exit', code => {
if (!expectedToExit) {
// Display all our output.
console.log(buf);
}
// We only reject if the child exits before CapTP is established.
reject(code);
});
tryConnect(resolve, reject);
});
}

function kill() {
// Try closing the WebSocket.
expectedToExit = true;
if (ws && ws.readyState === ws.OPEN) {
ws.close();
}
// Don't kill on exit anymore, as we're doing it now.
process.off('exit', kill);
// console.log('killing!');
process.kill(-cp.pid, 'SIGINT');
}

process.on('exit', kill);
process.on('SIGINT', kill);
return { homeP: connect(), kill };
}
51 changes: 51 additions & 0 deletions packages/cosmic-swingset/test/test-home.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { test } from 'tape-promise/tape';
import { makeFixture, E } from './captp-fixture';

// This runs before all the tests.
let home;
let teardown;
test('setup', async t => {
try {
const { homeP, kill } = makeFixture();
teardown = kill;
home = await homeP;
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

// Now come the tests that use `home`...
// =========================================

test('registry', async t => {
try {
const { registry } = E.G(home);
const regVal = await E(registry).get('foolobr_19191');
t.equals(regVal, undefined, 'random registry name is undefined');

const target = 'something';
const myRegKey = await E(registry).register('myname', target);
t.equals(typeof myRegKey, 'string', 'registry key is string');

const registered = await E(registry).get(myRegKey);
t.equals(registered, target, 'registry registers target');
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

// =========================================
// This runs after all the tests.
test('teardown', async t => {
try {
await teardown();
} catch (e) {
t.isNot(e, e, 'unexpected exception');
} finally {
t.end();
}
});

0 comments on commit 84752e2

Please sign in to comment.