Changeset View
Changeset View
Standalone View
Standalone View
contrib/devtools/test/generate_bestchainparams_test.py
- This file was added.
Property | Old Value | New Value |
---|---|---|
File Mode | null | 100755 |
#!/usr/bin/env python3 | |||||
# Copyright (c) 2019 The Bitcoin developers | |||||
# Distributed under the MIT software license, see the accompanying | |||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
import sys | |||||
sys.path.append('..') | |||||
from generate_bestchainparams import main as GenerateBestChainParams | |||||
import re | |||||
import unittest | |||||
def MockRPCResult(shell_call, exit_code, stdout): | |||||
# This method's output is used by generate_bestchainparams.py internally, | |||||
# so the resulting tuple should always match the form: | |||||
# shell_call (command + args), exit_code, stdout, stderr | |||||
return shell_call, exit_code, stdout, '' | |||||
def GetShellString(args, testnet): | |||||
bitcoin_cli = './bitcoin-cli' | |||||
if testnet: | |||||
bitcoin_cli += ' --testnet' | |||||
return '{} {}'.format(bitcoin_cli, args) | |||||
def rpcMock_getblockchaininfo(args, chain, numBlocks, testnet=False): | |||||
return MockRPCResult(GetShellString(args, testnet), 0, """{{ | |||||
"chain": "{chain}", | |||||
"blocks": {numBlocks}, | |||||
"headers": {numBlocks}, | |||||
"bestblockhash": "0000000000000000039c96605d7fca74a5e185ea5634198346e9e07fd235b666", | |||||
"difficulty": 274412074285.6605, | |||||
"mediantime": 1562168718, | |||||
"verificationprogress": 0.9999958005632363, | |||||
"initialblockdownload": false, | |||||
"chainwork": "000000000000000000000000000000000000000000f3145d6494c45afcc9e357", | |||||
"size_on_disk": 952031444, | |||||
"pruned": true, | |||||
"pruneheight": 582974, | |||||
"automatic_pruning": true, | |||||
"prune_target_size": 1048576000 | |||||
}}""".format(chain=chain, numBlocks=numBlocks)) | |||||
def rpcMock_getblockhash(args, blockhash, testnet=False): | |||||
return MockRPCResult(GetShellString(args, testnet), 0, blockhash) | |||||
def rpcMock_getblockheader(args, blockhash, chainwork, testnet=False): | |||||
return MockRPCResult(GetShellString(args, testnet), 0, """{{ | |||||
"hash": "{blockhash}", | |||||
"confirmations": 12732, | |||||
"height": 1300000, | |||||
"version": 536870912, | |||||
"versionHex": "20000000", | |||||
"merkleroot": "78fe397a5163796e7df159df5aa92096c92ec3cbf43955b996bfc0d347853e86", | |||||
"time": 1556004882, | |||||
"mediantime": 1555998692, | |||||
"nonce": 2401154079, | |||||
"bits": "1d00ffff", | |||||
"difficulty": 1, | |||||
"chainwork": "{chainwork}", | |||||
"previousblockhash": "00000000000303bb4d23987f5432c5e9ec6d05caed576c102f9e0f74e1d8fc6e", | |||||
"nextblockhash": "000000001ab7a68eb3e41dad9f4515344a3865da19363a54a691f7524819be9f" | |||||
}}""".format(blockhash=blockhash, chainwork=chainwork)) | |||||
def RPCMatcher(requests_and_responses, shell_call): | |||||
if shell_call in requests_and_responses: | |||||
return requests_and_responses[shell_call] | |||||
else: | |||||
return MockRPCResult(shell_call, 99, """error code: -99 | |||||
error message: | |||||
mock error""") | |||||
def RPCFactory(requests_and_responses): | |||||
return lambda cli: lambda request_args: RPCMatcher(requests_and_responses, '{} {}'.format(cli, request_args)) | |||||
def MakeRPCFactory(rpc_result_list): | |||||
rpc_map = {} | |||||
for rpc_result in rpc_result_list: | |||||
rpc_map[rpc_result[0]] = rpc_result | |||||
return RPCFactory(rpc_map) | |||||
def CheckResult(test, stdout, expectedRegexes=None): | |||||
for expectedRegex in expectedRegexes: | |||||
expectedPattern = re.compile(expectedRegex) | |||||
test.assertTrue(expectedPattern.search(stdout, re.MULTILINE), | |||||
"Expected pattern '{}' was not found.".format(expectedPattern)) | |||||
def CheckMockFailure(test, args, factoryMap): | |||||
with test.assertRaises(Exception) as context: | |||||
GenerateBestChainParams(args, factoryMap) | |||||
CheckResult(test, str(context.exception), ['error code: -99']) | |||||
class GenerateBestChainParamsTests(unittest.TestCase): | |||||
maxDiff = None | |||||
def setUp(self): | |||||
defaultMainnetBlockHash = '0000000000000000003ef673ae12bc6017481830d37b9c52ce1e79c080e812b8' | |||||
defaultMainnetChainWork = '000000000000000000000000000000000000000000f2537ccf2e07bbe15e70e1' | |||||
self.defaultFactoriesMainnet = [ | |||||
rpcMock_getblockchaininfo('getblockchaininfo', 'main', 123000), | |||||
rpcMock_getblockhash('getblockhash 122998', | |||||
defaultMainnetBlockHash), | |||||
rpcMock_getblockheader('getblockheader {}'.format( | |||||
defaultMainnetBlockHash), defaultMainnetBlockHash, defaultMainnetChainWork), | |||||
] | |||||
defaultTestnetBlockHash = '0000000000000298a9fa227f0ec32f2b7585f3e64c8b3369e7f8b4fd8ea3d836' | |||||
defaultTestnetChainWork = '00000000000000000000000000000000000000000000004fdb4795a837f19671' | |||||
self.defaultFactoriesTestnet = [ | |||||
rpcMock_getblockchaininfo( | |||||
'getblockchaininfo', 'test', 234000, testnet=True), | |||||
rpcMock_getblockhash('getblockhash 232000', | |||||
defaultTestnetBlockHash, testnet=True), | |||||
rpcMock_getblockheader('getblockheader {}'.format( | |||||
defaultTestnetBlockHash), defaultTestnetBlockHash, defaultTestnetChainWork, testnet=True), | |||||
] | |||||
altMainnetBlockHash = '000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201' | |||||
altMainnetChainWork = '0000000000000000000000000000000000000000007ae48aca46e3b449ad9714' | |||||
self.altFactoriesMainnet = [ | |||||
rpcMock_getblockchaininfo('getblockchaininfo', 'main', 345000), | |||||
rpcMock_getblockhash('getblockhash 345000', altMainnetBlockHash), | |||||
rpcMock_getblockheader('getblockheader {}'.format( | |||||
altMainnetBlockHash), altMainnetBlockHash, altMainnetChainWork), | |||||
] | |||||
altTestnetBlockHash = '000000002a7a59c4f88a049fa5e405e67cd689d75a1f330cbf26286cf0ec1d8f' | |||||
altTestnetChainWork = '00000000000000000000000000000000000000000000004802a671314f8f803f' | |||||
self.altFactoriesTestnet = [ | |||||
rpcMock_getblockchaininfo( | |||||
'getblockchaininfo', 'test', 456000, testnet=True), | |||||
rpcMock_getblockhash('getblockhash 456000', | |||||
altTestnetBlockHash, testnet=True), | |||||
rpcMock_getblockheader('getblockheader {}'.format( | |||||
altTestnetBlockHash), altTestnetBlockHash, altTestnetChainWork, testnet=True), | |||||
] | |||||
def test_happy_path(self): | |||||
factoryMap = MakeRPCFactory( | |||||
self.defaultFactoriesMainnet + self.defaultFactoriesTestnet) | |||||
CheckResult(self, GenerateBestChainParams([], factoryMap), [ | |||||
'MainNetMinimumChainWork.*"000000000000000000000000000000000000000000f2537ccf2e07bbe15e70e1"', | |||||
'MainNetDefaultAssumeValid.*"0000000000000000003ef673ae12bc6017481830d37b9c52ce1e79c080e812b8"', | |||||
'TestNetMinimumChainWork.*"00000000000000000000000000000000000000000000004fdb4795a837f19671"', | |||||
'TestNetDefaultAssumeValid.*"0000000000000298a9fa227f0ec32f2b7585f3e64c8b3369e7f8b4fd8ea3d836"', | |||||
]) | |||||
def test_happy_path_explicit_mainnet(self): | |||||
factoryMap = MakeRPCFactory( | |||||
self.altFactoriesMainnet + self.defaultFactoriesTestnet) | |||||
CheckResult(self, GenerateBestChainParams(['-m', '345000'], factoryMap), [ | |||||
'MainNetMinimumChainWork.*"0000000000000000000000000000000000000000007ae48aca46e3b449ad9714"', | |||||
'MainNetDefaultAssumeValid.*"000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201"', | |||||
'TestNetMinimumChainWork.*"00000000000000000000000000000000000000000000004fdb4795a837f19671"', | |||||
'TestNetDefaultAssumeValid.*"0000000000000298a9fa227f0ec32f2b7585f3e64c8b3369e7f8b4fd8ea3d836"', | |||||
]) | |||||
def test_happy_path_explicit_testnet(self): | |||||
factoryMap = MakeRPCFactory( | |||||
self.defaultFactoriesMainnet + self.altFactoriesTestnet) | |||||
CheckResult(self, GenerateBestChainParams(['-t', '456000'], factoryMap), [ | |||||
'MainNetMinimumChainWork.*"000000000000000000000000000000000000000000f2537ccf2e07bbe15e70e1"', | |||||
'MainNetDefaultAssumeValid.*"0000000000000000003ef673ae12bc6017481830d37b9c52ce1e79c080e812b8"', | |||||
'TestNetMinimumChainWork.*"00000000000000000000000000000000000000000000004802a671314f8f803f"', | |||||
'TestNetDefaultAssumeValid.*"000000002a7a59c4f88a049fa5e405e67cd689d75a1f330cbf26286cf0ec1d8f"', | |||||
]) | |||||
def test_happy_path_explicit_mainnet_and_testnet(self): | |||||
factoryMap = MakeRPCFactory( | |||||
self.altFactoriesMainnet + self.altFactoriesTestnet) | |||||
CheckResult(self, GenerateBestChainParams(['-m', '345000', '-t', '456000'], factoryMap), [ | |||||
'MainNetMinimumChainWork.*"0000000000000000000000000000000000000000007ae48aca46e3b449ad9714"', | |||||
'MainNetDefaultAssumeValid.*"000000000000000005e14d3f9fdfb70745308706615cfa9edca4f4558332b201"', | |||||
'TestNetMinimumChainWork.*"00000000000000000000000000000000000000000000004802a671314f8f803f"', | |||||
'TestNetDefaultAssumeValid.*"000000002a7a59c4f88a049fa5e405e67cd689d75a1f330cbf26286cf0ec1d8f"', | |||||
]) | |||||
def test_bitcoin_cli_failures(self): | |||||
for i in range(len(self.defaultFactoriesMainnet)): | |||||
CheckMockFailure(self, '', MakeRPCFactory( | |||||
self.defaultFactoriesTestnet + self.defaultFactoriesMainnet[:i])) | |||||
for i in range(len(self.defaultFactoriesTestnet)): | |||||
CheckMockFailure(self, '', MakeRPCFactory( | |||||
self.defaultFactoriesMainnet + self.defaultFactoriesTestnet[:i])) | |||||
unittest.main() |