Skip to content
This repository has been archived by the owner on Mar 10, 2020. It is now read-only.

feat(factory): use the factory mode #340

Merged
merged 3 commits into from
Aug 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
node_modules
*.log
test/tmp-disposable-nodes-addrs.json
test/setup/tmp-disposable-nodes-addrs.json
dist
lib
coverage
coverage
9 changes: 8 additions & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@

const gulp = require('gulp')

require('./tasks/test')
require('./test/setup/spawn-daemons')
require('./test/factory/factory-tasks')

gulp.task('test:node:before', ['daemons:start', 'factory:start'])
gulp.task('test:node:after', ['daemons:stop', 'factory:stop'])
gulp.task('test:browser:before', ['daemons:start', 'factory:start'])
gulp.task('test:browser:after', ['daemons:stop', 'factory:stop'])

require('aegir/gulp')(gulp)
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@
"aegir": "^6.0.0",
"chai": "^3.5.0",
"gulp": "^3.9.1",
"interface-ipfs-core": "^0.6.0",
"hapi": "^14.1.0",
"interface-ipfs-core": "^0.7.2",
"ipfsd-ctl": "^0.14.0",
"passthrough-counter": "^1.0.0",
"pre-commit": "^1.1.3",
"socket.io": "^1.4.8",
"socket.io-client": "^1.4.8",
"stream-equal": "^0.1.8",
"stream-http": "^2.3.1",
"streamifier": "^0.1.1"
Expand Down
10 changes: 0 additions & 10 deletions tasks/test.js

This file was deleted.

17 changes: 0 additions & 17 deletions test/api/object.spec.js

This file was deleted.

2 changes: 1 addition & 1 deletion test/browser.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
'use strict'

require('./setup')
require('./setup/setup-ipfs-api-clients')
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
89 changes: 89 additions & 0 deletions test/factory/daemon-spawner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use strict'

// const defaultConfig = require('./default-config.json')
const ipfsd = require('ipfsd-ctl')
const series = require('run-series')

module.exports = Factory

function Factory () {
if (!(this instanceof Factory)) {
return new Factory()
}

const nodes = []

this.spawnNode = (repoPath, config, callback) => {
if (typeof repoPath === 'function') {
callback = repoPath
repoPath = undefined
}
if (typeof config === 'function') {
callback = config
config = undefined
}

// if (!repoPath) {
// repoPath = '/tmp/.ipfs-' + Math.random()
// .toString()
// .substring(2, 8)
// }

// TODO
// - [ ] Support custom repoPath
// - [ ] Support custom config
// This will come once the new ipfsd-ctl is
// complete: https://github.com/ipfs/js-ipfsd-ctl/pull/89

spawnEphemeralNode((err, node) => {
if (err) {
return callback(err)
}
nodes.push(node)
callback(null, node.apiAddr)
})
}

this.dismantle = function (callback) {
series(
nodes.map((node) => {
return node.stopDaemon
}), callback)
}
}

function spawnEphemeralNode (callback) {
ipfsd.disposable((err, node) => {
if (err) {
return callback(err)
}
// Note: we have to set each config value
// independently since the config/replace endpoint
// doesn't work as expected
series([
(cb) => {
node.setConfig('Bootstrap', null, cb)
},
(cb) => {
node.setConfig('Discovery', '{}', cb)
},
(cb) => {
const headers = {
HTTPHeaders: {
'Access-Control-Allow-Origin': ['*']
}
}
node.setConfig('API', JSON.stringify(headers), cb)
},
(cb) => {
node.startDaemon(cb)
}
], (err) => {
if (err) {
return callback(err)
}

callback(null, node)
})
})
}
54 changes: 54 additions & 0 deletions test/factory/factory-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict'

const io = require('socket.io-client')
const ipfsAPI = require('../../src')

module.exports = Factory

function Factory () {
if (!(this instanceof Factory)) {
return new Factory()
}
const sioOptions = {
transports: ['websocket'],
'force new connection': true
}
const sioUrl = 'http://localhost:55155'
let sioConnected = false
let ioC

this.spawnNode = (repoPath, config, callback) => {
if (typeof repoPath === 'function') {
callback = repoPath
repoPath = undefined
}
if (typeof config === 'function') {
callback = config
config = undefined
}

if (sioConnected) {
spawnNode()
} else {
ioC = io.connect(sioUrl, sioOptions)
ioC.on('connect_error', callback)
ioC.on('connect', () => {
sioConnected = true
spawnNode()
})
}

function spawnNode () {
ioC.once('fc-node', (apiAddr) => {
const ipfs = ipfsAPI(apiAddr)
callback(null, ipfs)
})
ioC.emit('fs-spawn-node', repoPath, config)
}
}

this.dismantle = function (callback) {
ioC.once('fc-nodes-shutdown', callback)
ioC.emit('fs-dismantle')
}
}
34 changes: 34 additions & 0 deletions test/factory/factory-server-routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

const SocketIO = require('socket.io')
const DaemonSpawner = require('./daemon-spawner')

module.exports = (http) => {
const io = new SocketIO(http.listener)
io.on('connection', handle)

const ds = new DaemonSpawner()

function handle (socket) {
socket.on('fs-spawn-node', spawnNode.bind(socket))
socket.on('fs-dismantle', dismantle.bind(socket))
}

function spawnNode (repoPath, config) {
ds.spawnNode(repoPath, config, (err, apiAddr) => {
if (err) {
throw err
}
this.emit('fc-node', apiAddr)
})
}

function dismantle () {
ds.dismantle((err) => {
if (err) {
throw err
}
this.emit('fc-nodes-shutdown')
})
}
}
28 changes: 28 additions & 0 deletions test/factory/factory-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict'

const Hapi = require('hapi')

const port = Number(process.env.PORT) || 55155
const options = {
connections: {
routes: {
cors: true
}
}
}

module.exports = (callback) => {
const http = new Hapi.Server(options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to bring in hapi? just using core-http should be enough for serving socket.io

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like hapi because then I can just set CORS to true without having to write headers by hand. Also hapi is pretty modular, a lot of features (like template engine) are buy in modules, which makes it a 'smaller' framework


http.connection({ port: port })

http.start((err) => {
if (err) {
return callback(err)
}
require('./factory-server-routes')(http)

callback(null, http)
// note: http.stop(callback) to stop the server :)
})
}
20 changes: 20 additions & 0 deletions test/factory/factory-tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict'

const gulp = require('gulp')
const factoryServer = require('./factory-server')

let factory

gulp.task('factory:start', (done) => {
factoryServer((err, http) => {
if (err) {
throw err
}
factory = http
done()
})
})

gulp.task('factory:stop', (done) => {
factory.stop(done)
})
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('.config', () => {
return done()
}

apiClients.c.config.replace(path.join(__dirname, '/../r-config.json'), (err, res) => {
apiClients.c.config.replace(path.join(__dirname, '/../data/r-config.json'), (err, res) => {
expect(err).to.not.exist
expect(res).to.be.equal(null)
done()
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('.config', () => {
return
}

return apiClients.c.config.replace(path.join(__dirname, '/../r-config.json'))
return apiClients.c.config.replace(path.join(__dirname, '/../data/r-config.json'))
.then((res) => {
expect(res).to.be.equal(null)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ describe('.dht', () => {
// non ipns or pk hashes fail to fetch, known bug
// bug: https://github.com/ipfs/go-ipfs/issues/1923#issuecomment-152932234
// apiClients.a.dht.get('scope', (err, value) => {
// console.log('->>', err, value)
// expect(err).to.not.exist
// expect(value).to.be.equal('interplanetary')
// done()
Expand Down
34 changes: 25 additions & 9 deletions test/api/files.spec.js → test/interface-ipfs-core/files.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,41 @@ const expect = require('chai').expect
const isNode = require('detect-node')
const path = require('path')
const test = require('interface-ipfs-core')
const bs58 = require('bs58')
const fs = require('fs')
const FactoryClient = require('../factory/factory-client')
const testfile = fs.readFileSync(path.join(__dirname, '/../data/testfile.txt'))

let testfile
// add, cat, get and ls tests from interface-ipfs-core
let fc

testfile = require('fs').readFileSync(path.join(__dirname, '/../testfile.txt'))

// Load the add/cat/get/ls commands from interface-ipfs-core
const common = {
setup: function (cb) {
cb(null, apiClients.a)
setup: function (callback) {
fc = new FactoryClient()
callback(null, fc)
},
teardown: function (cb) {
cb()
teardown: function (callback) {
fc.dismantle(callback)
}
}

test.files(common)

// Describe the (mfs) tests
// mfs tests
describe('.files (pseudo mfs)', () => {
it('add file for testing', (done) => {
apiClients.a.files.add(testfile, (err, res) => {
expect(err).to.not.exist

expect(res).to.have.length(1)
const mh = bs58.encode(res[0].node.multihash()).toString()
expect(mh).to.equal('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP')
expect(res[0].path).to.equal(mh)
expect(res[0].node.links).to.have.length(0)
done()
})
})

it('files.mkdir', (done) => {
apiClients.a.files.mkdir('/test-folder', function (err) {
expect(err).to.not.exist
Expand Down
Loading