diff --git a/.travis.yml b/.travis.yml index 584f308f81..8253ebb93d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,22 +7,16 @@ matrix: env: CXX=g++-4.8 - node_js: 8 env: CXX=g++-4.8 - # - node_js: stable - # env: CXX=g++-4.8 script: - npm run lint - npm run test - - npm run coverage - make test before_script: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start -after_success: - - npm run coverage-publish - addons: firefox: 'latest' apt: diff --git a/circle.yml b/circle.yml index a0da9bc019..a132855ce9 100644 --- a/circle.yml +++ b/circle.yml @@ -2,6 +2,10 @@ machine: node: version: stable +test: + post: + - npm run coverage -- --upload + dependencies: pre: - google-chrome --version diff --git a/package.json b/package.json index 24cca718ad..762e9a9ef2 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "test:unit:node:gateway": "aegir test -t node -f test/gateway/index.js", "test:unit:node:cli": "aegir test -t node -f test/cli/index.js", "test:unit:browser": "aegir test -t browser --no-cors", - "test:interop": "IPFS_TEST=interop aegir test -t node -t browser -f test/interop", + "test:interop": "IPFS_TEST=interop aegir test -t node -f test/interop", "test:interop:node": "IPFS_TEST=interop aegir test -t node -f test/interop/node.js", "test:interop:browser": "IPFS_TEST=interop aegir test -t browser -f test/interop/browser.js", "test:bootstrapers": "IPFS_TEST=bootstrapers aegir test -t browser -f test/bootstrapers.js", @@ -63,7 +63,7 @@ }, "homepage": "https://github.com/ipfs/js-ipfs#readme", "devDependencies": { - "aegir": "^12.1.3", + "aegir": "^12.2.0", "buffer-loader": "0.0.1", "chai": "^4.1.2", "delay": "^2.0.0", @@ -75,8 +75,8 @@ "expose-loader": "^0.7.4", "form-data": "^2.3.1", "hat": "0.0.3", - "interface-ipfs-core": "~0.36.7", - "ipfsd-ctl": "~0.24.1", + "interface-ipfs-core": "~0.36.8", + "ipfsd-ctl": "~0.25.1", "left-pad": "^1.2.0", "lodash": "^4.17.4", "mocha": "^4.0.1", @@ -92,13 +92,14 @@ }, "dependencies": { "async": "^2.6.0", + "binary-querystring": "~0.1.2", "bl": "^1.2.1", "boom": "^7.1.1", "bs58": "^4.0.1", "byteman": "^1.3.5", "cids": "^0.5.2", "debug": "^3.1.0", - "file-type": "^7.2.0", + "file-type": "^7.3.0", "filesize": "^3.5.11", "fsm-event": "^2.1.0", "get-folder-size": "^1.0.0", @@ -106,7 +107,7 @@ "hapi": "^16.6.2", "hapi-set-header": "^1.0.2", "hoek": "^5.0.2", - "ipfs-api": "^17.1.0", + "ipfs-api": "^17.1.2", "ipfs-bitswap": "~0.17.4", "ipfs-block": "~0.6.1", "ipfs-block-service": "~0.13.0", @@ -120,7 +121,7 @@ "joi": "^13.0.2", "libp2p": "~0.13.1", "libp2p-circuit": "~0.1.4", - "libp2p-floodsub": "~0.12.1", + "libp2p-floodsub": "~0.13.0", "libp2p-kad-dht": "~0.6.0", "libp2p-mdns": "~0.9.1", "libp2p-multiplex": "~0.5.0", diff --git a/src/core/components/no-floodsub.js b/src/core/components/no-floodsub.js new file mode 100644 index 0000000000..95db571f5f --- /dev/null +++ b/src/core/components/no-floodsub.js @@ -0,0 +1,24 @@ +'use strict' + +const EventEmitter = require('events') + +function fail () { + throw new Error('The daemon must be run with \'--enable-pubsub-experiment\'') +} + +class NoFloodSub extends EventEmitter { + constructor () { + super() + + this.peers = new Map() + this.subscriptions = new Set() + } + + start (callback) { callback() } + stop (callback) { callback() } + publish () { fail() } + subscribe () { fail() } + unsubscribe () { fail() } +} + +module.exports = NoFloodSub diff --git a/src/core/components/start.js b/src/core/components/start.js index 54ff3c9833..9575c3e3c6 100644 --- a/src/core/components/start.js +++ b/src/core/components/start.js @@ -3,6 +3,7 @@ const series = require('async/series') const Bitswap = require('ipfs-bitswap') const FloodSub = require('libp2p-floodsub') +const NoFloodSub = require('./no-floodsub') const setImmediate = require('async/setImmediate') const promisify = require('promisify-es6') @@ -50,12 +51,10 @@ module.exports = (self) => { self._bitswap.start() self._blockService.setExchange(self._bitswap) - if (self._options.EXPERIMENTAL.pubsub) { - self._pubsub = new FloodSub(self._libp2pNode) - self._pubsub.start(done) - } else { - done() - } + self._pubsub = self._options.EXPERIMENTAL.pubsub + ? new FloodSub(self._libp2pNode) + : new NoFloodSub() + self._pubsub.start(done) }) }) } diff --git a/src/core/components/stop.js b/src/core/components/stop.js index 3a2dd8c04f..6ac0dc91a3 100644 --- a/src/core/components/stop.js +++ b/src/core/components/stop.js @@ -31,13 +31,7 @@ module.exports = (self) => { self._bitswap.stop() series([ - (cb) => { - if (self._options.EXPERIMENTAL.pubsub) { - self._pubsub.stop(cb) - } else { - cb() - } - }, + (cb) => self._pubsub.stop(cb), (cb) => self.libp2p.stop(cb), (cb) => self._repo.close(cb) ], done) diff --git a/src/http/api/resources/pubsub.js b/src/http/api/resources/pubsub.js index 6aa1ad6f82..a0dd21f748 100644 --- a/src/http/api/resources/pubsub.js +++ b/src/http/api/resources/pubsub.js @@ -2,6 +2,7 @@ const PassThrough = require('stream').PassThrough const bs58 = require('bs58') +const binaryQueryString = require('binary-querystring') exports = module.exports @@ -48,6 +49,7 @@ exports.subscribe = { reply(res) .header('X-Chunked-Output', '1') + .header('content-encoding', 'identity') // stop gzip from buffering, see https://github.com/hapijs/hapi/issues/2975 .header('content-type', 'application/json') }) } @@ -57,7 +59,9 @@ exports.publish = { handler: (request, reply) => { const arg = request.query.arg const topic = arg[0] - const buf = arg[1] + + const rawArgs = binaryQueryString(request.url.search) + const buf = rawArgs.arg && rawArgs.arg[1] const ipfs = request.server.app.ipfs @@ -65,11 +69,11 @@ exports.publish = { return reply(new Error('Missing topic')) } - if (!buf) { + if (!buf || buf.length === 0) { return reply(new Error('Missing buf')) } - ipfs.pubsub.publish(topic, Buffer.from(String(buf)), (err) => { + ipfs.pubsub.publish(topic, buf, (err) => { if (err) { return reply(new Error(`Failed to publish to topic ${topic}: ${err}`)) } diff --git a/test/cli/bitswap.js b/test/cli/bitswap.js index 90943ba561..40e0ba3455 100644 --- a/test/cli/bitswap.js +++ b/test/cli/bitswap.js @@ -4,36 +4,39 @@ const expect = require('chai').expect const runOn = require('../utils/on-and-off').on -describe('bitswap', () => runOn((thing) => { - let ipfs - const key = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' +describe('bitswap', function () { + runOn((thing) => { + this.timeout(30000) + let ipfs + const key = 'QmUBdnXXPyoDFXj3Hj39dNJ5VkN3QFRskXxcGaYFBB8CNR' - before((done) => { - ipfs = thing.ipfs - ipfs('block get ' + key) - .then(() => {}) - .catch(() => {}) - setTimeout(done, 800) - }) + before((done) => { + ipfs = thing.ipfs + ipfs('block get ' + key) + .then(() => {}) + .catch(() => {}) + setTimeout(done, 800) + }) - it('wantlist', () => { - return ipfs('bitswap wantlist').then((out) => { - expect(out).to.eql(key + '\n') + it('wantlist', () => { + return ipfs('bitswap wantlist').then((out) => { + expect(out).to.eql(key + '\n') + }) }) - }) - it('stat', () => { - return ipfs('bitswap stat').then((out) => { - expect(out).to.be.eql([ - 'bitswap status', - ' blocks received: 0', - ' dup blocks received: 0', - ' dup data received: 0B', - ' wantlist [1 keys]', - ` ${key}`, - ' partners [0]', - ' ' - ].join('\n') + '\n') + it('stat', () => { + return ipfs('bitswap stat').then((out) => { + expect(out).to.be.eql([ + 'bitswap status', + ' blocks received: 0', + ' dup blocks received: 0', + ' dup data received: 0B', + ' wantlist [1 keys]', + ` ${key}`, + ' partners [0]', + ' ' + ].join('\n') + '\n') + }) }) }) -})) +}) diff --git a/test/cli/block.js b/test/cli/block.js index 7d13fb5605..054e14995b 100644 --- a/test/cli/block.js +++ b/test/cli/block.js @@ -11,24 +11,31 @@ describe('block', () => runOnAndOff((thing) => { ipfs = thing.ipfs }) - it('put', () => { + it('put', function () { + this.timeout(40 * 1000) return ipfs('block put test/fixtures/test-data/hello').then((out) => { expect(out).to.eql('QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp\n') }) }) - it('put with flags, format and mhtype', () => { + it('put with flags, format and mhtype', function () { + this.timeout(40 * 1000) + return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block') .then((out) => expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n')) }) - it('get', () => { + it('get', function () { + this.timeout(40 * 1000) + return ipfs('block get QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') .then((out) => expect(out).to.eql('hello world\n')) }) - it('get block from file without a final newline', () => { + it('get block from file without a final newline', function () { + this.timeout(40 * 1000) + return ipfs('block put test/fixtures/test-data/no-newline').then((out) => { expect(out).to.eql('QmTwbQs4sGcCiPxV97SpbHS7QgmVg9SiKxcG1AcF1Ly2SL\n') return ipfs('block get QmTwbQs4sGcCiPxV97SpbHS7QgmVg9SiKxcG1AcF1Ly2SL') @@ -36,7 +43,9 @@ describe('block', () => runOnAndOff((thing) => { .then((out) => expect(out).to.eql('there is no newline at end of this file')) }) - it('stat', () => { + it('stat', function () { + this.timeout(40 * 1000) + return ipfs('block stat QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') .then((out) => { expect(out).to.eql([ @@ -46,7 +55,9 @@ describe('block', () => runOnAndOff((thing) => { }) }) - it.skip('rm', () => { + it.skip('rm', function () { + this.timeout(40 * 1000) + return ipfs('block rm QmZjTnYw2TFhn9Nn7tjmPSoTBoY7YRkwPzwSrSbabY24Kp') .then((out) => { expect(out).to.eql( diff --git a/test/cli/bootstrap.js b/test/cli/bootstrap.js index c5e440b85b..85b7851dcb 100644 --- a/test/cli/bootstrap.js +++ b/test/cli/bootstrap.js @@ -8,8 +8,7 @@ const runOnAndOff = require('../utils/on-and-off') describe('bootstrap', () => runOnAndOff((thing) => { let ipfs - before(function () { - this.timeout(30 * 1000) + before(() => { ipfs = thing.ipfs }) @@ -38,42 +37,50 @@ describe('bootstrap', () => runOnAndOff((thing) => { '/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD' ] - it('add default', () => { + it('add default', function () { + this.timeout(40 * 1000) + return ipfs('bootstrap add --default').then((out) => { - expect(out).to.be.eql(defaultList.join('\n') + '\n') + expect(out).to.equal(defaultList.join('\n') + '\n') }) }) - it('list the bootstrap nodes', () => { + it('list the bootstrap nodes', function () { + this.timeout(40 * 1000) + return ipfs('bootstrap list').then((out) => { - expect(out).to.eql(defaultList.join('\n') + '\n') + expect(out).to.equal(defaultList.join('\n') + '\n') }) }) - it('add another bootstrap node', () => { + it('add another bootstrap node', function () { + this.timeout(40 * 1000) + return ipfs('bootstrap add /ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD').then((out) => { - expect(out).to.be.eql('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD\n') + expect(out).to.equal('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD\n') return ipfs('bootstrap list') - }).then((out) => { - expect(out).to.be.eql(updatedList.join('\n') + '\n') - }) + }).then((out) => expect(out).to.equal(updatedList.join('\n') + '\n')) }) - it('rm a bootstrap node', () => { + it('rm a bootstrap node', function () { + this.timeout(40 * 1000) + return ipfs('bootstrap rm /ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD').then((out) => { - expect(out).to.be.eql('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD\n') + expect(out).to.equal('/ip4/111.111.111.111/tcp/1001/ipfs/QmcyFFKfLDGJKwufn2GeitxvhricsBQyNKTkrD14psikoD\n') return ipfs('bootstrap list') }).then((out) => { - expect(out).to.deep.equal(defaultList.join('\n') + '\n') + expect(out).to.equal(defaultList.join('\n') + '\n') }) }) - it('rm all bootstrap nodes', () => { + it('rm all bootstrap nodes', function () { + this.timeout(40 * 1000) + return ipfs('bootstrap rm --all').then((out) => { - expect(out).to.be.eql('') + expect(out).to.equal('') return ipfs('bootstrap list') }).then((out) => { - expect(out).to.deep.equal('') + expect(out).to.equal('') }) }) })) diff --git a/test/cli/config.js b/test/cli/config.js index 3b01700981..5f3e72c460 100644 --- a/test/cli/config.js +++ b/test/cli/config.js @@ -24,7 +24,9 @@ describe('config', () => runOnAndOff((thing) => { restoreConfig = () => fs.writeFileSync(configPath, fs.readFileSync(originalConfigPath, 'utf8'), 'utf8') }) - describe('get/set', () => { + describe('get/set', function () { + this.timeout(40 * 1000) + it('set a config key with a string value', () => { return ipfs('config foo bar').then((out) => { expect(updatedConfig().foo).to.equal('bar') @@ -64,7 +66,9 @@ describe('config', () => runOnAndOff((thing) => { }) }) - describe('show', () => { + describe('show', function () { + this.timeout(40 * 1000) + it('returns the full config', () => { return ipfs('config show').then((out) => { expect(JSON.parse(out)).to.be.eql(updatedConfig()) diff --git a/test/cli/dag.js b/test/cli/dag.js index 3a4a29785b..9cd6a3a586 100644 --- a/test/cli/dag.js +++ b/test/cli/dag.js @@ -11,7 +11,9 @@ describe('dag', () => runOnAndOff.off((thing) => { ipfs = thing.ipfs }) - it('get', () => { + it('get', function () { + this.timeout(20 * 1000) + // put test eth-block return ipfs('block put --format eth-block --mhtype keccak-256 test/fixtures/test-data/eth-block').then((out) => { expect(out).to.eql('z43AaGF23fmvRnDP56Ub9WcJCfzSfqtmzNCCvmz5eudT8dtdCDS\n') diff --git a/test/cli/files.js b/test/cli/files.js index 32933c95a5..5c57c7d208 100644 --- a/test/cli/files.js +++ b/test/cli/files.js @@ -106,7 +106,9 @@ describe('files', () => runOnAndOff((thing) => { ipfs = thing.ipfs }) - it('add with progress', () => { + it('add with progress', function () { + this.timeout(20 * 1000) + return ipfs('files add -p src/init-files/init-docs/readme') .then((out) => { expect(out) @@ -114,7 +116,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add', () => { + it('add', function () { + this.timeout(20 * 1000) + return ipfs('files add src/init-files/init-docs/readme') .then((out) => { expect(out) @@ -122,7 +126,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add alias', () => { + it('add alias', function () { + this.timeout(20 * 1000) + return ipfs('add src/init-files/init-docs/readme') .then((out) => { expect(out) @@ -130,21 +136,27 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add recursively test', () => { + it('add recursively test', function () { + this.timeout(20 * 1000) + return ipfs('files add -r test/fixtures/test-data/recursive-get-dir') .then((out) => { expect(out).to.eql(recursiveGetDirResults.join('\n') + '\n') }) }) - it('add directory with trailing slash test', () => { + it('add directory with trailing slash test', function () { + this.timeout(20 * 1000) + return ipfs('files add -r test/fixtures/test-data/recursive-get-dir/') .then((out) => { expect(out).to.eql(recursiveGetDirResults.join('\n') + '\n') }) }) - it('add and wrap with a directory', () => { + it('add and wrap with a directory', function () { + this.timeout(20 * 1000) + return ipfs('add -w src/init-files/init-docs/readme').then((out) => { expect(out).to.be.eql([ 'added QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB readme', @@ -153,7 +165,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add with cid-version=0', () => { + it('add with cid-version=0', function () { + this.timeout(20 * 1000) + return ipfs('add src/init-files/init-docs/readme --cid-version=0').then((out) => { expect(out) .to.eql('added QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB readme\n') @@ -169,7 +183,9 @@ describe('files', () => runOnAndOff((thing) => { // cid-version > 0 unless explicitly set to false. // // This retains feature parity without having to implement raw-leaves. - it('add with cid-version=1', () => { + it('add with cid-version=1', function () { + this.timeout(20 * 1000) + return new Promise((resolve, reject) => { ipfs('add src/init-files/init-docs/readme --cid-version=1') .then(() => reject(new Error('Raw leaves not expected to be implemented'))) @@ -197,7 +213,9 @@ describe('files', () => runOnAndOff((thing) => { // cid-version > 0 unless explicitly set to false. // // This retains feature parity without having to implement raw-leaves. - it('add with cid-version=1 and raw-leaves=true', () => { + it('add with cid-version=1 and raw-leaves=true', function () { + this.timeout(20 * 1000) + return new Promise((resolve, reject) => { ipfs('add src/init-files/init-docs/readme --cid-version=1 --raw-leaves=true') .then(() => reject(new Error('Raw leaves not expected to be implemented'))) @@ -208,7 +226,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add --quiet', () => { + it('add --quiet', function () { + this.timeout(20 * 1000) + return ipfs('files add -q src/init-files/init-docs/readme') .then((out) => { expect(out) @@ -216,7 +236,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add --quieter', () => { + it('add --quieter', function () { + this.timeout(20 * 1000) + return ipfs('files add -Q -w test/fixtures/test-data/hello test/test-data/node.json') .then((out) => { expect(out) @@ -224,7 +246,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('add --silent', () => { + it('add --silent', function () { + this.timeout(20 * 1000) + return ipfs('files add --silent src/init-files/init-docs/readme') .then((out) => { expect(out) @@ -232,14 +256,18 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('cat', () => { + it('cat', function () { + this.timeout(20 * 1000) + return ipfs('files cat QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') .then((out) => { expect(out).to.eql(readme) }) }) - it('cat alias', () => { + it('cat alias', function () { + this.timeout(20 * 1000) + return ipfs('cat QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') .then((out) => { expect(out).to.eql(readme) @@ -254,7 +282,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('ls', () => { + it('ls', function () { + this.timeout(20 * 1000) + return ipfs('ls QmYmW4HiZhotsoSqnv2o1oUusvkRM8b9RweBoH7ao5nki2') .then((out) => { expect(out).to.eql( @@ -266,7 +296,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('ls -v', () => { + it('ls -v', function () { + this.timeout(20 * 1000) + return ipfs('ls /ipfs/QmYmW4HiZhotsoSqnv2o1oUusvkRM8b9RweBoH7ao5nki2 -v') .then((out) => { expect(out).to.eql( @@ -279,7 +311,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('ls --help', () => { + it('ls --help', function () { + this.timeout(20 * 1000) + return ipfs('ls --help') .then((out) => { expect(out.split('\n').slice(1)).to.eql(['', @@ -297,7 +331,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('get', () => { + it('get', function () { + this.timeout(20 * 1000) + return ipfs('files get QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') .then((out) => { expect(out) @@ -311,7 +347,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('get alias', () => { + it('get alias', function () { + this.timeout(20 * 1000) + return ipfs('get QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB') .then((out) => { expect(out) @@ -325,7 +363,9 @@ describe('files', () => runOnAndOff((thing) => { }) }) - it('get recursively', () => { + it('get recursively', function () { + this.timeout(20 * 1000) + const outDir = path.join(process.cwd(), 'QmYmW4HiZhotsoSqnv2o1oUusvkRM8b9RweBoH7ao5nki2') rimraf(outDir) diff --git a/test/cli/id.js b/test/cli/id.js index 412837d386..6071a7e427 100644 --- a/test/cli/id.js +++ b/test/cli/id.js @@ -8,11 +8,13 @@ describe('id', () => runOnAndOff((thing) => { let ipfs before(function () { - this.timeout(30 * 1000) + this.timeout(40 * 1000) ipfs = thing.ipfs }) - it('get the id', () => { + it('get the id', function () { + this.timeout(40 * 1000) + return ipfs('id').then((res) => { const id = JSON.parse(res) expect(id).to.have.property('id') diff --git a/test/cli/init.js b/test/cli/init.js index 7ffa915f70..1c5fcf1a1d 100644 --- a/test/cli/init.js +++ b/test/cli/init.js @@ -5,10 +5,13 @@ const expect = require('chai').expect const path = require('path') const fs = require('fs') const clean = require('../utils/clean') +const hat = require('hat') const ipfsExec = require('../utils/ipfs-exec') const os = require('os') -describe('init', () => { +describe('init', function () { + this.timeout(40 * 1000) + let repoPath let ipfs @@ -23,14 +26,15 @@ describe('init', () => { }) } beforeEach(() => { - repoPath = os.tmpdir() + '/ipfs-' + Math.random().toString().substring(2, 8) + repoPath = os.tmpdir() + '/ipfs-' + hat() ipfs = ipfsExec(repoPath) }) afterEach(() => clean(repoPath)) it('basic', function () { - this.timeout(20 * 1000) + this.timeout(40 * 1000) + return ipfs('init').then((out) => { expect(repoDirSync('blocks')).to.have.length.above(2) expect(repoExistsSync('config')).to.equal(true) @@ -43,7 +47,9 @@ describe('init', () => { }).then((out) => expect(out).to.equal(readme)) }) - it('bits', () => { + it('bits', function () { + this.timeout(40 * 1000) + return ipfs('init --bits 1024').then(() => { expect(repoDirSync('blocks')).to.have.length.above(2) expect(repoExistsSync('config')).to.equal(true) @@ -51,7 +57,9 @@ describe('init', () => { }) }) - it('empty', () => { + it('empty', function () { + this.timeout(40 * 1000) + return ipfs('init --bits 1024 --empty-repo true').then(() => { expect(repoDirSync('blocks')).to.have.length(2) expect(repoExistsSync('config')).to.equal(true) diff --git a/test/cli/object.js b/test/cli/object.js index 3a6439d143..eb7aa9e189 100644 --- a/test/cli/object.js +++ b/test/cli/object.js @@ -44,7 +44,9 @@ describe('object', () => runOnAndOff((thing) => { }) }) - it('stat', () => { + it('stat', function () { + this.timeout(40 * 1000) + return ipfs('object stat QmZZmY4KCu9r3e7M2Pcn46Fc5qbn6NpzaAGaYb22kbfTqm').then((out) => { expect(out).to.eql([ 'NumLinks: 1', @@ -70,7 +72,9 @@ describe('object', () => runOnAndOff((thing) => { }) }) - describe('patch', () => { + describe('patch', function () { + this.timeout(40 * 1000) + it('append-data', () => { return ipfs('object patch append-data QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n test/fixtures/test-data/badconfig').then((out) => { expect(out).to.eql( diff --git a/test/cli/pubsub.js b/test/cli/pubsub.js index 703b83a5b0..d4fad22c93 100644 --- a/test/cli/pubsub.js +++ b/test/cli/pubsub.js @@ -7,112 +7,133 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) const delay = require('delay') -const waterfall = require('async/waterfall') -const HttpAPI = require('../../src/http') -// TODO needs to use ipfs-factory-daemon -const createTempNode = '' -const repoPath = require('./index').repoPath -const ipfs = require('../utils/ipfs-exec')(repoPath) - -describe.skip('pubsub', () => { +const series = require('async/series') +const InstanceFactory = require('../utils/ipfs-factory-instance') +const DaemonFactory = require('../utils/ipfs-factory-daemon') +const ipfsExec = require('../utils/ipfs-exec') + +describe('pubsub', function () { + this.timeout(40 * 1000) + + let instanceFactory + let daemonFactory + let node + let cli + let httpApi + const topicA = 'nonscentsA' const topicB = 'nonscentsB' const topicC = 'nonscentsC' - let node - let id - before((done) => { - createTempNode(1, (err, _node) => { + before(function (done) { + this.timeout(40 * 1000) + + instanceFactory = new InstanceFactory() + instanceFactory.spawnNode((err, _node) => { expect(err).to.not.exist() node = _node - node.goOnline(done) + done() }) }) - after((done) => { - node.goOffline(done) - }) + after((done) => instanceFactory.dismantle(done)) - describe('api running', () => { - let httpAPI - - before((done) => { - httpAPI = new HttpAPI(repoPath) - - waterfall([ - (cb) => httpAPI.start(cb), - (cb) => node.id(cb), - (_id, cb) => { - id = _id - ipfs(`swarm connect ${id.addresses[0]}`) - .then(() => cb()) - .catch(cb) - } - ], done) + before((done) => { + daemonFactory = new DaemonFactory() + daemonFactory.spawnNode((err, _node) => { + expect(err).to.not.exist() + httpApi = _node + done() }) + }) - after((done) => { - httpAPI.stop(done) - }) + after((done) => daemonFactory.dismantle(done)) - it('subscribe and publish', () => { - const sub = ipfs(`pubsub sub ${topicA}`) + before((done) => { + cli = ipfsExec(httpApi.repoPath) + done() + }) - sub.stdout.on('data', (c) => { - expect(c.toString()).to.be.eql('world\n') - sub.kill() - }) + it('subscribe and publish', () => { + const sub = cli(`pubsub sub ${topicA}`) - return Promise.all([ - sub.catch(ignoreKill), - delay(200) - .then(() => ipfs(`pubsub pub ${topicA} world`)) - .then((out) => { - expect(out).to.be.eql('') - }) - ]) + sub.stdout.on('data', (c) => { + expect(c.toString().trim()).to.be.eql('world') + sub.kill() }) - it('ls', () => { - const sub = ipfs(`pubsub sub ${topicB}`) + return Promise.all([ + sub.catch(ignoreKill), + delay(1000) + .then(() => cli(`pubsub pub ${topicA} world`)) + .then((out) => { + expect(out).to.be.eql('') + }) + ]) + }) - sub.stdout.once('data', (data) => { - expect(data.toString()).to.be.eql('world\n') - ipfs('pubsub ls') - .then((out) => { - expect(out).to.be.eql(topicB) - sub.kill() - }) - }) + it('ls', function () { + this.timeout(40 * 1000) - return Promise.all([ - sub.catch(ignoreKill), - delay(200) - .then(() => ipfs(`pubsub pub ${topicB} world`)) - ]) - }) + const sub = cli(`pubsub sub ${topicB}`) - it('peers', () => { - const handler = (msg) => { - expect(msg.data.toString()).to.be.eql('world') - ipfs(`pubsub peers ${topicC}`) - .then((out) => { - expect(out).to.be.eql(id.id) - sub2.kill() - node.pubsub.unsubscribe(topicC, handler) - }) - } - - const sub1 = node.pubsub.subscribe(topicC, handler) - const sub2 = ipfs(`pubsub sub ${topicC}`) - - return Promise.all([ - sub1, - sub2.catch(ignoreKill), - delay(200) - .then(() => ipfs(`pubsub pub ${topicC} world`)) - ]) + sub.stdout.once('data', (data) => { + expect(data.toString().trim()).to.be.eql('world') + cli('pubsub ls') + .then((out) => { + expect(out.trim()).to.be.eql(topicB) + sub.kill() + }) }) + + return Promise.all([ + sub.catch(ignoreKill), + delay(200) + .then(() => cli(`pubsub pub ${topicB} world`)) + ]) + }) + + it('peers', (done) => { + let sub + let instancePeerId + let peerAddress + const handler = (msg) => { + expect(msg.data.toString()).to.be.eql('world') + cli(`pubsub peers ${topicC}`) + .then((out) => { + expect(out.trim()).to.be.eql(instancePeerId) + sub.kill() + node.pubsub.unsubscribe(topicC, handler) + done() + }) + } + + series( + [ + (cb) => httpApi.id((err, peerInfo) => { + expect(err).to.not.exist() + peerAddress = peerInfo.addresses[0] + expect(peerAddress).to.exist() + cb() + }), + (cb) => node.id((err, peerInfo) => { + expect(err).to.not.exist() + instancePeerId = peerInfo.id.toString() + cb() + }), + (cb) => node.swarm.connect(peerAddress, cb), + (cb) => node.pubsub.subscribe(topicC, handler, cb) + ], + (err) => { + expect(err).to.not.exist() + sub = cli(`pubsub sub ${topicC}`) + + return Promise.all([ + sub.catch(ignoreKill), + delay(1000) + .then(() => cli(`pubsub pub ${topicC} world`)) + ]) + }) }) }) diff --git a/test/cli/swarm.js b/test/cli/swarm.js index 546984b707..46dff8881d 100644 --- a/test/cli/swarm.js +++ b/test/cli/swarm.js @@ -16,10 +16,9 @@ describe('swarm', () => { let ipfsA before(function (done) { - // CI takes longer to instantiate the daemon, - // so we need to increase the timeout for the - // before step - this.timeout(25 * 1000) + // CI takes longer to instantiate the daemon, so we need to increase the + // timeout for the before step + this.timeout(60 * 1000) factory = new Factory() @@ -47,7 +46,7 @@ describe('swarm', () => { after((done) => factory.dismantle(done)) describe('daemon on (through http-api)', function () { - this.timeout(10 * 1000) + this.timeout(40 * 1000) it('connect', () => { return ipfsA('swarm', 'connect', bMultiaddr).then((out) => { diff --git a/test/core/bitswap.spec.js b/test/core/bitswap.spec.js index 29b45d0320..007a77ec36 100644 --- a/test/core/bitswap.spec.js +++ b/test/core/bitswap.spec.js @@ -34,11 +34,13 @@ function makeBlock (callback) { }) } -describe('bitswap', () => { +describe('bitswap', function () { + this.timeout(80 * 1000) + let inProcNode // Node spawned inside this process beforeEach(function (done) { - this.timeout(30 * 1000) + this.timeout(60 * 1000) let config = { repo: createTempRepo(), @@ -212,7 +214,7 @@ describe('bitswap', () => { let node before(function (done) { - this.timeout(15 * 1000) + this.timeout(40 * 1000) node = new IPFS({ repo: createTempRepo(), @@ -248,7 +250,7 @@ describe('bitswap', () => { describe('while online', () => { before(function (done) { - this.timeout(15 * 1000) + this.timeout(40 * 1000) node.start(() => done()) }) diff --git a/test/core/create-node.spec.js b/test/core/create-node.spec.js index f1ce41f75a..8660ea8a4b 100644 --- a/test/core/create-node.spec.js +++ b/test/core/create-node.spec.js @@ -15,9 +15,11 @@ const IPFS = require('../../src/core') const createTempRepo = require('../utils/create-repo-nodejs.js') describe('create node', function () { - this.timeout(30 * 1000) + this.timeout(40 * 1000) it('custom repoPath', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: '/tmp/ipfs-repo-' + Math.random(), config: { @@ -41,6 +43,8 @@ describe('create node', function () { }) it('custom repo', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), config: { @@ -63,6 +67,8 @@ describe('create node', function () { }) it('IPFS.createNode', function (done) { + this.timeout(40 * 1000) + const node = IPFS.createNode({ repo: createTempRepo(), config: { @@ -87,7 +93,9 @@ describe('create node', function () { }) }) - it('init: { bits: 1024 }', (done) => { + it('init: { bits: 1024 }', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), init: { @@ -112,7 +120,9 @@ describe('create node', function () { }) }) - it('init: false errors (start default: true)', (done) => { + it('init: false errors (start default: true)', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), init: false, @@ -128,7 +138,9 @@ describe('create node', function () { }) }) - it('init: false, start: false', (done) => { + it('init: false, start: false', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), init: false, @@ -157,6 +169,8 @@ describe('create node', function () { }) it('init: true, start: false', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), init: true, @@ -177,6 +191,8 @@ describe('create node', function () { }) it('init: true, start: false, use callback', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), init: true, @@ -194,11 +210,10 @@ describe('create node', function () { }) it('overload config', function (done) { - this.timeout(20 * 1000) + this.timeout(40 * 1000) + + if (!isNode) { return done() } - if (!isNode) { - return done() - } const node = new IPFS({ repo: createTempRepo(), config: { @@ -226,6 +241,8 @@ describe('create node', function () { }) it('start and stop, start and stop', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), config: { @@ -245,6 +262,8 @@ describe('create node', function () { }) it('stop as promised', function (done) { + this.timeout(40 * 1000) + const node = new IPFS({ repo: createTempRepo(), config: { @@ -263,6 +282,8 @@ describe('create node', function () { }) it('can start node twice without crash', function (done) { + this.timeout(40 * 1000) + const options = { repo: createTempRepo(), config: { @@ -272,7 +293,9 @@ describe('create node', function () { Bootstrap: [] } } + let node = new IPFS(options) + series([ (cb) => node.once('start', cb), (cb) => node.stop(cb), diff --git a/test/core/files-sharding.spec.js b/test/core/files-sharding.spec.js index 9b0001c13d..aaf97c8b64 100644 --- a/test/core/files-sharding.spec.js +++ b/test/core/files-sharding.spec.js @@ -29,7 +29,7 @@ describe('files directory (sharding tests)', () => { let ipfs before(function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) ipfs = new IPFS({ repo: createTempRepo(), @@ -49,12 +49,12 @@ describe('files directory (sharding tests)', () => { }) after(function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) ipfs.stop(done) }) it('should be able to add dir without sharding', function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) pull( pull.values(createTestFiles()), @@ -74,7 +74,7 @@ describe('files directory (sharding tests)', () => { let ipfs before(function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) ipfs = new IPFS({ repo: createTempRepo(), @@ -97,12 +97,12 @@ describe('files directory (sharding tests)', () => { }) after(function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) ipfs.stop(done) }) it('should be able to add dir with sharding', function (done) { - this.timeout(30 * 1000) + this.timeout(40 * 1000) pull( pull.values(createTestFiles()), diff --git a/test/core/init.spec.js b/test/core/init.spec.js index b9a61fe209..07990027f2 100644 --- a/test/core/init.spec.js +++ b/test/core/init.spec.js @@ -18,9 +18,7 @@ const IPFS = require('../../src/core') const createTempRepo = require('../utils/create-repo-nodejs.js') describe('init', () => { - if (!isNode) { - return - } + if (!isNode) { return } let ipfs let repo @@ -38,7 +36,7 @@ describe('init', () => { afterEach((done) => repo.teardown(done)) it('basic', (done) => { - ipfs.init({ bits: 1024 }, (err) => { + ipfs.init({ bits: 512 }, (err) => { expect(err).to.not.exist() repo.exists((err, res) => { @@ -55,8 +53,9 @@ describe('init', () => { }) it('set # of bits in key', function (done) { - this.timeout(20 * 1000) - ipfs.init({ bits: 2048 }, (err) => { + this.timeout(40 * 1000) + + ipfs.init({ bits: 1024 }, (err) => { expect(err).to.not.exist() repo.config.get((err, config) => { @@ -68,7 +67,7 @@ describe('init', () => { }) it('init docs are written', (done) => { - ipfs.init({ bits: 1024 }, (err) => { + ipfs.init({ bits: 512 }, (err) => { expect(err).to.not.exist() const multihash = 'QmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB' @@ -81,7 +80,7 @@ describe('init', () => { }) it('empty repo', (done) => { - ipfs.init({ bits: 1024, emptyRepo: true }, (err) => { + ipfs.init({ bits: 512, emptyRepo: true }, (err) => { expect(err).to.not.exist() // Should not have default assets diff --git a/test/fixtures/go-ipfs-repo/version b/test/fixtures/go-ipfs-repo/version index 1e8b314962..62f9457511 100644 --- a/test/fixtures/go-ipfs-repo/version +++ b/test/fixtures/go-ipfs-repo/version @@ -1 +1 @@ -6 +6 \ No newline at end of file diff --git a/test/http-api/over-ipfs-api/block.js b/test/http-api/extra/block.js similarity index 100% rename from test/http-api/over-ipfs-api/block.js rename to test/http-api/extra/block.js diff --git a/test/http-api/over-ipfs-api/bootstrap.js b/test/http-api/extra/bootstrap.js similarity index 100% rename from test/http-api/over-ipfs-api/bootstrap.js rename to test/http-api/extra/bootstrap.js diff --git a/test/http-api/over-ipfs-api/config.js b/test/http-api/extra/config.js similarity index 100% rename from test/http-api/over-ipfs-api/config.js rename to test/http-api/extra/config.js diff --git a/test/http-api/over-ipfs-api/id.js b/test/http-api/extra/id.js similarity index 100% rename from test/http-api/over-ipfs-api/id.js rename to test/http-api/extra/id.js diff --git a/test/http-api/over-ipfs-api/object.js b/test/http-api/extra/object.js similarity index 100% rename from test/http-api/over-ipfs-api/object.js rename to test/http-api/extra/object.js diff --git a/test/http-api/over-ipfs-api/version.js b/test/http-api/extra/version.js similarity index 100% rename from test/http-api/over-ipfs-api/version.js rename to test/http-api/extra/version.js diff --git a/test/http-api/index.js b/test/http-api/index.js index e2c7f34ce3..85fc528a7d 100644 --- a/test/http-api/index.js +++ b/test/http-api/index.js @@ -18,8 +18,11 @@ describe('HTTP API', () => { let http = {} - before((done) => { - http.api = new API(repoTests) + before(function (done) { + this.timeout(40 * 1000) + + const options = { enablePubsubExperiment: true } + http.api = new API(repoTests, null, options) ncp(repoExample, repoTests, (err) => { expect(err).to.not.exist() @@ -28,28 +31,26 @@ describe('HTTP API', () => { }) }) - after((done) => { - http.api.stop((err) => { - expect(err).to.not.exist() - clean(repoTests) - done() - }) - }) + after((done) => http.api.stop((err) => { + expect(err).to.not.exist() + clean(repoTests) + done() + })) describe('## http-api spec tests', () => { fs.readdirSync(path.join(__dirname, '/spec')) .forEach((file) => require('./spec/' + file)(http)) }) - describe('## interface tests', () => { + describe('## interface-ipfs-core over ipfs-api', () => { fs.readdirSync(path.join(__dirname, '/interface')) .forEach((file) => require('./interface/' + file)) }) - describe('## custom ipfs-api tests', () => { + describe('## extra tests with ipfs-api', () => { const ctl = APIctl('/ip4/127.0.0.1/tcp/6001') - fs.readdirSync(path.join(__dirname, '/over-ipfs-api')) - .forEach((file) => require('./over-ipfs-api/' + file)(ctl)) + fs.readdirSync(path.join(__dirname, '/extra')) + .forEach((file) => require('./extra/' + file)(ctl)) }) }) diff --git a/test/http-api/interface/pubsub.js b/test/http-api/interface/pubsub.js index 968227c83b..ab474fac9f 100644 --- a/test/http-api/interface/pubsub.js +++ b/test/http-api/interface/pubsub.js @@ -2,8 +2,6 @@ 'use strict' -// TODO needs: https://github.com/ipfs/js-ipfs-api/pull/493 -/* const test = require('interface-ipfs-core') const FactoryClient = require('./../../utils/ipfs-factory-daemon') @@ -20,4 +18,3 @@ const common = { } test.pubsub(common) -*/ diff --git a/test/http-api/spec/pubsub.js b/test/http-api/spec/pubsub.js index 245b6d153c..bbb8b56e66 100644 --- a/test/http-api/spec/pubsub.js +++ b/test/http-api/spec/pubsub.js @@ -6,35 +6,17 @@ const chai = require('chai') const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) -const createTempNode = '' -// TODO migrate to use ipfs-factory-daemon module.exports = (http) => { - describe.skip('/pubsub', () => { + describe('/pubsub', () => { let api - let tmpNode const buf = Buffer.from('some message') const topic = 'nonScents' const topicNotSubscribed = 'somethingRandom' - before((done) => { + before(() => { api = http.api.server.select('API') - - createTempNode(47, (err, _ipfs) => { - expect(err).to.not.exist() - tmpNode = _ipfs - tmpNode.goOnline((err) => { - expect(err).to.not.exist() - done() - }) - }) - }) - - after((done) => { - setTimeout(() => { - tmpNode.goOffline(done) - }, 1000) }) describe('/sub', () => { @@ -76,7 +58,7 @@ module.exports = (http) => { it('returns 500 if no buffer is provided', (done) => { api.inject({ method: 'POST', - url: `/api/v0/pubsub/pub?arg=${topic}&arg=` + url: `/api/v0/pubsub/pub?arg=&arg=` }, (res) => { expect(res.statusCode).to.equal(500) expect(res.result.Code).to.be.eql(1) diff --git a/test/interop/exchange-files.js b/test/interop/exchange-files.js index f6b7b68d53..1c14ff57ef 100644 --- a/test/interop/exchange-files.js +++ b/test/interop/exchange-files.js @@ -8,7 +8,6 @@ chai.use(dirtyChai) const series = require('async/series') const parallel = require('async/parallel') const waterfall = require('async/waterfall') -const bl = require('bl') const crypto = require('crypto') const pretty = require('pretty-bytes') const randomFs = require('random-fs') @@ -128,8 +127,7 @@ describe('exchange files', () => { const data = crypto.randomBytes(size) waterfall([ (cb) => goDaemon.api.add(data, cb), - (res, cb) => jsDaemon.api.cat(res[0].hash, cb), - (stream, cb) => stream.pipe(bl(cb)) + (res, cb) => jsDaemon.api.cat(res[0].hash, cb) ], (err, file) => { expect(err).to.not.exist() expect(file).to.be.eql(data) @@ -141,8 +139,7 @@ describe('exchange files', () => { const data = crypto.randomBytes(size) waterfall([ (cb) => jsDaemon.api.add(data, cb), - (res, cb) => goDaemon.api.cat(res[0].hash, cb), - (stream, cb) => stream.pipe(bl(cb)) + (res, cb) => goDaemon.api.cat(res[0].hash, cb) ], (err, file) => { expect(err).to.not.exist() expect(file).to.be.eql(data) @@ -154,8 +151,7 @@ describe('exchange files', () => { const data = crypto.randomBytes(size) waterfall([ (cb) => js2Daemon.api.add(data, cb), - (res, cb) => jsDaemon.api.cat(res[0].hash, cb), - (stream, cb) => stream.pipe(bl(cb)) + (res, cb) => jsDaemon.api.cat(res[0].hash, cb) ], (err, file) => { expect(err).to.not.exist() expect(file).to.be.eql(data) @@ -164,6 +160,7 @@ describe('exchange files', () => { }) })) + // TODO these tests are not fetching the full dir?? describe('get directory', () => dirs.forEach((num) => { it(`go -> js: depth: 5, num: ${num}`, () => { const dir = tmpDir() diff --git a/test/interop/pubsub.js b/test/interop/pubsub.js index b76f21967f..0bfa11f143 100644 --- a/test/interop/pubsub.js +++ b/test/interop/pubsub.js @@ -8,10 +8,29 @@ chai.use(dirtyChai) const series = require('async/series') const parallel = require('async/parallel') -const GODaemon = require('../utils/interop-daemon-spawner/go') +const GoDaemon = require('../utils/interop-daemon-spawner/go') const JSDaemon = require('../utils/interop-daemon-spawner/js') -describe('pubsub', () => { +/* + * Wait for a condition to become true. When its true, callback is called. + */ +function waitFor (predicate, callback) { + const ttl = Date.now() + (2 * 1000) + const self = setInterval(() => { + if (predicate()) { + clearInterval(self) + return callback() + } + if (Date.now() > ttl) { + clearInterval(self) + return callback(new Error('waitFor time expired')) + } + }, 500) +} + +describe('pubsub', function () { + this.timeout(5 * 1000) + let jsD let goD let jsId @@ -20,7 +39,7 @@ describe('pubsub', () => { before(function (done) { this.timeout(50 * 1000) - goD = new GODaemon({ + goD = new GoDaemon({ disposable: true, init: true, flags: ['--enable-pubsub-experiment'] @@ -33,48 +52,295 @@ describe('pubsub', () => { ], (done)) }) - after((done) => { - series([ + after(function (done) { + this.timeout(50 * 1000) + + parallel([ (cb) => goD.stop(cb), (cb) => jsD.stop(cb) ], done) }) it('make connections', (done) => { - parallel([ + series([ (cb) => jsD.api.id(cb), (cb) => goD.api.id(cb) ], (err, ids) => { expect(err).to.not.exist() - jsId = ids[0].ID - goId = ids[0].ID + jsId = ids[0].id + goId = ids[1].id - console.log('jsId:', jsId) - console.log('goId:', goId) + const jsLocalAddr = ids[0].addresses.find(a => a.includes('127.0.0.1')) + const goLocalAddr = ids[1].addresses.find(a => a.includes('127.0.0.1')) parallel([ - (cb) => jsD.api.swarm.connect(ids[1].addresses[0], cb), - (cb) => goD.api.swarm.connect(ids[0].addresses[0], cb) + (cb) => jsD.api.swarm.connect(goLocalAddr, cb), + (cb) => goD.api.swarm.connect(jsLocalAddr, cb), + (cb) => setTimeout(() => { + cb() + }, 1000) ], done) }) }) - it.skip('publish from JS, subscribe on Go', (done) => { - // TODO write this test + describe('ascii data', () => { + const data = Buffer.from('hello world') + + it('publish from Go, subscribe on Go', (done) => { + const topic = 'pubsub-go-go' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on JS', (done) => { + const topic = 'pubsub-js-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on Go', (done) => { + const topic = 'pubsub-js-go' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from Go, subscribe on JS', (done) => { + const topic = 'pubsub-go-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) }) - it.skip('publish from Go, subscribe on JS', (done) => { - const topic = 'pubsub-go-js' - const data = Buffer.from('hello world') + describe('non-ascii data', () => { + const data = Buffer.from('你好世界') - function checkMessage () { - console.log('check message', arguments) - } + it('publish from Go, subscribe on Go', (done) => { + const topic = 'pubsub-non-ascii-go-go' + let n = 0 - series([ - cb => jsD.api.pubsub.subscribe(topic, checkMessage, cb), - cb => goD.api.pubsub.publish(topic, data, cb) - ], done) + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on JS', (done) => { + const topic = 'pubsub-non-ascii-js-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on Go', (done) => { + const topic = 'pubsub-non-ascii-js-go' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from Go, subscribe on JS', (done) => { + const topic = 'pubsub-non-ascii-go-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString()).to.equal(data.toString()) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + }) + + describe('binary data', () => { + const data = Buffer.from('a36161636179656162830103056164a16466666666f400010203040506070809', 'hex') + + it('publish from Go, subscribe on Go', (done) => { + const topic = 'pubsub-binary-go-go' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString('hex')).to.equal(data.toString('hex')) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from Go, subscribe on JS', (done) => { + const topic = 'pubsub-binary-go-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString('hex')).to.equal(data.toString('hex')) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', goId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => goD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on Go', (done) => { + const topic = 'pubsub-binary-js-go' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString('hex')).to.equal(data.toString('hex')) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => goD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) + + it('publish from JS, subscribe on JS', (done) => { + const topic = 'pubsub-binary-js-js' + let n = 0 + + function checkMessage (msg) { + ++n + expect(msg.data.toString('hex')).to.equal(data.toString('hex')) + expect(msg).to.have.property('seqno') + expect(Buffer.isBuffer(msg.seqno)).to.be.eql(true) + expect(msg).to.have.property('topicIDs').eql([topic]) + expect(msg).to.have.property('from', jsId) + } + + series([ + (cb) => jsD.api.pubsub.subscribe(topic, checkMessage, cb), + (cb) => setTimeout(() => { cb() }, 500), + (cb) => jsD.api.pubsub.publish(topic, data, cb), + (cb) => waitFor(() => n === 1, cb) + ], done) + }) }) }) diff --git a/test/interop/repo.js b/test/interop/repo.js index bd981d0ff9..b82ce74804 100644 --- a/test/interop/repo.js +++ b/test/interop/repo.js @@ -6,7 +6,6 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) const waterfall = require('async/waterfall') -const bl = require('bl') const crypto = require('crypto') const os = require('os') @@ -14,12 +13,9 @@ const GoDaemon = require('../utils/interop-daemon-spawner/go') const JsDaemon = require('../utils/interop-daemon-spawner/js') function catAndCheck (daemon, hash, data, callback) { - waterfall([ - (cb) => daemon.api.cat(hash, cb), - (stream, cb) => stream.pipe(bl(cb)) - ], (err, file) => { + daemon.api.cat(hash, (err, fileData) => { expect(err).to.not.exist() - expect(file).to.eql(data) + expect(fileData).to.eql(data) callback() }) } diff --git a/test/utils/interop-daemon-spawner/go.js b/test/utils/interop-daemon-spawner/go.js index 92a04ca99e..8010724d81 100644 --- a/test/utils/interop-daemon-spawner/go.js +++ b/test/utils/interop-daemon-spawner/go.js @@ -40,8 +40,7 @@ class GoDaemon { this.node = node this.node.setConfig('Bootstrap', '[]', cb) }, - (res, cb) => this.node.startDaemon(cb), - // (res, cb) => this.node.startDaemon(this.flags, cb), + (res, cb) => this.node.startDaemon(this.flags, cb), (api, cb) => { this.api = api diff --git a/test/utils/interop-daemon-spawner/js.js b/test/utils/interop-daemon-spawner/js.js index e96850c82b..bd376ff892 100644 --- a/test/utils/interop-daemon-spawner/js.js +++ b/test/utils/interop-daemon-spawner/js.js @@ -37,14 +37,17 @@ class JsDaemon extends EventEmitter { this.path = opts.path || tmpDir() this._started = false + const extras = { + enablePubsubExperiment: true + } if (this.init) { const p = portConfig(this.port) this.node = new HttpApi(this.path, { Bootstrap: [], Addresses: p - }) + }, extras) } else { - this.node = new HttpApi(this.path) + this.node = new HttpApi(this.path, null, extras) } this.node.start(this.init, (err) => { diff --git a/test/utils/interop-daemon-spawner/util.js b/test/utils/interop-daemon-spawner/util.js index 256f857f0c..c0ca77a338 100644 --- a/test/utils/interop-daemon-spawner/util.js +++ b/test/utils/interop-daemon-spawner/util.js @@ -7,7 +7,7 @@ const path = require('path') exports.tmpDir = (prefix) => { return path.join( os.tmpdir(), - prefix || 'tmp', + prefix || 'js-ipfs-interop', crypto.randomBytes(32).toString('hex') ) } diff --git a/test/utils/ipfs-exec.js b/test/utils/ipfs-exec.js index 2d7f3746e5..c9bcb53dc3 100644 --- a/test/utils/ipfs-exec.js +++ b/test/utils/ipfs-exec.js @@ -8,8 +8,7 @@ chai.use(dirtyChai) const _ = require('lodash') -// This is our new test utility to easily check and execute -// ipfs cli commands. +// This is our new test utility to easily check and execute ipfs cli commands. // // The top level export is a function that can be passed a `repoPath` // and optional `opts` to customize the execution of the commands. diff --git a/test/utils/ipfs-factory-daemon/default-config.json b/test/utils/ipfs-factory-daemon/default-config.json index 47eac6522a..f2203594df 100644 --- a/test/utils/ipfs-factory-daemon/default-config.json +++ b/test/utils/ipfs-factory-daemon/default-config.json @@ -3,15 +3,6 @@ "PeerID": "", "PrivKey": "" }, - "Datastore": { - "Type": "", - "Path": "", - "StorageMax": "", - "StorageGCWatermark": 0, - "GCPeriod": "", - "Params": null, - "NoSync": false - }, "Addresses": { "Swarm": [ "/ip4/127.0.0.1/tcp/0" @@ -19,11 +10,6 @@ "API": "/ip4/127.0.0.1/tcp/0", "Gateway": "/ip4/127.0.0.1/tcp/0" }, - "Mounts": { - "IPFS": "/ipfs", - "IPNS": "/ipns", - "FuseAllowOther": false - }, "Version": { "Current": "jsipfs-dev", "Check": "error", @@ -40,32 +26,16 @@ "Enabled": false } }, - "Ipns": { - "RepublishPeriod": "", - "RecordLifetime": "", - "ResolveCacheSize": 128 - }, "Bootstrap": [], - "Tour": { - "Last": "" - }, "Gateway": { "HTTPHeaders": null, "RootRedirect": "", "Writable": false }, - "SupernodeRouting": { - "Servers": [] - }, "API": { "HTTPHeaders": null }, "Swarm": { "AddrFilters": null - }, - "Log": { - "MaxSizeMB": 250, - "MaxBackups": 1, - "MaxAgeDays": 0 } } diff --git a/test/utils/ipfs-factory-daemon/index.js b/test/utils/ipfs-factory-daemon/index.js index 9c7a61ce73..2dde6d4eef 100644 --- a/test/utils/ipfs-factory-daemon/index.js +++ b/test/utils/ipfs-factory-daemon/index.js @@ -8,6 +8,7 @@ const series = require('async/series') const eachSeries = require('async/eachSeries') const defaultConfig = require('./default-config.json') const os = require('os') +const hat = require('hat') class Factory { constructor () { @@ -22,13 +23,10 @@ class Factory { } if (typeof suppliedConfig === 'function') { callback = suppliedConfig - suppliedConfig = undefined + suppliedConfig = {} } - repoPath = repoPath || - os.tmpdir() + '/ipfs-' + - Math.random().toString().substring(2, 8) + - '-' + Date.now() + repoPath = repoPath || os.tmpdir() + '/ipfs-' + hat() let daemon let ctl @@ -38,12 +36,10 @@ class Factory { (cb) => { // prepare config for node - config = Object.assign({}, defaultConfig, config || {}) + config = Object.assign({}, defaultConfig, suppliedConfig) PeerId.create({ bits: 1024 }, (err, id) => { - if (err) { - return cb(err) - } + if (err) { return cb(err) } const peerId = id.toJSON() config.Identity.PeerID = peerId.id @@ -52,7 +48,7 @@ class Factory { }) }, (cb) => { - daemon = new HttpApi(repoPath, config) + daemon = new HttpApi(repoPath, config, {enablePubsubExperiment: true}) daemon.repoPath = repoPath this.daemonsSpawned.push(daemon) @@ -70,11 +66,11 @@ class Factory { dismantle (callback) { eachSeries(this.daemonsSpawned, (d, cb) => { d.stop((err) => { + clean(d.repoPath) if (err) { console.error('error stopping', err) } - clean(d.repoPath) - cb() + cb(err) }) }, callback) } diff --git a/test/utils/ipfs-factory-instance/default-config.json b/test/utils/ipfs-factory-instance/default-config.json index 8428849538..677c7c85d9 100644 --- a/test/utils/ipfs-factory-instance/default-config.json +++ b/test/utils/ipfs-factory-instance/default-config.json @@ -1,13 +1,4 @@ { - "Datastore": { - "Type": "", - "Path": "", - "StorageMax": "", - "StorageGCWatermark": 0, - "GCPeriod": "", - "Params": null, - "NoSync": false - }, "Addresses": { "Swarm": [ "/ip4/127.0.0.1/tcp/0" @@ -31,11 +22,6 @@ "Enabled": false } }, - "Ipns": { - "RepublishPeriod": "", - "RecordLifetime": "", - "ResolveCacheSize": 128 - }, "Bootstrap": [], "API": { "HTTPHeaders": null diff --git a/test/utils/ipfs-factory-instance/index.js b/test/utils/ipfs-factory-instance/index.js index aacfe9b4ac..febc85ca86 100644 --- a/test/utils/ipfs-factory-instance/index.js +++ b/test/utils/ipfs-factory-instance/index.js @@ -2,6 +2,7 @@ const series = require('async/series') const each = require('async/each') +const hat = require('hat') const defaultConfig = require('./default-config.json') const IPFS = require('../../../src/core') @@ -16,31 +17,28 @@ function Factory () { const nodes = [] - /* yields a new started node */ - this.spawnNode = (repoPath, config, callback) => { + /* yields a new started node instance */ + this.spawnNode = (repoPath, suppliedConfig, callback) => { if (typeof repoPath === 'function') { callback = repoPath repoPath = undefined } - if (typeof config === 'function') { - callback = config - config = undefined + + if (typeof suppliedConfig === 'function') { + callback = suppliedConfig + suppliedConfig = {} } if (!repoPath) { - repoPath = '/tmp/.ipfs-' + Math.random() - .toString() - .substring(2, 8) + repoPath = '/tmp/.ipfs-' + hat() } - config = config || defaultConfig + const config = Object.assign({}, defaultConfig, suppliedConfig) const repo = createTempRepo(repoPath) const node = new IPFS({ repo: repo, - init: { - bits: 1024 - }, + init: { bits: 1024 }, config: config, EXPERIMENTAL: { pubsub: true,