Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

test: add tests and docs for ipfs.resolve #332

Merged
merged 5 commits into from
Aug 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions SPEC/MISCELLANEOUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* [ping](#ping)
* [pingPullStream](#pingpullstream)
* [pingReadableStream](#pingreadablestream)
* [resolve](#resolve)

#### `id`

Expand Down Expand Up @@ -242,6 +243,76 @@ stream.on('data', (res) => {

A great source of [examples][] can be found in the tests for this API.

#### `resolve`

> Resolve the value of names to IPFS

There are a number of mutable name protocols that can link among themselves and into IPNS. For example IPNS references can (currently) point at an IPFS object, and DNS links can point at other DNS links, IPNS entries, or IPFS objects. This command accepts any of these identifiers and resolves them to the referenced item.

##### `Go` **WIP**

##### `JavaScript` - ipfs.resolve(name, [options], [callback])

Where:

- `name` (string): The name to resolve
- `options` is an optional object that might include the following properties:
- `recursive` (boolean, default false): Resolve until the result is an IPFS name

`callback` must follow `function (err, res) {}` signature, where `err` is an error if the operation was not successful. `res` is a string, the resolved name.

If no `callback` is passed, a promise is returned.

**Examples:**

Resolve the value of your identity:

```JavaScript
const name = '/ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy'

ipfs.resolve(name, (err, res) => {
if (err) {
throw err
}
console.log(res) // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
})
```

Resolve the value of another name recursively:

```JavaScript
const name = '/ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n'

// Where:
// /ipns/QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
// ...resolves to:
// /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
// ...which in turn resolves to:
// /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj

ipfs.resolve(name, { recursive: true }, (err, res) => {
if (err) {
throw err
}
console.log(res) // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
})
```

Resolve the value of an IPFS path:

```JavaScript
const name = '/ipfs/QmeZy1fGbwgVSrqbfh9fKQrAWgeyRnj7h8fsHS1oy3k99x/beep/boop'

ipfs.resolve(name, (err, res) => {
if (err) {
throw err
}
console.log(res) // /ipfs/QmYRMjyvAiHKN9UTi8Bzt1HUspmSRD8T8DwxfSMzLgBon1
})
```

A great source of [examples][] can be found in the tests for this API.

[examples]: https://github.com/ipfs/interface-ipfs-core/blob/master/js/src/miscellaneous
[rs]: https://www.npmjs.com/package/readable-stream
[ps]: https://www.npmjs.com/package/pull-stream
3 changes: 2 additions & 1 deletion js/src/miscellaneous/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const tests = {
id: require('./id'),
version: require('./version'),
dns: require('./dns'),
stop: require('./stop')
stop: require('./stop'),
resolve: require('./resolve')
}

module.exports = createSuite(tests)
113 changes: 113 additions & 0 deletions js/src/miscellaneous/resolve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/* eslint-env mocha */
'use strict'

const isIpfs = require('is-ipfs')
const loadFixture = require('aegir/fixtures')
const hat = require('hat')
const { getDescribe, getIt, expect } = require('../utils/mocha')

module.exports = (createCommon, options) => {
const describe = getDescribe(options)
const it = getIt(options)
const common = createCommon()

describe('.resolve', () => {
let ipfs

before(function (done) {
// 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
done()
})
})
})

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

it('should resolve an IPFS hash', (done) => {
const content = loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core')

ipfs.files.add(content, (err, res) => {
expect(err).to.not.exist()
expect(isIpfs.cid(res[0].hash)).to.be.true()

ipfs.resolve(`/ipfs/${res[0].hash}`, (err, path) => {
expect(err).to.not.exist()
expect(path).to.equal(`/ipfs/${res[0].hash}`)
done()
})
})
})

// Test resolve turns /ipfs/QmRootHash/path/to/file into /ipfs/QmFileHash
it('should resolve an IPFS path link', (done) => {
const path = '/path/to/testfile.txt'
const content = loadFixture('js/test/fixtures/testfile.txt', 'interface-ipfs-core')

ipfs.files.add([{ path, content }], { wrapWithDirectory: true }, (err, res) => {
expect(err).to.not.exist()

const rootHash = res.find(r => r.path === '').hash
const fileHash = res.find(r => r.path === path).hash

ipfs.resolve(`/ipfs/${rootHash}${path}`, (err, path) => {
expect(err).to.not.exist()
expect(path).to.equal(`/ipfs/${fileHash}`)
done()
})
})
})

it('should not resolve an IPFS path non-link', (done) => {
const content = { path: { to: { file: hat() } } }
const options = { format: 'dag-cbor', hashAlg: 'sha2-256' }

ipfs.dag.put(content, options, (err, cid) => {
expect(err).to.not.exist()

const path = `/ipfs/${cid.toBaseEncodedString()}/path/to/file`
ipfs.resolve(path, (err, path) => {
expect(err).to.exist()
expect(err.message).to.equal('found non-link at given path')
done()
})
})
})

// Test resolve turns /ipns/domain.com into /ipfs/QmHash
it('should resolve an IPNS DNS link', function (done) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This case is a bit worrisome. First we have the reliance on a remote service, secondly we're not actually checking if the output is correct.

My first thought is that in general for the ipns tests, we should have a mini-dns service running together with the tests, that the local daemon can resolve IPNS to. So instead of testing /ipns/ipfs.io we should test /ipns/local-dns-service.home which would be resolved only locally and we can then assert correct output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like that too. I have no idea how to do that or if it's even possible but I'll look into it. Do you have any pointers?

this.timeout(20 * 1000)

ipfs.resolve('/ipns/ipfs.io', (err, path) => {
expect(err).to.not.exist()
expect(isIpfs.ipfsPath(path)).to.be.true()
done()
})
})

// Test resolve turns /ipns/QmPeerHash into /ipns/domain.com into /ipfs/QmHash
it('should resolve IPNS link recursively', function (done) {
this.timeout(2 * 60 * 1000)

ipfs.name.publish('/ipns/ipfs.io', { resolve: false }, (err, res) => {
expect(err).to.not.exist()

ipfs.resolve(`/ipns/${res.name}`, { recursive: true }, (err, res) => {
expect(err).to.not.exist()
expect(res).to.not.equal('/ipns/ipfs.io')
expect(isIpfs.ipfsPath(res)).to.be.true()
done()
})
})
})
})
}