Skip to content

Commit

Permalink
chore: add test setup for node tests and test for auto-relay
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Nov 10, 2020
1 parent 2bd1a2f commit a09ac4a
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,12 @@ jobs:
- npm install
- LIBP2P_JS=${TRAVIS_BUILD_DIR}/src/index.js npx aegir test -t node --bail

- stage: test
name: example - auto-relay
script:
- cd examples
- npm install
- npm run test -- auto-relay

notifications:
email: false
94 changes: 94 additions & 0 deletions examples/auto-relay/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict'

const path = require('path')
const execa = require('execa')
const pDefer = require('p-defer')
const uint8ArrayToString = require('uint8arrays/to-string')

function startProcess (name, args = []) {
return execa('node', [path.join(__dirname, name), ...args], {
cwd: path.resolve(__dirname),
all: true
})
}

async function test () {
let output1 = ''
let output2 = ''
let output3 = ''
let relayAddr
let autoRelayAddr

const proc1Ready = pDefer()
const proc2Ready = pDefer()

// Step 1 process
process.stdout.write('relay.js\n')

const proc1 = startProcess('relay.js')
proc1.all.on('data', async (data) => {
process.stdout.write(data)

output1 += uint8ArrayToString(data)

if (output1.includes('Listening on:') && output1.includes('/p2p/')) {
relayAddr = output1.trim().split('Listening on:\n')[1].split('\n')[0]
proc1Ready.resolve()
}
})

await proc1Ready.promise
process.stdout.write('==================================================================\n')

// Step 2 process
process.stdout.write('auto-relay.js\n')

const proc2 = startProcess('auto-relay.js', [relayAddr])
proc2.all.on('data', async (data) => {
process.stdout.write(data)

output2 += uint8ArrayToString(data)

if (output2.includes('Listening on:') && output2.includes('/p2p/')) {
autoRelayAddr = output2.trim().split('Listening on:\n')[1]
proc2Ready.resolve()
}
})

await proc2Ready.promise
process.stdout.write('==================================================================\n')

// Step 3 process
process.stdout.write('other-node.js\n')

const proc3 = startProcess('other-node.js', [autoRelayAddr])
proc3.all.on('data', async (data) => {
process.stdout.write(data)

output3 += uint8ArrayToString(data)

if (output3.includes('Connected to the auto relay node via')) {
const remoteAddr = output3.trim().split('Connected to the auto relay node via ')[1]

if (remoteAddr === autoRelayAddr) {
proc3.kill()
proc2.kill()
proc1.kill()
} else {
throw new Error('other-node did not dial through the relay')
}
}
})

await Promise.all([
proc1,
proc2,
proc3
]).catch((err) => {
if (err.signal !== 'SIGTERM') {
throw err
}
})
}

module.exports = test
16 changes: 16 additions & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "libp2p-examples",
"version": "1.0.0",
"description": "Examples of how to use libp2p",
"scripts": {
"test": "node ./test.js",
"test:all": "node ./test-all.js"
},
"license": "MIT",
"dependencies": {
"execa": "^2.1.0",
"fs-extra": "^8.1.0",
"p-defer": "^3.0.0",
"which": "^2.0.1"
}
}
33 changes: 33 additions & 0 deletions examples/test-all.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict'

process.on('unhandedRejection', (err) => {
console.error(err)

process.exit(1)
})

const path = require('path')
const fs = require('fs')
const {
waitForOutput
} = require('./utils')

async function testAll () {
for (const dir of fs.readdirSync(__dirname)) {
if (dir === 'node_modules' || dir === 'tests_output') {
continue
}

const stats = fs.statSync(path.join(__dirname, dir))

if (!stats.isDirectory()) {
continue
}

await waitForOutput('npm info ok', 'npm', ['test', '--', dir], {
cwd: __dirname
})
}
}

testAll()
95 changes: 95 additions & 0 deletions examples/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'use strict'

process.env.NODE_ENV = 'test'
process.env.CI = true // needed for some "clever" build tools

const fs = require('fs-extra')
const path = require('path')
const execa = require('execa')
const dir = path.join(__dirname, process.argv[2])

testExample(dir)
.then(() => {}, (err) => {
if (err.exitCode) {
process.exit(err.exitCode)
}

console.error(err)
process.exit(1)
})

async function testExample (dir) {
await installDeps(dir)
await build(dir)
await runTest(dir)
// TODO: add browser test setup
}

async function installDeps (dir) {
if (!fs.existsSync(path.join(dir, 'package.json'))) {
console.info('Nothing to install in', dir)
return
}

if (fs.existsSync(path.join(dir, 'node_modules'))) {
console.info('Dependencies already installed in', dir)
return
}

const proc = execa.command('npm install', {
cwd: dir
})
proc.all.on('data', (data) => {
process.stdout.write(data)
})

await proc
}

async function build (dir) {
const pkgJson = path.join(dir, 'package.json')

if (!fs.existsSync(pkgJson)) {
console.info('Nothing to build in', dir)
return
}

const pkg = require(pkgJson)
let build

if (pkg.scripts.bundle) {
build = 'bundle'
}

if (pkg.scripts.build) {
build = 'build'
}

if (!build) {
console.info('No "build" or "bundle" script in', pkgJson)
return
}

const proc = execa('npm', ['run', build], {
cwd: dir
})
proc.all.on('data', (data) => {
process.stdout.write(data)
})

await proc
}

async function runTest (dir) {
console.info('Running node tests in', dir)
const testFile = path.join(dir, 'test.js')

if (!fs.existsSync(testFile)) {
console.info('Nothing to test in', dir)
return
}

const runTest = require(testFile)

await runTest()
}
61 changes: 61 additions & 0 deletions examples/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use strict'

const execa = require('execa')
const fs = require('fs-extra')
const which = require('which')

async function isExecutable (command) {
try {
await fs.access(command, fs.constants.X_OK)

return true
} catch (err) {
if (err.code === 'ENOENT') {
return isExecutable(await which(command))
}

if (err.code === 'EACCES') {
return false
}

throw err
}
}

async function waitForOutput (expectedOutput, command, args = [], opts = {}) {
if (!await isExecutable(command)) {
args.unshift(command)
command = 'node'
}

const proc = execa(command, args, opts)
let output = ''
let time = 120000

let timeout = setTimeout(() => {
throw new Error(`Did not see "${expectedOutput}" in output from "${[command].concat(args).join(' ')}" after ${time/1000}s`)
}, time)

proc.all.on('data', (data) => {
process.stdout.write(data)

output += data.toString('utf8')

if (output.includes(expectedOutput)) {
clearTimeout(timeout)
proc.kill()
}
})

try {
await proc
} catch (err) {
if (!err.killed) {
throw err
}
}
}

module.exports = {
waitForOutput
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test": "npm run test:node && npm run test:browser",
"test:node": "aegir test -t node -f \"./test/**/*.{node,spec}.js\"",
"test:browser": "aegir test -t browser",
"test:examples": "cd examples && npm run test:all",
"release": "aegir release -t node -t browser",
"release-minor": "aegir release --type minor -t node -t browser",
"release-major": "aegir release --type major -t node -t browser",
Expand Down

0 comments on commit a09ac4a

Please sign in to comment.