Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright 2014 BitPay Inc.3# Copyright 2016-present The Bitcoin Core developers4# Distributed under the MIT software license, see the accompanying5# file COPYING or https://opensource.org/license/mit.6"""Exercise the utils via json-defined tests."""8from test_framework.test_framework import BitcoinTestFramework10import difflib11import json12import os13import subprocess14from pathlib import Path17class ToolUtils(BitcoinTestFramework):18def set_test_params(self):19self.num_nodes = 0 # No node/datadir needed21def setup_network(self):22pass24def skip_test_if_missing_module(self):25self.skip_if_no_bitcoin_tx()26self.skip_if_no_bitcoin_util()28def run_test(self):29self.testcase_dir = Path(self.config["environment"]["SRCDIR"]) / "test" / "functional" / "data" / "util"30self.bins = self.get_binaries()31with open(self.testcase_dir / "bitcoin-util-test.json") as f:32input_data = json.loads(f.read())34for i, test_obj in enumerate(input_data):35self.log.debug(f"Running [{i}]: " + test_obj["description"])36self.test_one(test_obj)38def test_one(self, testObj):39"""Runs a single test, comparing output and RC to expected output and RC.41Raises an error if input can't be read, executable fails, or output/RC42are not as expected. Error is caught by bctester() and reported.43"""44# Get the exec names and arguments45if testObj["exec"] == "./bitcoin-util":46execrun = self.bins.util_argv() + testObj["args"]47elif testObj["exec"] == "./bitcoin-tx":48execrun = self.bins.tx_argv() + testObj["args"]50# Read the input data (if there is any)51inputData = None52if "input" in testObj:53with open(self.testcase_dir / testObj["input"]) as f:54inputData = f.read()56# Read the expected output data (if there is any)57outputFn = None58outputData = None59outputType = None60if "output_cmp" in testObj:61outputFn = testObj['output_cmp']62outputType = os.path.splitext(outputFn)[1][1:] # output type from file extension (determines how to compare)63with open(self.testcase_dir / outputFn) as f:64outputData = f.read()65if not outputData:66raise Exception(f"Output data missing for {outputFn}")67if not outputType:68raise Exception(f"Output file {outputFn} does not have a file extension")70# Run the test71res = subprocess.run(execrun, capture_output=True, text=True, input=inputData)73if outputData:74data_mismatch, formatting_mismatch = False, False75# Parse command output and expected output76try:77a_parsed = parse_output(res.stdout, outputType)78except Exception as e:79self.log.error(f"Error parsing command output as {outputType}: '{str(e)}'; res: {str(res)}")80raise81try:82b_parsed = parse_output(outputData, outputType)83except Exception as e:84self.log.error('Error parsing expected output %s as %s: %s' % (outputFn, outputType, e))85raise86# Compare data87if a_parsed != b_parsed:88self.log.error(f"Output data mismatch for {outputFn} (format {outputType}); res: {str(res)}")89data_mismatch = True90# Compare formatting91if res.stdout != outputData:92error_message = f"Output formatting mismatch for {outputFn}:\nres: {str(res)}\n"93error_message += "".join(difflib.context_diff(outputData.splitlines(True),94res.stdout.splitlines(True),95fromfile=outputFn,96tofile="returned"))97self.log.error(error_message)98formatting_mismatch = True100assert not data_mismatch and not formatting_mismatch102# Compare the return code to the expected return code103wantRC = 0104if "return_code" in testObj:105wantRC = testObj['return_code']106if res.returncode != wantRC:107raise Exception(f"Return code mismatch for {outputFn}; res: {str(res)}")109if "error_txt" in testObj:110want_error = testObj["error_txt"]111# A partial match instead of an exact match makes writing tests easier112# and should be sufficient.113if want_error not in res.stderr:114raise Exception(f"Error mismatch:\nExpected: {want_error}\nReceived: {res.stderr.rstrip()}\nres: {str(res)}")115else:116if res.stderr:117raise Exception(f"Unexpected error received: {res.stderr.rstrip()}\nres: {str(res)}")120def parse_output(a, fmt):121"""Parse the output according to specified format.123Raise an error if the output can't be parsed."""124if fmt == 'json': # json: compare parsed data125return json.loads(a)126elif fmt == 'hex': # hex: parse and compare binary data127return bytes.fromhex(a.strip())128else:129raise NotImplementedError("Don't know how to compare %s" % fmt)132if __name__ == "__main__":133ToolUtils(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.