diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/README.md | 29 | ||||
-rwxr-xr-x | test/functional/feature_config_args.py | 10 | ||||
-rwxr-xr-x | test/functional/feature_filelock.py | 36 | ||||
-rwxr-xr-x | test/functional/feature_notifications.py | 47 | ||||
-rwxr-xr-x | test/functional/feature_uacomment.py | 2 | ||||
-rwxr-xr-x | test/functional/interface_bitcoin_cli.py | 34 | ||||
-rwxr-xr-x | test/functional/interface_zmq.py | 40 | ||||
-rwxr-xr-x | test/functional/rpc_deprecated.py | 12 | ||||
-rwxr-xr-x | test/functional/rpc_scantxoutset.py | 4 | ||||
-rwxr-xr-x | test/functional/rpc_zmq.py | 37 | ||||
-rw-r--r-- | test/functional/test_framework/address.py | 3 | ||||
-rwxr-xr-x | test/functional/test_framework/mininode.py | 4 | ||||
-rwxr-xr-x | test/functional/test_framework/test_node.py | 23 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 2 | ||||
-rwxr-xr-x | test/functional/wallet_basic.py | 5 | ||||
-rwxr-xr-x | test/functional/wallet_keypool.py | 9 | ||||
-rwxr-xr-x | test/functional/wallet_labels.py | 9 | ||||
-rwxr-xr-x | test/functional/wallet_multiwallet.py | 16 | ||||
-rwxr-xr-x | test/lint/lint-python.sh | 2 | ||||
-rw-r--r-- | test/lint/lint-spelling.ignore-words.txt | 1 | ||||
-rwxr-xr-x | test/lint/lint-spelling.sh | 3 |
21 files changed, 203 insertions, 125 deletions
diff --git a/test/README.md b/test/README.md index a5ba732bc0..680f9bf9a6 100644 --- a/test/README.md +++ b/test/README.md @@ -3,17 +3,18 @@ utilities in their entirety. It does not contain unit tests, which can be found in [/src/test](/src/test), [/src/wallet/test](/src/wallet/test), etc. -There are currently two sets of tests in this directory: +This directory contains the following sets of tests: - [functional](/test/functional) which test the functionality of bitcoind and bitcoin-qt by interacting with them through the RPC and P2P interfaces. - [util](/test/util) which tests the bitcoin utilities, currently only bitcoin-tx. +- [lint](/test/lint/) which perform various static analysis checks. The util tests are run as part of `make check` target. The functional -tests are run by the travis continuous build process whenever a pull -request is opened. Both sets of tests can also be run locally. +tests and lint scripts are run by the travis continuous build process whenever a pull +request is opened. All sets of tests can also be run locally. # Running tests locally @@ -30,7 +31,7 @@ The ZMQ functional test requires a python ZMQ library. To install it: #### Running the tests -Individual tests can be run by directly calling the test script, eg: +Individual tests can be run by directly calling the test script, e.g.: ``` test/functional/feature_rbf.py @@ -180,6 +181,26 @@ Note: gdb attach step may require `sudo` Util tests can be run locally by running `test/util/bitcoin-util-test.py`. Use the `-v` option for verbose output. +### Lint tests + +#### Dependencies + +The lint tests require codespell and flake8. To install: `pip3 install codespell flake8`. + +#### Running the tests + +Individual tests can be run by directly calling the test script, e.g.: + +``` +test/lint/lint-filenames.sh +``` + +You can run all the shell-based lint tests by running: + +``` +test/lint/lint-all.sh +``` + # Writing functional tests You are encouraged to write functional tests for new or existing features. diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py index 1124119e2b..492772d5e3 100755 --- a/test/functional/feature_config_args.py +++ b/test/functional/feature_config_args.py @@ -14,9 +14,6 @@ class ConfArgsTest(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() - def test_config_file_parser(self): # Assume node is stopped @@ -68,13 +65,18 @@ class ConfArgsTest(BitcoinTestFramework): # Temporarily disabled, because this test would access the user's home dir (~/.bitcoin) #self.start_node(0, ['-conf='+conf_file, '-wallet=w1']) #self.stop_node(0) + #assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'blocks')) + #if self.is_wallet_compiled(): #assert os.path.exists(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1')) # Ensure command line argument overrides datadir in conf os.mkdir(new_data_dir_2) self.nodes[0].datadir = new_data_dir_2 self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2']) - assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2')) + assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'blocks')) + if self.is_wallet_compiled(): + assert os.path.exists(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2')) + if __name__ == '__main__': ConfArgsTest().main() diff --git a/test/functional/feature_filelock.py b/test/functional/feature_filelock.py new file mode 100755 index 0000000000..9fb0d35a68 --- /dev/null +++ b/test/functional/feature_filelock.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# Copyright (c) 2018 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Check that it's not possible to start a second bitcoind instance using the same datadir or wallet.""" +import os + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.test_node import ErrorMatch + +class FilelockTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 2 + + def setup_network(self): + self.add_nodes(self.num_nodes, extra_args=None) + self.nodes[0].start([]) + self.nodes[0].wait_for_rpc_connection() + + def run_test(self): + datadir = os.path.join(self.nodes[0].datadir, 'regtest') + self.log.info("Using datadir {}".format(datadir)) + + self.log.info("Check that we can't start a second bitcoind instance using the same datadir") + expected_msg = "Error: Cannot obtain a lock on data directory {}. Bitcoin Core is probably already running.".format(datadir) + self.nodes[1].assert_start_raises_init_error(extra_args=['-datadir={}'.format(self.nodes[0].datadir), '-noserver'], expected_msg=expected_msg) + + if self.is_wallet_compiled(): + wallet_dir = os.path.join(datadir, 'wallets') + self.log.info("Check that we can't start a second bitcoind instance using the same wallet") + expected_msg = "Error: Error initializing wallet database environment" + self.nodes[1].assert_start_raises_init_error(extra_args=['-walletdir={}'.format(wallet_dir), '-noserver'], expected_msg=expected_msg, match=ErrorMatch.PARTIAL_REGEX) + +if __name__ == '__main__': + FilelockTest().main() diff --git a/test/functional/feature_notifications.py b/test/functional/feature_notifications.py index a93443f2db..d8083b2840 100755 --- a/test/functional/feature_notifications.py +++ b/test/functional/feature_notifications.py @@ -5,17 +5,16 @@ """Test the -alertnotify, -blocknotify and -walletnotify options.""" import os +from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, wait_until, connect_nodes_bi + class NotificationsTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() - def setup_network(self): self.alertnotify_dir = os.path.join(self.options.tmpdir, "alertnotify") self.blocknotify_dir = os.path.join(self.options.tmpdir, "blocknotify") @@ -25,7 +24,7 @@ class NotificationsTest(BitcoinTestFramework): os.mkdir(self.walletnotify_dir) # -alertnotify and -blocknotify on node0, walletnotify on node1 - self.extra_args = [["-blockversion=2", + self.extra_args = [[ "-alertnotify=echo > {}".format(os.path.join(self.alertnotify_dir, '%s')), "-blocknotify=echo > {}".format(os.path.join(self.blocknotify_dir, '%s'))], ["-blockversion=211", @@ -36,7 +35,7 @@ class NotificationsTest(BitcoinTestFramework): def run_test(self): self.log.info("test -blocknotify") block_count = 10 - blocks = self.nodes[1].generate(block_count) + blocks = self.nodes[1].generatetoaddress(block_count, self.nodes[1].getnewaddress() if self.is_wallet_compiled() else ADDRESS_BCRT1_UNSPENDABLE) # wait at most 10 seconds for expected number of files before reading the content wait_until(lambda: len(os.listdir(self.blocknotify_dir)) == block_count, timeout=10) @@ -44,30 +43,32 @@ class NotificationsTest(BitcoinTestFramework): # directory content should equal the generated blocks hashes assert_equal(sorted(blocks), sorted(os.listdir(self.blocknotify_dir))) - self.log.info("test -walletnotify") - # wait at most 10 seconds for expected number of files before reading the content - wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10) + if self.is_wallet_compiled(): + self.log.info("test -walletnotify") + # wait at most 10 seconds for expected number of files before reading the content + wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10) - # directory content should equal the generated transaction hashes - txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) - assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) - for tx_file in os.listdir(self.walletnotify_dir): - os.remove(os.path.join(self.walletnotify_dir, tx_file)) + # directory content should equal the generated transaction hashes + txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) + assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) + self.stop_node(1) + for tx_file in os.listdir(self.walletnotify_dir): + os.remove(os.path.join(self.walletnotify_dir, tx_file)) - self.log.info("test -walletnotify after rescan") - # restart node to rescan to force wallet notifications - self.restart_node(1) - connect_nodes_bi(self.nodes, 0, 1) + self.log.info("test -walletnotify after rescan") + # restart node to rescan to force wallet notifications + self.start_node(1) + connect_nodes_bi(self.nodes, 0, 1) - wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10) + wait_until(lambda: len(os.listdir(self.walletnotify_dir)) == block_count, timeout=10) - # directory content should equal the generated transaction hashes - txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) - assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) + # directory content should equal the generated transaction hashes + txids_rpc = list(map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) + assert_equal(sorted(txids_rpc), sorted(os.listdir(self.walletnotify_dir))) # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st. self.log.info("test -alertnotify") - self.nodes[1].generate(41) + self.nodes[1].generatetoaddress(41, ADDRESS_BCRT1_UNSPENDABLE) self.sync_all() # Give bitcoind 10 seconds to write the alert notification @@ -77,7 +78,7 @@ class NotificationsTest(BitcoinTestFramework): os.remove(os.path.join(self.alertnotify_dir, notify_file)) # Mine more up-version blocks, should not get more alerts: - self.nodes[1].generate(2) + self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE) self.sync_all() self.log.info("-alertnotify should not continue notifying for more unknown version blocks") diff --git a/test/functional/feature_uacomment.py b/test/functional/feature_uacomment.py index 691a39b825..fb4ad21359 100755 --- a/test/functional/feature_uacomment.py +++ b/test/functional/feature_uacomment.py @@ -31,7 +31,7 @@ class UacommentTest(BitcoinTestFramework): self.nodes[0].assert_start_raises_init_error(["-uacomment=" + 'a' * 256], expected, match=ErrorMatch.FULL_REGEX) self.log.info("test -uacomment unsafe characters") - for unsafe_char in ['/', ':', '(', ')']: + for unsafe_char in ['/', ':', '(', ')', '₿', '🏃']: expected = "Error: User Agent comment \(" + re.escape(unsafe_char) + "\) contains unsafe characters." self.nodes[0].assert_start_raises_init_error(["-uacomment=" + unsafe_char], expected, match=ErrorMatch.FULL_REGEX) diff --git a/test/functional/interface_bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py index f311858bee..aed439339f 100755 --- a/test/functional/interface_bitcoin_cli.py +++ b/test/functional/interface_bitcoin_cli.py @@ -12,19 +12,17 @@ class TestBitcoinCli(BitcoinTestFramework): self.setup_clean_chain = True self.num_nodes = 1 - def skip_test_if_missing_module(self): - self.skip_if_no_wallet() - def run_test(self): """Main test logic""" cli_response = self.nodes[0].cli("-version").send_cli() assert("Bitcoin Core RPC client version" in cli_response) - self.log.info("Compare responses from gewalletinfo RPC and `bitcoin-cli getwalletinfo`") - cli_response = self.nodes[0].cli.getwalletinfo() - rpc_response = self.nodes[0].getwalletinfo() - assert_equal(cli_response, rpc_response) + self.log.info("Compare responses from getwalletinfo RPC and `bitcoin-cli getwalletinfo`") + if self.is_wallet_compiled(): + cli_response = self.nodes[0].cli.getwalletinfo() + rpc_response = self.nodes[0].getwalletinfo() + assert_equal(cli_response, rpc_response) self.log.info("Compare responses from getblockchaininfo RPC and `bitcoin-cli getblockchaininfo`") cli_response = self.nodes[0].cli.getblockchaininfo() @@ -52,26 +50,30 @@ class TestBitcoinCli(BitcoinTestFramework): self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.") cli_get_info = self.nodes[0].cli('-getinfo').send_cli() - wallet_info = self.nodes[0].getwalletinfo() + if self.is_wallet_compiled(): + wallet_info = self.nodes[0].getwalletinfo() network_info = self.nodes[0].getnetworkinfo() blockchain_info = self.nodes[0].getblockchaininfo() assert_equal(cli_get_info['version'], network_info['version']) assert_equal(cli_get_info['protocolversion'], network_info['protocolversion']) - assert_equal(cli_get_info['walletversion'], wallet_info['walletversion']) - assert_equal(cli_get_info['balance'], wallet_info['balance']) + if self.is_wallet_compiled(): + assert_equal(cli_get_info['walletversion'], wallet_info['walletversion']) + assert_equal(cli_get_info['balance'], wallet_info['balance']) assert_equal(cli_get_info['blocks'], blockchain_info['blocks']) assert_equal(cli_get_info['timeoffset'], network_info['timeoffset']) assert_equal(cli_get_info['connections'], network_info['connections']) assert_equal(cli_get_info['proxy'], network_info['networks'][0]['proxy']) assert_equal(cli_get_info['difficulty'], blockchain_info['difficulty']) assert_equal(cli_get_info['testnet'], blockchain_info['chain'] == "test") - assert_equal(cli_get_info['balance'], wallet_info['balance']) - assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest']) - assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize']) - assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee']) - assert_equal(cli_get_info['relayfee'], network_info['relayfee']) - # unlocked_until is not tested because the wallet is not encrypted + if self.is_wallet_compiled(): + assert_equal(cli_get_info['balance'], wallet_info['balance']) + assert_equal(cli_get_info['keypoololdest'], wallet_info['keypoololdest']) + assert_equal(cli_get_info['keypoolsize'], wallet_info['keypoolsize']) + assert_equal(cli_get_info['paytxfee'], wallet_info['paytxfee']) + assert_equal(cli_get_info['relayfee'], network_info['relayfee']) + # unlocked_until is not tested because the wallet is not encrypted + if __name__ == '__main__': TestBitcoinCli().main() diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py index 1c518eab75..48136a0108 100755 --- a/test/functional/interface_zmq.py +++ b/test/functional/interface_zmq.py @@ -5,6 +5,7 @@ """Test the ZMQ notification interface.""" import struct +from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE from test_framework.test_framework import BitcoinTestFramework from test_framework.messages import CTransaction from test_framework.util import ( @@ -14,6 +15,7 @@ from test_framework.util import ( ) from io import BytesIO +ADDRESS = "tcp://127.0.0.1:28332" class ZMQSubscriber: def __init__(self, socket, topic): @@ -41,7 +43,6 @@ class ZMQTest (BitcoinTestFramework): def skip_test_if_missing_module(self): self.skip_if_no_py3_zmq() self.skip_if_no_bitcoind_zmq() - self.skip_if_no_wallet() def setup_nodes(self): import zmq @@ -51,11 +52,10 @@ class ZMQTest (BitcoinTestFramework): # that this test fails if the publishing order changes. # Note that the publishing order is not defined in the documentation and # is subject to change. - address = "tcp://127.0.0.1:28332" self.zmq_context = zmq.Context() socket = self.zmq_context.socket(zmq.SUB) socket.set(zmq.RCVTIMEO, 60000) - socket.connect(address) + socket.connect(ADDRESS) # Subscribe to all available topics. self.hashblock = ZMQSubscriber(socket, b"hashblock") @@ -64,7 +64,7 @@ class ZMQTest (BitcoinTestFramework): self.rawtx = ZMQSubscriber(socket, b"rawtx") self.extra_args = [ - ["-zmqpub%s=%s" % (sub.topic.decode(), address) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]], + ["-zmqpub%s=%s" % (sub.topic.decode(), ADDRESS) for sub in [self.hashblock, self.hashtx, self.rawblock, self.rawtx]], [], ] self.add_nodes(self.num_nodes, self.extra_args) @@ -81,7 +81,7 @@ class ZMQTest (BitcoinTestFramework): def _zmq_test(self): num_blocks = 5 self.log.info("Generate %(n)d blocks (and %(n)d coinbase txes)" % {"n": num_blocks}) - genhashes = self.nodes[0].generate(num_blocks) + genhashes = self.nodes[0].generatetoaddress(num_blocks, ADDRESS_BCRT1_UNSPENDABLE) self.sync_all() for x in range(num_blocks): @@ -105,17 +105,29 @@ class ZMQTest (BitcoinTestFramework): block = self.rawblock.receive() assert_equal(genhashes[x], bytes_to_hex_str(hash256(block[:80]))) - self.log.info("Wait for tx from second node") - payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0) - self.sync_all() + if self.is_wallet_compiled(): + self.log.info("Wait for tx from second node") + payment_txid = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0) + self.sync_all() + + # Should receive the broadcasted txid. + txid = self.hashtx.receive() + assert_equal(payment_txid, bytes_to_hex_str(txid)) + + # Should receive the broadcasted raw transaction. + hex = self.rawtx.receive() + assert_equal(payment_txid, bytes_to_hex_str(hash256(hex))) + - # Should receive the broadcasted txid. - txid = self.hashtx.receive() - assert_equal(payment_txid, bytes_to_hex_str(txid)) + self.log.info("Test the getzmqnotifications RPC") + assert_equal(self.nodes[0].getzmqnotifications(), [ + {"type": "pubhashblock", "address": ADDRESS}, + {"type": "pubhashtx", "address": ADDRESS}, + {"type": "pubrawblock", "address": ADDRESS}, + {"type": "pubrawtx", "address": ADDRESS}, + ]) - # Should receive the broadcasted raw transaction. - hex = self.rawtx.receive() - assert_equal(payment_txid, bytes_to_hex_str(hash256(hex))) + assert_equal(self.nodes[1].getzmqnotifications(), []) if __name__ == '__main__': ZMQTest().main() diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py index 58074803cc..588bfbe083 100755 --- a/test/functional/rpc_deprecated.py +++ b/test/functional/rpc_deprecated.py @@ -4,12 +4,17 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test deprecation of RPC calls.""" from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_raises_rpc_error class DeprecatedRpcTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.setup_clean_chain = True - self.extra_args = [[], ["-deprecatedrpc=validateaddress"]] + self.extra_args = [[], ["-deprecatedrpc=generate"]] + + def skip_test_if_missing_module(self): + # The generate RPC method requires the wallet to be compiled + self.skip_if_no_wallet() def run_test(self): # This test should be used to verify correct behaviour of deprecated @@ -18,7 +23,10 @@ class DeprecatedRpcTest(BitcoinTestFramework): # self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses") # assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()]) # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()]) - pass + + self.log.info("Test generate RPC") + assert_raises_rpc_error(-32, 'The wallet generate rpc method is deprecated', self.nodes[0].rpc.generate, 1) + self.nodes[1].generate(1) if __name__ == '__main__': DeprecatedRpcTest().main() diff --git a/test/functional/rpc_scantxoutset.py b/test/functional/rpc_scantxoutset.py index 96f9ccdbdb..881b839a4e 100755 --- a/test/functional/rpc_scantxoutset.py +++ b/test/functional/rpc_scantxoutset.py @@ -65,6 +65,8 @@ class ScantxoutsetTest(BitcoinTestFramework): assert_equal(self.nodes[0].scantxoutset("start", [ "addr(" + addr_P2SH_SEGWIT + ")", "addr(" + addr_LEGACY + ")", "combo(" + pubk3 + ")"])['total_amount'], Decimal("0.007")) self.log.info("Test extended key derivation.") + # Run various scans, and verify that the sum of the amounts of the matches corresponds to the expected subset. + # Note that all amounts in the UTXO set are powers of 2 multiplied by 0.001 BTC, so each amounts uniquely identifies a subset. assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0h/0h)"])['total_amount'], Decimal("0.008")) assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0'/0'/1h)"])['total_amount'], Decimal("0.016")) assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0h/0'/1500')"])['total_amount'], Decimal("0.032")) @@ -82,7 +84,7 @@ class ScantxoutsetTest(BitcoinTestFramework): assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1)"])['total_amount'], Decimal("8.192")) assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/1500)"])['total_amount'], Decimal("16.384")) assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/0)"])['total_amount'], Decimal("4.096")) - assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192")) + assert_equal(self.nodes[0].scantxoutset("start", [ "combo([abcdef88/1/2'/3/4h]tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1)"])['total_amount'], Decimal("8.192")) assert_equal(self.nodes[0].scantxoutset("start", [ "combo(tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/1/1500)"])['total_amount'], Decimal("16.384")) assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1499}])['total_amount'], Decimal("1.536")) assert_equal(self.nodes[0].scantxoutset("start", [ {"desc": "combo(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*')", "range": 1500}])['total_amount'], Decimal("3.584")) diff --git a/test/functional/rpc_zmq.py b/test/functional/rpc_zmq.py deleted file mode 100755 index bfa6b06f67..0000000000 --- a/test/functional/rpc_zmq.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2018 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -"""Test for the ZMQ RPC methods.""" - -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal - - -class RPCZMQTest(BitcoinTestFramework): - - address = "tcp://127.0.0.1:28332" - - def set_test_params(self): - self.num_nodes = 1 - self.setup_clean_chain = True - - def skip_test_if_missing_module(self): - self.skip_if_no_py3_zmq() - self.skip_if_no_bitcoind_zmq() - - def run_test(self): - self._test_getzmqnotifications() - - def _test_getzmqnotifications(self): - self.restart_node(0, extra_args=[]) - assert_equal(self.nodes[0].getzmqnotifications(), []) - - self.restart_node(0, extra_args=["-zmqpubhashtx=%s" % self.address]) - assert_equal(self.nodes[0].getzmqnotifications(), [ - {"type": "pubhashtx", "address": self.address}, - ]) - - -if __name__ == '__main__': - RPCZMQTest().main() diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index d1fb97b024..456d43aa2e 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -9,8 +9,11 @@ from .util import bytes_to_hex_str, hex_str_to_bytes from . import segwit_addr +ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj' + chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' + def byte_to_base58(b, version): result = '' str = bytes_to_hex_str(b) diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py index f8caa57250..6864e8a838 100755 --- a/test/functional/test_framework/mininode.py +++ b/test/functional/test_framework/mininode.py @@ -500,9 +500,9 @@ class P2PDataStore(P2PInterface): wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock) if expect_disconnect: - self.wait_for_disconnect() + self.wait_for_disconnect(timeout=timeout) else: - self.sync_with_ping() + self.sync_with_ping(timeout=timeout) if success: wait_until(lambda: node.getbestblockhash() == blocks[-1].hash, timeout=timeout) diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index 7ab7fcfcb4..cc1bfabbfa 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -187,7 +187,9 @@ class TestNode(): if e.errno != errno.ECONNREFUSED: # Port not yet open? raise # unknown IO error except JSONRPCException as e: # Initialization phase - if e.error['code'] != -28: # RPC in warmup? + # -28 RPC in warmup + # -342 Service unavailable, RPC server started but is shutting down due to error + if e.error['code'] != -28 and e.error['code'] != -342: raise # unknown JSON RPC exception except ValueError as e: # cookie file not found and no rpcuser or rpcassword. bitcoind still starting if "No RPC credentials" not in str(e): @@ -195,6 +197,25 @@ class TestNode(): time.sleep(1.0 / poll_per_s) self._raise_assertion_error("Unable to connect to bitcoind") + def generate(self, nblocks, maxtries=1000000): + self.log.debug("TestNode.generate() dispatches `generate` call to `generatetoaddress`") + # Try to import the node's deterministic private key. This is a no-op if the private key + # has already been imported. + try: + self.rpc.importprivkey(privkey=self.get_deterministic_priv_key().key, label='coinbase', rescan=False) + except JSONRPCException as e: + # This may fail if: + # - wallet is disabled ('Method not found') + # - there are multiple wallets to import to ('Wallet file not specified') + # - wallet is locked ('Error: Please enter the wallet passphrase with walletpassphrase first') + # Just ignore those errors. We can make this tidier by importing the privkey during TestFramework.setup_nodes + # TODO: tidy up deterministic privkey import. + assert str(e).startswith('Method not found') or \ + str(e).startswith('Wallet file not specified') or \ + str(e).startswith('Error: Please enter the wallet passphrase with walletpassphrase first') + + return self.generatetoaddress(nblocks=nblocks, address=self.get_deterministic_priv_key().address, maxtries=maxtries) + def get_wallet_rpc(self, wallet_name): if self.use_cli: return self.cli("-rpcwallet={}".format(wallet_name)) diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index d9960460d9..3f990924ec 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -152,7 +152,6 @@ BASE_SCRIPTS = [ 'feature_versionbits_warning.py', 'rpc_preciousblock.py', 'wallet_importprunedfunds.py', - 'rpc_zmq.py', 'rpc_signmessage.py', 'feature_nulldummy.py', 'mempool_accept.py', @@ -175,6 +174,7 @@ BASE_SCRIPTS = [ 'rpc_getblockstats.py', 'p2p_fingerprint.py', 'feature_uacomment.py', + 'feature_filelock.py', 'p2p_unrequested_blocks.py', 'feature_includeconf.py', 'rpc_scantxoutset.py', diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py index 8bbff7f7ef..4de3356d79 100755 --- a/test/functional/wallet_basic.py +++ b/test/functional/wallet_basic.py @@ -11,6 +11,7 @@ from test_framework.util import ( assert_array_result, assert_equal, assert_fee_amount, + assert_greater_than, assert_raises_rpc_error, connect_nodes_bi, sync_blocks, @@ -92,13 +93,13 @@ class WalletTest(BitcoinTestFramework): assert_equal(txout['value'], 50) # Send 21 BTC from 0 to 2 using sendtoaddress call. - # Locked memory should use at least 32 bytes to sign each transaction + # Locked memory should increase to sign transactions self.log.info("test getmemoryinfo") memory_before = self.nodes[0].getmemoryinfo() self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) mempool_txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) memory_after = self.nodes[0].getmemoryinfo() - assert(memory_before['locked']['used'] + 64 <= memory_after['locked']['used']) + assert_greater_than(memory_after['locked']['used'], memory_before['locked']['used']) self.log.info("test gettxout (second part)") # utxo spent in mempool should be visible if you exclude mempool diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 51afa0cb1a..ceb9709712 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -73,11 +73,10 @@ class KeyPoolTest(BitcoinTestFramework): time.sleep(1.1) assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0) - # drain them by mining - nodes[0].generate(1) - nodes[0].generate(1) - nodes[0].generate(1) - assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].generate, 1) + # drain the keypool + for _ in range(3): + nodes[0].getnewaddress() + assert_raises_rpc_error(-12, "Keypool ran out", nodes[0].getnewaddress) nodes[0].walletpassphrase('test', 100) nodes[0].keypoolrefill(100) diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py index 8d7c77bb96..b71dae9f40 100755 --- a/test/functional/wallet_labels.py +++ b/test/functional/wallet_labels.py @@ -29,8 +29,8 @@ class WalletLabelsTest(BitcoinTestFramework): # Note each time we call generate, all generated coins go into # the same address, so we call twice to get two addresses w/50 each - node.generate(1) - node.generate(101) + node.generatetoaddress(nblocks=1, address=node.getnewaddress(label='coinbase')) + node.generatetoaddress(nblocks=101, address=node.getnewaddress(label='coinbase')) assert_equal(node.getbalance(), 100) # there should be 2 address groups @@ -42,8 +42,9 @@ class WalletLabelsTest(BitcoinTestFramework): linked_addresses = set() for address_group in address_groups: assert_equal(len(address_group), 1) - assert_equal(len(address_group[0]), 2) + assert_equal(len(address_group[0]), 3) assert_equal(address_group[0][1], 50) + assert_equal(address_group[0][2], 'coinbase') linked_addresses.add(address_group[0][0]) # send 50 from each address to a third address not in this wallet @@ -77,7 +78,7 @@ class WalletLabelsTest(BitcoinTestFramework): label.verify(node) # Check all labels are returned by listlabels. - assert_equal(node.listlabels(), [label.name for label in labels]) + assert_equal(node.listlabels(), sorted(['coinbase'] + [label.name for label in labels])) # Send a transaction to each label. for label in labels: diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py index 189bc2d50e..30ab750fac 100755 --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -38,6 +38,8 @@ class MultiWalletTest(BitcoinTestFramework): return wallet_dir(name, "wallet.dat") return wallet_dir(name) + assert_equal(self.nodes[0].listwalletdir(), { 'wallets': [{ 'name': '' }] }) + # check wallet.dat is created self.stop_nodes() assert_equal(os.path.isfile(wallet_dir('wallet.dat')), True) @@ -71,6 +73,8 @@ class MultiWalletTest(BitcoinTestFramework): wallet_names.remove('w7_symlink') extra_args = ['-wallet={}'.format(n) for n in wallet_names] self.start_node(0, extra_args) + assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', 'sub/w5', 'w7', 'w7', 'w1', 'w8', 'w'])) + assert_equal(set(node.listwallets()), set(wallet_names)) # check that all requested wallets were created @@ -125,7 +129,7 @@ class MultiWalletTest(BitcoinTestFramework): self.start_node(0, ['-wallet=w4', '-wallet=w5']) assert_equal(set(node.listwallets()), {"w4", "w5"}) w5 = wallet("w5") - w5.generate(1) + node.generatetoaddress(nblocks=1, address=w5.getnewaddress()) # now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded os.rename(wallet_dir2, wallet_dir()) @@ -143,11 +147,13 @@ class MultiWalletTest(BitcoinTestFramework): self.restart_node(0, extra_args) + assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', 'sub/w5', 'w7', 'w7', 'w8_copy', 'w1', 'w8', 'w'])) + wallets = [wallet(w) for w in wallet_names] wallet_bad = wallet("bad") # check wallet names and balances - wallets[0].generate(1) + node.generatetoaddress(nblocks=1, address=wallets[0].getnewaddress()) for wallet_name, wallet in zip(wallet_names, wallets): info = wallet.getwalletinfo() assert_equal(info['immature_balance'], 50 if wallet is wallets[0] else 0) @@ -160,7 +166,7 @@ class MultiWalletTest(BitcoinTestFramework): assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo) w1, w2, w3, w4, *_ = wallets - w1.generate(101) + node.generatetoaddress(nblocks=101, address=w1.getnewaddress()) assert_equal(w1.getbalance(), 100) assert_equal(w2.getbalance(), 0) assert_equal(w3.getbalance(), 0) @@ -169,7 +175,7 @@ class MultiWalletTest(BitcoinTestFramework): w1.sendtoaddress(w2.getnewaddress(), 1) w1.sendtoaddress(w3.getnewaddress(), 2) w1.sendtoaddress(w4.getnewaddress(), 3) - w1.generate(1) + node.generatetoaddress(nblocks=1, address=w1.getnewaddress()) assert_equal(w2.getbalance(), 1) assert_equal(w3.getbalance(), 2) assert_equal(w4.getbalance(), 3) @@ -281,6 +287,8 @@ class MultiWalletTest(BitcoinTestFramework): assert_equal(self.nodes[0].listwallets(), ['w1']) assert_equal(w1.getwalletinfo()['walletname'], 'w1') + assert_equal(set(map(lambda w: w['name'], self.nodes[0].listwalletdir()['wallets'])), set(['', 'w3', 'w2', 'sub/w5', 'w7', 'w9', 'w7', 'w8_copy', 'w1', 'w8', 'w'])) + # Test backing up and restoring wallets self.log.info("Test wallet backup") self.restart_node(0, ['-nowallet']) diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh index 4f4542ff0c..d44a585294 100755 --- a/test/lint/lint-python.sh +++ b/test/lint/lint-python.sh @@ -87,4 +87,4 @@ elif PYTHONWARNINGS="ignore" flake8 --version | grep -q "Python 2"; then exit 0 fi -PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=E101,E112,E113,E115,E116,E125,E129,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,E901,E902,F401,F402,F403,F404,F405,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W191,W291,W292,W293,W504,W601,W602,W603,W604,W605,W606 . +PYTHONWARNINGS="ignore" flake8 --ignore=B,C,E,F,I,N,W --select=E101,E112,E113,E115,E116,E125,E129,E131,E133,E223,E224,E242,E266,E271,E272,E273,E274,E275,E304,E306,E401,E402,E502,E701,E702,E703,E714,E721,E741,E742,E743,E901,E902,F401,F402,F403,F404,F405,F406,F407,F601,F602,F621,F622,F631,F701,F702,F703,F704,F705,F706,F707,F811,F812,F821,F822,F823,F831,F841,W191,W291,W292,W293,W504,W601,W602,W603,W604,W605,W606 "${@:-.}" diff --git a/test/lint/lint-spelling.ignore-words.txt b/test/lint/lint-spelling.ignore-words.txt index 9a49f32271..f0415443db 100644 --- a/test/lint/lint-spelling.ignore-words.txt +++ b/test/lint/lint-spelling.ignore-words.txt @@ -1,6 +1,7 @@ cas hights mor +mut objext unselect useable diff --git a/test/lint/lint-spelling.sh b/test/lint/lint-spelling.sh index ebeafd7d58..5d672698a7 100755 --- a/test/lint/lint-spelling.sh +++ b/test/lint/lint-spelling.sh @@ -9,10 +9,7 @@ export LC_ALL=C -EXIT_CODE=0 IGNORE_WORDS_FILE=test/lint/lint-spelling.ignore-words.txt if ! codespell --check-filenames --disable-colors --quiet-level=7 --ignore-words=${IGNORE_WORDS_FILE} $(git ls-files -- ":(exclude)build-aux/m4/" ":(exclude)contrib/seeds/*.txt" ":(exclude)depends/" ":(exclude)doc/release-notes/" ":(exclude)src/leveldb/" ":(exclude)src/qt/locale/" ":(exclude)src/secp256k1/" ":(exclude)src/univalue/"); then echo "^ Warning: codespell identified likely spelling errors. Any false positives? Add them to the list of ignored words in ${IGNORE_WORDS_FILE}" - EXIT_CODE=1 fi -exit ${EXIT_CODE} |