Skip to content

Commit

Permalink
refactor: tests of addFromURL in browsers (ipfs#514)
Browse files Browse the repository at this point in the history
> Required by ipfs#2304

Old version of `addFromURL` tests was Node-centric and did not work in web browser contexts.

This PR:

- moves the HTTP server to a separate file to enable spawning it from
  aegir hook (see .aegir.js/hooks/browser/pre|post in js-ipfs from ipfs#2304)
- simplifies the way we use HTTP Echo Server by moving it to aegir
hooks and removing HTTPS version
    - ipfs-inactive/interface-js-ipfs-core#514 (comment)
- removes  overhead of starting and stopping HTTP servers multiple times
- shortens/simplifies test code a bit

License: MIT
Signed-off-by: Marcin Rataj <lidel@lidel.org>
  • Loading branch information
lidel authored and Alan Shaw committed Sep 5, 2019
1 parent 56caa89 commit 524a110
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 231 deletions.
285 changes: 58 additions & 227 deletions src/files-regular/add-from-url.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/* eslint-env mocha */
'use strict'

const { fixtures } = require('./utils')
const { getDescribe, getIt, expect } = require('../utils/mocha')
const http = require('http')
const https = require('https')
const each = require('async/each')
const waterfall = require('async/waterfall')
const parallel = require('async/parallel')
const { echoUrl, redirectUrl } = require('../utils/echo-http-server')

module.exports = (createCommon, options) => {
const describe = getDescribe(options)
Expand All @@ -23,10 +19,8 @@ module.exports = (createCommon, options) => {
// CI takes longer to instantiate the daemon, so we need to increase the
// timeout for the before step
this.timeout(60 * 1000)

common.setup((err, factory) => {
expect(err).to.not.exist()

factory.spawnNode((err, node) => {
expect(err).to.not.exist()
ipfs = node
Expand All @@ -37,260 +31,97 @@ module.exports = (createCommon, options) => {

after((done) => common.teardown(done))

let testServers = []

const sslOpts = fixtures.sslOpts

const startTestServer = (handler, opts, cb) => {
if (typeof opts === 'function') {
cb = opts
opts = {}
}

const server = opts.secure
? https.createServer(sslOpts, handler)
: http.createServer(handler)

server.listen((err) => {
if (err) return cb(err)
testServers.push(server)
cb(null, server)
})
}

beforeEach(() => {
// Instructs node to not reject our snake oil SSL certificate when it
// can't verify the certificate authority
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0
})

afterEach((done) => {
// Reinstate unauthorised SSL cert rejection
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 1

each(testServers, (server, cb) => server.close(cb), (err) => {
testServers = []
done(err)
})
})

it('should add from a HTTP URL', (done) => {
const data = Buffer.from(`TEST${Date.now()}`)

const text = `TEST${Date.now()}`
const url = echoUrl(text)
parallel({
server: (cb) => {
const handler = (req, res) => {
res.write(data)
res.end()
}
startTestServer(handler, cb)
},
expectedResult: (cb) => ipfs.add(data, cb)
}, (err, taskResult) => {
result: (cb) => ipfs.addFromURL(url, cb),
expectedResult: (cb) => ipfs.add(Buffer.from(text), cb)
}, (err, { result, expectedResult }) => {
expect(err).to.not.exist()
const { server, expectedResult } = taskResult

const url = `http://127.0.0.1:${server.address().port}/`
ipfs.addFromURL(url, (err, result) => {
expect(err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
})
})

it('should add from a HTTPS URL', (done) => {
const data = Buffer.from(`TEST${Date.now()}`)

parallel({
server: (cb) => {
const handler = (req, res) => {
res.write(data)
res.end()
}
startTestServer(handler, { secure: true }, cb)
},
expectedResult: (cb) => ipfs.add(data, cb)
}, (err, taskResult) => {
expect(err).to.not.exist()
const { server, expectedResult } = taskResult

const url = `https://127.0.0.1:${server.address().port}/`
ipfs.addFromURL(url, (err, result) => {
expect(err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
expect(result.err).to.not.exist()
expect(expectedResult.err).to.not.exist()
expect(result[0].hash).to.equal(expectedResult[0].hash)
expect(result[0].size).to.equal(expectedResult[0].size)
expect(result[0].path).to.equal(text)
done()
})
})

it('should add from a HTTP URL with redirection', (done) => {
const data = Buffer.from(`TEST${Date.now()}`)

waterfall([
(cb) => {
const handler = (req, res) => {
res.write(data)
res.end()
}
startTestServer(handler, cb)
},
(serverA, cb) => {
const url = `http://127.0.0.1:${serverA.address().port}`
const handler = (req, res) => {
res.statusCode = 302
res.setHeader('Location', url)
res.end()
}
startTestServer(handler, (err, serverB) => {
if (err) return cb(err)
cb(null, { a: serverA, b: serverB })
})
}
], (err, servers) => {
expect(err).to.not.exist()

ipfs.add(data, (err, res) => {
expect(err).to.not.exist()

const expectedHash = res[0].hash
const url = `http://127.0.0.1:${servers.b.address().port}`
const text = `TEST${Date.now()}`
const url = echoUrl(text) + '?foo=bar#buzz'

ipfs.addFromURL(url, (err, result) => {
expect(err).to.not.exist()
expect(result[0].hash).to.equal(expectedHash)
done()
})
})
})
})

it('should add from a HTTPS URL with redirection', (done) => {
const data = Buffer.from(`TEST${Date.now()}`)

waterfall([
(cb) => {
const handler = (req, res) => {
res.write(data)
res.end()
}
startTestServer(handler, { secure: true }, cb)
},
(serverA, cb) => {
const url = `https://127.0.0.1:${serverA.address().port}`
const handler = (req, res) => {
res.statusCode = 302
res.setHeader('Location', url)
res.end()
}
startTestServer(handler, { secure: true }, (err, serverB) => {
if (err) return cb(err)
cb(null, { a: serverA, b: serverB })
})
}
], (err, servers) => {
parallel({
result: (cb) => ipfs.addFromURL(redirectUrl(url), cb),
expectedResult: (cb) => ipfs.add(Buffer.from(text), cb)
}, (err, { result, expectedResult }) => {
expect(err).to.not.exist()

ipfs.add(data, (err, res) => {
expect(err).to.not.exist()

const expectedHash = res[0].hash
const url = `https://127.0.0.1:${servers.b.address().port}`

ipfs.addFromURL(url, (err, result) => {
expect(err).to.not.exist()
expect(result[0].hash).to.equal(expectedHash)
done()
})
})
expect(result.err).to.not.exist()
expect(expectedResult.err).to.not.exist()
expect(result[0].hash).to.equal(expectedResult[0].hash)
expect(result[0].size).to.equal(expectedResult[0].size)
expect(result[0].path).to.equal(text)
done()
})
})

it('should add from a URL with only-hash=true', (done) => {
const handler = (req, res) => {
res.write(`TEST${Date.now()}`)
res.end()
}

startTestServer(handler, (err, server) => {
const text = `TEST${Date.now()}`
const url = echoUrl(text)
ipfs.addFromURL(url, { onlyHash: true }, (err, res) => {
expect(err).to.not.exist()

const url = `http://127.0.0.1:${server.address().port}/`

ipfs.addFromURL(url, { onlyHash: true }, (err, res) => {
expect(err).to.not.exist()

// A successful object.get for this size data took my laptop ~14ms
let didTimeout = false
const timeoutId = setTimeout(() => {
didTimeout = true
done()
}, 500)
// A successful object.get for this size data took my laptop ~14ms
let didTimeout = false
const timeoutId = setTimeout(() => {
didTimeout = true
done()
}, 500)

ipfs.object.get(res[0].hash, () => {
clearTimeout(timeoutId)
if (didTimeout) return
expect(new Error('did not timeout')).to.not.exist()
})
ipfs.object.get(res[0].hash, () => {
clearTimeout(timeoutId)
if (didTimeout) return
expect(new Error('did not timeout')).to.not.exist()
})
})
})

it('should add from a URL with wrap-with-directory=true', (done) => {
const filename = `TEST${Date.now()}.txt`
const data = Buffer.from(`TEST${Date.now()}`)

const filename = `TEST${Date.now()}.txt` // also acts as data
const url = echoUrl(filename) + '?foo=bar#buzz'
const addOpts = { wrapWithDirectory: true }
parallel({
server: (cb) => startTestServer((req, res) => {
res.write(data)
res.end()
}, cb),
expectedResult: (cb) => {
ipfs.add([{ path: filename, content: data }], { wrapWithDirectory: true }, cb)
}
}, (err, taskResult) => {
result: (cb) => ipfs.addFromURL(url, addOpts, cb),
expectedResult: (cb) => ipfs.add([{ path: filename, content: Buffer.from(filename) }], addOpts, cb)
}, (err, { result, expectedResult }) => {
expect(err).to.not.exist()

const { server, expectedResult } = taskResult
const url = `http://127.0.0.1:${server.address().port}/${filename}?foo=bar#buzz`

ipfs.addFromURL(url, { wrapWithDirectory: true }, (err, result) => {
expect(err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
expect(result.err).to.not.exist()
expect(expectedResult.err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
})

it('should add from a URL with wrap-with-directory=true and URL-escaped file name', (done) => {
const filename = '320px-Domažlice,_Jiráskova_43_(9102).jpg'
const data = Buffer.from(`TEST${Date.now()}`)

const filename = `320px-Domažlice,_Jiráskova_43_(${Date.now()}).jpg` // also acts as data
const url = echoUrl(filename) + '?foo=bar#buzz'
const addOpts = { wrapWithDirectory: true }
parallel({
server: (cb) => startTestServer((req, res) => {
res.write(data)
res.end()
}, cb),
expectedResult: (cb) => {
ipfs.add([{ path: filename, content: data }], { wrapWithDirectory: true }, cb)
}
}, (err, taskResult) => {
result: (cb) => ipfs.addFromURL(url, addOpts, cb),
expectedResult: (cb) => ipfs.add([{ path: filename, content: Buffer.from(filename) }], addOpts, cb)
}, (err, { result, expectedResult }) => {
expect(err).to.not.exist()

const { server, expectedResult } = taskResult
const url = `http://127.0.0.1:${server.address().port}/${encodeURIComponent(filename)}?foo=bar#buzz`

ipfs.addFromURL(url, { wrapWithDirectory: true }, (err, result) => {
expect(err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
expect(result.err).to.not.exist()
expect(expectedResult.err).to.not.exist()
expect(result).to.deep.equal(expectedResult)
done()
})
})

it('should not add from an invalid url', (done) => {
ipfs.addFromURL('http://invalid', (err, result) => {
expect(err.code).to.equal('ENOTFOUND')
expect(err).to.exist()
expect(result).to.not.exist()
done()
})
Expand Down
4 changes: 0 additions & 4 deletions src/files-regular/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,5 @@ exports.fixtures = Object.freeze({
bigFile: Object.freeze({
cid: 'Qme79tX2bViL26vNjPsF3DP1R9rMKMvnPYJiKTTKPrXJjq',
data: loadFixture('test/fixtures/15mb.random', 'interface-ipfs-core')
}),
sslOpts: Object.freeze({
key: loadFixture('test/fixtures/ssl/privkey.pem', 'interface-ipfs-core'),
cert: loadFixture('test/fixtures/ssl/cert.pem', 'interface-ipfs-core')
})
})
Loading

0 comments on commit 524a110

Please sign in to comment.