aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kraft <d@domob.eu>2014-10-20 14:14:04 +0200
committerDaniel Kraft <d@domob.eu>2014-10-24 08:53:04 +0200
commitdcb98466b4f8193fc28656d17b2317f21665fa3a (patch)
treeaf414ee4e69a16a680ec364ab51c2ac5b7f549c0
parent3552d4b859d56726cd25baa6f1e5988050bdad33 (diff)
Extend getchaintips RPC test.
Add the capability to simulate network splits to the RPC test framework and use it to do more extensive testing of 'getchaintips'.
-rwxr-xr-xqa/rpc-tests/forknotify.py35
-rwxr-xr-xqa/rpc-tests/getblocktemplate.py20
-rwxr-xr-xqa/rpc-tests/getchaintips.py50
-rwxr-xr-xqa/rpc-tests/listtransactions.py50
-rwxr-xr-xqa/rpc-tests/receivedby.py68
-rwxr-xr-xqa/rpc-tests/smartfees.py48
-rwxr-xr-xqa/rpc-tests/test_framework.py71
7 files changed, 207 insertions, 135 deletions
diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py
index a482f7cc5a..23bfb74175 100755
--- a/qa/rpc-tests/forknotify.py
+++ b/qa/rpc-tests/forknotify.py
@@ -17,31 +17,30 @@ class ForkNotifyTest(BitcoinTestFramework):
alert_filename = None # Set by setup_network
- def setup_network(self, test_dir):
- nodes = []
- self.alert_filename = os.path.join(test_dir, "alert.txt")
+ def setup_network(self):
+ self.nodes = []
+ self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
with open(self.alert_filename, 'w') as f:
pass # Just open then close to create zero-length file
- nodes.append(start_node(0, test_dir,
+ self.nodes.append(start_node(0, self.options.tmpdir,
["-blockversion=2", "-alertnotify=echo %s >> '" + self.alert_filename + "'"]))
# Node1 mines block.version=211 blocks
- nodes.append(start_node(1, test_dir,
+ self.nodes.append(start_node(1, self.options.tmpdir,
["-blockversion=211"]))
- connect_nodes(nodes[1], 0)
+ connect_nodes(self.nodes[1], 0)
- sync_blocks(nodes)
- return nodes
-
+ self.is_network_split = False
+ self.sync_all()
- def run_test(self, nodes):
+ def run_test(self):
# Mine 51 up-version blocks
- nodes[1].setgenerate(True, 51)
- sync_blocks(nodes)
+ self.nodes[1].setgenerate(True, 51)
+ self.sync_all()
# -alertnotify should trigger on the 51'st,
# but mine and sync another to give
# -alertnotify time to write
- nodes[1].setgenerate(True, 1)
- sync_blocks(nodes)
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
with open(self.alert_filename, 'r') as f:
alert_text = f.read()
@@ -50,10 +49,10 @@ class ForkNotifyTest(BitcoinTestFramework):
raise AssertionError("-alertnotify did not warn of up-version blocks")
# Mine more up-version blocks, should not get more alerts:
- nodes[1].setgenerate(True, 1)
- sync_blocks(nodes)
- nodes[1].setgenerate(True, 1)
- sync_blocks(nodes)
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
with open(self.alert_filename, 'r') as f:
alert_text2 = f.read()
diff --git a/qa/rpc-tests/getblocktemplate.py b/qa/rpc-tests/getblocktemplate.py
index 8d97719ec3..5ae5d09601 100755
--- a/qa/rpc-tests/getblocktemplate.py
+++ b/qa/rpc-tests/getblocktemplate.py
@@ -51,40 +51,40 @@ class GetBlockTemplateTest(BitcoinTestFramework):
Test longpolling with getblocktemplate.
'''
- def run_test(self, nodes):
+ def run_test(self):
print "Warning: this test will take about 70 seconds in the best case. Be patient."
- nodes[0].setgenerate(True, 10)
- templat = nodes[0].getblocktemplate()
+ self.nodes[0].setgenerate(True, 10)
+ templat = self.nodes[0].getblocktemplate()
longpollid = templat['longpollid']
# longpollid should not change between successive invocations if nothing else happens
- templat2 = nodes[0].getblocktemplate()
+ templat2 = self.nodes[0].getblocktemplate()
assert(templat2['longpollid'] == longpollid)
# Test 1: test that the longpolling wait if we do nothing
- thr = LongpollThread(nodes[0])
+ thr = LongpollThread(self.nodes[0])
thr.start()
# check that thread still lives
thr.join(5) # wait 5 seconds or until thread exits
assert(thr.is_alive())
# Test 2: test that longpoll will terminate if another node generates a block
- nodes[1].setgenerate(True, 1) # generate a block on another node
+ self.nodes[1].setgenerate(True, 1) # generate a block on another node
# check that thread will exit now that new transaction entered mempool
thr.join(5) # wait 5 seconds or until thread exits
assert(not thr.is_alive())
# Test 3: test that longpoll will terminate if we generate a block ourselves
- thr = LongpollThread(nodes[0])
+ thr = LongpollThread(self.nodes[0])
thr.start()
- nodes[0].setgenerate(True, 1) # generate a block on another node
+ self.nodes[0].setgenerate(True, 1) # generate a block on another node
thr.join(5) # wait 5 seconds or until thread exits
assert(not thr.is_alive())
# Test 4: test that introducing a new transaction into the mempool will terminate the longpoll
- thr = LongpollThread(nodes[0])
+ thr = LongpollThread(self.nodes[0])
thr.start()
# generate a random transaction and submit it
- (txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"), Decimal("0.0"), Decimal("0.001"), 20)
+ (txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"), Decimal("0.0"), Decimal("0.001"), 20)
# after one minute, every 10 seconds the mempool is probed, so in 80 seconds it should have returned
thr.join(60 + 20)
assert(not thr.is_alive())
diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py
index a83c499743..842fcad2b2 100755
--- a/qa/rpc-tests/getchaintips.py
+++ b/qa/rpc-tests/getchaintips.py
@@ -3,22 +3,52 @@
# Distributed under the MIT/X11 software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-# Exercise the getchaintips API.
-
-# Since the test framework does not generate orphan blocks, we can
-# unfortunately not check for them!
+# Exercise the getchaintips API. We introduce a network split, work
+# on chains of different lengths, and join the network together again.
+# This gives us two tips, verify that it works.
from test_framework import BitcoinTestFramework
from util import assert_equal
class GetChainTipsTest (BitcoinTestFramework):
- def run_test (self, nodes):
- res = nodes[0].getchaintips ()
- assert_equal (len (res), 1)
- res = res[0]
- assert_equal (res['branchlen'], 0)
- assert_equal (res['height'], 200)
+ def run_test (self):
+ BitcoinTestFramework.run_test (self)
+
+ tips = self.nodes[0].getchaintips ()
+ assert_equal (len (tips), 1)
+ assert_equal (tips[0]['branchlen'], 0)
+ assert_equal (tips[0]['height'], 200)
+
+ # Split the network and build two chains of different lengths.
+ self.split_network ()
+ self.nodes[0].setgenerate (True, 10);
+ self.nodes[2].setgenerate (True, 20);
+ self.sync_all ()
+
+ tips = self.nodes[1].getchaintips ()
+ assert_equal (len (tips), 1)
+ shortTip = tips[0]
+ assert_equal (shortTip['branchlen'], 0)
+ assert_equal (shortTip['height'], 210)
+
+ tips = self.nodes[3].getchaintips ()
+ assert_equal (len (tips), 1)
+ longTip = tips[0]
+ assert_equal (longTip['branchlen'], 0)
+ assert_equal (longTip['height'], 220)
+
+ # Join the network halves and check that we now have two tips
+ # (at least at the nodes that previously had the short chain).
+ self.join_network ()
+
+ tips = self.nodes[0].getchaintips ()
+ assert_equal (len (tips), 2)
+ assert_equal (tips[0], longTip)
+
+ assert_equal (tips[1]['branchlen'], 10)
+ tips[1]['branchlen'] = 0;
+ assert_equal (tips[1], shortTip)
if __name__ == '__main__':
GetChainTipsTest ().main ()
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 50385b4372..6102052a6f 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -33,62 +33,64 @@ def check_array_result(object_array, to_match, expected):
class ListTransactionsTest(BitcoinTestFramework):
- def run_test(self, nodes):
+ def run_test(self):
# Simple send, 0 to 1:
- txid = nodes[0].sendtoaddress(nodes[1].getnewaddress(), 0.1)
- sync_mempools(nodes)
- check_array_result(nodes[0].listtransactions(),
+ txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
+ self.sync_all()
+ check_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
# mine a block, confirmations should change:
- nodes[0].setgenerate(True, 1)
- sync_blocks(nodes)
- check_array_result(nodes[0].listtransactions(),
+ self.nodes[0].setgenerate(True, 1)
+ self.sync_all()
+ check_array_result(self.nodes[0].listtransactions(),
{"txid":txid},
{"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"txid":txid},
{"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
# send-to-self:
- txid = nodes[0].sendtoaddress(nodes[0].getnewaddress(), 0.2)
- check_array_result(nodes[0].listtransactions(),
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
+ check_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"send"},
{"amount":Decimal("-0.2")})
- check_array_result(nodes[0].listtransactions(),
+ check_array_result(self.nodes[0].listtransactions(),
{"txid":txid, "category":"receive"},
{"amount":Decimal("0.2")})
# sendmany from node1: twice to self, twice to node2:
- send_to = { nodes[0].getnewaddress() : 0.11, nodes[1].getnewaddress() : 0.22,
- nodes[0].getaccountaddress("from1") : 0.33, nodes[1].getaccountaddress("toself") : 0.44 }
- txid = nodes[1].sendmany("", send_to)
- sync_mempools(nodes)
- check_array_result(nodes[1].listtransactions(),
+ send_to = { self.nodes[0].getnewaddress() : 0.11,
+ self.nodes[1].getnewaddress() : 0.22,
+ self.nodes[0].getaccountaddress("from1") : 0.33,
+ self.nodes[1].getaccountaddress("toself") : 0.44 }
+ txid = self.nodes[1].sendmany("", send_to)
+ self.sync_all()
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.11")},
{"txid":txid} )
- check_array_result(nodes[0].listtransactions(),
+ check_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.11")},
{"txid":txid} )
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.22")},
{"txid":txid} )
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.22")},
{"txid":txid} )
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.33")},
{"txid":txid} )
- check_array_result(nodes[0].listtransactions(),
+ check_array_result(self.nodes[0].listtransactions(),
{"category":"receive","amount":Decimal("0.33")},
{"txid":txid, "account" : "from1"} )
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"send","amount":Decimal("-0.44")},
{"txid":txid, "account" : ""} )
- check_array_result(nodes[1].listtransactions(),
+ check_array_result(self.nodes[1].listtransactions(),
{"category":"receive","amount":Decimal("0.44")},
{"txid":txid, "account" : "toself"} )
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
index 61f5e0452b..7170255242 100755
--- a/qa/rpc-tests/receivedby.py
+++ b/qa/rpc-tests/receivedby.py
@@ -54,36 +54,36 @@ def check_array_result(object_array, to_match, expected, should_not_find = False
class ReceivedByTest(BitcoinTestFramework):
- def run_test(self, nodes):
+ def run_test(self):
'''
listreceivedbyaddress Test
'''
# Send from node 0 to 1
- addr = nodes[1].getnewaddress()
- txid = nodes[0].sendtoaddress(addr, 0.1)
- sync_mempools(nodes)
+ addr = self.nodes[1].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(addr, 0.1)
+ self.sync_all()
#Check not listed in listreceivedbyaddress because has 0 confirmations
- check_array_result(nodes[1].listreceivedbyaddress(),
+ check_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{ },
True)
#Bury Tx under 10 block so it will be returned by listreceivedbyaddress
- nodes[1].setgenerate(True, 10)
- sync_blocks(nodes)
- check_array_result(nodes[1].listreceivedbyaddress(),
+ self.nodes[1].setgenerate(True, 10)
+ self.sync_all()
+ check_array_result(self.nodes[1].listreceivedbyaddress(),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence < 10
- check_array_result(nodes[1].listreceivedbyaddress(5),
+ check_array_result(self.nodes[1].listreceivedbyaddress(5),
{"address":addr},
{"address":addr, "account":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]})
#With min confidence > 10, should not find Tx
- check_array_result(nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
+ check_array_result(self.nodes[1].listreceivedbyaddress(11),{"address":addr},{ },True)
#Empty Tx
- addr = nodes[1].getnewaddress()
- check_array_result(nodes[1].listreceivedbyaddress(0,True),
+ addr = self.nodes[1].getnewaddress()
+ check_array_result(self.nodes[1].listreceivedbyaddress(0,True),
{"address":addr},
{"address":addr, "account":"", "amount":0, "confirmations":0, "txids":[]})
@@ -91,24 +91,24 @@ class ReceivedByTest(BitcoinTestFramework):
getreceivedbyaddress Test
'''
# Send from node 0 to 1
- addr = nodes[1].getnewaddress()
- txid = nodes[0].sendtoaddress(addr, 0.1)
- sync_mempools(nodes)
+ addr = self.nodes[1].getnewaddress()
+ txid = self.nodes[0].sendtoaddress(addr, 0.1)
+ self.sync_all()
#Check balance is 0 because of 0 confirmations
- balance = nodes[1].getreceivedbyaddress(addr)
+ balance = self.nodes[1].getreceivedbyaddress(addr)
if balance != Decimal("0.0"):
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
#Check balance is 0.1
- balance = nodes[1].getreceivedbyaddress(addr,0)
+ balance = self.nodes[1].getreceivedbyaddress(addr,0)
if balance != Decimal("0.1"):
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
#Bury Tx under 10 block so it will be returned by the default getreceivedbyaddress
- nodes[1].setgenerate(True, 10)
- sync_blocks(nodes)
- balance = nodes[1].getreceivedbyaddress(addr)
+ self.nodes[1].setgenerate(True, 10)
+ self.sync_all()
+ balance = self.nodes[1].getreceivedbyaddress(addr)
if balance != Decimal("0.1"):
raise AssertionError("Wrong balance returned by getreceivedbyaddress, %0.2f"%(balance))
@@ -116,40 +116,40 @@ class ReceivedByTest(BitcoinTestFramework):
listreceivedbyaccount + getreceivedbyaccount Test
'''
#set pre-state
- addrArr = nodes[1].getnewaddress()
- account = nodes[1].getaccount(addrArr)
- received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(),{"account":account})
+ addrArr = self.nodes[1].getnewaddress()
+ account = self.nodes[1].getaccount(addrArr)
+ received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(),{"account":account})
if len(received_by_account_json) == 0:
raise AssertionError("No accounts found in node")
- balance_by_account = rec_by_accountArr = nodes[1].getreceivedbyaccount(account)
+ balance_by_account = rec_by_accountArr = self.nodes[1].getreceivedbyaccount(account)
- txid = nodes[0].sendtoaddress(addr, 0.1)
+ txid = self.nodes[0].sendtoaddress(addr, 0.1)
# listreceivedbyaccount should return received_by_account_json because of 0 confirmations
- check_array_result(nodes[1].listreceivedbyaccount(),
+ check_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
received_by_account_json)
# getreceivedbyaddress should return same balance because of 0 confirmations
- balance = nodes[1].getreceivedbyaccount(account)
+ balance = self.nodes[1].getreceivedbyaccount(account)
if balance != balance_by_account:
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
- nodes[1].setgenerate(True, 10)
- sync_blocks(nodes)
+ self.nodes[1].setgenerate(True, 10)
+ self.sync_all()
# listreceivedbyaccount should return updated account balance
- check_array_result(nodes[1].listreceivedbyaccount(),
+ check_array_result(self.nodes[1].listreceivedbyaccount(),
{"account":account},
{"account":received_by_account_json["account"], "amount":(received_by_account_json["amount"] + Decimal("0.1"))})
# getreceivedbyaddress should return updates balance
- balance = nodes[1].getreceivedbyaccount(account)
+ balance = self.nodes[1].getreceivedbyaccount(account)
if balance != balance_by_account + Decimal("0.1"):
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
#Create a new account named "mynewaccount" that has a 0 balance
- nodes[1].getaccountaddress("mynewaccount")
- received_by_account_json = get_sub_array_from_array(nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
+ self.nodes[1].getaccountaddress("mynewaccount")
+ received_by_account_json = get_sub_array_from_array(self.nodes[1].listreceivedbyaccount(0,True),{"account":"mynewaccount"})
if len(received_by_account_json) == 0:
raise AssertionError("No accounts found in node")
@@ -158,7 +158,7 @@ class ReceivedByTest(BitcoinTestFramework):
raise AssertionError("Wrong balance returned by listreceivedbyaccount, %0.2f"%(received_by_account_json["amount"]))
# Test getreceivedbyaccount for 0 amount accounts
- balance = nodes[1].getreceivedbyaccount("mynewaccount")
+ balance = self.nodes[1].getreceivedbyaccount("mynewaccount")
if balance != Decimal("0.0"):
raise AssertionError("Wrong balance returned by getreceivedbyaccount, %0.2f"%(balance))
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
index 352a1de2d0..065bdb01c3 100755
--- a/qa/rpc-tests/smartfees.py
+++ b/qa/rpc-tests/smartfees.py
@@ -10,48 +10,48 @@ from util import *
class EstimateFeeTest(BitcoinTestFramework):
- def setup_network(self, test_dir):
- nodes = []
- nodes.append(start_node(0, test_dir,
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir,
["-debug=mempool", "-debug=estimatefee"]))
# Node1 mines small-but-not-tiny blocks, and allows free transactions.
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
# so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
# 6 or 7 transactions)
- nodes.append(start_node(1, test_dir,
+ self.nodes.append(start_node(1, self.options.tmpdir,
["-blockprioritysize=1500", "-blockmaxsize=2000",
"-debug=mempool", "-debug=estimatefee"]))
- connect_nodes(nodes[1], 0)
+ connect_nodes(self.nodes[1], 0)
# Node2 is a stingy miner, that
# produces very small blocks (room for only 3 or so transactions)
node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
"-debug=mempool", "-debug=estimatefee"]
- nodes.append(start_node(2, test_dir, node2args))
- connect_nodes(nodes[2], 0)
+ self.nodes.append(start_node(2, self.options.tmpdir, node2args))
+ connect_nodes(self.nodes[2], 0)
- sync_blocks(nodes)
- return nodes
+ self.is_network_split = False
+ self.sync_all()
- def run_test(self, nodes):
+ def run_test(self):
# Prime the memory pool with pairs of transactions
# (high-priority, random fee and zero-priority, random fee)
min_fee = Decimal("0.001")
fees_per_kb = [];
for i in range(12):
- (txid, txhex, fee) = random_zeropri_transaction(nodes, Decimal("1.1"),
+ (txid, txhex, fee) = random_zeropri_transaction(self.nodes, Decimal("1.1"),
min_fee, min_fee, 20)
tx_kbytes = (len(txhex)/2)/1000.0
fees_per_kb.append(float(fee)/tx_kbytes)
# Mine blocks with node2 until the memory pool clears:
- count_start = nodes[2].getblockcount()
- while len(nodes[2].getrawmempool()) > 0:
- nodes[2].setgenerate(True, 1)
- sync_blocks(nodes)
+ count_start = self.nodes[2].getblockcount()
+ while len(self.nodes[2].getrawmempool()) > 0:
+ self.nodes[2].setgenerate(True, 1)
+ self.sync_all()
- all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates]))
# Estimates should be within the bounds of what transactions fees actually were:
@@ -63,25 +63,25 @@ class EstimateFeeTest(BitcoinTestFramework):
# Generate transactions while mining 30 more blocks, this time with node1:
for i in range(30):
for j in range(random.randrange(6-4,6+4)):
- (txid, txhex, fee) = random_transaction(nodes, Decimal("1.1"),
+ (txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"),
Decimal("0.0"), min_fee, 20)
tx_kbytes = (len(txhex)/2)/1000.0
fees_per_kb.append(float(fee)/tx_kbytes)
- nodes[1].setgenerate(True, 1)
- sync_blocks(nodes)
+ self.nodes[1].setgenerate(True, 1)
+ self.sync_all()
- all_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates]))
for e in filter(lambda x: x >= 0, all_estimates):
if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
# Finish by mining a normal-sized block:
- while len(nodes[0].getrawmempool()) > 0:
- nodes[0].setgenerate(True, 1)
- sync_blocks(nodes)
+ while len(self.nodes[0].getrawmempool()) > 0:
+ self.nodes[0].setgenerate(True, 1)
+ self.sync_all()
- final_estimates = [ nodes[0].estimatefee(i) for i in range(1,20) ]
+ final_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
print("Final fee estimates: "+str([ str(e) for e in final_estimates]))
diff --git a/qa/rpc-tests/test_framework.py b/qa/rpc-tests/test_framework.py
index 5a18556655..f226496d0f 100755
--- a/qa/rpc-tests/test_framework.py
+++ b/qa/rpc-tests/test_framework.py
@@ -21,22 +21,64 @@ from util import *
class BitcoinTestFramework(object):
# These may be over-ridden by subclasses:
- def run_test(self, nodes):
+ def run_test(self):
+ for node in self.nodes:
assert_equal(node.getblockcount(), 200)
assert_equal(node.getbalance(), 25*50)
def add_options(self, parser):
pass
- def setup_chain(self, tmp_directory):
- print("Initializing test directory "+tmp_directory)
- initialize_chain(tmp_directory)
-
- def setup_network(self, tmp_directory):
- nodes = start_nodes(2, tmp_directory)
- connect_nodes(nodes[1], 0)
- sync_blocks(nodes)
- return nodes
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain(self.options.tmpdir)
+
+ def setup_network(self, split = False):
+ self.nodes = start_nodes(4, self.options.tmpdir)
+
+ # Connect the nodes as a "chain". This allows us
+ # to split the network between nodes 1 and 2 to get
+ # two halves that can work on competing chains.
+
+ # If we joined network halves, connect the nodes from the joint
+ # on outward. This ensures that chains are properly reorganised.
+ if not split:
+ connect_nodes(self.nodes[2], 1)
+ sync_blocks(self.nodes[1:2])
+ sync_mempools(self.nodes[1:2])
+
+ connect_nodes(self.nodes[1], 0)
+ connect_nodes(self.nodes[3], 2)
+ self.is_network_split = split
+ self.sync_all()
+
+ def split_network(self):
+ """
+ Split the network of four nodes into nodes 0/1 and 2/3.
+ """
+ assert not self.is_network_split
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ self.setup_network(True)
+
+ def sync_all(self):
+ if self.is_network_split:
+ sync_blocks(self.nodes[:1])
+ sync_blocks(self.nodes[2:])
+ sync_mempools(self.nodes[:1])
+ sync_mempools(self.nodes[2:])
+ else:
+ sync_blocks(self.nodes)
+ sync_mempools(self.nodes)
+
+ def join_network(self):
+ """
+ Join the (previously split) network halves together.
+ """
+ assert self.is_network_split
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ self.setup_network(False)
def main(self):
import optparse
@@ -56,15 +98,14 @@ class BitcoinTestFramework(object):
check_json_precision()
success = False
- nodes = []
try:
if not os.path.isdir(self.options.tmpdir):
os.makedirs(self.options.tmpdir)
- self.setup_chain(self.options.tmpdir)
+ self.setup_chain()
- nodes = self.setup_network(self.options.tmpdir)
+ self.setup_network()
- self.run_test(nodes)
+ self.run_test()
success = True
@@ -80,7 +121,7 @@ class BitcoinTestFramework(object):
if not self.options.nocleanup:
print("Cleaning up")
- stop_nodes(nodes)
+ stop_nodes(self.nodes)
wait_bitcoinds()
shutil.rmtree(self.options.tmpdir)