266 lines
6.7 KiB
JavaScript
266 lines
6.7 KiB
JavaScript
var fs = require('fs')
|
|
var test = require('tape')
|
|
var spawn = require('child_process').spawn
|
|
var exec = require('child_process').exec
|
|
var crypto = require('crypto')
|
|
var net = require('net')
|
|
var mkdirp = require('mkdirp')
|
|
var join = require('path').join
|
|
var ma = require('multiserver-address')
|
|
|
|
// travis currently does not support ipv6, becaue GCE does not.
|
|
var has_ipv6 = process.env.TRAVIS === undefined
|
|
var children = []
|
|
|
|
process.on('exit', function () {
|
|
children.forEach(function (e) {
|
|
e.kill('SIGKILL')
|
|
})
|
|
})
|
|
process.on('SIGINT', function () {
|
|
children.forEach(function (e) {
|
|
e.kill('SIGKILL')
|
|
})
|
|
process.exit(1)
|
|
})
|
|
|
|
var exited = false
|
|
var count = 0
|
|
function ssbServer(t, argv, opts) {
|
|
count ++
|
|
exited = false
|
|
opts = opts || {}
|
|
|
|
var sh = spawn(
|
|
process.execPath,
|
|
[join(__dirname, '../bin.js')]
|
|
.concat(argv),
|
|
Object.assign({
|
|
env: Object.assign({}, process.env, {ssb_appname: 'test'}),
|
|
}, opts)
|
|
)
|
|
|
|
sh.once('exit', function (code, name) {
|
|
exited = true
|
|
t.equal(name,'SIGKILL')
|
|
if(--count) return
|
|
t.end()
|
|
})
|
|
|
|
sh.stdout.pipe(process.stdout)
|
|
sh.stderr.pipe(process.stderr)
|
|
|
|
children.push(sh)
|
|
|
|
return function end () {
|
|
while(children.length) children.shift().kill('SIGKILL')
|
|
}
|
|
}
|
|
|
|
function try_often(times, opts, work, done) {
|
|
if (typeof opts == 'function') {
|
|
done = work
|
|
work = opts
|
|
opts = {}
|
|
}
|
|
const delay = 2000
|
|
setTimeout(function() { // delay first try
|
|
console.log('try more:', times)
|
|
work(function(err, result) {
|
|
if (!err) return done(null, result)
|
|
if (opts.ignore && err.message && !err.message.match(opts.ignore)) {
|
|
console.error('Fatal error:', err)
|
|
return done(err)
|
|
}
|
|
if (!times) return done(err)
|
|
if(exited) return done(new Error('already exited'))
|
|
console.warn('retry run', times)
|
|
console.error('work(err):', err)
|
|
try_often(times-1, work, done)
|
|
})
|
|
}, delay)
|
|
}
|
|
|
|
function connect(port, host, cb) {
|
|
var done = false
|
|
var socket = net.connect(port, host)
|
|
socket.on('error', function(err) {
|
|
if (done) return
|
|
done = true
|
|
cb(err)
|
|
})
|
|
socket.on('connect', function() {
|
|
if (done) return
|
|
done = true
|
|
cb(null)
|
|
})
|
|
}
|
|
|
|
function testSsbServer(t, opts, asConfig, port, cb) {
|
|
var dir = '/tmp/ssb-server_binjstest_' + Date.now()
|
|
if('function' === typeof port)
|
|
cb = port, port = opts.port
|
|
mkdirp.sync(dir)
|
|
var args = [
|
|
'start',
|
|
'--path '+dir
|
|
]
|
|
|
|
if(asConfig) {
|
|
fs.writeFileSync(join(dir, '.testrc'), JSON.stringify(opts))
|
|
} else {
|
|
;(function toArgs (prefix, opts) {
|
|
for(var k in opts) {
|
|
if(opts[k] && 'object' == typeof opts[k])
|
|
toArgs(prefix+k+'.', opts[k])
|
|
else
|
|
args.push(prefix+k+'='+opts[k])
|
|
}
|
|
})('--', opts)
|
|
}
|
|
|
|
var end = ssbServer(t, args, {
|
|
cwd: dir
|
|
})
|
|
|
|
try_often(10, {
|
|
ignore: /ECONNREFUSED/
|
|
}, function work(cb) {
|
|
connect(port, opts.host, cb)
|
|
}, function (err) {
|
|
cb(err)
|
|
end()
|
|
})
|
|
}
|
|
|
|
var c = 0
|
|
;['::1', '::', '127.0.0.1', 'localhost'].forEach(function (host) {
|
|
if(!has_ipv6 && /:/.test(host)) return
|
|
|
|
;[9002, 9001].forEach(function (port) {
|
|
;[true, false].forEach(function (asConfig) {
|
|
var opts = {
|
|
host: host,
|
|
port: 9001,
|
|
ws: { port: 9002 }
|
|
}
|
|
// if(c++) return
|
|
test('run bin.js server with ' +
|
|
(asConfig ? 'a config file' : 'command line options') +
|
|
':'+JSON.stringify(opts)+' then connect to port:'+port
|
|
, function(t) {
|
|
testSsbServer(t, opts, true, function (err) {
|
|
t.error(err, 'Successfully connect eventually')
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
test('ssbServer should have websockets and http server by default', function(t) {
|
|
var path = '/tmp/ssbServer_binjstest_' + Date.now()
|
|
var caps = crypto.randomBytes(32).toString('base64')
|
|
var end = ssbServer(t, [
|
|
'start',
|
|
'--host=127.0.0.1',
|
|
'--port=9001',
|
|
'--ws.port=9002',
|
|
'--path', path,
|
|
'--caps.shs', caps
|
|
])
|
|
|
|
try_often(10, function work(cb) {
|
|
exec([
|
|
join(__dirname, '../bin.js'),
|
|
'getAddress',
|
|
'device',
|
|
'--',
|
|
'--host=127.0.0.1',
|
|
'--port=9001',
|
|
'--path', path,
|
|
'--caps.shs', caps
|
|
].join(' '), {
|
|
env: Object.assign({}, process.env, {ssb_appname: 'test'})
|
|
}, function(err, stdout, sderr) {
|
|
if (err) return cb(err)
|
|
cb(null, JSON.parse(stdout)) // remove quotes
|
|
})
|
|
}, function(err, addr) {
|
|
t.error(err, 'ssbServer getAdress succeeds eventually')
|
|
if (err) return end()
|
|
t.ok(addr, 'address is not null')
|
|
t.comment('result of ssb-server getAddress: ' + addr)
|
|
|
|
var remotes = ma.decode(addr)
|
|
console.log('remotes', remotes, addr)
|
|
ws_remotes = remotes.filter(function(a) {
|
|
return a.find(function(component) {
|
|
return component.name == 'ws'
|
|
})
|
|
})
|
|
t.equal(ws_remotes.length, 1, 'has one ws remote')
|
|
var remote = ma.encode([ws_remotes[0]])
|
|
// this breaks if multiserver address encoding changes
|
|
t.ok(remote.indexOf('9002') > 0, 'ws address contains expected port')
|
|
|
|
// this is a bit annoying. we can't signal ssb-client to load the secret from .path
|
|
// it either has to be the first argument, already loaded
|
|
var key = require('ssb-keys').loadOrCreateSync(join(path, 'secret'))
|
|
require('ssb-client')(key, {
|
|
path: path,
|
|
caps: { shs: caps }, // has to be set when setting any config
|
|
remote: remote
|
|
}, function(err, ssb) {
|
|
t.error(err, 'ssb-client returns no error')
|
|
t.ok(ssb.manifest, 'got manifest from api')
|
|
t.ok(ssb.version, 'got version from api')
|
|
ssb.whoami(function(err, feed) {
|
|
t.error(err, 'ssb.whoami succeeds')
|
|
t.equal(feed.id[0], '@', 'feed.id has @ sigil')
|
|
end()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
test('ssb-server client should work without options', function(t) {
|
|
var path = '/tmp/ssb-server_binjstest_' + Date.now()
|
|
mkdirp.sync(path)
|
|
fs.writeFileSync(path+'/config',
|
|
JSON.stringify({
|
|
port: 43293, ws: { port: 43294 }
|
|
})
|
|
)
|
|
var caps = crypto.randomBytes(32).toString('base64')
|
|
var end = ssbServer(t, [
|
|
'start',
|
|
'--path', path,
|
|
'--config', path+'/config',
|
|
'--caps.shs', caps
|
|
])
|
|
|
|
try_often(10, function work(cb) {
|
|
exec([
|
|
join(__dirname, '../bin.js'),
|
|
'getAddress',
|
|
'device',
|
|
'--path', path,
|
|
'--config', path+'/config',
|
|
'--caps.shs', caps
|
|
].join(' '), {
|
|
env: Object.assign({}, process.env, {ssb_appname: 'test'})
|
|
}, function(err, stdout, sderr) {
|
|
if (err) return cb(err)
|
|
cb(null, JSON.parse(stdout)) // remove quotes
|
|
})
|
|
}, function(err, addr) {
|
|
t.error(err, 'ssb-server getAddress succeeds eventually')
|
|
if (err) return end()
|
|
t.ok(addr)
|
|
|
|
t.comment('result of ssb-server getAddress: ' + addr)
|
|
end()
|
|
})
|
|
})
|
|
|
|
|