Skip to content

Conversation

@jnewbery
Copy link
Contributor

@jnewbery jnewbery commented Mar 21, 2017

EDITED 2017/03/23. This PR is now ready for wider review

This PR adds the following make targets:

  • make unit_tests: runs the unit tests
  • make functional_tests: runs a small number of functional tests. Currently those tests are:
    • nodehandling - 'Test node handling'
    • httpbasics - 'Test the RPC HTTP basics'
    • invalidblockrequest - 'Test node responses to invalid blocks'
    • blockchain - 'Test RPCs related to blockchain state'
    • rpcnamedargs - 'Test using named arguments for RPCs'
      (but any feedback is welcome on whether we should change that list)
  • make all_functional_tests: runs all the functional tests, including the extended tests
  • make util_tests: runs the bitcoin-tx tests

make check is updated to run the unit_tests, functional_tests and util_tests targets.

All make test targets can be run from the root directory or the src directory.

In this implementation I've moved the functional and util targets to their own /test/Makefile.include file to separate them from the unit tests.

This is a WIP PR and shouldn't be merged yet. I've opened this to solicit feedback, particularly from @theuni , @MarcoFalke and @jtimon.

This PR does the following:

  • move the running of the 'integration' tests (currently the python functional tests and bitcoin-tx tests) from make check in /src/Makefile.test.include to make check in a new /test/Makefile.include file. Functionally, there is no difference for users running make check from the base dir, but it makes more sense to contain the integration tests in their own makefile rather then executing them from /src
  • runs a small number of functional tests as part of make check. I picked the following since they cover basic functionality and are fairly quick to run (20s when run in parallel on my PC), but I'm happy to change the list if people think we should add/remove particular tests:
    • nodehandling - 'Test node handling'
    • httpbasics - 'Test the RPC HTTP basics'
    • invalidblockrequest - 'Test node responses to invalid blocks'
    • blockchain - 'Test RPCs related to blockchain state'
    • rpcnamedargs - 'Test using named arguments for RPCs'

@jtimon - you mentioned wanting to keep separate make targets for just running the unit tests or just running the functional tests. I haven't implemented that yet, but I plan to before this PR gets merged. Are you happy with the target names make unittests and make functionaltests?

@fanquake fanquake added the Tests label Mar 21, 2017
Copy link
Member

@theuni theuni left a comment

Choose a reason for hiding this comment

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

Concept ACK.

Copy link
Member

Choose a reason for hiding this comment

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

Please enumerate the files here as before so that it remains deterministic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

Choose a reason for hiding this comment

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

I like this! But please make a var for it so that we can have obvious diffs when we add tests. Something like:

FUNCTIONAL_TESTS =
FUNCTIONAL_TESTS += nodehandling
FUNCTIONAL_TESTS += httpbasics
...
$(top_builddir)/test/functional/test_runner.py $(FUNCTIONAL_TESTS)

Going even further, as a later step, we may be able to use test_runner.py as an automake test launcher, so that each test gets parallelized as its own make job.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

Choose a reason for hiding this comment

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

I think all of these can just be (builddir), since this file is included rather than invoked recursively.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

Choose a reason for hiding this comment

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

As you mentioned in the OP, the python tests will only be run now when running 'make check' from the root dir.

I was going to suggest adding a target "check-full" or so, to run the python checks from src/, but that would effectively give us 3 levels of checking, confusion, and lots more bikeshedding.

So I think it would be wise to not differentiate what "make check" does based on your pwd. Let's call the other tests from here as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@jnewbery jnewbery changed the title [WIP] Run functional tests in make check Run functional tests in make check Mar 23, 2017
@jtimon
Copy link
Contributor

jtimon commented Mar 23, 2017

Concept ACK, this includes all the targets we discussed and more.

@jnewbery jnewbery force-pushed the reorg_makefiles branch 5 times, most recently from 4aca0a7 to a77e25a Compare March 24, 2017 19:45
@sipa
Copy link
Member

sipa commented Mar 24, 2017

@theuni Can you update your "Changes requested" review if they no longer apply?

@jnewbery
Copy link
Contributor Author

This builds locally and on travis. I'm still happy to receive input on the following:

  • are people happy with the new target names make unit_tests, make functional_tests, make all_functional_tests, make util_tests and the new behaviour of make check?
  • are people happy with the list of functional tests I've chosen?
  • this currently calls into the test_runner with multiple test cases as arguments, which runs multiple tests in parallel. I don't know whether it's better to get make to run each test as a separate job. That could be done as a later step outside this PR, but feedback here would be welcomed.

@maflcko
Copy link
Member

maflcko commented Mar 25, 2017

Shouldn't make check -j 2 pass down the number of jobs?

@jnewbery
Copy link
Contributor Author

@MarcoFalke I haven't tested. By default test_runner.py will run 4 tests in parallel, but I don't know how that compares with make starting 4 different instances of test_runner.py, each running a single test.

@maflcko
Copy link
Member

maflcko commented Mar 25, 2017

No, running several instances of test_runner is not supported. What I meant is that make check -j 2 will call ./test_runner.py --jobs 2 instead of ./test_rnner.py (--jobs 4), which is the default. (I choose 4 as the default because it was the best performing option on travis at that time)

@JeremyRubin
Copy link
Contributor

utack, I reviewed the changeset and it seems reasonable (but I don't know Make well enough to fully Ack).

@MarcoFalke -j is for the number of jobs allocated across the Make DAG traversal build process, not for sub-processes; that should be handled somehow else.

@TheBlueMatt
Copy link
Contributor

Concept ACK. I have no ability to judge whether the makefile changes are sane, but do wonder about removing the various caches in test, eg test/pycache and test/tmp, as clean should usually restore the state of the directory to what it was pre-make, afaiu.

@jnewbery
Copy link
Contributor Author

@TheBlueMatt good catch. I'd added these to the CLEANFILES variable, but that only cleans files, not directories! I've restored the previous clean-local: target now.

@fanquake
Copy link
Member

fanquake commented Apr 2, 2017

Started testing this on top of fbf36ca . Just ran make initially, then:
make unit_tests

bash-3.2$ make unit_tests
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C src unit_tests
  CC       src/tests-tests.o
  CCLD     tests
  CC       src/exhaustive_tests-tests_exhaustive.o
  CCLD     exhaustive_tests
/Applications/Xcode.app/Contents/Developer/usr/bin/make  check-TESTS
PASS: tests
PASS: exhaustive_tests
============================================================================
Testsuite summary for libsecp256k1 0.1
============================================================================
# TOTAL: 2
# PASS:  2
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================
  CXX      test/test_unitester-unitester.o
  CXXLD    test/unitester
/Applications/Xcode.app/Contents/Developer/usr/bin/make  check-TESTS
PASS: test/unitester
============================================================================
Testsuite summary for univalue 1.0.2
============================================================================
# TOTAL: 1
# PASS:  1
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================

make util_tests

bash-3.2$ make util_tests
Running test/util/bitcoin-util-test.py...
/usr/local/bin/python3.6 ./test/util/bitcoin-util-test.py

make functional_tests

bash-3.2$ make functional_tests
Running test/functional/test_runner.py...
./test/functional/test_runner.py nodehandling httpbasics invalidblockrequest blockchain rpcnamedargs
..........
invalidblockrequest.py passed, Duration: 5 s
......
blockchain.py passed, Duration: 9 s

rpcnamedargs.py passed, Duration: 4 s
......
httpbasics.py passed, Duration: 13 s
...........................
nodehandling.py passed, Duration: 27 s

TEST                   | STATUS  | DURATION

invalidblockrequest.py | Passed  | 5 s
blockchain.py          | Passed  | 9 s
rpcnamedargs.py        | Passed  | 4 s
httpbasics.py          | Passed  | 13 s
nodehandling.py        | Passed  | 27 s

ALL                    | True    | 58 s (accumulated)

Runtime: 27 s

make all_functional_tests

bash-3.2$ make all_functional_tests
Running all functional tests
./test/functional/test_runner.py --extended
.........................................................................................................................................................................................................................................................................................................................................................
fundrawtransaction.py passed, Duration: 173 s
.....................................................................................................................................................................................................................
p2p-compactblocks.py passed, Duration: 107 s
.....................................................................................................
walletbackup.py passed, Duration: 332 s
.........................................................................
segwit.py passed, Duration: 88 s
..................................................................................................
wallet-accounts.py passed, Duration: 50 s
.............................................................................................
wallet.py passed, Duration: 134 s
....................................................................................
wallet-hd.py passed, Duration: 510 s
................................
p2p-segwit.py passed, Duration: 107 s

... snip ... 

Makefile.am Outdated
Copy link
Member

@fanquake fanquake Apr 2, 2017

Choose a reason for hiding this comment

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

Should functional/test_framework/__pycache__ and util/__pycache__ be included here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I think you're right. Thanks.

@jnewbery
Copy link
Contributor Author

jnewbery commented Apr 3, 2017

nits addressed and commits squashed

@fanquake
Copy link
Member

fanquake commented Apr 4, 2017

Both linux builds failed with:

Traceback (most recent call last):
  File "test/functional/test_runner.py", line 435, in <module>
    main()
  File "test/functional/test_runner.py", line 231, in main
    run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args)
  File "test/functional/test_runner.py", line 270, in run_tests
    (name, stdout, stderr, status, duration) = job_queue.get_next()
  File "test/functional/test_runner.py", line 329, in get_next
    stderr=log_stderr),
  File "/usr/lib/python3.4/subprocess.py", line 859, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.4/subprocess.py", line 1457, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: '/home/travis/build/bitcoin/bitcoin/build/bitcoin-i686-pc-linux-gnu/test/functional/net.py'

@ryanofsky
Copy link
Contributor

There are a lot of targets to keep track of here. It would be nice at some point to add a make help rule that would describe common targets you expect people will want to run.

@jnewbery
Copy link
Contributor Author

jnewbery commented Apr 4, 2017

thanks @fanquake . This was a bad merge that github wasn't warning about. Hopefully should work now that I've rebased.

@theuni
Copy link
Member

theuni commented Apr 13, 2017

As travis runs "make check" as well as the functional tests, I believe it will be running some of these twice now? If so, I'm afraid we'll need yet another target that means either check+all_functional_tests, or check - functional_tests.

@jnewbery
Copy link
Contributor Author

@theuni I really don't want to add yet another make target. As @ryanofsky has pointed out there are already too many to reasonably keep track of. Ideally the functional tests run by make check should be so fast that it doesn't matter that travis is running them twice.

Thinking about this a little bit more, I think it might make sense to have a new basic_tests.py functional test script specifically for this purpose. There are a few requirements:

  • it should be fast. Ideally < 1 second for the script and < 5 seconds including set up and tear down.
  • it shouldn't start more than one instance of bitcoind, so there are no issues running it on a low-powered machine
  • it should cover mainline basic functionality (RPCs, P2P, tx/block validation & propogation)

I chose invalidblockrequest.py, blockchain.py, rpcnamedargs.py, httpbasics.py and nodehandling.py initially since they provided a fairly good cover of basic functionality. If instead of those, we ran a more targeted basic_tests script, we could probably have better test coverage with a lower run time.

Thoughts?

@maflcko
Copy link
Member

maflcko commented Apr 17, 2017

So the basic test is a single test script with excerpts taken from the other test scripts, and is exclusively run by make check?

An alternative would be to unfiddle the make check on travis into make unit_tests && make util_tests.

@jnewbery
Copy link
Contributor Author

So the basic test is a single test script with excerpts taken from the other test scripts, and is exclusively run by make check?

That's basically the idea, yes. Not exactly copy-and-pasted from those other tests, but modified slightly to ensure good functional coverage, fast execution, and low resource demands.

blockchain \
rpcnamedargs

.PHONY: all_functional_tests functional_tests util_tests
Copy link
Contributor

Choose a reason for hiding this comment

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

why these targets need to be here in the new file instead of alongside unit_tests and check-local?
It seems nice for EXTRA_DIST and FUNCTIONAL_TESTS, but that's it IMO.

@jtimon
Copy link
Contributor

jtimon commented Apr 18, 2017

As travis runs "make check" as well as the functional tests, I believe it will be running some of these twice now? If so, I'm afraid we'll need yet another target that means either check+all_functional_tests, or check - functional_tests.

What about just excluding the tests in FUNCTIONAL_TESTS for travis? We have the exclude option now, it seems we just need a file that both the makefile and travis can read to put FUNCTIONAL_TESTS in. Wouldn't test/Makefile.include do it directly if some of the things were left out?

@sipa
Copy link
Member

sipa commented May 5, 2017

What is needed here to fix Travis?

@jnewbery
Copy link
Contributor Author

jnewbery commented May 5, 2017

This PR breaks whenever functional tests are added/renamed. In this instance nodehandling.py was renamed disconnect_ban.py. I haven't fixed it because there didn't seem to be much general interest in reviewing or providing concept feedback so I've been focusing on other things.

@TheBlueMatt
Copy link
Contributor

I think we should be happy to let make check go for 10/30 minutes, we wouldnt be the only project to do so, and its good to get test coverage during package building (which, really, is the largest make check user). My vote would be for moving all the test running into make, then we also dont have the double-file-listing of alll the tests in the makefile and in the test_runner.

@jnewbery
Copy link
Contributor Author

jnewbery commented May 9, 2017

@TheBlueMatt - I'm not sure that we should run all the test in make. Some of them have quite high memory/CPU/disk requirements - for example pruning.py runs 6 nodes concurrently and uses > 4GiB of disk space. We don't want make check to fail for users with lower powered systems.

I also don't think this resolves the double-file-listing issue. The functional tests need to be listed in EXTRA_DIST in the make file to be included in a distdir.

@TheBlueMatt
Copy link
Contributor

@jnewbery indeed, I meant that we should avoid the travis issue by putting everything that normally runs in travis in make check, essentially. if we then had a second make target (extended-tests), we could drop test_runner.py and then we dont need to double-list anything :).

@jnewbery
Copy link
Contributor Author

jnewbery commented May 9, 2017

test_runner is doing more than you think. For one, we can't run multiple tests in parallel without providing a different port seed to each (otherwise they'll fight over ports). There are various other checks and nice things (such as logging) that it does. I don't think we can remove it and rely on make.

@sipa
Copy link
Member

sipa commented May 9, 2017

Why not just invoke test_runner.py in Travis/make check, then? test_runner already distinguishes between normal and extended tests.

@jnewbery
Copy link
Contributor Author

Why not just invoke test_runner.py in Travis/make check, then? test_runner already distinguishes between normal and extended tests.

Because I don't want make check to become impossible or unusably slow for people running on constrained hardware. There are tests in the normal tests which fire up multiple versions of bitcoind or create long blockchains. Systems with limited memory could easily end up paging heavily or running out of memory. My understanding is that anyone building bitcoind locally, even on their raspberry pi, should be able to run make check to verify their build.

test_runner.py also controls how many tests are run in parallel. If we change the default from 4 down to 1, it may make it easier to run on more limited systems, at the cost of making make check take even longer.

@jnewbery jnewbery changed the title Run functional tests in make check [tests] [build] Run functional tests in make check Jun 30, 2017
@jnewbery
Copy link
Contributor Author

Closing for now. I'll pick this up again at some point

@jnewbery jnewbery closed this Sep 14, 2017
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants