UNPKG

ipfs-interop

Version:

Interoperability Tests for IPFS

178 lines (144 loc) 4.01 kB
/* eslint max-nested-callbacks: ["error", 7] */ /* eslint-env mocha */ import randomBytes from 'iso-random-stream/src/random.js' import pretty from 'pretty-bytes' import { nanoid } from 'nanoid' import isCi from 'is-ci' import concat from 'it-concat' import { expect } from 'aegir/chai' import { daemonFactory } from './utils/daemon-factory.js' import last from 'it-last' /** * @typedef {import('ipfsd-ctl').Controller} Controller * @typedef {import('ipfsd-ctl').Factory} Factory * @typedef {import('ipfsd-ctl').ControllerOptions} ControllerOptions */ /** * @param {string} dir * @param {number} depth * @param {number} numFiles */ async function * dirContent (dir, depth, numFiles) { const dirs = new Array(depth).fill(0).map(() => nanoid()) for (let i = 0; i < numFiles; i++) { const path = `${dir}/${dirs.slice(0, depth).join('/')}/${nanoid()}.txt` yield { path, content: randomBytes(5) } } } const KB = 1024 const MB = KB * 1024 // const GB = MB * 1024 const sizes = [ KB, 62 * KB, // starts failing with spdy 64 * KB, 512 * KB, 768 * KB, 1023 * KB, MB, 4 * MB, 8 * MB, 64 * MB, 128 * MB ] const dirs = [ 5, 10 ] const depth = [ 5, 10 ] const min = 60 * 1000 const timeout = isCi ? 2 * min : min /** * @type {ControllerOptions} */ const daemonOptions = { test: true, ipfsOptions: { config: { Routing: { Type: 'none' } } } } describe('exchange files', function () { this.timeout(timeout) /** @type {Record<string, ('go' | 'js')[]>} */ const tests = { 'go -> js': ['go', 'js'], 'go -> go2': ['go', 'go'], 'js -> go': ['js', 'go'], 'js -> js2': ['js', 'js'] } /** @type {Factory} */ let factory before(async () => { factory = await daemonFactory() }) Object.keys(tests).forEach((name) => { describe(name, () => { /** @type {Controller} */ let daemon1 /** @type {Controller} */ let daemon2 before('spawn nodes', async function () { [daemon1, daemon2] = await Promise.all(tests[name].map(type => factory.spawn({ ...daemonOptions, type }))) }) before('connect', async function () { this.timeout(timeout); // eslint-disable-line await daemon1.api.swarm.connect(daemon2.peer.addresses[0]) await daemon2.api.swarm.connect(daemon1.peer.addresses[0]) const [peer1, peer2] = await Promise.all([ daemon1.api.swarm.peers(), daemon2.api.swarm.peers() ]) expect(peer1.map((p) => p.peer.toString())).to.include(daemon2.peer.id.toString()) expect(peer2.map((p) => p.peer.toString())).to.include(daemon1.peer.id.toString()) }) after(() => factory.clean()) describe('cat file', () => sizes.forEach((size) => { it(`${name}: ${pretty(size)}`, async function () { const data = randomBytes(size) const { cid } = await daemon1.api.add(data) const file = await concat(daemon2.api.cat(cid)) expect(file.slice()).to.eql(data) }) })) describe('get directory', () => depth.forEach((d) => dirs.forEach((num) => { it(`${name}: depth: ${d}, num: ${num}`, async function () { const dir = `/${nanoid()}` const res = await last(daemon1.api.addAll(dirContent(dir, d, num), { wrapWithDirectory: true })) if (res == null) { throw new Error('Nothing added') } const { cid } = res await expect(countFiles(cid, daemon2.api)).to.eventually.equal(num) }) }))) }) }) }) /** * @param {import('../src/types.js').CID} cid * @param {Controller["api"]} ipfs */ async function countFiles (cid, ipfs) { let fileCount = 0 for await (const entry of ipfs.ls(cid)) { if (entry.type === 'file') { fileCount++ } else if (entry.type === 'dir') { fileCount += await countFiles(entry.cid, ipfs) } } return fileCount }