aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md8
-rwxr-xr-xtest/functional/rpc_net.py4
-rw-r--r--test/functional/test_framework/authproxy.py2
-rwxr-xr-xtest/functional/test_runner.py7
-rwxr-xr-xtest/functional/wallet_basic.py122
-rwxr-xr-xtest/functional/wallet_bumpfee.py26
-rwxr-xr-xtest/functional/wallet_multiwallet.py29
-rwxr-xr-xtest/lint/lint-includes.sh2
-rwxr-xr-xtest/lint/lint-python.sh1
-rwxr-xr-xtest/lint/lint-shell.sh1
-rw-r--r--test/sanitizer_suppressions/tsan1
11 files changed, 191 insertions, 12 deletions
diff --git a/test/README.md b/test/README.md
index b036a66f67..2341eef00d 100644
--- a/test/README.md
+++ b/test/README.md
@@ -260,11 +260,11 @@ Use the `-v` option for verbose output.
| Lint test | Dependency | Version [used by CI](../ci/lint/04_install.sh) | Installation
|-----------|:----------:|:-------------------------------------------:|--------------
-| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8) | [3.7.8](https://github.com/bitcoin/bitcoin/pull/15257) | `pip3 install flake8==3.7.8`
-| [`lint-python.sh`](lint/lint-python.sh) | [mypy](https://github.com/python/mypy) | [0.700](https://github.com/bitcoin/bitcoin/pull/18210) | `pip3 install mypy==0.700`
-| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck) | [0.6.0](https://github.com/bitcoin/bitcoin/pull/15166) | [details...](https://github.com/koalaman/shellcheck#installing)
+| [`lint-python.sh`](lint/lint-python.sh) | [flake8](https://gitlab.com/pycqa/flake8) | [3.8.3](https://github.com/bitcoin/bitcoin/pull/19348) | `pip3 install flake8==3.8.3`
+| [`lint-python.sh`](lint/lint-python.sh) | [mypy](https://github.com/python/mypy) | [0.781](https://github.com/bitcoin/bitcoin/pull/19348) | `pip3 install mypy==0.781`
+| [`lint-shell.sh`](lint/lint-shell.sh) | [ShellCheck](https://github.com/koalaman/shellcheck) | [0.7.1](https://github.com/bitcoin/bitcoin/pull/19348) | [details...](https://github.com/koalaman/shellcheck#installing)
| [`lint-shell.sh`](lint/lint-shell.sh) | [yq](https://github.com/kislyuk/yq) | default | `pip3 install yq`
-| [`lint-spelling.sh`](lint/lint-spelling.sh) | [codespell](https://github.com/codespell-project/codespell) | [1.15.0](https://github.com/bitcoin/bitcoin/pull/16186) | `pip3 install codespell==1.15.0`
+| [`lint-spelling.sh`](lint/lint-spelling.sh) | [codespell](https://github.com/codespell-project/codespell) | [1.17.1](https://github.com/bitcoin/bitcoin/pull/19348) | `pip3 install codespell==1.17.1`
Please be aware that on Linux distributions all dependencies are usually available as packages, but could be outdated.
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 58d8c4abe1..ca26152e7e 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -46,10 +46,12 @@ class NetTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.extra_args = [["-minrelaytxfee=0.00001000"],["-minrelaytxfee=0.00000500"]]
+ self.extra_args = [["-minrelaytxfee=0.00001000"], ["-minrelaytxfee=0.00000500"]]
self.supports_cli = False
def run_test(self):
+ self.log.info('Get out of IBD for the minfeefilter test')
+ self.nodes[0].generate(1)
self.log.info('Connect nodes both way')
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 0)
diff --git a/test/functional/test_framework/authproxy.py b/test/functional/test_framework/authproxy.py
index 05308931e3..81eb881234 100644
--- a/test/functional/test_framework/authproxy.py
+++ b/test/functional/test_framework/authproxy.py
@@ -115,6 +115,8 @@ class AuthServiceProxy():
except OSError as e:
retry = (
'[WinError 10053] An established connection was aborted by the software in your host machine' in str(e))
+ # Workaround for a bug on macOS. See https://bugs.python.org/issue33450
+ retry = retry or ('[Errno 41] Protocol wrong type for socket' in str(e))
if retry:
self.__conn.close()
self.__conn.request(method, path, postdata, headers)
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 41f9bde183..2fa48006f4 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -396,11 +396,12 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
args = args or []
# Warn if bitcoind is already running
- # pidof might fail or return an empty string if bitcoind is not running
try:
- if subprocess.check_output(["pidof", "bitcoind"]) not in [b'']:
+ # pgrep exits with code zero when one or more matching processes found
+ if subprocess.run(["pgrep", "-x", "bitcoind"], stdout=subprocess.DEVNULL).returncode == 0:
print("%sWARNING!%s There is already a bitcoind process running on this system. Tests may fail unexpectedly due to resource contention!" % (BOLD[1], BOLD[0]))
- except (OSError, subprocess.SubprocessError):
+ except OSError:
+ # pgrep not supported
pass
# Warn if there is a cache directory
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 797c903dd3..8962362276 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -219,6 +219,60 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), node_2_bal)
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ # Sendmany with explicit fee (BTC/kB)
+ # Throw if no conf_target provided
+ assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
+ self.nodes[2].sendmany,
+ amounts={ address: 10 },
+ estimate_mode='bTc/kB')
+ # Throw if negative feerate
+ assert_raises_rpc_error(-3, "Amount out of range",
+ self.nodes[2].sendmany,
+ amounts={ address: 10 },
+ conf_target=-1,
+ estimate_mode='bTc/kB')
+ fee_per_kb = 0.0002500
+ explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
+ txid = self.nodes[2].sendmany(
+ amounts={ address: 10 },
+ conf_target=fee_per_kb,
+ estimate_mode='bTc/kB',
+ )
+ self.nodes[2].generate(1)
+ self.sync_all(self.nodes[0:3])
+ node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ assert_equal(self.nodes[2].getbalance(), node_2_bal)
+ node_0_bal += Decimal('10')
+ assert_equal(self.nodes[0].getbalance(), node_0_bal)
+
+ # Sendmany with explicit fee (SAT/B)
+ # Throw if no conf_target provided
+ assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
+ self.nodes[2].sendmany,
+ amounts={ address: 10 },
+ estimate_mode='sat/b')
+ # Throw if negative feerate
+ assert_raises_rpc_error(-3, "Amount out of range",
+ self.nodes[2].sendmany,
+ amounts={ address: 10 },
+ conf_target=-1,
+ estimate_mode='sat/b')
+ fee_sat_per_b = 2
+ fee_per_kb = fee_sat_per_b / 100000.0
+ explicit_fee_per_byte = Decimal(fee_per_kb) / 1000
+ txid = self.nodes[2].sendmany(
+ amounts={ address: 10 },
+ conf_target=fee_sat_per_b,
+ estimate_mode='sAT/b',
+ )
+ self.nodes[2].generate(1)
+ self.sync_all(self.nodes[0:3])
+ balance = self.nodes[2].getbalance()
+ node_2_bal = self.check_fee_amount(balance, node_2_bal - Decimal('10'), explicit_fee_per_byte, self.get_vsize(self.nodes[2].gettransaction(txid)['hex']))
+ assert_equal(balance, node_2_bal)
+ node_0_bal += Decimal('10')
+ assert_equal(self.nodes[0].getbalance(), node_0_bal)
+
self.start_node(3, self.nodes[3].extra_args)
connect_nodes(self.nodes[0], 3)
self.sync_all()
@@ -349,6 +403,74 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all(self.nodes[0:3])
+ # send with explicit btc/kb fee
+ self.log.info("test explicit fee (sendtoaddress as btc/kb)")
+ self.nodes[0].generate(1)
+ self.sync_all(self.nodes[0:3])
+ prebalance = self.nodes[2].getbalance()
+ assert prebalance > 2
+ address = self.nodes[1].getnewaddress()
+ # Throw if no conf_target provided
+ assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
+ self.nodes[2].sendtoaddress,
+ address=address,
+ amount=1.0,
+ estimate_mode='BTc/Kb')
+ # Throw if negative feerate
+ assert_raises_rpc_error(-3, "Amount out of range",
+ self.nodes[2].sendtoaddress,
+ address=address,
+ amount=1.0,
+ conf_target=-1,
+ estimate_mode='btc/kb')
+ txid = self.nodes[2].sendtoaddress(
+ address=address,
+ amount=1.0,
+ conf_target=0.00002500,
+ estimate_mode='btc/kb',
+ )
+ tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
+ self.sync_all(self.nodes[0:3])
+ self.nodes[0].generate(1)
+ self.sync_all(self.nodes[0:3])
+ postbalance = self.nodes[2].getbalance()
+ fee = prebalance - postbalance - Decimal('1')
+ assert_fee_amount(fee, tx_size, Decimal('0.00002500'))
+
+ # send with explicit sat/b fee
+ self.sync_all(self.nodes[0:3])
+ self.log.info("test explicit fee (sendtoaddress as sat/b)")
+ self.nodes[0].generate(1)
+ prebalance = self.nodes[2].getbalance()
+ assert prebalance > 2
+ address = self.nodes[1].getnewaddress()
+ # Throw if no conf_target provided
+ assert_raises_rpc_error(-8, "Selected estimate_mode requires a fee rate",
+ self.nodes[2].sendtoaddress,
+ address=address,
+ amount=1.0,
+ estimate_mode='SAT/b')
+ # Throw if negative feerate
+ assert_raises_rpc_error(-3, "Amount out of range",
+ self.nodes[2].sendtoaddress,
+ address=address,
+ amount=1.0,
+ conf_target=-1,
+ estimate_mode='SAT/b')
+ txid = self.nodes[2].sendtoaddress(
+ address=address,
+ amount=1.0,
+ conf_target=2,
+ estimate_mode='SAT/B',
+ )
+ tx_size = self.get_vsize(self.nodes[2].gettransaction(txid)['hex'])
+ self.sync_all(self.nodes[0:3])
+ self.nodes[0].generate(1)
+ self.sync_all(self.nodes[0:3])
+ postbalance = self.nodes[2].getbalance()
+ fee = prebalance - postbalance - Decimal('1')
+ assert_fee_amount(fee, tx_size, Decimal('0.00002000'))
+
# 2. Import address from node2 to node1
self.nodes[1].importaddress(address_to_import)
diff --git a/test/functional/wallet_bumpfee.py b/test/functional/wallet_bumpfee.py
index 27197e3b6d..72c85b8832 100755
--- a/test/functional/wallet_bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -71,6 +71,7 @@ class BumpFeeTest(BitcoinTestFramework):
self.log.info("Running tests")
dest_address = peer_node.getnewaddress()
+ test_invalid_parameters(rbf_node, dest_address)
test_simple_bumpfee_succeeds(self, "default", rbf_node, peer_node, dest_address)
test_simple_bumpfee_succeeds(self, "fee_rate", rbf_node, peer_node, dest_address)
test_feerate_args(self, rbf_node, peer_node, dest_address)
@@ -92,6 +93,28 @@ class BumpFeeTest(BitcoinTestFramework):
test_small_output_with_feerate_succeeds(self, rbf_node, dest_address)
test_no_more_inputs_fails(self, rbf_node, dest_address)
+def test_invalid_parameters(node, dest_address):
+ txid = spend_one_input(node, dest_address)
+ # invalid estimate mode
+ assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
+ "estimate_mode": "moo",
+ })
+ assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
+ "estimate_mode": 38,
+ })
+ assert_raises_rpc_error(-3, "Expected type string", node.bumpfee, txid, {
+ "estimate_mode": {
+ "foo": "bar",
+ },
+ })
+ assert_raises_rpc_error(-8, "Invalid estimate_mode parameter", node.bumpfee, txid, {
+ "estimate_mode": Decimal("3.141592"),
+ })
+ # confTarget and conf_target
+ assert_raises_rpc_error(-8, "confTarget and conf_target options should not both be set", node.bumpfee, txid, {
+ "confTarget": 123,
+ "conf_target": 456,
+ })
def test_simple_bumpfee_succeeds(self, mode, rbf_node, peer_node, dest_address):
self.log.info('Test simple bumpfee: {}'.format(mode))
@@ -127,9 +150,10 @@ def test_feerate_args(self, rbf_node, peer_node, dest_address):
self.sync_mempools((rbf_node, peer_node))
assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool()
- assert_raises_rpc_error(-8, "confTarget can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "confTarget": 1})
+ assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate": NORMAL, "confTarget": 1})
assert_raises_rpc_error(-3, "Unexpected key totalFee", rbf_node.bumpfee, rbfid, {"totalFee": NORMAL})
+ assert_raises_rpc_error(-8, "conf_target can't be set with fee_rate. Please provide either a confirmation target in blocks for automatic fee estimation, or an explicit fee rate.", rbf_node.bumpfee, rbfid, {"fee_rate":0.00001, "confTarget": 1})
# Bumping to just above minrelay should fail to increase total fee enough, at least
assert_raises_rpc_error(-8, "Insufficient total fee", rbf_node.bumpfee, rbfid, {"fee_rate": INSUFFICIENT})
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index ff9ff34185..88beef1034 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -7,19 +7,36 @@
Verify that a bitcoind node can load multiple wallet files
"""
from decimal import Decimal
+from threading import Thread
import os
import shutil
import time
+from test_framework.authproxy import JSONRPCException
from test_framework.test_framework import BitcoinTestFramework
from test_framework.test_node import ErrorMatch
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
+ get_rpc_proxy,
)
FEATURE_LATEST = 169900
+got_loading_error = False
+def test_load_unload(node, name):
+ global got_loading_error
+ for i in range(10):
+ if got_loading_error:
+ return
+ try:
+ node.loadwallet(name)
+ node.unloadwallet(name)
+ except JSONRPCException as e:
+ if e.error['code'] == -4 and 'Wallet already being loading' in e.error['message']:
+ got_loading_error = True
+ return
+
class MultiWalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -212,6 +229,18 @@ class MultiWalletTest(BitcoinTestFramework):
w2 = node.get_wallet_rpc(wallet_names[1])
w2.getwalletinfo()
+ self.log.info("Concurrent wallet loading")
+ threads = []
+ for _ in range(3):
+ n = node.cli if self.options.usecli else get_rpc_proxy(node.url, 1, timeout=600, coveragedir=node.coverage_dir)
+ t = Thread(target=test_load_unload, args=(n, wallet_names[2], ))
+ t.start()
+ threads.append(t)
+ for t in threads:
+ t.join()
+ global got_loading_error
+ assert_equal(got_loading_error, True)
+
self.log.info("Load remaining wallets")
for wallet_name in wallet_names[2:]:
loadwallet_name = self.nodes[0].loadwallet(wallet_name)
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index 5404565b94..611bd4a8c4 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -64,7 +64,7 @@ EXPECTED_BOOST_INCLUDES=(
boost/preprocessor/cat.hpp
boost/preprocessor/stringize.hpp
boost/signals2/connection.hpp
- boost/signals2/last_value.hpp
+ boost/signals2/optional_last_value.hpp
boost/signals2/signal.hpp
boost/test/unit_test.hpp
boost/thread/condition_variable.hpp
diff --git a/test/lint/lint-python.sh b/test/lint/lint-python.sh
index decea38c4f..72e8ef7c7d 100755
--- a/test/lint/lint-python.sh
+++ b/test/lint/lint-python.sh
@@ -39,7 +39,6 @@ enabled=(
E711 # comparison to None should be 'if cond is None:'
E714 # test for object identity should be "is not"
E721 # do not compare types, use "isinstance()"
- E741 # do not use variables named "l", "O", or "I"
E742 # do not define classes named "l", "O", or "I"
E743 # do not define functions named "l", "O", or "I"
E901 # SyntaxError: invalid syntax
diff --git a/test/lint/lint-shell.sh b/test/lint/lint-shell.sh
index 563e076b35..9a26cd9c02 100755
--- a/test/lint/lint-shell.sh
+++ b/test/lint/lint-shell.sh
@@ -25,7 +25,6 @@ disabled=(
disabled_gitian=(
SC2094 # Make sure not to read and write the same file in the same pipeline.
SC2129 # Consider using { cmd1; cmd2; } >> file instead of individual redirects.
- SC2230 # which is non-standard. Use builtin 'command -v' instead.
)
EXIT_CODE=0
diff --git a/test/sanitizer_suppressions/tsan b/test/sanitizer_suppressions/tsan
index b8fe75c5c5..16a0bf8ea8 100644
--- a/test/sanitizer_suppressions/tsan
+++ b/test/sanitizer_suppressions/tsan
@@ -19,6 +19,7 @@ race:CConnman::ThreadMessageHandler
race:fHaveGenesis
race:ProcessNewBlock
race:ThreadImport
+race:LoadWallet
race:WalletBatch::WriteHDChain
race:BerkeleyDatabase
race:zmq::*