aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md29
-rwxr-xr-xtest/functional/feature_config_args.py10
-rwxr-xr-xtest/functional/feature_filelock.py36
-rwxr-xr-xtest/functional/feature_notifications.py47
-rwxr-xr-xtest/functional/feature_uacomment.py2
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py34
-rwxr-xr-xtest/functional/interface_zmq.py40
-rwxr-xr-xtest/functional/rpc_deprecated.py12
-rwxr-xr-xtest/functional/rpc_scantxoutset.py4
-rwxr-xr-xtest/functional/rpc_zmq.py37
-rw-r--r--test/functional/test_framework/address.py3
-rwxr-xr-xtest/functional/test_framework/mininode.py4
-rwxr-xr-xtest/functional/test_framework/test_node.py23
-rwxr-xr-xtest/functional/test_runner.py2
-rwxr-xr-xtest/functional/wallet_basic.py5
-rwxr-xr-xtest/functional/wallet_keypool.py9
-rwxr-xr-xtest/functional/wallet_labels.py9
-rwxr-xr-xtest/functional/wallet_multiwallet.py16
-rwxr-xr-xtest/lint/lint-python.sh2
-rw-r--r--test/lint/lint-spelling.ignore-words.txt1
-rwxr-xr-xtest/lint/lint-spelling.sh3
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}