aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/functional/rpc_net.py55
-rwxr-xr-xtest/fuzz/test_runner.py72
2 files changed, 98 insertions, 29 deletions
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 068a76f36b..d4cfb48881 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -8,6 +8,8 @@ Tests correspond to code in rpc/net.cpp.
"""
from decimal import Decimal
+from itertools import product
+import time
from test_framework.p2p import P2PInterface
import test_framework.messages
@@ -17,6 +19,7 @@ from test_framework.messages import (
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
+ assert_approx,
assert_equal,
assert_greater_than_or_equal,
assert_greater_than,
@@ -48,25 +51,27 @@ class NetTest(BitcoinTestFramework):
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')
+ # Get out of IBD for the minfeefilter and getpeerinfo tests.
+ self.nodes[0].generate(101)
+ # Connect nodes both ways.
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 0)
- self._test_connection_count()
- self._test_getnettotals()
- self._test_getnetworkinfo()
- self._test_getaddednodeinfo()
- self._test_getpeerinfo()
+ self.test_connection_count()
+ self.test_getpeerinfo()
+ self.test_getnettotals()
+ self.test_getnetworkinfo()
+ self.test_getaddednodeinfo()
self.test_service_flags()
- self._test_getnodeaddresses()
+ self.test_getnodeaddresses()
- def _test_connection_count(self):
- # connect_nodes connects each node to the other
+ def test_connection_count(self):
+ self.log.info("Test getconnectioncount")
+ # After using `connect_nodes` to connect nodes 0 and 1 to each other.
assert_equal(self.nodes[0].getconnectioncount(), 2)
- def _test_getnettotals(self):
+ def test_getnettotals(self):
+ self.log.info("Test getnettotals")
# getnettotals totalbytesrecv and totalbytessent should be
# consistent with getpeerinfo. Since the RPC calls are not atomic,
# and messages might have been recvd or sent between RPC calls, call
@@ -96,7 +101,8 @@ class NetTest(BitcoinTestFramework):
assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), before['bytesrecv_per_msg'].get('pong', 0) + 32)
assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), before['bytessent_per_msg'].get('ping', 0) + 32)
- def _test_getnetworkinfo(self):
+ def test_getnetworkinfo(self):
+ self.log.info("Test getnetworkinfo")
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
assert_equal(self.nodes[0].getnetworkinfo()['connections'], 2)
@@ -108,7 +114,7 @@ class NetTest(BitcoinTestFramework):
with self.nodes[0].assert_debug_log(expected_msgs=['SetNetworkActive: true\n']):
self.nodes[0].setnetworkactive(state=True)
- self.log.info('Connect nodes both way')
+ # Connect nodes both ways.
connect_nodes(self.nodes[0], 1)
connect_nodes(self.nodes[1], 0)
@@ -120,7 +126,8 @@ class NetTest(BitcoinTestFramework):
for info in network_info:
assert_net_servicesnames(int(info["localservices"], 0x10), info["localservicesnames"])
- def _test_getaddednodeinfo(self):
+ def test_getaddednodeinfo(self):
+ self.log.info("Test getaddednodeinfo")
assert_equal(self.nodes[0].getaddednodeinfo(), [])
# add a node (node2) to node0
ip_port = "127.0.0.1:{}".format(p2p_port(2))
@@ -139,8 +146,20 @@ class NetTest(BitcoinTestFramework):
# check that a non-existent node returns an error
assert_raises_rpc_error(-24, "Node has not been added", self.nodes[0].getaddednodeinfo, '1.1.1.1')
- def _test_getpeerinfo(self):
+ def test_getpeerinfo(self):
+ self.log.info("Test getpeerinfo")
+ # Create a few getpeerinfo last_block/last_transaction values.
+ if self.is_wallet_compiled():
+ self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
+ self.nodes[1].generate(1)
+ self.sync_all()
+ time_now = int(time.time())
peer_info = [x.getpeerinfo() for x in self.nodes]
+ # Verify last_block and last_transaction keys/values.
+ for node, peer, field in product(range(self.num_nodes), range(2), ['last_block', 'last_transaction']):
+ assert field in peer_info[node][peer].keys()
+ if peer_info[node][peer][field] != 0:
+ assert_approx(peer_info[node][peer][field], time_now, vspan=60)
# check both sides of bidirectional connection between nodes
# the address bound to on one side will be the source address for the other node
assert_equal(peer_info[0][0]['addrbind'], peer_info[1][0]['addr'])
@@ -152,11 +171,13 @@ class NetTest(BitcoinTestFramework):
assert_net_servicesnames(int(info[0]["services"], 0x10), info[0]["servicesnames"])
def test_service_flags(self):
+ self.log.info("Test service flags")
self.nodes[0].add_p2p_connection(P2PInterface(), services=(1 << 4) | (1 << 63))
assert_equal(['UNKNOWN[2^4]', 'UNKNOWN[2^63]'], self.nodes[0].getpeerinfo()[-1]['servicesnames'])
self.nodes[0].disconnect_p2ps()
- def _test_getnodeaddresses(self):
+ def test_getnodeaddresses(self):
+ self.log.info("Test getnodeaddresses")
self.nodes[0].add_p2p_connection(P2PInterface())
# Add some addresses to the Address Manager over RPC. Due to the way
diff --git a/test/fuzz/test_runner.py b/test/fuzz/test_runner.py
index 56b18752ec..c7895edbcc 100755
--- a/test/fuzz/test_runner.py
+++ b/test/fuzz/test_runner.py
@@ -56,6 +56,14 @@ def main():
'--m_dir',
help='Merge inputs from this directory into the seed_dir. Needs /target subdirectory.',
)
+ parser.add_argument(
+ '-g',
+ '--generate',
+ action='store_true',
+ help='Create new corpus seeds (or extend the existing ones) by running'
+ ' the given targets for a finite number of times. Outputs them to'
+ ' the passed seed_dir.'
+ )
args = parser.parse_args()
@@ -100,19 +108,20 @@ def main():
logging.info("{} of {} detected fuzz target(s) selected: {}".format(len(test_list_selection), len(test_list_all), " ".join(test_list_selection)))
- test_list_seedless = []
- for t in test_list_selection:
- corpus_path = os.path.join(args.seed_dir, t)
- if not os.path.exists(corpus_path) or len(os.listdir(corpus_path)) == 0:
- test_list_seedless.append(t)
- test_list_seedless.sort()
- if test_list_seedless:
- logging.info(
- "Fuzzing harnesses lacking a seed corpus: {}".format(
- " ".join(test_list_seedless)
+ if not args.generate:
+ test_list_seedless = []
+ for t in test_list_selection:
+ corpus_path = os.path.join(args.seed_dir, t)
+ if not os.path.exists(corpus_path) or len(os.listdir(corpus_path)) == 0:
+ test_list_seedless.append(t)
+ test_list_seedless.sort()
+ if test_list_seedless:
+ logging.info(
+ "Fuzzing harnesses lacking a seed corpus: {}".format(
+ " ".join(test_list_seedless)
+ )
)
- )
- logging.info("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets")
+ logging.info("Please consider adding a fuzz seed corpus at https://github.com/bitcoin-core/qa-assets")
try:
help_output = subprocess.run(
@@ -133,6 +142,14 @@ def main():
sys.exit(1)
with ThreadPoolExecutor(max_workers=args.par) as fuzz_pool:
+ if args.generate:
+ return generate_corpus_seeds(
+ fuzz_pool=fuzz_pool,
+ build_dir=config["environment"]["BUILDDIR"],
+ seed_dir=args.seed_dir,
+ targets=test_list_selection,
+ )
+
if args.m_dir:
merge_inputs(
fuzz_pool=fuzz_pool,
@@ -152,6 +169,37 @@ def main():
)
+def generate_corpus_seeds(*, fuzz_pool, build_dir, seed_dir, targets):
+ """Generates new corpus seeds.
+
+ Run {targets} without input, and outputs the generated corpus seeds to
+ {seed_dir}.
+ """
+ logging.info("Generating corpus seeds to {}".format(seed_dir))
+
+ def job(command):
+ logging.debug("Running '{}'\n".format(" ".join(command)))
+ logging.debug("Command '{}' output:\n'{}'\n".format(
+ ' '.join(command),
+ subprocess.run(command, check=True, stderr=subprocess.PIPE,
+ universal_newlines=True).stderr
+ ))
+
+ futures = []
+ for target in targets:
+ target_seed_dir = os.path.join(seed_dir, target)
+ os.makedirs(target_seed_dir, exist_ok=True)
+ command = [
+ os.path.join(build_dir, "src", "test", "fuzz", target),
+ "-runs=100000",
+ target_seed_dir,
+ ]
+ futures.append(fuzz_pool.submit(job, command))
+
+ for future in as_completed(futures):
+ future.result()
+
+
def merge_inputs(*, fuzz_pool, corpus, test_list, build_dir, merge_dir):
logging.info("Merge the inputs in the passed dir into the seed_dir. Passed dir {}".format(merge_dir))
jobs = []