-
Notifications
You must be signed in to change notification settings - Fork 124
feat: modularise tests by command, add tools to skip and only #290
Conversation
c0afce8
to
c351f5e
Compare
This hits a lot of points that Victor and I wanted to try and look into this quarter. I really like the way this is laid out and the removal of the I would love to help take this through to competition. |
BREAKING CHANGE: Consumers of this test suite now have fine grained control over what tests are run. Tests can now be skipped and "onlyed" (run only specific tests). This can be done on a test, command and sub-system level. See the updated usage guide for instructions: https://github.com/ipfs/interface-ipfs-core/blob/master/README.md#usage. This means that tests skips depending on implementation (e.g. go/js), environment (e.g. node/browser) or platform (e.g. macOS/linux/windows) that were previously present in this suite have been removed. Consumers of this library should add their own skips based on the implementation that's being tested and the environment/platform that the tests are running on. The following other breaking changes have been made: 1. The common object passed to test suites has changed. It must now be a function that returns a common object (same shape and functions as before). 2. The `ipfs.ls` tests (not MFS `ipfs.files.ls`) is now a root level suite. You'll need to import it and use like `tests.ls(createCommon)` to have those tests run. 3. The `generic` suite (an alias to `miscellaneous`) has been removed. See #290 for more details. License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
I appreciate this is a massive PR to review, but a lot of it is mechanical changes. Please read the PR description above first (a lot of this is echoed in the changes to the README). Just to highlight how things have moved around: Each sub-system (dag, files, swarm etc.) is now a folder with an All the tests for
BREAKING CHANGE: Consumers of this test suite now have fine grained control over what tests are run. Tests can now be skipped and "onlyed" (run only specific tests). This can be done on a test, command and sub-system level. See the updated usage guide for instructions. This means that tests skips depending on implementation (e.g. go/js), environment (e.g. node/browser) or platform (e.g. macOS/linux/windows) that were previously present in this suite have been removed. Consumers of this library should add their own skips based on the implementation that's being tested and the environment/platform that the tests are running on. The following other breaking changes have been made:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a first long pass. I'll double back and take another look at a bit to refresh my eyes.
}) | ||
|
||
// This works because dag-cbor will just treat pbNode as a regular object | ||
it.skip('should not put dag-pb node with wrong multicodec', (done) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this skip
be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly, but it is currently skipped:
ipfs.dht.provide(new CID(res[0].hash), (err) => { | ||
expect(err).to.not.exist() | ||
done() | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe many of these tests will work anymore as there will never be any peers on the dht to provide too, and there isn't much of a reason to provide to self
.
The dht for go-ipfs I know will error if no peers are connected when running provides
[0]. Should this be valid, and an issue opened for go-ipfs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve run these tests against js-ipfs and js-ipfs-api (talks to go-ipfs) and they all pass, so the tests that could fail might already be skipped...I’ll check and get back to you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DHT tests are completely commented out in js-ipfs currently 😟 https://github.com/ipfs/js-ipfs/blob/master/test/core/interface/dht.js
Some tests in js-ipfs-api were already skipped, but not any provide
tests. I will investigate further...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Historically there were only a couple of DHT tests. The suite was increased with #288 which led me to found some issues with the http-api.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weirdly, these tests just started failing for me. I'll fix.
js/src/swarm/peers.js
Outdated
const it = getIt(options) | ||
const common = createCommon() | ||
|
||
describe('.swarm', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is .swarm.peers
right?
js/src/swarm/local-addrs.js
Outdated
expect(err).to.not.exist() | ||
ipfs = nodes[0] | ||
done() | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have an extra node
js/src/swarm/addrs.js
Outdated
spawnNodes(2, factory, (err, nodes) => { | ||
expect(err).to.not.exist() | ||
ipfs = nodes[0] | ||
done() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have an extra node?
Sorry for the late adding of reviewers, I realised that this is a change that'll affect you all so I'd like you to all see it and know what is going on 🚀 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to this, it's a great step towards better tests.
js/src/block/get.js
Outdated
const dirtyChai = require('dirty-chai') | ||
const multihash = require('multihashes') | ||
const CID = require('cids') | ||
const Buffer = require('safe-buffer').Buffer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for safe-buffer anymore.
js/src/bootstrap/rm.js
Outdated
const { getDescribe, getIt } = require('../utils/mocha') | ||
|
||
const expect = chai.expect | ||
chai.use(dirtyChai) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are going to get describe
and it
through a local module, better to also pick expect
from it, saving 4 lines from each module (and avoiding forgetting about it in the future).
js/src/bootstrap/rm.js
Outdated
const expect = chai.expect | ||
chai.use(dirtyChai) | ||
|
||
const invalidArg = 'this/Is/So/Invalid/' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move it inside the module.exports
module.exports = (createCommon, options) => { | ||
const describe = getDescribe(options) | ||
const it = getIt(options) | ||
const common = createCommon() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does common need to created here, if there are no options for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to create a common
object for each command now that they have been split into modules since it tracks nodes that are created so that they can be destroyed when teardown is called.
// Before:
tests.files(common)
// -> calls:
tests.files.add(common) // teardown destroys nodes created for files.add
tests.files.get(common) // teardown destroys nodes created for files.add AND files.get - ruh roh!
// etc.
// Now:
tests.files(createCommon)
// -> calls:
tests.files.add(createCommon) // teardown destroys nodes created for files.add
tests.files.get(createCommon) // teardown destroys nodes created for files.get
The alternative would be to make the common
object smarter - to remove nodes from it's nodes
array when teardown is called. However I was thinking that if we were to ever run these suites concurrently (please! one day!) then things would break.
From the PR description:
This work is backwards compatible with the previous API so no changes to dependent code needs to be made.I wanted this to be backwards compatible, but quickly ran into an issue where thecommon
object we pass to suites expects to only be used once. I started to pass it to multiple suites and theteardown
function was trying to tear down nodes that were already stopped! So, unfortunately breaking change:common
should now be a function that creates acommon
object for use with the tests. I'll submit PR's to js-ipfs (ipfs/js-ipfs#1389) and js-ipfs-api (ipfs-inactive/js-ipfs-http-client#785) to deal with this.
js/src/dag/put.js
Outdated
}, done) | ||
}) | ||
|
||
it('should not put dag-cbor node with wrong multicodec', function (done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to use function if no special timeout needs to be added.
js/src/dag/tree.js
Outdated
|
||
const chai = require('chai') | ||
const dirtyChai = require('dirty-chai') | ||
const { series, eachSeries } = require('async') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use require('async/series') as a good practice to avoid requiring the whole module into our codebase.
js/src/dht/findpeer.js
Outdated
}) | ||
}) | ||
|
||
it('should fail to find other peer if peer does not exist', function (done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If no special timeout, please use a arrow func
js/src/dht/findpeer.js
Outdated
it('should fail to find other peer if peer does not exist', function (done) { | ||
nodeA.dht.findpeer('Qmd7qZS4T7xXtsNFdRoK1trfMs5zU94EpokQ9WFtxdPxsZ', (err, peer) => { | ||
expect(err).to.not.exist() | ||
expect(peer).to.be.equal(null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick s/to.be.equal(null)/to.not.exist()
js/src/dht/findprovs.js
Outdated
const common = createCommon() | ||
|
||
describe('.dht.findprovs', function () { | ||
this.timeout(80 * 1000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the global timeout in favor of by test timeout.
It seems a really better approach! Thanks @alanshaw |
js/src/pubsub/peers.js
Outdated
], done) | ||
}) | ||
|
||
describe('.peers', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you want to drop this describe as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes! thanks :D
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
BREAKING CHANGE: Consumers of this test suite now have fine grained control over what tests are run. Tests can now be skipped and "onlyed" (run only specific tests). This can be done on a test, command and sub-system level. See the updated usage guide for instructions: https://github.com/ipfs/interface-ipfs-core/blob/master/README.md#usage. This means that tests skips depending on implementation (e.g. go/js), environment (e.g. node/browser) or platform (e.g. macOS/linux/windows) that were previously present in this suite have been removed. Consumers of this library should add their own skips based on the implementation that's being tested and the environment/platform that the tests are running on. The following other breaking changes have been made: 1. The common object passed to test suites has changed. It must now be a function that returns a common object (same shape and functions as before). 2. The `ipfs.ls` tests (not MFS `ipfs.files.ls`) is now a root level suite. You'll need to import it and use like `tests.ls(createCommon)` to have those tests run. 3. The `generic` suite (an alias to `miscellaneous`) has been removed. See #290 for more details. License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
Added originally in #308 License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
Originally from PR #267 License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
As per original PR #311 License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
0d50c67
to
7a9c4d0
Compare
I think I've addressed all the feedback now, if there's no further comments then I'll merge this in tomorrow. Thank you and much ❤️ for your time and thoughts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put it on a boat 🚢 \o/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like there is a lingering file js/src/bitswap.js
that should be removed.
License: MIT Signed-off-by: Alan Shaw <alan@tableflip.io>
This PR modularises tests by command and provides tools for consumers of this library to use skip/only on a command basis.
repo.version
andrepo.stat
are implemented butrepo.gc
is not. This allows us to import tests forrepo.version
andrepo.stat
without failing the suite but also import and skip tests forrepo.gc
for visibility until the implementation is completewithGo
goes away because we can just run the tests we want to run on any given implementationisNode
goes away because we can just run the tests we want to run on any given platformThis work is backwards compatible with the previous API so no changes to dependant code needs to be made.I wanted this to be backwards compatible, but quickly ran into an issue where thecommon
object we pass to suites expects to only be used once. I started to pass it to multiple suites and theteardown
function was trying to tear down nodes that were already stopped! So, unfortunately breaking change:common
should now be a function that creates acommon
object for use with the tests. I'll submit PR's to js-ipfs (ipfs/js-ipfs#1389) and js-ipfs-api (ipfs-inactive/js-ipfs-http-client#785) to deal with this.running tests by command
N.B. you can still run a whole sub-system suite like this:
skipping tests for a specific command
skipping specific tests
only
The idea here is that
only
can be used during development/bug fixing to run only problematic tests without having tonpm link
and find the test(s) to add.only
to.running only tests for a specific command
running only specific tests