diff --git a/.aegir.js b/.aegir.js index c9ede37d..36e730a6 100644 --- a/.aegir.js +++ b/.aegir.js @@ -3,7 +3,6 @@ const createServer = require('./src').createServer const server = createServer() // using defaults - module.exports = { karma: { files: [{ diff --git a/README.md b/README.md index b909f4a4..97c84854 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,8 @@ Install one or both of the following modules: Spawn the daemon - `options` is an optional object the following properties: - - `init` bool (default true) - should the node be initialized + - `init` bool (default true) or Object - should the node be initialized + - `initOptions` object - should be of the form `{bits: }`, which sets the desired key size - `start` bool (default true) - should the node be started - `repoPath` string - the repository path to use for this node, ignored if node is disposable - `disposable` bool (default true) - a new repo is created and initialized for each invocation, as well as cleaned up automatically once the process exits diff --git a/package.json b/package.json index c46915ad..1ec702c9 100644 --- a/package.json +++ b/package.json @@ -78,17 +78,19 @@ "detect-node": "^2.0.3", "hapi": "^16.6.2", "hat": "0.0.3", + "ipfs-api": "^18.1.1", "ipfs-repo": "^0.18.5", "joi": "^13.0.2", "lodash.clone": "^4.5.0", + "lodash.defaults": "^4.2.0", "lodash.defaultsdeep": "^4.6.0", "multiaddr": "^3.0.2", "once": "^1.4.0", "readable-stream": "^2.3.3", "rimraf": "^2.6.2", "safe-json-parse": "^4.0.0", + "safe-json-stringify": "^1.0.4", "shutdown": "^0.3.0", - "ipfs-api": "^17.3.0", "stream-http": "^2.7.2", "subcomandante": "^1.0.5", "superagent": "^3.8.2", @@ -97,6 +99,7 @@ "devDependencies": { "aegir": "^12.4.0", "chai": "^4.1.2", + "cross-env": "^5.1.3", "detect-port": "^1.2.2", "dirty-chai": "^2.0.1", "go-ipfs-dep": "0.4.13", diff --git a/src/endpoint/routes.js b/src/endpoint/routes.js index 83f8c712..9e851c7b 100644 --- a/src/endpoint/routes.js +++ b/src/endpoint/routes.js @@ -96,12 +96,12 @@ module.exports = (server) => { const payload = request.payload || {} - nodes[id].init(payload.initOpts, (err, node) => { + nodes[id].init(payload.initOpts, (err) => { if (err) { return reply(boom.badRequest(err)) } - reply({ initialized: node.initialized }) + reply({ initialized: nodes[id].initialized }) }) }, config: routeConfig diff --git a/src/factory-daemon.js b/src/factory-daemon.js index 4af08c40..53391421 100644 --- a/src/factory-daemon.js +++ b/src/factory-daemon.js @@ -2,7 +2,7 @@ const defaultsDeep = require('lodash.defaultsdeep') const clone = require('lodash.clone') -const waterfall = require('async/waterfall') +const series = require('async/series') const path = require('path') const tmpDir = require('./utils/tmp-dir') @@ -75,6 +75,7 @@ class FactoryDaemon { * * Options are: * - `init` bool - should the node be initialized + * - `initOptions` Object, it is expected to be of the form `{bits: }`, which sets the desired key size * - `start` bool - should the node be started * - `repoPath` string - the repository path to use for this node, ignored if node is disposable * - `disposable` bool - a new repo is created and initialized for each invocation @@ -128,11 +129,11 @@ class FactoryDaemon { const node = new Daemon(options) - waterfall([ + series([ (cb) => options.init ? node.init(cb) : cb(null, node), - (node, cb) => options.start + (cb) => options.start ? node.start(options.args, cb) : cb() ], (err) => { diff --git a/src/factory-in-proc.js b/src/factory-in-proc.js index a3eeb773..c9ad38ab 100644 --- a/src/factory-in-proc.js +++ b/src/factory-in-proc.js @@ -76,7 +76,8 @@ class FactoryInProc { * Spawn JSIPFS instances * * Options are: - * - `init` bool - should the node be initialized + * - `init` {bool|Object} - should the node be initialized + * - `initOptions` Object, it is expected to be of the form `{bits: }`, which sets the desired key size * - `start` bool - should the node be started * - `repoPath` string - the repository path to use for this node, ignored if node is disposable * - `disposable` bool - a new repo is created and initialized for each invocation diff --git a/src/ipfsd-client.js b/src/ipfsd-client.js index 86d93119..b58c835d 100644 --- a/src/ipfsd-client.js +++ b/src/ipfsd-client.js @@ -94,7 +94,7 @@ class DaemonClient { } this.initialized = res.body.initialized - cb(null, res.body) + cb() }) } diff --git a/src/ipfsd-daemon.js b/src/ipfsd-daemon.js index 1a903900..e19895a2 100644 --- a/src/ipfsd-daemon.js +++ b/src/ipfsd-daemon.js @@ -2,23 +2,26 @@ const fs = require('fs') const waterfall = require('async/waterfall') +const series = require('async/series') const ipfs = require('ipfs-api') const multiaddr = require('multiaddr') const rimraf = require('rimraf') const path = require('path') const once = require('once') const truthy = require('truthy') -const flatten = require('./utils/flatten') +const defaults = require('lodash.defaults') const debug = require('debug') +const os = require('os') +const hat = require('hat') const log = debug('ipfsd-ctl:daemon') const safeParse = require('safe-json-parse/callback') +const safeStringify = require('safe-json-stringify') const parseConfig = require('./utils/parse-config') const tmpDir = require('./utils/tmp-dir') const findIpfsExecutable = require('./utils/find-ipfs-executable') const setConfigValue = require('./utils/set-config-value') -const configureNode = require('./utils/configure-node') const run = require('./utils/run') const GRACE_PERIOD = 10500 // amount of ms to wait before sigkill @@ -42,8 +45,6 @@ class Daemon { const type = truthy(process.env.IPFS_TYPE) this.opts = opts || { type: type || 'go' } - this.opts.config = flatten(this.opts.config) - const td = tmpDir(opts.type === 'js') this.path = this.opts.disposable ? td @@ -57,6 +58,7 @@ class Daemon { this._gatewayAddr = null this._started = false this.api = null + this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null if (this.opts.env) { Object.assign(this.env, this.opts.env) @@ -111,41 +113,50 @@ class Daemon { /** * Initialize a repo. * - * @param {Object} [initOpts={}] - * @param {number} [initOpts.keysize=2048] - The bit size of the identiy key. - * @param {string} [initOpts.directory=IPFS_PATH] - The location of the repo. - * @param {string} [initOpts.pass] - The passphrase of the keychain. + * @param {Object} [initOptions={}] + * @param {number} [initOptions.bits=2048] - The bit size of the identiy key. + * @param {string} [initOptions.directory=IPFS_PATH] - The location of the repo. + * @param {string} [initOptions.pass] - The passphrase of the keychain. * @param {function (Error, Node)} callback * @returns {undefined} */ - init (initOpts, callback) { - if (!callback) { - callback = initOpts - initOpts = {} + init (initOptions, callback) { + if (typeof initOptions === 'function') { + callback = initOptions + initOptions = {} } - if (initOpts.directory && initOpts.directory !== this.path) { - this.path = initOpts.directory + if (initOptions.directory && initOptions.directory !== this.path) { + this.path = initOptions.directory } - const args = ['init', '-b', initOpts.keysize || 2048] - if (initOpts.pass) { + const bits = initOptions.bits || this.bits + const args = ['init'] + // do not just set a default keysize, + // in case we decide to change it at + // the daemon level in the future + if (bits) { + args.concat(['-b', bits]) + log(`initializing with keysize: ${bits}`) + } + if (initOptions.pass) { args.push('--pass') - args.push('"' + initOpts.pass + '"') + args.push('"' + initOptions.pass + '"') } run(this, args, { env: this.env }, (err, result) => { if (err) { return callback(err) } - configureNode(this, this.opts.config, (err) => { - if (err) { - return callback(err) - } - - this.clean = false - this.initialized = true - callback(null, this) + const self = this + waterfall([ + (cb) => this.getConfig(cb), + (conf, cb) => this.replaceConfig(defaults({}, this.opts.config, conf), cb) + ], (err) => { + if (err) { return callback(err) } + self.clean = false + self.initialized = true + return callback() }) }) } @@ -328,7 +339,7 @@ class Daemon { cb ), (config, cb) => { - if (!key) { + if (key === 'show') { return safeParse(config, cb) } cb(null, config.trim()) @@ -348,6 +359,32 @@ class Daemon { setConfigValue(this, key, value, callback) } + /** + * Replace the current config with the provided one + * + * @param {object} config + * @param {function(Error)} callback + * @return {undefined} + */ + replaceConfig (config, callback) { + const tmpFile = path.join(os.tmpdir(), hat()) + // TODO: we're using tmp file here until + // https://github.com/ipfs/js-ipfs/pull/785 + // is ready + series([ + (cb) => fs.writeFile(tmpFile, safeStringify(config), cb), + (cb) => run( + this, + ['config', 'replace', `${tmpFile}`], + { env: this.env }, + cb + ) + ], (err) => { + if (err) { return callback(err) } + fs.unlink(tmpFile, callback) + }) + } + /** * Get the version of ipfs * diff --git a/src/ipfsd-in-proc.js b/src/ipfsd-in-proc.js index 3775a222..2866212a 100644 --- a/src/ipfsd-in-proc.js +++ b/src/ipfsd-in-proc.js @@ -1,10 +1,13 @@ 'use strict' -const eachOf = require('async/eachOf') const multiaddr = require('multiaddr') -const defaults = require('lodash.defaultsdeep') +const defaultsDeep = require('lodash.defaultsdeep') const createRepo = require('./utils/repo/create-nodejs') -const flatten = require('./utils/flatten') +const defaults = require('lodash.defaults') +const waterfall = require('async/waterfall') +const debug = require('debug') + +const log = debug('ipfsd-ctl:in-proc') /** * ipfsd for a js-ipfs instance (aka in-process IPFS node) @@ -32,8 +35,9 @@ class Node { this._started = false this.initialized = false this.api = null + this.bits = this.opts.initOptions ? this.opts.initOptions.bits : null - this.opts.EXPERIMENTAL = defaults({}, opts.EXPERIMENTAL, { + this.opts.EXPERIMENTAL = defaultsDeep({}, opts.EXPERIMENTAL, { pubsub: false, sharding: false, relay: { @@ -55,6 +59,7 @@ class Node { throw new Error('Unkown argument ' + arg) } }) + this.exec = new IPFS({ repo: this.repo, init: false, @@ -113,36 +118,41 @@ class Node { /** * Initialize a repo. * - * @param {Object} [initOpts={}] - * @param {number} [initOpts.keysize=2048] - The bit size of the identiy key. - * @param {string} [initOpts.directory=IPFS_PATH] - The location of the repo. - * @param {string} [initOpts.pass] - The passphrase of the keychain. + * @param {Object} [initOptions={}] + * @param {number} [initOptions.bits=2048] - The bit size of the identiy key. + * @param {string} [initOptions.directory=IPFS_PATH] - The location of the repo. + * @param {string} [initOptions.pass] - The passphrase of the keychain. * @param {function (Error, Node)} callback * @returns {undefined} */ - init (initOpts, callback) { - if (!callback) { - callback = initOpts - initOpts = {} + init (initOptions, callback) { + if (typeof initOptions === 'function') { + callback = initOptions + initOptions = {} } - initOpts.bits = initOpts.keysize || 2048 - this.exec.init(initOpts, (err) => { + const bits = initOptions.keysize ? initOptions.bits : this.bits + // do not just set a default keysize, + // in case we decide to change it at + // the daemon level in the future + if (bits) { + initOptions.bits = bits + log(`initializing with keysize: ${bits}`) + } + this.exec.init(initOptions, (err) => { if (err) { return callback(err) } - const conf = flatten(this.opts.config) - eachOf(conf, (val, key, cb) => { - this.setConfig(key, val, cb) - }, (err) => { - if (err) { - return callback(err) - } - - this.initialized = true - this.clean = false - callback(null, this) + const self = this + waterfall([ + (cb) => this.getConfig(cb), + (conf, cb) => this.replaceConfig(defaults({}, this.opts.config, conf), cb) + ], (err) => { + if (err) { return callback } + self.clean = false + self.initialized = true + return callback() }) }) } @@ -278,6 +288,17 @@ class Node { this.exec.config.set(key, value, callback) } + /** + * Replace the current config with the provided one + * + * @param {object} config + * @param {function(Error)} callback + * @return {undefined} + */ + replaceConfig (config, callback) { + this.exec.config.replace(config, callback) + } + /** * Get the version of ipfs * diff --git a/src/utils/run.js b/src/utils/run.js index 93dd32ac..9dd00894 100644 --- a/src/utils/run.js +++ b/src/utils/run.js @@ -13,5 +13,8 @@ module.exports = (node, args, opts, callback) => { executable = process.execPath } + // Don't pass on arguments that were passed into the node executable + opts.execArgv = [] + return exec(executable, args, opts, callback) } diff --git a/test/add-retrieve.spec.js b/test/add-retrieve.spec.js index 2ba0d830..439efb35 100644 --- a/test/add-retrieve.spec.js +++ b/test/add-retrieve.spec.js @@ -11,9 +11,9 @@ const IPFSFactory = require('../src') const JSIPFS = require('ipfs') const tests = [ - { type: 'go' }, - { type: 'js' }, - { type: 'proc', exec: JSIPFS } + { type: 'go', bits: 1024 }, + { type: 'js', bits: 512 }, + { type: 'proc', exec: JSIPFS, bits: 512 } ] describe('data can be put and fetched', () => { @@ -21,11 +21,11 @@ describe('data can be put and fetched', () => { let ipfsd before(function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) const f = IPFSFactory.create(dfOpts) - f.spawn((err, _ipfsd) => { + f.spawn({ initOptions: { bits: dfOpts.bits } }, (err, _ipfsd) => { expect(err).to.not.exist() expect(_ipfsd).to.exist() expect(_ipfsd.api).to.exist() @@ -37,12 +37,12 @@ describe('data can be put and fetched', () => { }) after(function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) ipfsd.stop(done) }) it('put and fetch a block', function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) const data = Buffer.from('blorb') diff --git a/test/api.spec.js b/test/api.spec.js index d4ad07b7..249c159d 100644 --- a/test/api.spec.js +++ b/test/api.spec.js @@ -40,7 +40,7 @@ describe('ipfsd.api for Daemons', () => { }) it('test the ipfsd.api', function (done) { - this.timeout(40 * 1000) + this.timeout(20 * 1000) // TODO skip in browser - can we avoid using file system operations here? if (!isNode) { this.skip() } @@ -55,7 +55,11 @@ describe('ipfsd.api for Daemons', () => { series([ (cb) => { - df.spawn({ start: false, config: config }, (err, _ipfsd) => { + df.spawn({ + start: false, + config: config, + initOptions: { bits: 1024 } + }, (err, _ipfsd) => { expect(err).to.not.exist() ipfsd = _ipfsd ipfsd.start((err, _api) => { @@ -108,9 +112,12 @@ describe('ipfsd.api for Daemons', () => { }) it('check if API and Gateway addrs are correct', function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) - df.spawn({ config: config }, (err, _ipfsd) => { + df.spawn({ + config: config, + initOptions: { bits: 1024 } + }, (err, _ipfsd) => { expect(err).to.not.exist() const ipfsd = _ipfsd diff --git a/test/endpoint/client.js b/test/endpoint/client.js index 1a305909..646460e7 100644 --- a/test/endpoint/client.js +++ b/test/endpoint/client.js @@ -89,7 +89,6 @@ describe('client', () => { it('should handle valid request', (done) => { mock.post('http://localhost:9999/init', (req) => { expect(req.query.id).to.exist() - expect(req.body.initOpts.initOpt1).to.equal('hello!') return { body: { @@ -98,9 +97,9 @@ describe('client', () => { } }) - node.init({ initOpt1: 'hello!' }, (err, res) => { + node.init({ bits: 512 }, (err) => { expect(err).to.not.exist() - expect(res.initialized).to.be.ok() + expect(node.initialized).to.be.ok() done() }) }) diff --git a/test/spawn-options.spec.js b/test/spawn-options.spec.js index cfb22a8b..3b3e4721 100644 --- a/test/spawn-options.spec.js +++ b/test/spawn-options.spec.js @@ -13,11 +13,14 @@ const isNode = require('detect-node') const hat = require('hat') const IPFSFactory = require('../src') const JSIPFS = require('ipfs') +const os = require('os') + +const isWindows = os.platform() === 'win32' const tests = [ - { type: 'go' }, - { type: 'js' }, - { type: 'proc', exec: JSIPFS } + { type: 'go', bits: 1024 }, + { type: 'js', bits: 512 }, + { type: 'proc', exec: JSIPFS, bits: 512 } ] const jsVersion = require('ipfs/package.json').version @@ -69,7 +72,8 @@ describe('Spawn options', () => { repoPath: repoPath, init: false, start: false, - disposable: false + disposable: false, + initOptions: { bits: fOpts.bits } } f.spawn(options, (err, _ipfsd) => { @@ -120,6 +124,9 @@ describe('Spawn options', () => { let ipfsd it('f.spawn', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) const options = { @@ -140,6 +147,9 @@ describe('Spawn options', () => { }) it('ipfsd.start', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) ipfsd.start((err, api) => { @@ -151,6 +161,9 @@ describe('Spawn options', () => { }) it('ipfsd.stop', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) ipfsd.stop(done) @@ -163,29 +176,30 @@ describe('Spawn options', () => { let ipfsd it('create init and start node', function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) - f.spawn((err, _ipfsd) => { - expect(err).to.not.exist() - expect(_ipfsd).to.exist() - expect(_ipfsd.api).to.exist() - expect(_ipfsd.api.id).to.exist() + f.spawn({ initOptions: { bits: fOpts.bits } }, + (err, _ipfsd) => { + expect(err).to.not.exist() + expect(_ipfsd).to.exist() + expect(_ipfsd.api).to.exist() + expect(_ipfsd.api.id).to.exist() - ipfsd = _ipfsd - done() - }) + ipfsd = _ipfsd + done() + }) }) it('ipfsd.stop', function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) ipfsd.stop(done) }) }) - describe('custom init options', () => { + describe('custom config options', () => { it('custom config', function (done) { - this.timeout(40 * 1000) + this.timeout(30 * 1000) const addr = '/ip4/127.0.0.1/tcp/5678' const swarmAddr1 = '/ip4/127.0.0.1/tcp/35666' @@ -198,7 +212,7 @@ describe('Spawn options', () => { } } - const options = { config: config } + const options = { config: config, initOptions: { bits: fOpts.bits } } waterfall([ (cb) => f.spawn(options, cb), @@ -215,6 +229,7 @@ describe('Spawn options', () => { config = JSON.parse(config) } expect(config).to.eql([swarmAddr1]) + // expect(config).to.include(swarmAddr1) cb(null, ipfsd) }) ], (err, ipfsd) => { @@ -241,7 +256,7 @@ describe('Spawn options', () => { }) it('allows passing custom repo path to spawn', function (done) { - this.timeout(50 * 1000) + this.timeout(20 * 1000) const config = { Addresses: { @@ -259,7 +274,8 @@ describe('Spawn options', () => { init: false, start: false, repoPath: repoPath, - config: config + config: config, + initOptions: { bits: fOpts.bits } } series([ @@ -298,7 +314,8 @@ describe('Spawn options', () => { this.timeout(30 * 1000) const options = { - args: ['--enable-pubsub-experiment'] + args: ['--enable-pubsub-experiment'], + initOptions: { bits: fOpts.bits } } f.spawn(options, (err, _ipfsd) => { @@ -336,15 +353,17 @@ describe('Spawn options', () => { let ipfsd before(function (done) { - this.timeout(50 * 1000) - f.spawn((err, _ipfsd) => { - expect(err).to.not.exist() - ipfsd = _ipfsd - done() - }) + this.timeout(20 * 1000) + f.spawn({ initOptions: { bits: fOpts.bits } }, + (err, _ipfsd) => { + expect(err).to.not.exist() + ipfsd = _ipfsd + done() + }) }) - after((done) => { + after(function (done) { + this.timeout(20 * 1000) ipfsd.stop(done) }) diff --git a/test/start-stop.node.js b/test/start-stop.node.js index de09c4f9..7ce59707 100644 --- a/test/start-stop.node.js +++ b/test/start-stop.node.js @@ -20,16 +20,19 @@ const IPFSFactory = require('../src') const dfBaseConfig = require('./utils/df-config-nodejs') -const types = ['js', 'go'] +const tests = [ + { type: 'go', bits: 1024 }, + { type: 'js', bits: 512 } +] const exec = { js: 'ipfs/src/cli/bin.js', go: 'go-ipfs-dep/go-ipfs/ipfs' } -types.forEach((type) => { - describe(`${type} daemon`, () => { - const dfConfig = Object.assign({}, dfBaseConfig, { type: type }) +tests.forEach((fOpts) => { + describe(`${fOpts.type} daemon`, () => { + const dfConfig = Object.assign({}, dfBaseConfig, { type: fOpts.type }) describe('start and stop', () => { if (isWindows) { return } @@ -48,7 +51,8 @@ types.forEach((type) => { f.spawn({ init: true, start: false, - disposable: true + disposable: true, + initOptions: { bits: fOpts.bits } }, (err, _ipfsd) => { expect(err).to.not.exist() expect(_ipfsd).to.exist() @@ -64,7 +68,7 @@ types.forEach((type) => { }) it('daemon exec path should match type', () => { - let execPath = exec[type] + let execPath = exec[fOpts.type] expect(ipfsd.exec).to.include.string(execPath) }) @@ -117,7 +121,7 @@ types.forEach((type) => { it('is stopped', function (done) { // shutdown grace period is already 10500 - this.timeout(30 * 1000) + this.timeout(20 * 1000) ipfsd.pid((pid) => { expect(pid).to.not.exist() @@ -135,11 +139,14 @@ types.forEach((type) => { it('fail on start with non supported flags', function (done) { // TODO js-ipfs doesn't fail on unrecognized args. // Decided what should be the desired behaviour - if (type === 'js') { return this.skip() } + if (fOpts.type === 'js') { return this.skip() } const df = IPFSFactory.create(dfConfig) - df.spawn({ start: false }, (err, ipfsd) => { + df.spawn({ + start: false, + initOptions: { bits: fOpts.bits } + }, (err, ipfsd) => { expect(err).to.not.exist() ipfsd.start(['--should-not-exist'], (err) => { expect(err).to.exist() @@ -157,12 +164,15 @@ types.forEach((type) => { let exec before(function (done) { - this.timeout(30 * 1000) + this.timeout(20 * 1000) const df = IPFSFactory.create(dfConfig) - exec = findIpfsExecutable(type) + exec = findIpfsExecutable(fOpts.type) - df.spawn({ exec }, (err, daemon) => { + df.spawn({ + exec, + initOptions: { bits: fOpts.bits } + }, (err, daemon) => { expect(err).to.not.exist() expect(daemon).to.exist() @@ -180,29 +190,37 @@ types.forEach((type) => { it('ipfsd.exec should match exec', () => { expect(ipfsd.exec).to.equal(exec) }) + }) - describe('should fail on invalid exec path', function () { - this.timeout(20 * 1000) + describe('should fail on invalid exec path', function () { + this.timeout(20 * 1000) - before((done) => { - const df = IPFSFactory.create(dfConfig) - const exec = path.join('invalid', 'exec', 'ipfs') + let ipfsd + before((done) => { + const df = IPFSFactory.create(dfConfig) + const exec = path.join('invalid', 'exec', 'ipfs') - df.spawn({ init: false, start: false, exec: exec }, (err, daemon) => { - expect(err).to.not.exist() - expect(daemon).to.exist() + df.spawn({ + init: false, + start: false, + exec: exec, + initOptions: { bits: fOpts.bits } + }, (err, daemon) => { + expect(err).to.not.exist() + expect(daemon).to.exist() - ipfsd = daemon - done() - }) + ipfsd = daemon + done() }) + }) - it('should fail on init', (done) => { - ipfsd.init((err, node) => { - expect(err).to.exist() - expect(node).to.not.exist() - done() - }) + after((done) => ipfsd.stop(done)) + + it('should fail on init', (done) => { + ipfsd.init((err, node) => { + expect(err).to.exist() + expect(node).to.not.exist() + done() }) }) }) @@ -211,16 +229,17 @@ types.forEach((type) => { let ipfsd before(function (done) { - this.timeout(40 * 1000) + this.timeout(20 * 1000) const f = IPFSFactory.create(dfConfig) async.series([ (cb) => f.spawn({ - init: true, - start: true, + init: false, + start: false, disposable: false, - repoPath: tempDir(type), + repoPath: tempDir(fOpts.type), + initOptions: { bits: fOpts.bits }, config: { Addresses: { Swarm: [`/ip4/127.0.0.1/tcp/0`], @@ -240,11 +259,17 @@ types.forEach((type) => { ], done) }) - it('should return a node', () => { + it('should return a node', function () { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + expect(ipfsd).to.exist() }) - it('daemon should not be running', (done) => { + it('daemon should be running', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + ipfsd.pid((pid) => { expect(pid).to.exist() done() @@ -252,6 +277,9 @@ types.forEach((type) => { }) it('.stop', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) ipfsd.stop((err) => { @@ -264,6 +292,9 @@ types.forEach((type) => { }) it('.start', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) ipfsd.start((err) => { @@ -276,6 +307,9 @@ types.forEach((type) => { }) it('.stop and cleanup', function (done) { + // TODO: wont work on windows until we get `/shutdown` implemented in js-ipfs + if (isWindows) { this.skip() } + this.timeout(20 * 1000) ipfsd.stop((err) => {