From 2000d220ddf9e6b2f72920cd207ae25a77fc3a3a Mon Sep 17 00:00:00 2001 From: David Dias Date: Wed, 11 May 2016 13:17:13 +0100 Subject: [PATCH] use object tests from interface-ipfs-core --- package.json | 8 +- src/api/object.js | 279 ++++++++++++++++++++++++++++++++++++---- test/api/object.spec.js | 242 ++-------------------------------- 3 files changed, 272 insertions(+), 257 deletions(-) diff --git a/package.json b/package.json index 8ebfdddf0..d58b86b7f 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,15 @@ "jsnext:main": "src/index.js", "dependencies": { "babel-runtime": "^6.6.1", + "bs58": "^3.0.0", "detect-node": "^2.0.3", "flatmap": "0.0.3", "glob": "^7.0.3", + "ipfs-merkle-dag": "^0.5.1", "multiaddr": "^1.3.0", "multipart-stream": "^2.0.1", "ndjson": "^1.4.3", + "promisify-es6": "^1.0.1", "qs": "^6.1.0", "wreck": "^7.0.2" }, @@ -23,9 +26,10 @@ "url": "https://github.com/ipfs/js-ipfs-api" }, "devDependencies": { + "aegir": "^3.0.2", "chai": "^3.5.0", - "aegir": "^3.0.1", "gulp": "^3.9.1", + "interface-ipfs-core": "^0.1.3", "ipfsd-ctl": "^0.13.0", "pre-commit": "^1.1.2", "raw-loader": "^0.5.1", @@ -93,4 +97,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/api/object.js b/src/api/object.js index 7aafe7749..29cf38408 100644 --- a/src/api/object.js +++ b/src/api/object.js @@ -1,33 +1,264 @@ 'use strict' -const argCommand = require('../cmd-helpers').argCommand +const DAGNode = require('ipfs-merkle-dag').DAGNode +const DAGLink = require('ipfs-merkle-dag').DAGLink +const promisify = require('promisify-es6') +const bs58 = require('bs58') +const bl = require('bl') module.exports = (send) => { - return { - get: argCommand(send, 'object/get'), - put (file, encoding, cb) { - if (typeof encoding === 'function') { - return cb(null, new Error("Must specify an object encoding ('json' or 'protobuf')")) - } - return send('object/put', encoding, null, file, cb) - }, - data: argCommand(send, 'object/data'), - links: argCommand(send, 'object/links'), - stat: argCommand(send, 'object/stat'), - new: argCommand(send, 'object/new'), + const api = { + get: promisify((multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/get', multihash, null, null, (err, result) => { + if (err) { + return callback(err) + } + + const node = new DAGNode(result.Data, result.Links.map( + (l) => { + return new DAGLink(l.Name, l.Size, new Buffer(bs58.decode(l.Hash))) + })) + + callback(null, node) + }) + }), + put: promisify((obj, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + + let tmpObj = { + Data: null, + Links: [] + } + + if (Buffer.isBuffer(obj)) { + if (!options.enc) { + tmpObj = { Data: obj.toString(), Links: [] } + } + } else if (obj.multihash) { + tmpObj = { + Data: obj.data.toString(), + Links: obj.links.map((l) => { return l.toJSON() }) + } + } else if (typeof obj === 'object') { + tmpObj.Data = obj.Data.toString() + } else { + return callback(new Error('obj not recognized')) + } + + let buf + if (Buffer.isBuffer(obj) && options.enc) { + buf = obj + } else { + buf = new Buffer(JSON.stringify(tmpObj)) + } + const enc = options.enc || 'json' + + send('object/put', enc, null, buf, (err, result) => { + if (err) { + return callback(err) + } + + if (Buffer.isBuffer(obj)) { + if (!options.enc) { + obj = { Data: obj, Links: [] } + } else { + obj = JSON.parse(obj.toString()) + } + } + let node + if (obj.multihash) { + node = obj + } else { + node = new DAGNode(obj.Data, obj.Links) + } + + if (node.toJSON().Hash !== result.Hash) { + return callback(new Error('Stored object was different from constructed object')) + } + + callback(null, node) + }) + }), + data: promisify((multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/data', multihash, null, null, (err, result) => { + if (err) { + return callback(err) + } + + result.pipe(bl(callback)) + }) + }), + links: promisify((multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/links', multihash, null, null, (err, result) => { + if (err) { + return callback(err) + } + + let links = [] + + if (result.Links) { + links = result.Links.map((l) => { + return new DAGLink(l.Name, l.Size, new Buffer(bs58.decode(l.Hash))) + }) + } + callback(null, links) + }) + }), + stat: promisify((multihash, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/stat', multihash, null, null, callback) + }), + new: promisify((callback) => { + send('object/new', null, null, null, (err, result) => { + if (err) { + return callback(err) + } + const node = new DAGNode() + + if (node.toJSON().Hash !== result.Hash) { + return callback(new Error('Stored object was different from constructed object')) + } + + callback(null, node) + }) + }), patch: { - rmLink: (root, link, cb) => { - return send('object/patch/rm-link', [root, link], null, null, cb) - }, - setData: (root, data, cb) => { - return send('object/patch/set-data', [root], null, data, cb) - }, - appendData: (root, data, cb) => { - return send('object/patch/append-data', [root], null, data, cb) - }, - addLink: (root, name, ref, cb) => { - return send('object/patch/add-link', [root, name, ref], null, null, cb) + addLink: promisify((multihash, dLink, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/patch/add-link', [multihash, dLink.name, bs58.encode(dLink.hash).toString()], null, null, (err, result) => { + if (err) { + return callback(err) + } + api.get(result.Hash, { enc: 'base58' }, callback) + }) + }), + rmLink: promisify((multihash, dLink, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/patch/rm-link', [multihash, dLink.name], null, null, (err, result) => { + if (err) { + return callback(err) + } + api.get(result.Hash, { enc: 'base58' }, callback) + }) + }), + setData: promisify((multihash, data, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/patch/set-data', [multihash], null, data, (err, result) => { + if (err) { + return callback(err) + } + api.get(result.Hash, { enc: 'base58' }, callback) + }) + }), + appendData: promisify((multihash, data, options, callback) => { + if (typeof options === 'function') { + callback = options + options = {} + } + if (!options) { + options = {} + } + multihash = cleanMultihash(multihash, options) + + send('object/patch/append-data', [multihash], null, data, (err, result) => { + if (err) { + return callback(err) + } + api.get(result.Hash, { enc: 'base58' }, callback) + }) + }) + } + } + return api +} + +function cleanMultihash (multihash, options) { + if (Buffer.isBuffer(multihash)) { + if (options.enc) { + switch (options.enc) { + case 'base58': { + multihash = multihash.toString() + break + } + default: throw new Error('invalid multihash') } + } else { + multihash = bs58.encode(multihash).toString() + } + } else if (typeof multihash === 'string') { + if (options.enc) { + // For the future, when we support more than one enc + // switch (options.enc) { + // case 'base58': // It is good + // } + } else { + throw new Error('not valid multihash') } } + return multihash } diff --git a/test/api/object.spec.js b/test/api/object.spec.js index e60f75e87..ae50909dd 100644 --- a/test/api/object.spec.js +++ b/test/api/object.spec.js @@ -1,237 +1,17 @@ /* eslint-env mocha */ /* globals apiClients */ -'use strict' - -const expect = require('chai').expect - -describe('.object', () => { - const testObject = Buffer(JSON.stringify({Data: 'testdata', Links: []})) - const testObjectHash = 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD' - const testPatchObject = Buffer(JSON.stringify({Data: 'new test data'})) - const testPatchObjectHash = 'QmWJDtdQWQSajQPx1UVAGWKaSGrHVWdjnrNhbooHP7LuF2' - - it('object.put', (done) => { - apiClients.a.object.put(testObject, 'json', (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Hash', testObjectHash) - expect(res.Links).to.be.empty - done() - }) - }) - - it('object.get', (done) => { - apiClients.a.object.get(testObjectHash, (err, res) => { - expect(err).to.not.exist - expect(res).to.have.a.property('Data', 'testdata') - expect(res.Links).to.be.empty - done() - }) - }) - - it('object.data', (done) => { - apiClients.a.object.data(testObjectHash, (err, res) => { - expect(err).to.not.exist - - let buf = '' - res - .on('error', (err) => { - expect(err).to.not.exist - }) - .on('data', (data) => { - buf += data - }) - .on('end', () => { - expect(buf).to.equal('testdata') - done() - }) - }) - }) - - it('object.stat', (done) => { - apiClients.a.object.stat(testObjectHash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD', - NumLinks: 0, - BlockSize: 10, - LinksSize: 2, - DataSize: 8, - CumulativeSize: 10 - }) - done() - }) - }) - - it('object.links', (done) => { - apiClients.a.object.links(testObjectHash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD' - }) - done() - }) - }) - - describe('object.patch', () => { - before((done) => { - apiClients.a.object.put(testPatchObject, 'json', (err, res) => { - expect(err).to.not.exist - done() - }) - }) - - it('.addLink', (done) => { - apiClients.a.object.patch - .addLink(testObjectHash, 'next', testPatchObjectHash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: 'QmZFdJ3CQsY4kkyQtjoUo8oAzsEs5BNguxBhp8sjQMpgkd' - }) - apiClients.a.object.get(res.Hash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Data: 'testdata', - Links: [{ - Name: 'next', - Hash: 'QmWJDtdQWQSajQPx1UVAGWKaSGrHVWdjnrNhbooHP7LuF2', - Size: 15 - }] - }) - done() - }) - }) - }) - - it('.rmLink', (done) => { - apiClients.a.object.patch - .rmLink('QmZFdJ3CQsY4kkyQtjoUo8oAzsEs5BNguxBhp8sjQMpgkd', 'next', (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: testObjectHash - }) - apiClients.a.object.get(res.Hash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Data: 'testdata', - Links: [] - }) - done() - }) - }) - }) - - it('.appendData', (done) => { - apiClients.a.object.patch - .appendData(testObjectHash, new Buffer(' hello'), (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: 'Qmcjhr2QztQxCAoEf8tJPTGTVkTsUrTQ36JurH14DNYNsc' - }) - apiClients.a.object.get(res.Hash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Data: 'testdata hello', - Links: [] - }) - done() - }) - }) - }) - it('.setData', (done) => { - apiClients.a.object.patch - .setData(testObjectHash, new Buffer('hello world'), (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Hash: 'QmU1Sq1B7RPQD2XcQNLB58qJUyJffVJqihcxmmN1STPMxf' - }) - apiClients.a.object.get(res.Hash, (err, res) => { - expect(err).to.not.exist - expect(res).to.be.eql({ - Data: 'hello world', - Links: [] - }) - done() - }) - }) - }) - }) - - it('object.new', (done) => { - apiClients.a.object.new('unixfs-dir', (err, res) => { - expect(err).to.not.exist - expect(res).to.deep.equal({ - Hash: 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn' - }) - done() - }) - }) - - describe('promise', () => { - it('object.put', () => { - return apiClients.a.object.put(testObject, 'json') - .then((res) => { - expect(res).to.have.a.property('Hash', testObjectHash) - expect(res.Links).to.be.empty - }) - }) - - it('object.get', () => { - return apiClients.a.object.get(testObjectHash) - .then((res) => { - expect(res).to.have.a.property('Data', 'testdata') - expect(res.Links).to.be.empty - }) - }) - - it('object.data', (done) => { - return apiClients.a.object.data(testObjectHash) - .then((res) => { - let buf = '' - res - .on('error', (err) => { - throw err - }) - .on('data', (data) => { - buf += data - }) - .on('end', () => { - expect(buf).to.equal('testdata') - done() - }) - }) - }) +'use strict' - it('object.stat', () => { - return apiClients.a.object.stat(testObjectHash) - .then((res) => { - expect(res).to.be.eql({ - Hash: 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD', - NumLinks: 0, - BlockSize: 10, - LinksSize: 2, - DataSize: 8, - CumulativeSize: 10 - }) - }) - }) +const test = require('interface-ipfs-core') - it('object.links', () => { - return apiClients.a.object.links(testObjectHash) - .then((res) => { - expect(res).to.be.eql({ - Hash: 'QmPTkMuuL6PD8L2SwTwbcs1NPg14U8mRzerB1ZrrBrkSDD' - }) - }) - }) +const common = { + setup: function (cb) { + cb(null, apiClients.a) + }, + teardown: function (cb) { + cb() + } +} - it('object.new', () => { - return apiClients.a.object.new('unixfs-dir') - .then((res) => { - expect(res).to.deep.equal({ - Hash: 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn' - }) - }) - }) - }) -}) +test.object(common)