From 38da280235991d8c52182ae630ee60f5e39c1bff Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 12 Feb 2020 13:53:49 +0000 Subject: [PATCH 1/9] chore: move pin tests from ipfs core to interface tests --- src/pin/add.js | 4 +- src/pin/index.js | 3 +- src/pin/ls.js | 52 ++-- src/pin/pins.js | 433 ++++++++++++++++++++++++++ src/pin/rm.js | 21 +- src/pin/utils.js | 11 +- test/fixtures/planets/mercury/wiki.md | 12 + test/fixtures/planets/solar-system.md | 10 + 8 files changed, 505 insertions(+), 41 deletions(-) create mode 100644 src/pin/pins.js create mode 100644 test/fixtures/planets/mercury/wiki.md create mode 100644 test/fixtures/planets/solar-system.md diff --git a/src/pin/add.js b/src/pin/add.js index 5e4cb2f3d..6c2e3559a 100644 --- a/src/pin/add.js +++ b/src/pin/add.js @@ -28,8 +28,8 @@ module.exports = (common, options) => { after(() => common.clean()) it('should add a pin', async () => { - const pinset = await ipfs.pin.add(fixtures.files[0].cid, { recursive: false }) - expect(pinset.map(p => p.cid.toString())).to.include(fixtures.files[0].cid) + const pinset = await all(ipfs.pin.add(fixtures.files[0].cid, { recursive: false })) + expect(pinset.map(p => p.cid)).to.deep.include(fixtures.files[0].cid) }) }) } diff --git a/src/pin/index.js b/src/pin/index.js index b3723d07c..ad97a96df 100644 --- a/src/pin/index.js +++ b/src/pin/index.js @@ -4,7 +4,8 @@ const { createSuite } = require('../utils/suite') const tests = { ls: require('./ls'), rm: require('./rm'), - add: require('./add') + add: require('./add'), + core: require('./pins') } module.exports = createSuite(tests) diff --git a/src/pin/ls.js b/src/pin/ls.js index ffdfe7986..1b1cdd603 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -4,6 +4,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const last = require('it-last') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -23,22 +24,21 @@ module.exports = (common, options) => { ipfs = (await common.spawn()).api // two files wrapped in directories, only root CID pinned recursively const dir = fixtures.directory.files.map((file) => ({ path: file.path, content: file.data })) - await all(ipfs.add(dir, { pin: false, cidVersion: 0 })) - await ipfs.pin.add(fixtures.directory.cid, { recursive: true }) + await last(ipfs.add(dir, { pin: false, cidVersion: 0 })) + await last(ipfs.pin.add(fixtures.directory.cid, { recursive: true })) // a file (CID pinned recursively) - await all(ipfs.add(fixtures.files[0].data, { pin: false, cidVersion: 0 })) - await ipfs.pin.add(fixtures.files[0].cid, { recursive: true }) + await last(ipfs.add(fixtures.files[0].data, { pin: false, cidVersion: 0 })) + await last(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) // a single CID (pinned directly) - await all(ipfs.add(fixtures.files[1].data, { pin: false, cidVersion: 0 })) - await ipfs.pin.add(fixtures.files[1].cid, { recursive: false }) + await last(ipfs.add(fixtures.files[1].data, { pin: false, cidVersion: 0 })) + await last(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) }) after(() => common.clean()) // 1st, because ipfs.add pins automatically it('should list all recursive pins', async () => { - const pinset = (await all(ipfs.pin.ls({ type: 'recursive' }))) - .map(p => ({ ...p, cid: p.cid.toString() })) + const pinset = await all(ipfs.pin.ls({ type: 'recursive' })) expect(pinset).to.deep.include({ type: 'recursive', @@ -51,8 +51,7 @@ module.exports = (common, options) => { }) it('should list all indirect pins', async () => { - const pinset = (await all(ipfs.pin.ls({ type: 'indirect' }))) - .map(p => ({ ...p, cid: p.cid.toString() })) + const pinset = await all(ipfs.pin.ls({ type: 'indirect' })) expect(pinset).to.not.deep.include({ type: 'recursive', @@ -77,8 +76,7 @@ module.exports = (common, options) => { }) it('should list all types of pins', async () => { - const pinset = (await all(ipfs.pin.ls())) - .map(p => ({ ...p, cid: p.cid.toString() })) + const pinset = await all(ipfs.pin.ls()) expect(pinset).to.not.be.empty() // check the three "roots" @@ -107,15 +105,19 @@ module.exports = (common, options) => { it('should list all direct pins', async () => { const pinset = await all(ipfs.pin.ls({ type: 'direct' })) expect(pinset).to.have.lengthOf(1) - expect(pinset[0].type).to.equal('direct') - expect(pinset[0].cid.toString()).to.equal(fixtures.files[1].cid) + expect(pinset).to.deep.include({ + type: 'direct', + cid: fixtures.files[1].cid + }) }) it('should list pins for a specific hash', async () => { const pinset = await all(ipfs.pin.ls(fixtures.files[0].cid)) expect(pinset).to.have.lengthOf(1) - expect(pinset[0].type).to.equal('recursive') - expect(pinset[0].cid.toString()).to.equal(fixtures.files[0].cid) + expect(pinset).to.deep.include({ + type: 'recursive', + cid: fixtures.files[0].cid + }) }) it('should throw an error on missing direct pins for existing path', () => { @@ -136,22 +138,26 @@ module.exports = (common, options) => { it('should list indirect pins for a specific path', async () => { const pinset = await all(ipfs.pin.ls(`/ipfs/${fixtures.directory.cid}/files/ipfs.txt`, { type: 'indirect' })) expect(pinset).to.have.lengthOf(1) - expect(pinset[0].type).to.equal(`indirect through ${fixtures.directory.cid}`) - expect(pinset[0].cid.toString()).to.equal(fixtures.directory.files[1].cid) + expect(pinset).to.deep.include({ + type: `indirect through ${fixtures.directory.cid}`, + cid: fixtures.directory.files[1].cid + }) }) it('should list recursive pins for a specific hash', async () => { const pinset = await all(ipfs.pin.ls(fixtures.files[0].cid, { type: 'recursive' })) expect(pinset).to.have.lengthOf(1) - expect(pinset[0].type).to.equal('recursive') - expect(pinset[0].cid.toString()).to.equal(fixtures.files[0].cid) + expect(pinset).to.deep.include({ + type: 'recursive', + cid: fixtures.files[0].cid + }) }) it('should list pins for multiple CIDs', async () => { const pinset = await all(ipfs.pin.ls([fixtures.files[0].cid, fixtures.files[1].cid])) - const cids = pinset.map(p => p.cid.toString()) - expect(cids).to.include(fixtures.files[0].cid) - expect(cids).to.include(fixtures.files[1].cid) + const cids = pinset.map(p => p.cid) + expect(cids).to.deep.include(fixtures.files[0].cid) + expect(cids).to.deep.include(fixtures.files[1].cid) }) }) } diff --git a/src/pin/pins.js b/src/pin/pins.js new file mode 100644 index 000000000..74d277d3f --- /dev/null +++ b/src/pin/pins.js @@ -0,0 +1,433 @@ +/* eslint-env mocha */ +'use strict' + +const { getDescribe, getIt, expect } = require('../utils/mocha') +const fs = require('fs') +const { + DAGNode +} = require('ipld-dag-pb') +const all = require('it-all') +const last = require('it-last') +const CID = require('cids') +const path = require('path') + +// fixture structure: +// planets/ +// solar-system.md +// mercury/ +// wiki.md +const pins = { + root: new CID('QmTAMavb995EHErSrKo7mB8dYkpaSJxu6ys1a6XJyB2sys'), + solarWiki: new CID('QmTMbkDfvHwq3Aup6Nxqn3KKw9YnoKzcZvuArAfQ9GF3QG'), + mercuryDir: new CID('QmbJCNKXJqVK8CzbjpNFz2YekHwh3CSHpBA86uqYg3sJ8q'), + mercuryWiki: new CID('QmVgSHAdMxFAuMP2JiMAYkB8pCWP1tcB9djqvq8GKAFiHi') +} +const pinTypes = { + direct: 'direct', + recursive: 'recursive', + indirect: 'indirect', + all: 'all' +} + +/** @typedef { import("ipfsd-ctl/src/factory") } Factory */ +/** + * @param {Factory} common + * @param {Object} options + */ +module.exports = (common, options) => { + const describe = getDescribe(options) + const it = getIt(options) + + describe('pin', function () { + this.timeout(50 * 1000) + + const fixtures = [ + path.resolve(path.join(__dirname, '../../test/fixtures/planets/mercury/wiki.md')), + path.resolve(path.join(__dirname, '../../test/fixtures/planets/solar-system.md')) + ].map(path => ({ + path, + content: fs.readFileSync(path) + })) + + let ipfs + + async function isPinnedWithType (path, type) { + try { + for await (const _ of ipfs.pin.ls(path, { type })) { // eslint-disable-line no-unused-vars + return true + } + return false + } catch (err) { + return false + } + } + + async function expectPinned (cid, type = pinTypes.all, pinned = true) { + if (typeof type === 'boolean') { + pinned = type + type = pinTypes.all + } + + const result = await isPinnedWithType(cid, type) + expect(result).to.eql(pinned) + } + + async function clearPins () { + for await (const { cid } of ipfs.pin.ls({ type: pinTypes.recursive })) { + await last(ipfs.pin.rm(cid)) + } + + for await (const { cid } of ipfs.pin.ls({ type: pinTypes.direct })) { + await last(ipfs.pin.rm(cid)) + } + } + + before(async () => { + ipfs = (await common.spawn()).api + await last(ipfs.add(fixtures)) + }) + + after(() => common.clean()) + + describe('pinned status', function () { + beforeEach(async () => { + await clearPins() + await last(ipfs.pin.add(pins.root)) + }) + + it('should be pinned when added', async () => { + await last(ipfs.pin.add(pins.solarWiki)) + return expectPinned(pins.solarWiki) + }) + + it('should not be pinned when not in datastore', () => { + const falseHash = `${`${pins.root}`.slice(0, -2)}ss` + return expectPinned(falseHash, false) + }) + + it('should not be pinned when in datastore but not added', async () => { + await last(ipfs.pin.rm(pins.root)) + return expectPinned(pins.root, false) + }) + + it('should be pinned recursively when added', () => { + return expectPinned(pins.root, pinTypes.recursive) + }) + + it('should be pinned indirectly', () => { + return expectPinned(pins.mercuryWiki, pinTypes.indirect) + }) + + it('should be pinned directly', async () => { + await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + return expectPinned(pins.mercuryDir, pinTypes.direct) + }) + + it('should not be pinned when not in datastore or added', async () => { + await clearPins() + return expectPinned(pins.mercuryDir, pinTypes.direct, false) + }) + }) + + describe('add', function () { + beforeEach(function () { + return clearPins() + }) + + it('should add recursively', async () => { + await last(ipfs.pin.add(pins.root)) + await expectPinned(pins.root, pinTypes.recursive) + + const pinChecks = Object.values(pins).map(hash => expectPinned(hash)) + return Promise.all(pinChecks) + }) + + it('should add directly', async () => { + await last(ipfs.pin.add(pins.root, { recursive: false })) + await Promise.all([ + expectPinned(pins.root, pinTypes.direct), + expectPinned(pins.solarWiki, false) + ]) + }) + + it('should recursively pin parent of direct pin', async () => { + await last(ipfs.pin.add(pins.solarWiki, { recursive: false })) + await last(ipfs.pin.add(pins.root)) + await Promise.all([ + // solarWiki is pinned both directly and indirectly o.O + expectPinned(pins.solarWiki, pinTypes.direct), + expectPinned(pins.solarWiki, pinTypes.indirect) + ]) + }) + + it('should fail to directly pin a recursive pin', async () => { + await last(ipfs.pin.add(pins.root)) + return expect(last(ipfs.pin.add(pins.root, { recursive: false }))) + .to.eventually.be.rejected() + .with(/already pinned recursively/) + }) + + it('should fail to pin a hash not in datastore', function () { + this.timeout(5 * 1000) + const falseHash = `${`${pins.root}`.slice(0, -2)}ss` + return expect(last(ipfs.pin.add(falseHash, { timeout: '2s' }))) + .to.eventually.be.rejected() + // TODO: http api TimeoutErrors do not have this property + //.with.a.property('code').that.equals('ERR_TIMEOUT') + }) + + // TODO block rm breaks subsequent tests + // it.skip('needs all children in datastore to pin recursively', () => { + // return ipfs.block.rm(pins.mercuryWiki) + // .then(() => expectTimeout(pin.add(pins.root), 4000)) + // }) + }) + + describe('ls', function () { + before(async () => { + await clearPins() + await last(ipfs.pin.add(pins.root)) + await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + }) + + it('should list pins of a particular CID', async () => { + const out = await all(ipfs.pin.ls(pins.mercuryDir)) + expect(out[0].cid).to.deep.equal(pins.mercuryDir) + expect(out[0].type).to.eql(pinTypes.direct) + }) + + it('should list indirect pins that supersede direct pins', async () => { + const ls = await all(ipfs.pin.ls()) + + const pinType = ls.find(out => out.cid.equals(pins.mercuryDir)).type + expect(pinType).to.eql(pinTypes.indirect) + }) + + it('should list all pins', async () => { + const out = await all(ipfs.pin.ls()) + + expect(out).to.deep.include.members([ + { + type: 'recursive', + cid: new CID(pins.root) + }, + { + type: 'indirect', + cid: new CID(pins.solarWiki) + }, + { + type: 'indirect', + cid: new CID(pins.mercuryDir) + }, + { + type: 'indirect', + cid: new CID(pins.mercuryWiki) + } + ]) + }) + + it('should list all direct pins', async () => { + const out = await all(ipfs.pin.ls({ type: 'direct' })) + + expect(out).to.deep.include.members([ + { + type: 'direct', + cid: new CID(pins.mercuryDir) + } + ]) + }) + + it('should list all recursive pins', async () => { + const out = await all(ipfs.pin.ls({ type: 'recursive' })) + + expect(out).to.deep.include.members([ + { + type: 'recursive', + cid: new CID(pins.root) + } + ]) + }) + + it('should list all indirect pins', async () => { + const out = await all(ipfs.pin.ls({ type: 'indirect' })) + + expect(out).to.deep.include.members([ + { + type: 'indirect', + cid: new CID(pins.solarWiki) + }, + { + type: 'indirect', + cid: new CID(pins.mercuryDir) + }, + { + type: 'indirect', + cid: new CID(pins.mercuryWiki) + } + ]) + }) + + it('should list direct pins for CID', async () => { + const out = await all(ipfs.pin.ls(pins.mercuryDir, { type: 'direct' })) + + expect(out).to.have.deep.members([ + { + type: 'direct', + cid: new CID(pins.mercuryDir) + } + ]) + }) + + it('should list direct pins for path', async () => { + const out = await all(ipfs.pin.ls(`/ipfs/${pins.root}/mercury/`, { type: 'direct' })) + + expect(out).to.have.deep.members([ + { + type: 'direct', + cid: new CID(pins.mercuryDir) + } + ]) + }) + + it('should list direct pins for path (no match)', () => { + return expect(all(ipfs.pin.ls(`/ipfs/${pins.root}/mercury/wiki.md`, { type: 'direct' }))) + .to.eventually.be.rejected() + }) + + it('should list direct pins for CID (no match)', () => { + return expect(all(ipfs.pin.ls(pins.root, { type: 'direct' }))) + .to.eventually.be.rejected() + }) + + it('should list recursive pins for CID', async () => { + const out = await all(ipfs.pin.ls(pins.root, { type: 'recursive' })) + + expect(out).to.have.deep.members([ + { + type: 'recursive', + cid: new CID(pins.root) + } + ]) + }) + + it('should list recursive pins for CID (no match)', () => { + return expect(all(ipfs.pin.ls(pins.mercuryDir, { type: 'recursive' }))) + .to.eventually.be.rejected() + }) + + it('should list indirect pins for CID', async () => { + const out = await all(ipfs.pin.ls(pins.solarWiki, { type: 'indirect' })) + + expect(out).to.have.deep.members([ + { + type: `indirect through ${pins.root}`, + cid: new CID(pins.solarWiki) + } + ]) + }) + + it('should list indirect pins for CID (no match)', async () => { + return expect(all(ipfs.pin.ls(pins.root, { type: 'indirect' }))) + .to.eventually.be.rejected() + }) + }) + + describe('rm', function () { + beforeEach(async () => { + await clearPins() + await last(ipfs.pin.add(pins.root)) + }) + + it('should remove a recursive pin', async () => { + await last(ipfs.pin.rm(pins.root)) + await Promise.all([ + expectPinned(pins.root, false), + expectPinned(pins.mercuryWiki, false) + ]) + }) + + it('should remove a direct pin', async () => { + await clearPins() + await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + await last(ipfs.pin.rm(pins.mercuryDir)) + await expectPinned(pins.mercuryDir, false) + }) + + it('should fail to remove an indirect pin', async () => { + await expect(last(ipfs.pin.rm(pins.solarWiki))) + .to.eventually.be.rejected() + .with(/is pinned indirectly under/) + await expectPinned(pins.solarWiki) + }) + + it('should fail when an item is not pinned', async () => { + await last(ipfs.pin.rm(pins.root)) + await expect(last(ipfs.pin.rm(pins.root))) + .to.eventually.be.rejected() + .with(/is not pinned/) + }) + }) + + describe('non-dag-pb nodes', function () { + it('should pin dag-cbor', async () => { + const cid = await ipfs.dag.put({}, { + format: 'dag-cbor', + hashAlg: 'sha2-256' + }) + + await last(ipfs.pin.add(cid)) + + const pins = await all(ipfs.pin.ls()) + + expect(pins).to.deep.include({ + type: 'recursive', + cid + }) + }) + + it('should pin raw', async () => { + const cid = await ipfs.dag.put(Buffer.alloc(0), { + format: 'raw', + hashAlg: 'sha2-256' + }) + + await last(ipfs.pin.add(cid)) + + const pins = await all(ipfs.pin.ls()) + + expect(pins).to.deep.include({ + type: 'recursive', + cid + }) + }) + + it('should pin dag-cbor with dag-pb child', async () => { + const child = await ipfs.dag.put(new DAGNode(Buffer.from(`${Math.random()}`)), { + format: 'dag-pb', + hashAlg: 'sha2-256' + }) + const parent = await ipfs.dag.put({ + child + }, { + format: 'dag-cbor', + hashAlg: 'sha2-256' + }) + + await last(ipfs.pin.add(parent, { + recursive: true + })) + + const pins = await all(ipfs.pin.ls()) + + expect(pins).to.deep.include({ + cid: parent, + type: 'recursive' + }) + expect(pins).to.deep.include({ + cid: child, + type: 'indirect' + }) + }) + }) + }) +} diff --git a/src/pin/rm.js b/src/pin/rm.js index 756538168..ae1eec430 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -4,6 +4,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') +const last = require('it-last') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -20,31 +21,31 @@ module.exports = (common, options) => { let ipfs before(async () => { ipfs = (await common.spawn()).api - await all(ipfs.add(fixtures.files[0].data, { pin: false })) - await ipfs.pin.add(fixtures.files[0].cid, { recursive: true }) - await all(ipfs.add(fixtures.files[1].data, { pin: false })) - await ipfs.pin.add(fixtures.files[1].cid, { recursive: false }) + await last(ipfs.add(fixtures.files[0].data, { pin: false })) + await last(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) + await last(ipfs.add(fixtures.files[1].data, { pin: false })) + await last(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) }) after(() => common.clean()) it('should remove a recursive pin', async () => { - const removedPinset = await ipfs.pin.rm(fixtures.files[0].cid, { recursive: true }) - expect(removedPinset.map(p => p.cid.toString())).to.deep.equal([fixtures.files[0].cid]) + const removedPinset = await all(ipfs.pin.rm(fixtures.files[0].cid, { recursive: true })) + expect(removedPinset.map(p => p.cid)).to.deep.equal([fixtures.files[0].cid]) const pinset = await all(ipfs.pin.ls({ type: 'recursive' })) - expect(pinset.map(p => ({ ...p, cid: p.cid.toString() }))).to.not.deep.include({ + expect(pinset).to.not.deep.include({ cid: fixtures.files[0].cid, type: 'recursive' }) }) it('should remove a direct pin', async () => { - const removedPinset = await ipfs.pin.rm(fixtures.files[1].cid, { recursive: false }) - expect(removedPinset.map(p => p.cid.toString())).to.deep.equal([fixtures.files[1].cid]) + const removedPinset = await all(ipfs.pin.rm(fixtures.files[1].cid, { recursive: false })) + expect(removedPinset.map(p => p.cid)).to.deep.equal([fixtures.files[1].cid]) const pinset = await all(ipfs.pin.ls({ type: 'direct' })) - expect(pinset.map(p => p.cid.toString())).to.not.include(fixtures.files[1].cid) + expect(pinset.map(p => p.cid)).to.not.deep.include(fixtures.files[1].cid) }) }) } diff --git a/src/pin/utils.js b/src/pin/utils.js index 3ee67f0d5..34b33eee6 100644 --- a/src/pin/utils.js +++ b/src/pin/utils.js @@ -1,26 +1,27 @@ 'use strict' const loadFixture = require('aegir/fixtures') +const CID = require('cids') exports.fixtures = Object.freeze({ // NOTE: files under 'directory' need to be different than standalone ones in 'files' directory: Object.freeze({ - cid: 'QmY8KdYQSYKFU5hM7F5ioZ5yYSgV5VZ1kDEdqfRL3rFgcd', + cid: new CID('QmY8KdYQSYKFU5hM7F5ioZ5yYSgV5VZ1kDEdqfRL3rFgcd'), files: Object.freeze([Object.freeze({ path: 'test-folder/ipfs-add.js', data: loadFixture('test/fixtures/test-folder/ipfs-add.js', 'interface-ipfs-core'), - cid: 'QmbKtKBrmeRHjNCwR4zAfCJdMVu6dgmwk9M9AE9pUM9RgG' + cid: new CID('QmbKtKBrmeRHjNCwR4zAfCJdMVu6dgmwk9M9AE9pUM9RgG') }), Object.freeze({ path: 'test-folder/files/ipfs.txt', data: loadFixture('test/fixtures/test-folder/files/ipfs.txt', 'interface-ipfs-core'), - cid: 'QmdFyxZXsFiP4csgfM5uPu99AvFiKH62CSPDw5TP92nr7w' + cid: new CID('QmdFyxZXsFiP4csgfM5uPu99AvFiKH62CSPDw5TP92nr7w') })]) }), files: Object.freeze([Object.freeze({ data: loadFixture('test/fixtures/testfile.txt', 'interface-ipfs-core'), - cid: 'Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP' + cid: new CID('Qma4hjFTnCasJ8PVp3mZbZK5g2vGDT4LByLJ7m8ciyRFZP') }), Object.freeze({ data: loadFixture('test/fixtures/test-folder/files/hello.txt', 'interface-ipfs-core'), - cid: 'QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu' + cid: new CID('QmY9cxiHqTFoWamkQVkpmmqzBrY3hCBEL2XNu3NtX74Fuu') })]) }) diff --git a/test/fixtures/planets/mercury/wiki.md b/test/fixtures/planets/mercury/wiki.md new file mode 100644 index 000000000..1b4039ba8 --- /dev/null +++ b/test/fixtures/planets/mercury/wiki.md @@ -0,0 +1,12 @@ +# Mercury (planet) +> From Wikipedia, the free encyclopedia + +Mercury is the smallest and innermost planet in the Solar System. Its orbital period around the Sun of 87.97 days is the shortest of all the planets in the Solar System. It is named after the Roman deity Mercury, the messenger of the gods. + +Like Venus, Mercury orbits the Sun within Earth's orbit as an inferior planet, and never exceeds 28° away from the Sun. When viewed from Earth, this proximity to the Sun means the planet can only be seen near the western or eastern horizon during the early evening or early morning. At this time it may appear as a bright star-like object, but is often far more difficult to observe than Venus. The planet telescopically displays the complete range of phases, similar to Venus and the Moon, as it moves in its inner orbit relative to Earth, which reoccurs over the so-called synodic period approximately every 116 days. + +Mercury is gravitationally locked with the Sun in a 3:2 spin-orbit resonance, and rotates in a way that is unique in the Solar System. As seen relative to the fixed stars, it rotates on its axis exactly three times for every two revolutions it makes around the Sun. As seen from the Sun, in a frame of reference that rotates with the orbital motion, it appears to rotate only once every two Mercurian years. An observer on Mercury would therefore see only one day every two years. + +Mercury's axis has the smallest tilt of any of the Solar System's planets (about ​1⁄30 degree). Its orbital eccentricity is the largest of all known planets in the Solar System; at perihelion, Mercury's distance from the Sun is only about two-thirds (or 66%) of its distance at aphelion. Mercury's surface appears heavily cratered and is similar in appearance to the Moon's, indicating that it has been geologically inactive for billions of years. Having almost no atmosphere to retain heat, it has surface temperatures that vary diurnally more than on any other planet in the Solar System, ranging from 100 K (−173 °C; −280 °F) at night to 700 K (427 °C; 800 °F) during the day across the equatorial regions. The polar regions are constantly below 180 K (−93 °C; −136 °F). The planet has no known natural satellites. + +Two spacecraft have visited Mercury: Mariner 10 flew by in 1974 and 1975; and MESSENGER, launched in 2004, orbited Mercury over 4,000 times in four years before exhausting its fuel and crashing into the planet's surface on April 30, 2015. diff --git a/test/fixtures/planets/solar-system.md b/test/fixtures/planets/solar-system.md new file mode 100644 index 000000000..f249cd3a5 --- /dev/null +++ b/test/fixtures/planets/solar-system.md @@ -0,0 +1,10 @@ +# Solar System +> From Wikipedia, the free encyclopedia + +The Solar System is the gravitationally bound system comprising the Sun and the objects that orbit it, either directly or indirectly. Of those objects that orbit the Sun directly, the largest eight are the planets, with the remainder being smaller objects, such as dwarf planets and small Solar System bodies. Of the objects that orbit the Sun indirectly, the moons, two are larger than the smallest planet, Mercury. + +The Solar System formed 4.6 billion years ago from the gravitational collapse of a giant interstellar molecular cloud. The vast majority of the system's mass is in the Sun, with the majority of the remaining mass contained in Jupiter. The four smaller inner planets, Mercury, Venus, Earth and Mars, are terrestrial planets, being primarily composed of rock and metal. The four outer planets are giant planets, being substantially more massive than the terrestrials. The two largest, Jupiter and Saturn, are gas giants, being composed mainly of hydrogen and helium; the two outermost planets, Uranus and Neptune, are ice giants, being composed mostly of substances with relatively high melting points compared with hydrogen and helium, called volatiles, such as water, ammonia and methane. All eight planets have almost circular orbits that lie within a nearly flat disc called the ecliptic. + +The Solar System also contains smaller objects. The asteroid belt, which lies between the orbits of Mars and Jupiter, mostly contains objects composed, like the terrestrial planets, of rock and metal. Beyond Neptune's orbit lie the Kuiper belt and scattered disc, which are populations of trans-Neptunian objects composed mostly of ices, and beyond them a newly discovered population of sednoids. Within these populations are several dozen to possibly tens of thousands of objects large enough that they have been rounded by their own gravity. Such objects are categorized as dwarf planets. Identified dwarf planets include the asteroid Ceres and the trans-Neptunian objects Pluto and Eris. In addition to these two regions, various other small-body populations, including comets, centaurs and interplanetary dust clouds, freely travel between regions. Six of the planets, at least four of the dwarf planets, and many of the smaller bodies are orbited by natural satellites, usually termed "moons" after the Moon. Each of the outer planets is encircled by planetary rings of dust and other small objects. + +The solar wind, a stream of charged particles flowing outwards from the Sun, creates a bubble-like region in the interstellar medium known as the heliosphere. The heliopause is the point at which pressure from the solar wind is equal to the opposing pressure of the interstellar medium; it extends out to the edge of the scattered disc. The Oort cloud, which is thought to be the source for long-period comets, may also exist at a distance roughly a thousand times further than the heliosphere. The Solar System is located in the Orion Arm, 26,000 light-years from the center of the Milky Way. From b1df075647957ae0640cab37e948ed910c5517c3 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 04:33:59 -0500 Subject: [PATCH 2/9] docs: update api docs --- SPEC/PIN.md | 30 +++++++++++++++++------------- src/pin/pins.js | 18 ++++++++++++++++-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/SPEC/PIN.md b/SPEC/PIN.md index 0958ce80b..70a108ecf 100644 --- a/SPEC/PIN.md +++ b/SPEC/PIN.md @@ -8,11 +8,11 @@ > Adds an IPFS object to the pinset and also stores it to the IPFS repo. pinset is the set of hashes currently pinned (not gc'able). -##### `ipfs.pin.add(hash, [options])` +##### `ipfs.pin.add(source, [options])` Where: -- `hash` is an IPFS multihash. +- `source` is a [CID], an array of CIDs or an (async) iterable that yields CIDs - `options` is an object that can contain the following keys - `recursive` (`boolean`) - Recursively pin the object linked. Type: bool. Default: `true` - `timeout` (`number`|`string`) - Throw an error if the request does not complete within the specified milliseconds timeout. If `timeout` is a string, the value is parsed as a [human readable duration](https://www.npmjs.com/package/parse-duration). There is no timeout by default. @@ -21,9 +21,9 @@ Where: | Type | Description | | -------- | -------- | -| `Promise<{ cid: CID }>` | An array of objects that represent the files that were pinned | +| `AsyncIterable<{ cid: CID }>` | An async iterable that yields objects containing the CIDs that were pinned | -an array of objects is returned, each of the form: +Each yielded object has the form: ```JavaScript { @@ -34,10 +34,12 @@ an array of objects is returned, each of the form: **Example:** ```JavaScript -const pinset = await ipfs.pin.add('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') -console.log(pinset) +for await (const pin of ipfs.pin.add(new CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u'))) { + console.log(pin) +} + // Logs: -// [ { cid: CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') } ] +// { cid: CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') } ``` A great source of [examples][] can be found in the tests for this API. @@ -77,10 +79,10 @@ A great source of [examples][] can be found in the tests for this API. > Remove a hash from the pinset -##### `ipfs.pin.rm(hash, [options])` +##### `ipfs.pin.rm(source, [options])` Where: -- `hash` is a multihash. +- `source` is a [CID], an array of CIDs or an (async) iterable that yields CIDs - `options` is an object that can contain the following keys - 'recursive' - Recursively unpin the object linked. Type: bool. Default: `true` @@ -88,15 +90,17 @@ Where: | Type | Description | | -------- | -------- | -| `Promise<{ cid: CID }>` | An array of unpinned objects | +| `AsyncIterable<{ cid: CID }>` | An async iterable that yields objects containing the CIDs that were unpinned | **Example:** ```JavaScript -const pinset = await ipfs.pin.rm('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') -console.log(pinset) +for await (const unpinned of ipfs.pin.rm(new CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u'))) { + console.log(unpinned) +} + // prints the hashes that were unpinned -// [ { cid: CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') } ] +// { cid: CID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u') } ``` A great source of [examples][] can be found in the tests for this API. diff --git a/src/pin/pins.js b/src/pin/pins.js index 74d277d3f..9c790f75d 100644 --- a/src/pin/pins.js +++ b/src/pin/pins.js @@ -173,7 +173,7 @@ module.exports = (common, options) => { return expect(last(ipfs.pin.add(falseHash, { timeout: '2s' }))) .to.eventually.be.rejected() // TODO: http api TimeoutErrors do not have this property - //.with.a.property('code').that.equals('ERR_TIMEOUT') + // .with.a.property('code').that.equals('ERR_TIMEOUT') }) // TODO block rm breaks subsequent tests @@ -326,7 +326,7 @@ module.exports = (common, options) => { ]) }) - it('should list indirect pins for CID (no match)', async () => { + it('should list indirect pins for CID (no match)', () => { return expect(all(ipfs.pin.ls(pins.root, { type: 'indirect' }))) .to.eventually.be.rejected() }) @@ -429,5 +429,19 @@ module.exports = (common, options) => { }) }) }) + + describe('ls', () => { + it('should throw error for invalid non-string pin type option', () => { + return expect(all(ipfs.pin.ls({ type: 6 }))) + .to.eventually.be.rejected() + .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') + }) + + it('should throw error for invalid string pin type option', () => { + return expect(all(ipfs.pin.ls({ type: '__proto__' }))) + .to.eventually.be.rejected() + .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') + }) + }) }) } From ead7f157a5524cf2a76c8ce54b1eb2918047aef9 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 04:37:22 -0500 Subject: [PATCH 3/9] fix: go-ipfs does not return error codes --- src/pin/pins.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pin/pins.js b/src/pin/pins.js index 9c790f75d..568923b71 100644 --- a/src/pin/pins.js +++ b/src/pin/pins.js @@ -434,13 +434,15 @@ module.exports = (common, options) => { it('should throw error for invalid non-string pin type option', () => { return expect(all(ipfs.pin.ls({ type: 6 }))) .to.eventually.be.rejected() - .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') + // TODO: go-ipfs does not return error codes + // .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') }) it('should throw error for invalid string pin type option', () => { return expect(all(ipfs.pin.ls({ type: '__proto__' }))) .to.eventually.be.rejected() - .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') + // TODO: go-ipfs does not return error codes + // .with.property('code').that.equals('ERR_INVALID_PIN_TYPE') }) }) }) From 51e06cd0fab11b21ceac52a7dba6b333cb95fe16 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 09:54:09 -0500 Subject: [PATCH 4/9] fix: wait for pin.add to complete before removing block --- src/block/rm.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/block/rm.js b/src/block/rm.js index 37cd17d98..a4f4b2744 100644 --- a/src/block/rm.js +++ b/src/block/rm.js @@ -4,6 +4,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const hat = require('hat') const all = require('it-all') +const last = require('it-last') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -142,9 +143,9 @@ module.exports = (common, options) => { format: 'raw', hashAlg: 'sha2-256' }) - await ipfs.pin.add(cid.toString()) + await last(ipfs.pin.add(cid)) - const result = await all(ipfs.block.rm(cid)) + const result = await last(ipfs.block.rm(cid)) expect(result).to.be.an('array').and.to.have.lengthOf(1) expect(result[0]).to.have.property('error') From 2b3d56b6490d0eb26457a42bc67aa255eb540508 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 11:20:15 -0500 Subject: [PATCH 5/9] chore: be specific about draining iterables vs last --- package.json | 1 + src/block/rm.js | 3 ++- src/name/resolve.js | 5 +++-- src/pin/ls.js | 13 +++++++------ src/pin/pins.js | 45 +++++++++++++++++++++++---------------------- src/pin/rm.js | 9 +++++---- 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 912c95a57..95c149c33 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "is-ipfs": "~0.6.1", "it-all": "^1.0.1", "it-concat": "^1.0.0", + "it-drain": "^1.0.0", "it-last": "^1.0.1", "it-pushable": "^1.3.1", "multiaddr": "^7.2.1", diff --git a/src/block/rm.js b/src/block/rm.js index a4f4b2744..bbc7b987a 100644 --- a/src/block/rm.js +++ b/src/block/rm.js @@ -5,6 +5,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const hat = require('hat') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -143,7 +144,7 @@ module.exports = (common, options) => { format: 'raw', hashAlg: 'sha2-256' }) - await last(ipfs.pin.add(cid)) + await drain(ipfs.pin.add(cid)) const result = await last(ipfs.block.rm(cid)) diff --git a/src/name/resolve.js b/src/name/resolve.js index 334e6e322..f27b71a70 100644 --- a/src/name/resolve.js +++ b/src/name/resolve.js @@ -6,6 +6,7 @@ const delay = require('delay') const CID = require('cids') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -121,7 +122,7 @@ module.exports = (common, options) => { // go only has 1 possible error https://github.com/ipfs/go-ipfs/blob/master/namesys/interface.go#L51 // so here we just expect an Error and don't match the error type to expiration try { - await last(ipfs.name.resolve(nodeId)) + await drain(ipfs.name.resolve(nodeId)) } catch (error) { expect(error).to.exist() } @@ -170,7 +171,7 @@ module.exports = (common, options) => { it('should fail to resolve /ipns/ipfs.a', async () => { try { - await last(ipfs.name.resolve('ipfs.a')) + await drain(ipfs.name.resolve('ipfs.a')) } catch (error) { expect(error).to.exist() } diff --git a/src/pin/ls.js b/src/pin/ls.js index 1b1cdd603..4d4a2dbe5 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -5,6 +5,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -24,14 +25,14 @@ module.exports = (common, options) => { ipfs = (await common.spawn()).api // two files wrapped in directories, only root CID pinned recursively const dir = fixtures.directory.files.map((file) => ({ path: file.path, content: file.data })) - await last(ipfs.add(dir, { pin: false, cidVersion: 0 })) - await last(ipfs.pin.add(fixtures.directory.cid, { recursive: true })) + await drain(ipfs.add(dir, { pin: false, cidVersion: 0 })) + await drain(ipfs.pin.add(fixtures.directory.cid, { recursive: true })) // a file (CID pinned recursively) - await last(ipfs.add(fixtures.files[0].data, { pin: false, cidVersion: 0 })) - await last(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) + await drain(ipfs.add(fixtures.files[0].data, { pin: false, cidVersion: 0 })) + await drain(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) // a single CID (pinned directly) - await last(ipfs.add(fixtures.files[1].data, { pin: false, cidVersion: 0 })) - await last(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) + await drain(ipfs.add(fixtures.files[1].data, { pin: false, cidVersion: 0 })) + await drain(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) }) after(() => common.clean()) diff --git a/src/pin/pins.js b/src/pin/pins.js index 568923b71..12c051c59 100644 --- a/src/pin/pins.js +++ b/src/pin/pins.js @@ -8,6 +8,7 @@ const { } = require('ipld-dag-pb') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') const CID = require('cids') const path = require('path') @@ -74,17 +75,17 @@ module.exports = (common, options) => { async function clearPins () { for await (const { cid } of ipfs.pin.ls({ type: pinTypes.recursive })) { - await last(ipfs.pin.rm(cid)) + await drain(ipfs.pin.rm(cid)) } for await (const { cid } of ipfs.pin.ls({ type: pinTypes.direct })) { - await last(ipfs.pin.rm(cid)) + await drain(ipfs.pin.rm(cid)) } } before(async () => { ipfs = (await common.spawn()).api - await last(ipfs.add(fixtures)) + await drain(ipfs.add(fixtures)) }) after(() => common.clean()) @@ -92,11 +93,11 @@ module.exports = (common, options) => { describe('pinned status', function () { beforeEach(async () => { await clearPins() - await last(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.root)) }) it('should be pinned when added', async () => { - await last(ipfs.pin.add(pins.solarWiki)) + await drain(ipfs.pin.add(pins.solarWiki)) return expectPinned(pins.solarWiki) }) @@ -106,7 +107,7 @@ module.exports = (common, options) => { }) it('should not be pinned when in datastore but not added', async () => { - await last(ipfs.pin.rm(pins.root)) + await drain(ipfs.pin.rm(pins.root)) return expectPinned(pins.root, false) }) @@ -119,7 +120,7 @@ module.exports = (common, options) => { }) it('should be pinned directly', async () => { - await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + await drain(ipfs.pin.add(pins.mercuryDir, { recursive: false })) return expectPinned(pins.mercuryDir, pinTypes.direct) }) @@ -135,7 +136,7 @@ module.exports = (common, options) => { }) it('should add recursively', async () => { - await last(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.root)) await expectPinned(pins.root, pinTypes.recursive) const pinChecks = Object.values(pins).map(hash => expectPinned(hash)) @@ -143,7 +144,7 @@ module.exports = (common, options) => { }) it('should add directly', async () => { - await last(ipfs.pin.add(pins.root, { recursive: false })) + await drain(ipfs.pin.add(pins.root, { recursive: false })) await Promise.all([ expectPinned(pins.root, pinTypes.direct), expectPinned(pins.solarWiki, false) @@ -151,8 +152,8 @@ module.exports = (common, options) => { }) it('should recursively pin parent of direct pin', async () => { - await last(ipfs.pin.add(pins.solarWiki, { recursive: false })) - await last(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.solarWiki, { recursive: false })) + await drain(ipfs.pin.add(pins.root)) await Promise.all([ // solarWiki is pinned both directly and indirectly o.O expectPinned(pins.solarWiki, pinTypes.direct), @@ -161,7 +162,7 @@ module.exports = (common, options) => { }) it('should fail to directly pin a recursive pin', async () => { - await last(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.root)) return expect(last(ipfs.pin.add(pins.root, { recursive: false }))) .to.eventually.be.rejected() .with(/already pinned recursively/) @@ -186,8 +187,8 @@ module.exports = (common, options) => { describe('ls', function () { before(async () => { await clearPins() - await last(ipfs.pin.add(pins.root)) - await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + await drain(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.mercuryDir, { recursive: false })) }) it('should list pins of a particular CID', async () => { @@ -335,11 +336,11 @@ module.exports = (common, options) => { describe('rm', function () { beforeEach(async () => { await clearPins() - await last(ipfs.pin.add(pins.root)) + await drain(ipfs.pin.add(pins.root)) }) it('should remove a recursive pin', async () => { - await last(ipfs.pin.rm(pins.root)) + await drain(ipfs.pin.rm(pins.root)) await Promise.all([ expectPinned(pins.root, false), expectPinned(pins.mercuryWiki, false) @@ -348,8 +349,8 @@ module.exports = (common, options) => { it('should remove a direct pin', async () => { await clearPins() - await last(ipfs.pin.add(pins.mercuryDir, { recursive: false })) - await last(ipfs.pin.rm(pins.mercuryDir)) + await drain(ipfs.pin.add(pins.mercuryDir, { recursive: false })) + await drain(ipfs.pin.rm(pins.mercuryDir)) await expectPinned(pins.mercuryDir, false) }) @@ -361,7 +362,7 @@ module.exports = (common, options) => { }) it('should fail when an item is not pinned', async () => { - await last(ipfs.pin.rm(pins.root)) + await drain(ipfs.pin.rm(pins.root)) await expect(last(ipfs.pin.rm(pins.root))) .to.eventually.be.rejected() .with(/is not pinned/) @@ -375,7 +376,7 @@ module.exports = (common, options) => { hashAlg: 'sha2-256' }) - await last(ipfs.pin.add(cid)) + await drain(ipfs.pin.add(cid)) const pins = await all(ipfs.pin.ls()) @@ -391,7 +392,7 @@ module.exports = (common, options) => { hashAlg: 'sha2-256' }) - await last(ipfs.pin.add(cid)) + await drain(ipfs.pin.add(cid)) const pins = await all(ipfs.pin.ls()) @@ -413,7 +414,7 @@ module.exports = (common, options) => { hashAlg: 'sha2-256' }) - await last(ipfs.pin.add(parent, { + await drain(ipfs.pin.add(parent, { recursive: true })) diff --git a/src/pin/rm.js b/src/pin/rm.js index ae1eec430..90153a3ab 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -5,6 +5,7 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') const last = require('it-last') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -21,10 +22,10 @@ module.exports = (common, options) => { let ipfs before(async () => { ipfs = (await common.spawn()).api - await last(ipfs.add(fixtures.files[0].data, { pin: false })) - await last(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) - await last(ipfs.add(fixtures.files[1].data, { pin: false })) - await last(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) + await drain(ipfs.add(fixtures.files[0].data, { pin: false })) + await drain(ipfs.pin.add(fixtures.files[0].cid, { recursive: true })) + await drain(ipfs.add(fixtures.files[1].data, { pin: false })) + await drain(ipfs.pin.add(fixtures.files[1].cid, { recursive: false })) }) after(() => common.clean()) From 5b15bc12c1c2ddb3276949436f31906a5e247d03 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 13:11:17 -0500 Subject: [PATCH 6/9] chore: fix linting --- src/pin/ls.js | 1 - src/pin/rm.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pin/ls.js b/src/pin/ls.js index 4d4a2dbe5..29d21f2e9 100644 --- a/src/pin/ls.js +++ b/src/pin/ls.js @@ -4,7 +4,6 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') -const last = require('it-last') const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ diff --git a/src/pin/rm.js b/src/pin/rm.js index 90153a3ab..91bc802ea 100644 --- a/src/pin/rm.js +++ b/src/pin/rm.js @@ -4,7 +4,6 @@ const { fixtures } = require('./utils') const { getDescribe, getIt, expect } = require('../utils/mocha') const all = require('it-all') -const last = require('it-last') const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ From 1a825cad26a1d49a4f51fc73ad9fc8b090880488 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 15:48:17 -0500 Subject: [PATCH 7/9] fix: fix up test as output is not an array with last --- src/block/rm.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/block/rm.js b/src/block/rm.js index bbc7b987a..ee43bdf20 100644 --- a/src/block/rm.js +++ b/src/block/rm.js @@ -148,9 +148,8 @@ module.exports = (common, options) => { const result = await last(ipfs.block.rm(cid)) - expect(result).to.be.an('array').and.to.have.lengthOf(1) - expect(result[0]).to.have.property('error') - expect(result[0].error.message).to.include('pinned') + expect(result).to.have.property('error').that.is.an('Error') + .with.property('message').that.includes('pinned') }) }) } From fa4239468d442b2f66c7805d1e89cf612d0a61b7 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 16:25:32 -0500 Subject: [PATCH 8/9] fix: drain pin.rm calls --- src/repo/gc.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/repo/gc.js b/src/repo/gc.js index da4966250..99a566a2c 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -4,6 +4,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha') const { DAGNode } = require('ipld-dag-pb') const all = require('it-all') +const drain = require('it-drain') /** @typedef { import("ipfsd-ctl/src/factory") } Factory */ /** @@ -29,8 +30,8 @@ module.exports = (common, options) => { const pinset = await all(ipfs.pin.ls()) expect(pinset.map(obj => obj.cid.toString())).includes(res[0].cid.toString()) - await ipfs.pin.rm(res[0].cid) - await all(ipfs.repo.gc()) + await drain(ipfs.pin.rm(res[0].cid)) + await drain(ipfs.repo.gc()) const finalPinset = await all(ipfs.pin.ls()) expect(finalPinset.map(obj => obj.cid.toString())).not.includes(res[0].cid.toString()) @@ -53,7 +54,7 @@ module.exports = (common, options) => { expect(refsAfterAdd.map(r => r.ref)).includes(cid.toString()) // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // Get the list of local blocks after GC, should still contain the hash, // because the file is still pinned @@ -61,7 +62,7 @@ module.exports = (common, options) => { expect(refsAfterGc.map(r => r.ref)).includes(cid.toString()) // Unpin the data - await ipfs.pin.rm(cid) + await drain(ipfs.pin.rm(cid)) // Run garbage collection await all(ipfs.repo.gc()) @@ -88,7 +89,7 @@ module.exports = (common, options) => { expect(refsAfterAdd.map(r => r.ref)).includes(hash) // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // Get the list of local blocks after GC, should still contain the hash, // because the file is in MFS @@ -99,7 +100,7 @@ module.exports = (common, options) => { await ipfs.files.rm('/test') // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // The list of local blocks should no longer contain the hash const refsAfterUnpinAndGc = await all(ipfs.refs.local()) @@ -131,7 +132,7 @@ module.exports = (common, options) => { expect(hashesAfterAdd).includes(dataCid.toString()) // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // Get the list of local blocks after GC, should still contain the hash, // because the file is pinned and in MFS @@ -143,7 +144,7 @@ module.exports = (common, options) => { await ipfs.files.rm('/test') // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // Get the list of local blocks after GC, should still contain the hash, // because the file is still pinned @@ -156,7 +157,7 @@ module.exports = (common, options) => { await ipfs.pin.rm(dataCid) // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // The list of local blocks should no longer contain the hashes const refsAfterUnpinAndGc = await all(ipfs.refs.local()) @@ -205,7 +206,7 @@ module.exports = (common, options) => { expect(pins.find(p => p.cid.toString() === dataCid.toString()).type).to.eql('indirect') // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // Get the list of local blocks after GC, should still contain the data // hash, because the data is still (indirectly) pinned @@ -213,10 +214,10 @@ module.exports = (common, options) => { expect(refsAfterGc.map(r => r.ref)).includes(dataCid.toString()) // Recursively unpin the object - await ipfs.pin.rm(objCid.toString()) + await drain(ipfs.pin.rm(objCid.toString())) // Run garbage collection - await all(ipfs.repo.gc()) + await drain(ipfs.repo.gc()) // The list of local blocks should no longer contain the hashes const refsAfterUnpinAndGc = await all(ipfs.refs.local()) From ed3f1705400f8954c24fb3078ce8194290752645 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 17 Feb 2020 17:11:42 -0500 Subject: [PATCH 9/9] fix: create fixtures in test --- src/pin/pins.js | 34 +++++++++++++++++---------- src/repo/gc.js | 6 ++--- test/fixtures/planets/mercury/wiki.md | 12 ---------- test/fixtures/planets/solar-system.md | 10 -------- 4 files changed, 25 insertions(+), 37 deletions(-) delete mode 100644 test/fixtures/planets/mercury/wiki.md delete mode 100644 test/fixtures/planets/solar-system.md diff --git a/src/pin/pins.js b/src/pin/pins.js index 12c051c59..a171d0b91 100644 --- a/src/pin/pins.js +++ b/src/pin/pins.js @@ -2,7 +2,6 @@ 'use strict' const { getDescribe, getIt, expect } = require('../utils/mocha') -const fs = require('fs') const { DAGNode } = require('ipld-dag-pb') @@ -10,19 +9,19 @@ const all = require('it-all') const last = require('it-last') const drain = require('it-drain') const CID = require('cids') -const path = require('path') // fixture structure: // planets/ // solar-system.md // mercury/ // wiki.md -const pins = { +/* const pins = { root: new CID('QmTAMavb995EHErSrKo7mB8dYkpaSJxu6ys1a6XJyB2sys'), solarWiki: new CID('QmTMbkDfvHwq3Aup6Nxqn3KKw9YnoKzcZvuArAfQ9GF3QG'), mercuryDir: new CID('QmbJCNKXJqVK8CzbjpNFz2YekHwh3CSHpBA86uqYg3sJ8q'), mercuryWiki: new CID('QmVgSHAdMxFAuMP2JiMAYkB8pCWP1tcB9djqvq8GKAFiHi') -} +} */ +let pins const pinTypes = { direct: 'direct', recursive: 'recursive', @@ -42,13 +41,13 @@ module.exports = (common, options) => { describe('pin', function () { this.timeout(50 * 1000) - const fixtures = [ - path.resolve(path.join(__dirname, '../../test/fixtures/planets/mercury/wiki.md')), - path.resolve(path.join(__dirname, '../../test/fixtures/planets/solar-system.md')) - ].map(path => ({ - path, - content: fs.readFileSync(path) - })) + const fixtures = [{ + path: 'planets/mercury/wiki.md', + content: 'solar system content' + }, { + path: 'planets/solar-system.md', + content: 'wiki content' + }] let ipfs @@ -85,7 +84,18 @@ module.exports = (common, options) => { before(async () => { ipfs = (await common.spawn()).api - await drain(ipfs.add(fixtures)) + const added = (await all(ipfs.add(fixtures))).reduce((acc, curr) => { + acc[curr.path] = curr.cid + + return acc + }, {}) + + pins = { + root: added.planets, + solarWiki: added['planets/solar-system.md'], + mercuryDir: added['planets/mercury'], + mercuryWiki: added['planets/mercury/wiki.md'] + } }) after(() => common.clean()) diff --git a/src/repo/gc.js b/src/repo/gc.js index 99a566a2c..dcf55652a 100644 --- a/src/repo/gc.js +++ b/src/repo/gc.js @@ -154,7 +154,7 @@ module.exports = (common, options) => { expect(hashesAfterRmAndGc).includes(dataCid.toString()) // Unpin the data - await ipfs.pin.rm(dataCid) + await drain(ipfs.pin.rm(dataCid)) // Run garbage collection await drain(ipfs.repo.gc()) @@ -175,7 +175,7 @@ module.exports = (common, options) => { const dataCid = addRes[0].cid // Unpin the data - await ipfs.pin.rm(dataCid) + await drain(ipfs.pin.rm(dataCid)) // Create a link to the data from an object const obj = await new DAGNode(Buffer.from('fruit'), [{ @@ -199,7 +199,7 @@ module.exports = (common, options) => { expect(hashesAfterAdd).includes(dataCid.toString()) // Recursively pin the object - await ipfs.pin.add(objCid, { recursive: true }) + await drain(ipfs.pin.add(objCid, { recursive: true })) // The data should now be indirectly pinned const pins = await all(ipfs.pin.ls()) diff --git a/test/fixtures/planets/mercury/wiki.md b/test/fixtures/planets/mercury/wiki.md deleted file mode 100644 index 1b4039ba8..000000000 --- a/test/fixtures/planets/mercury/wiki.md +++ /dev/null @@ -1,12 +0,0 @@ -# Mercury (planet) -> From Wikipedia, the free encyclopedia - -Mercury is the smallest and innermost planet in the Solar System. Its orbital period around the Sun of 87.97 days is the shortest of all the planets in the Solar System. It is named after the Roman deity Mercury, the messenger of the gods. - -Like Venus, Mercury orbits the Sun within Earth's orbit as an inferior planet, and never exceeds 28° away from the Sun. When viewed from Earth, this proximity to the Sun means the planet can only be seen near the western or eastern horizon during the early evening or early morning. At this time it may appear as a bright star-like object, but is often far more difficult to observe than Venus. The planet telescopically displays the complete range of phases, similar to Venus and the Moon, as it moves in its inner orbit relative to Earth, which reoccurs over the so-called synodic period approximately every 116 days. - -Mercury is gravitationally locked with the Sun in a 3:2 spin-orbit resonance, and rotates in a way that is unique in the Solar System. As seen relative to the fixed stars, it rotates on its axis exactly three times for every two revolutions it makes around the Sun. As seen from the Sun, in a frame of reference that rotates with the orbital motion, it appears to rotate only once every two Mercurian years. An observer on Mercury would therefore see only one day every two years. - -Mercury's axis has the smallest tilt of any of the Solar System's planets (about ​1⁄30 degree). Its orbital eccentricity is the largest of all known planets in the Solar System; at perihelion, Mercury's distance from the Sun is only about two-thirds (or 66%) of its distance at aphelion. Mercury's surface appears heavily cratered and is similar in appearance to the Moon's, indicating that it has been geologically inactive for billions of years. Having almost no atmosphere to retain heat, it has surface temperatures that vary diurnally more than on any other planet in the Solar System, ranging from 100 K (−173 °C; −280 °F) at night to 700 K (427 °C; 800 °F) during the day across the equatorial regions. The polar regions are constantly below 180 K (−93 °C; −136 °F). The planet has no known natural satellites. - -Two spacecraft have visited Mercury: Mariner 10 flew by in 1974 and 1975; and MESSENGER, launched in 2004, orbited Mercury over 4,000 times in four years before exhausting its fuel and crashing into the planet's surface on April 30, 2015. diff --git a/test/fixtures/planets/solar-system.md b/test/fixtures/planets/solar-system.md deleted file mode 100644 index f249cd3a5..000000000 --- a/test/fixtures/planets/solar-system.md +++ /dev/null @@ -1,10 +0,0 @@ -# Solar System -> From Wikipedia, the free encyclopedia - -The Solar System is the gravitationally bound system comprising the Sun and the objects that orbit it, either directly or indirectly. Of those objects that orbit the Sun directly, the largest eight are the planets, with the remainder being smaller objects, such as dwarf planets and small Solar System bodies. Of the objects that orbit the Sun indirectly, the moons, two are larger than the smallest planet, Mercury. - -The Solar System formed 4.6 billion years ago from the gravitational collapse of a giant interstellar molecular cloud. The vast majority of the system's mass is in the Sun, with the majority of the remaining mass contained in Jupiter. The four smaller inner planets, Mercury, Venus, Earth and Mars, are terrestrial planets, being primarily composed of rock and metal. The four outer planets are giant planets, being substantially more massive than the terrestrials. The two largest, Jupiter and Saturn, are gas giants, being composed mainly of hydrogen and helium; the two outermost planets, Uranus and Neptune, are ice giants, being composed mostly of substances with relatively high melting points compared with hydrogen and helium, called volatiles, such as water, ammonia and methane. All eight planets have almost circular orbits that lie within a nearly flat disc called the ecliptic. - -The Solar System also contains smaller objects. The asteroid belt, which lies between the orbits of Mars and Jupiter, mostly contains objects composed, like the terrestrial planets, of rock and metal. Beyond Neptune's orbit lie the Kuiper belt and scattered disc, which are populations of trans-Neptunian objects composed mostly of ices, and beyond them a newly discovered population of sednoids. Within these populations are several dozen to possibly tens of thousands of objects large enough that they have been rounded by their own gravity. Such objects are categorized as dwarf planets. Identified dwarf planets include the asteroid Ceres and the trans-Neptunian objects Pluto and Eris. In addition to these two regions, various other small-body populations, including comets, centaurs and interplanetary dust clouds, freely travel between regions. Six of the planets, at least four of the dwarf planets, and many of the smaller bodies are orbited by natural satellites, usually termed "moons" after the Moon. Each of the outer planets is encircled by planetary rings of dust and other small objects. - -The solar wind, a stream of charged particles flowing outwards from the Sun, creates a bubble-like region in the interstellar medium known as the heliosphere. The heliopause is the point at which pressure from the solar wind is equal to the opposing pressure of the interstellar medium; it extends out to the edge of the scattered disc. The Oort cloud, which is thought to be the source for long-period comets, may also exist at a distance roughly a thousand times further than the heliosphere. The Solar System is located in the Orion Arm, 26,000 light-years from the center of the Milky Way.