-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1077 from Agoric/cosmic-test-fixture
Provide scaffolding for testing scenario3's home objects
- Loading branch information
Showing
7 changed files
with
202 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Lint check | ||
|
||
# run CI on pushes to master, and on all PRs (even the ones that target other | ||
# branches) | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
pull_request: | ||
|
||
jobs: | ||
lint: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v1 | ||
- uses: actions/setup-node@v1 | ||
with: | ||
node-version: '12.16.1' | ||
|
||
# FIXME: Reenable after 2020-04-01 when Github cache doesn't take forever. | ||
#- name: cache node modules | ||
# uses: actions/cache@v1 | ||
# with: | ||
# path: ~/.cache/yarn | ||
# key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} | ||
# restore-keys: | | ||
# ${{ runner.os }}-yarn- | ||
|
||
# 'yarn install' must be done at the top level, to build all the | ||
# cross-package symlinks | ||
- name: yarn install | ||
run: yarn install | ||
# 'yarn build' loops over all workspaces | ||
- name: yarn build | ||
run: yarn build | ||
|
||
# 'yarn lint-check' just checks the lint where desired | ||
- name: lint check | ||
run: yarn lint-check |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
}); |