This repository has been archived by the owner on Aug 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4bfac3c
commit 5100bd3
Showing
5 changed files
with
307 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ | |
require('./kad-dht') | ||
require('./circuit') | ||
// require('./repo') | ||
require('./mfs') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
/* eslint-env mocha */ | ||
'use strict' | ||
|
||
const chai = require('chai') | ||
const dirtyChai = require('dirty-chai') | ||
const expect = chai.expect | ||
chai.use(dirtyChai) | ||
const CID = require('cids') | ||
const crypto = require('crypto') | ||
const UnixFs = require('ipfs-unixfs') | ||
const { | ||
spawnInitAndStartGoDaemon, | ||
spawnInitAndStartJsDaemon, | ||
stopDaemon | ||
} = require('./utils/daemon') | ||
|
||
class ExpectedError extends Error { | ||
|
||
} | ||
|
||
function checkNodeTypes (daemon, file) { | ||
return daemon.api.object.get(file.hash) | ||
.then(node => { | ||
const meta = UnixFs.unmarshal(node.data) | ||
|
||
expect(meta.type).to.equal('file') | ||
expect(node.links.length).to.equal(2) | ||
|
||
return Promise.all( | ||
node.links.map(link => daemon.api.object.get(link.toJSON().multihash).then(child => { | ||
const childMeta = UnixFs.unmarshal(child.data) | ||
|
||
expect(childMeta.type).to.equal('raw') | ||
})) | ||
) | ||
}) | ||
} | ||
|
||
function addFile (daemon, data) { | ||
const fileName = 'test-file' | ||
|
||
return daemon.api.files.write(`/${fileName}`, data, { | ||
create: true | ||
}) | ||
// cannot list file directly - https:/ipfs/go-ipfs/issues/5044 | ||
.then(() => { | ||
return daemon.api.files.ls('/', { | ||
l: true | ||
}) | ||
}) | ||
.then(files => { | ||
return files.filter(file => file.name === fileName).pop() | ||
}) | ||
} | ||
|
||
const compare = (...ops) => { | ||
expect(ops.length).to.be.above(1) | ||
|
||
return Promise.all( | ||
ops | ||
) | ||
.then(results => { | ||
expect(results.length).to.equal(ops.length) | ||
|
||
const result = results.pop() | ||
|
||
results.forEach(res => expect(res).to.deep.equal(result)) | ||
}) | ||
} | ||
|
||
const compareErrors = (...ops) => { | ||
expect(ops.length).to.be.above(1) | ||
|
||
return Promise.all( | ||
// even if operations fail, their errors should be the same | ||
ops.map(op => op.then(() => { | ||
throw new ExpectedError('Expected operation to fail') | ||
}).catch(error => { | ||
if (error instanceof ExpectedError) { | ||
throw error | ||
} | ||
|
||
return { | ||
message: error.message, | ||
code: error.code | ||
} | ||
})) | ||
) | ||
.then(results => { | ||
expect(results.length).to.equal(ops.length) | ||
|
||
const result = results.pop() | ||
|
||
results.forEach(res => expect(res).to.deep.equal(result)) | ||
}) | ||
} | ||
|
||
describe.only('files', function () { | ||
this.timeout(50 * 1000) | ||
|
||
let go | ||
let js | ||
|
||
before(() => { | ||
return Promise.all([ | ||
spawnInitAndStartGoDaemon(), | ||
spawnInitAndStartJsDaemon() | ||
]) | ||
.then(([goDaemon, jsDaemon]) => { | ||
go = goDaemon | ||
js = jsDaemon | ||
}) | ||
}) | ||
|
||
after(() => { | ||
return Promise.all([ | ||
stopDaemon(go), | ||
stopDaemon(js) | ||
]) | ||
}) | ||
|
||
it('returns an error when reading non-existent files', () => { | ||
const readNonExistentFile = (daemon) => { | ||
return daemon.api.files.read(`/i-do-not-exist-${Math.random()}`) | ||
} | ||
|
||
return compareErrors( | ||
readNonExistentFile(go), | ||
readNonExistentFile(js) | ||
) | ||
}) | ||
|
||
it('uses raw nodes for leaf data', () => { | ||
const data = crypto.randomBytes(1024 * 300) | ||
const testLeavesAreRaw = (daemon) => { | ||
return addFile(daemon, data) | ||
.then(file => checkNodeTypes(daemon, file)) | ||
} | ||
|
||
return compare( | ||
testLeavesAreRaw(go), | ||
testLeavesAreRaw(js) | ||
) | ||
}) | ||
|
||
it('errors when creating the same directory twice', () => { | ||
const path = `/test-dir-${Math.random()}` | ||
|
||
return compareErrors( | ||
go.api.files.mkdir(path).then(() => go.api.files.mkdir(path)), | ||
js.api.files.mkdir(path).then(() => js.api.files.mkdir(path)) | ||
) | ||
}) | ||
|
||
it('does not error when creating the same directory twice and -p is passed', () => { | ||
const path = `/test-dir-${Math.random()}` | ||
|
||
return compare( | ||
go.api.files.mkdir(path).then(() => go.api.files.mkdir(path, {p: true})), | ||
js.api.files.mkdir(path).then(() => js.api.files.mkdir(path, {p: true})) | ||
) | ||
}) | ||
|
||
describe('has the same hashes for', () => { | ||
const testHashesAreEqual = (daemon, data) => { | ||
return daemon.api.files.add(data) | ||
.then(file => file.hash) | ||
} | ||
|
||
const _writeData = (daemon, initialData, newData, options) => { | ||
const fileName = `file-${Math.random()}.txt` | ||
|
||
return daemon.api.files.write(`/${fileName}`, initialData, { | ||
create: true | ||
}) | ||
.then(() => daemon.api.files.ls('/', { | ||
l: true | ||
})) | ||
.then(files => files.filter(file => file.name === fileName).pop().hash) | ||
} | ||
|
||
const appendData = (daemon, initialData, appendedData) => { | ||
return _writeData(daemon, initialData, appendedData, { | ||
offset: initialData.length | ||
}) | ||
} | ||
|
||
const overwriteData = (daemon, initialData, newData) => { | ||
return _writeData(daemon, initialData, newData, { | ||
offset: 0 | ||
}) | ||
} | ||
|
||
it('empty files', () => { | ||
const data = Buffer.alloc(0) | ||
|
||
return compare( | ||
testHashesAreEqual(go, data), | ||
testHashesAreEqual(js, data) | ||
) | ||
}) | ||
|
||
it('small files', () => { | ||
const data = Buffer.from([0x00, 0x01, 0x02]) | ||
|
||
return compare( | ||
testHashesAreEqual(go, data), | ||
testHashesAreEqual(js, data) | ||
) | ||
}) | ||
|
||
it('big files', () => { | ||
const data = crypto.randomBytes(1024 * 3000) | ||
|
||
return compare( | ||
testHashesAreEqual(go, data), | ||
testHashesAreEqual(js, data) | ||
) | ||
}) | ||
|
||
it('files that have had data appended', () => { | ||
const initialData = crypto.randomBytes(1024 * 300) | ||
const appendedData = crypto.randomBytes(1024 * 300) | ||
|
||
return compare( | ||
appendData(go, initialData, appendedData), | ||
appendData(js, initialData, appendedData) | ||
) | ||
}) | ||
|
||
it('files that have had data overwritten', () => { | ||
const bytes = 1024 * 300 | ||
const initialData = crypto.randomBytes(bytes) | ||
const newData = crypto.randomBytes(bytes) | ||
|
||
return compare( | ||
overwriteData(go, initialData, newData), | ||
overwriteData(js, initialData, newData) | ||
) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ require('./repo') | |
require('./exchange-files') | ||
require('./kad-dht') | ||
require('./pubsub') | ||
require('./files') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
'use strict' | ||
|
||
const os = require('os') | ||
const path = require('path') | ||
const hat = require('hat') | ||
const waterfall = require('async/waterfall') | ||
const DaemonFactory = require('ipfsd-ctl') | ||
const goDf = DaemonFactory.create() | ||
const jsDf = DaemonFactory.create({ type: 'js' }) | ||
|
||
const spawnInitAndStartDaemon = (factory) => { | ||
const dir = path.join(os.tmpdir(), hat()) | ||
let instance | ||
|
||
return new Promise((resolve, reject) => { | ||
waterfall([ | ||
(cb) => factory.spawn({ | ||
repoPath: dir, | ||
disposable: false, | ||
initOptions: { | ||
bits: 1024 | ||
} | ||
}, cb), | ||
(node, cb) => { | ||
instance = node | ||
instance.init(cb) | ||
}, | ||
(cb) => instance.start((error) => cb(error, instance)), | ||
], (error) => { | ||
if (error) { | ||
return reject(error) | ||
} | ||
|
||
resolve(instance) | ||
}) | ||
}) | ||
} | ||
|
||
const stopDaemon = (daemon) => { | ||
return new Promise((resolve, reject) => { | ||
daemon.stop((error) => { | ||
if (error) { | ||
return reject(error) | ||
} | ||
|
||
resolve() | ||
}) | ||
}) | ||
} | ||
|
||
module.exports = { | ||
spawnInitAndStartDaemon, | ||
spawnInitAndStartGoDaemon: () => spawnInitAndStartDaemon(goDf), | ||
spawnInitAndStartJsDaemon: () => spawnInitAndStartDaemon(jsDf), | ||
stopDaemon | ||
} |