aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/p2p_blocksonly.py58
-rwxr-xr-xtest/functional/rpc_misc.py8
-rwxr-xr-xtest/functional/test_framework/mininode.py8
-rwxr-xr-xtest/functional/test_framework/test_framework.py19
-rw-r--r--test/functional/test_framework/util.py2
-rwxr-xr-xtest/functional/test_runner.py9
-rwxr-xr-xtest/functional/wallet_createwallet.py23
-rwxr-xr-xtest/functional/wallet_import_rescan.py25
-rwxr-xr-xtest/lint/lint-all.sh8
9 files changed, 137 insertions, 23 deletions
diff --git a/test/functional/p2p_blocksonly.py b/test/functional/p2p_blocksonly.py
new file mode 100755
index 0000000000..12cb06a407
--- /dev/null
+++ b/test/functional/p2p_blocksonly.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+# Copyright (c) 2019 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 p2p blocksonly"""
+
+from test_framework.messages import msg_tx, CTransaction, FromHex
+from test_framework.mininode import P2PInterface
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+
+class P2PBlocksOnly(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+ self.extra_args = [["-blocksonly"]]
+
+ def run_test(self):
+ self.nodes[0].add_p2p_connection(P2PInterface())
+
+ self.log.info('Check that txs from p2p are rejected')
+ prevtx = self.nodes[0].getblock(self.nodes[0].getblockhash(1), 2)['tx'][0]
+ rawtx = self.nodes[0].createrawtransaction(
+ inputs=[{
+ 'txid': prevtx['txid'],
+ 'vout': 0
+ }],
+ outputs=[{
+ self.nodes[0].get_deterministic_priv_key().address: 50 - 0.00125
+ }],
+ )
+ sigtx = self.nodes[0].signrawtransactionwithkey(
+ hexstring=rawtx,
+ privkeys=[self.nodes[0].get_deterministic_priv_key().key],
+ prevtxs=[{
+ 'txid': prevtx['txid'],
+ 'vout': 0,
+ 'scriptPubKey': prevtx['vout'][0]['scriptPubKey']['hex'],
+ }],
+ )['hex']
+ assert_equal(self.nodes[0].getnetworkinfo()['localrelay'], False)
+ with self.nodes[0].assert_debug_log(['transaction sent in violation of protocol peer=0']):
+ self.nodes[0].p2p.send_message(msg_tx(FromHex(CTransaction(), sigtx)))
+ self.nodes[0].p2p.sync_with_ping()
+ assert_equal(self.nodes[0].getmempoolinfo()['size'], 0)
+
+ self.log.info('Check that txs from rpc are not rejected and relayed to other peers')
+ assert_equal(self.nodes[0].getpeerinfo()[0]['relaytxes'], True)
+ txid = self.nodes[0].testmempoolaccept([sigtx])[0]['txid']
+ with self.nodes[0].assert_debug_log(['received getdata for: tx {} peer=0'.format(txid)]):
+ self.nodes[0].sendrawtransaction(sigtx)
+ self.nodes[0].p2p.wait_for_tx(txid)
+ assert_equal(self.nodes[0].getmempoolinfo()['size'], 1)
+
+
+if __name__ == '__main__':
+ P2PBlocksOnly().main()
diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py
index 7bf8e68176..8a3f8c6f06 100755
--- a/test/functional/rpc_misc.py
+++ b/test/functional/rpc_misc.py
@@ -46,5 +46,13 @@ class RpcMiscTest(BitcoinTestFramework):
assert_raises_rpc_error(-8, "unknown mode foobar", node.getmemoryinfo, mode="foobar")
+ self.log.info("test logging")
+ assert_equal(node.logging()['qt'], True)
+ node.logging(exclude=['qt'])
+ assert_equal(node.logging()['qt'], False)
+ node.logging(include=['qt'])
+ assert_equal(node.logging()['qt'], True)
+
+
if __name__ == '__main__':
RpcMiscTest().main()
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 11ea968257..cc3a4cc72a 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -361,6 +361,14 @@ class P2PInterface(P2PConnection):
# Message receiving helper methods
+ def wait_for_tx(self, txid, timeout=60):
+ def test_function():
+ if not self.last_message.get('tx'):
+ return False
+ return self.last_message['tx'].tx.rehash() == txid
+
+ wait_until(test_function, timeout=timeout, lock=mininode_lock)
+
def wait_for_block(self, blockhash, timeout=60):
test_function = lambda: self.last_message.get("block") and self.last_message["block"].block.rehash() == blockhash
wait_until(test_function, timeout=timeout, lock=mininode_lock)
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 555d55d97f..2187bf5f5f 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -10,6 +10,7 @@ import logging
import argparse
import os
import pdb
+import random
import shutil
import sys
import tempfile
@@ -129,6 +130,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="use bitcoin-cli instead of RPC for all commands")
parser.add_argument("--perf", dest="perf", default=False, action="store_true",
help="profile running nodes with perf for the duration of the test")
+ parser.add_argument("--randomseed", type=int,
+ help="set a random seed for deterministically reproducing a previous test run")
self.add_options(parser)
self.options = parser.parse_args()
@@ -158,6 +161,22 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.options.tmpdir = tempfile.mkdtemp(prefix=TMPDIR_PREFIX)
self._start_logging()
+ # Seed the PRNG. Note that test runs are reproducible if and only if
+ # a single thread accesses the PRNG. For more information, see
+ # https://docs.python.org/3/library/random.html#notes-on-reproducibility.
+ # The network thread shouldn't access random. If we need to change the
+ # network thread to access randomness, it should instantiate its own
+ # random.Random object.
+ seed = self.options.randomseed
+
+ if seed is None:
+ seed = random.randrange(sys.maxsize)
+ else:
+ self.log.debug("User supplied random seed {}".format(seed))
+
+ random.seed(seed)
+ self.log.debug("PRNG seed is: {}".format(seed))
+
self.log.debug('Setting up network thread')
self.network_thread = NetworkThread()
self.network_thread.start()
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 190301b215..0583b42388 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -216,7 +216,7 @@ def wait_until(predicate, *, attempts=float('inf'), timeout=float('inf'), lock=N
time.sleep(0.05)
# Print the cause of the timeout
- predicate_source = inspect.getsourcelines(predicate)
+ predicate_source = "''''\n" + inspect.getsource(predicate) + "'''"
logger.error("wait_until() failed. Predicate: {}".format(predicate_source))
if attempt >= attempts:
raise AssertionError("Predicate {} not true after {} attempts".format(predicate_source, attempts))
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index ec5d6f1715..80dced733e 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -141,6 +141,7 @@ BASE_SCRIPTS = [
'rpc_net.py',
'wallet_keypool.py',
'p2p_mempool.py',
+ 'p2p_blocksonly.py',
'mining_prioritisetransaction.py',
'p2p_invalid_locator.py',
'p2p_invalid_block.py',
@@ -401,16 +402,18 @@ def run_tests(*, test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=
print_results(test_results, max_len_name, (int(time.time() - start_time)))
if coverage:
- coverage.report_rpc_coverage()
+ coverage_passed = coverage.report_rpc_coverage()
logging.debug("Cleaning up coverage data")
coverage.cleanup()
+ else:
+ coverage_passed = True
# Clear up the temp directory if all subdirectories are gone
if not os.listdir(tmpdir):
os.rmdir(tmpdir)
- all_passed = all(map(lambda test_result: test_result.was_successful, test_results))
+ all_passed = all(map(lambda test_result: test_result.was_successful, test_results)) and coverage_passed
# This will be a no-op unless failfast is True in which case there may be dangling
# processes which need to be killed.
@@ -612,8 +615,10 @@ class RPCCoverage():
if uncovered:
print("Uncovered RPC commands:")
print("".join((" - %s\n" % command) for command in sorted(uncovered)))
+ return False
else:
print("All RPC commands covered.")
+ return True
def cleanup(self):
return shutil.rmtree(self.dir)
diff --git a/test/functional/wallet_createwallet.py b/test/functional/wallet_createwallet.py
index 8ec4b98b6e..fc7969ad19 100755
--- a/test/functional/wallet_createwallet.py
+++ b/test/functional/wallet_createwallet.py
@@ -96,5 +96,28 @@ class CreateWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getnewaddress)
assert_raises_rpc_error(-4, "Error: This wallet has no available keys", w5.getrawchangeaddress)
+ self.log.info('New blank and encrypted wallets can be created')
+ self.nodes[0].createwallet(wallet_name='wblank', disable_private_keys=False, blank=True, passphrase='thisisapassphrase')
+ wblank = node.get_wallet_rpc('wblank')
+ assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", wblank.signmessage, "needanargument", "test")
+ wblank.walletpassphrase('thisisapassphrase', 10)
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getnewaddress)
+ assert_raises_rpc_error(-4, "Error: This wallet has no available keys", wblank.getrawchangeaddress)
+
+ self.log.info('Test creating a new encrypted wallet.')
+ # Born encrypted wallet is created (has keys)
+ self.nodes[0].createwallet(wallet_name='w6', disable_private_keys=False, blank=False, passphrase='thisisapassphrase')
+ w6 = node.get_wallet_rpc('w6')
+ assert_raises_rpc_error(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.", w6.signmessage, "needanargument", "test")
+ w6.walletpassphrase('thisisapassphrase', 10)
+ w6.signmessage(w6.getnewaddress('', 'legacy'), "test")
+ w6.keypoolrefill(1)
+ # There should only be 1 key
+ walletinfo = w6.getwalletinfo()
+ assert_equal(walletinfo['keypoolsize'], 1)
+ assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
+ # Empty passphrase, error
+ assert_raises_rpc_error(-16, 'Cannot encrypt a wallet with a blank password', self.nodes[0].createwallet, 'w7', False, False, '')
+
if __name__ == '__main__':
CreateWalletTest().main()
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index 9de30d0374..47c97f62bf 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -21,7 +21,6 @@ happened previously.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
- assert_raises_rpc_error,
connect_nodes,
assert_equal,
set_node_times,
@@ -39,23 +38,17 @@ Rescan = enum.Enum("Rescan", "no yes late_timestamp")
class Variant(collections.namedtuple("Variant", "call data rescan prune")):
"""Helper for importing one key and verifying scanned transactions."""
- def try_rpc(self, func, *args, **kwargs):
- if self.expect_disabled:
- assert_raises_rpc_error(-4, "Rescan is disabled in pruned mode", func, *args, **kwargs)
- else:
- return func(*args, **kwargs)
-
def do_import(self, timestamp):
"""Call one key import RPC."""
rescan = self.rescan == Rescan.yes
if self.call == Call.single:
if self.data == Data.address:
- response = self.try_rpc(self.node.importaddress, address=self.address["address"], label=self.label, rescan=rescan)
+ response = self.node.importaddress(address=self.address["address"], label=self.label, rescan=rescan)
elif self.data == Data.pub:
- response = self.try_rpc(self.node.importpubkey, pubkey=self.address["pubkey"], label=self.label, rescan=rescan)
+ response = self.node.importpubkey(pubkey=self.address["pubkey"], label=self.label, rescan=rescan)
elif self.data == Data.priv:
- response = self.try_rpc(self.node.importprivkey, privkey=self.key, label=self.label, rescan=rescan)
+ response = self.node.importprivkey(privkey=self.key, label=self.label, rescan=rescan)
assert_equal(response, None)
elif self.call in (Call.multiaddress, Call.multiscript):
@@ -172,8 +165,7 @@ class ImportRescanTest(BitcoinTestFramework):
# check the results from getbalance and listtransactions.
for variant in IMPORT_VARIANTS:
self.log.info('Run import for variant {}'.format(variant))
- variant.expect_disabled = variant.rescan == Rescan.yes and variant.prune and variant.call == Call.single
- expect_rescan = variant.rescan == Rescan.yes and not variant.expect_disabled
+ expect_rescan = variant.rescan == Rescan.yes
variant.node = self.nodes[2 + IMPORT_NODES.index(ImportNode(variant.prune, expect_rescan))]
variant.do_import(timestamp)
if expect_rescan:
@@ -198,12 +190,9 @@ class ImportRescanTest(BitcoinTestFramework):
# Check the latest results from getbalance and listtransactions.
for variant in IMPORT_VARIANTS:
self.log.info('Run check for variant {}'.format(variant))
- if not variant.expect_disabled:
- variant.expected_balance += variant.sent_amount
- variant.expected_txs += 1
- variant.check(variant.sent_txid, variant.sent_amount, 1)
- else:
- variant.check()
+ variant.expected_balance += variant.sent_amount
+ variant.expected_txs += 1
+ variant.check(variant.sent_txid, variant.sent_amount, 1)
if __name__ == "__main__":
ImportRescanTest().main()
diff --git a/test/lint/lint-all.sh b/test/lint/lint-all.sh
index 7c4f96cb3b..fabc24c91b 100755
--- a/test/lint/lint-all.sh
+++ b/test/lint/lint-all.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
#
-# Copyright (c) 2017 The Bitcoin Core developers
+# Copyright (c) 2017-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
@@ -16,11 +16,15 @@ set -u
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
LINTALL=$(basename "${BASH_SOURCE[0]}")
+EXIT_CODE=0
+
for f in "${SCRIPTDIR}"/lint-*.sh; do
if [ "$(basename "$f")" != "$LINTALL" ]; then
if ! "$f"; then
echo "^---- failure generated from $f"
- exit 1
+ EXIT_CODE=1
fi
fi
done
+
+exit ${EXIT_CODE}