diff options
28 files changed, 208 insertions, 192 deletions
diff --git a/.travis.yml b/.travis.yml index f57a19c4ca..503172f2a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,7 +70,8 @@ script: - make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && make $GOAL V=1 ; false ) - export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib - if [ "$RUN_TESTS" = "true" ]; then make $MAKEJOBS check VERBOSE=1; fi - - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --coverage; fi + - if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude pruning"; fi + - if [ "$RUN_TESTS" = "true" ]; then test/functional/test_runner.py --coverage ${extended}; fi after_script: - echo $TRAVIS_COMMIT_RANGE - echo $TRAVIS_COMMIT_LOG diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc8d58d97d..0766d89f55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -130,7 +130,7 @@ pull requests which attempt to do too much, are overly large, or overly complex as this makes review difficult. -###Features +### Features When adding a new feature, thought must be given to the long term technical debt and maintenance that feature may require after inclusion. Before proposing a new @@ -139,7 +139,7 @@ maintain it (including bug fixing). If features get orphaned with no maintainer in the future, they may be removed by the Repository Maintainer. -###Refactoring +### Refactoring Refactoring is a necessary part of any software project's evolution. The following guidelines cover refactoring pull requests for the project. @@ -187,7 +187,7 @@ other kinds of patches because of increased peer review and consensus building requirements. -###Peer Review +### Peer Review Anyone may participate in peer review which is expressed by comments in the pull request. Typically reviewers will review the code for obvious errors, as well as diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index ac0701e6be..86366eb8e3 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -13,7 +13,7 @@ Usage: # Released under MIT License import os from itertools import islice -from base58 import b58encode, b58decode, b58encode_chk, b58decode_chk, b58chars +from base58 import b58encode_chk, b58decode_chk, b58chars import random from binascii import b2a_hex diff --git a/src/Makefile.am b/src/Makefile.am index e8d22313dc..8a32156884 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -167,8 +167,8 @@ BITCOIN_CORE_H = \ obj/build.h: FORCE @$(MKDIR_P) $(builddir)/obj - @$(top_srcdir)/share/genbuild.sh $(abs_top_builddir)/src/obj/build.h \ - $(abs_top_srcdir) + @$(top_srcdir)/share/genbuild.sh "$(abs_top_builddir)/src/obj/build.h" \ + "$(abs_top_srcdir)" libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between bitcoind and bitcoin-qt diff --git a/src/core_write.cpp b/src/core_write.cpp index b0993a131f..a3ca87c8b5 100644 --- a/src/core_write.cpp +++ b/src/core_write.cpp @@ -114,9 +114,9 @@ std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDeco return str; } -std::string EncodeHexTx(const CTransaction& tx, const int serialFlags) +std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags) { - CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serialFlags); + CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION | serializeFlags); ssTx << tx; return HexStr(ssTx.begin(), ssTx.end()); } diff --git a/src/init.cpp b/src/init.cpp index 81a12d431e..a78224d5d7 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -373,13 +373,13 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-banscore=<n>", strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD)); strUsage += HelpMessageOpt("-bantime=<n>", strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"), DEFAULT_MISBEHAVING_BANTIME)); strUsage += HelpMessageOpt("-bind=<addr>", _("Bind to given address and always listen on it. Use [host]:port notation for IPv6")); - strUsage += HelpMessageOpt("-connect=<ip>", _("Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections")); + strUsage += HelpMessageOpt("-connect=<ip>", _("Connect only to the specified node(s); -connect=0 disables automatic connections")); strUsage += HelpMessageOpt("-discover", _("Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)")); strUsage += HelpMessageOpt("-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") + " " + strprintf(_("(default: %u)"), DEFAULT_NAME_LOOKUP)); - strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect)")); + strUsage += HelpMessageOpt("-dnsseed", _("Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect used)")); strUsage += HelpMessageOpt("-externalip=<ip>", _("Specify your own public address")); strUsage += HelpMessageOpt("-forcednsseed", strprintf(_("Always query for peer addresses via DNS lookup (default: %u)"), DEFAULT_FORCEDNSSEED)); - strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect/-noconnect)")); + strUsage += HelpMessageOpt("-listen", _("Accept connections from outside (default: 1 if no -proxy or -connect)")); strUsage += HelpMessageOpt("-listenonion", strprintf(_("Automatically create Tor hidden service (default: %d)"), DEFAULT_LISTEN_ONION)); strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf(_("Maintain at most <n> connections to peers (default: %u)"), DEFAULT_MAX_PEER_CONNECTIONS)); strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), DEFAULT_MAXRECEIVEBUFFER)); diff --git a/src/miner.cpp b/src/miner.cpp index ff28a5680e..4fd99c5282 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -26,8 +26,6 @@ #include "validationinterface.h" #include <algorithm> -#include <boost/thread.hpp> -#include <boost/tuple/tuple.hpp> #include <queue> #include <utility> @@ -46,17 +44,6 @@ uint64_t nLastBlockTx = 0; uint64_t nLastBlockSize = 0; uint64_t nLastBlockWeight = 0; -class ScoreCompare -{ -public: - ScoreCompare() {} - - bool operator()(const CTxMemPool::txiter a, const CTxMemPool::txiter b) - { - return CompareTxMemPoolEntryByScore()(*b,*a); // Convert to less than - } -}; - int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { int64_t nOldTime = pblock->nTime; diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp index 60406c2059..5167232d6a 100644 --- a/src/qt/rpcconsole.cpp +++ b/src/qt/rpcconsole.cpp @@ -175,6 +175,10 @@ bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string & nDepthInsideSensitive = 1; filter_begin_pos = chpos; } + // Make sure stack is not empty before adding something + if (stack.empty()) { + stack.push_back(std::vector<std::string>()); + } stack.back().push_back(strArg); }; @@ -626,9 +630,12 @@ void RPCConsole::setClientModel(ClientModel *model) for (size_t i = 0; i < commandList.size(); ++i) { wordList << commandList[i].c_str(); + wordList << ("help " + commandList[i]).c_str(); } + wordList.sort(); autoCompleter = new QCompleter(wordList, this); + autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel); ui->lineEdit->setCompleter(autoCompleter); autoCompleter->popup()->installEventFilter(this); // Start thread to execute RPC commands. diff --git a/src/rpc/server.h b/src/rpc/server.h index ad064e5690..de14c7ed3e 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -68,7 +68,7 @@ void SetRPCWarmupStatus(const std::string& newStatus); void SetRPCWarmupFinished(); /* returns the current warmup state. */ -bool RPCIsInWarmup(std::string *statusOut); +bool RPCIsInWarmup(std::string *outStatus); /** * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that diff --git a/src/txmempool.cpp b/src/txmempool.cpp index fb58208774..6e1d7a42b5 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -108,7 +108,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan // vHashesToUpdate is the set of transaction hashes from a disconnected block // which has been re-added to the mempool. -// for each entry, look for descendants that are outside hashesToUpdate, and +// for each entry, look for descendants that are outside vHashesToUpdate, and // add fee/size information for such descendants to the parent. // for each such descendant, also update the ancestor state to include the parent. void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate) diff --git a/src/txmempool.h b/src/txmempool.h index f9a9d088d0..4222789510 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -552,12 +552,12 @@ public: * new mempool entries may have children in the mempool (which is generally * not the case when otherwise adding transactions). * UpdateTransactionsFromBlock() will find child transactions and update the - * descendant state for each transaction in hashesToUpdate (excluding any - * child transactions present in hashesToUpdate, which are already accounted - * for). Note: hashesToUpdate should be the set of transactions from the + * descendant state for each transaction in vHashesToUpdate (excluding any + * child transactions present in vHashesToUpdate, which are already accounted + * for). Note: vHashesToUpdate should be the set of transactions from the * disconnected block that have been accepted back into the mempool. */ - void UpdateTransactionsFromBlock(const std::vector<uint256> &hashesToUpdate); + void UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate); /** Try to calculate all in-mempool ancestors of entry. * (these are all calculated including the tx itself) diff --git a/src/validation.h b/src/validation.h index 43f0dbae34..5f8e9a689c 100644 --- a/src/validation.h +++ b/src/validation.h @@ -314,7 +314,7 @@ void FlushStateToDisk(); /** Prune block files and flush state to disk. */ void PruneAndFlush(); /** Prune block files up to a given height */ -void PruneBlockFilesManual(int nPruneUpToHeight); +void PruneBlockFilesManual(int nManualPruneHeight); /** (try to) add transaction to memory pool * plTxnReplaced will be appended to with all transactions replaced from mempool **/ diff --git a/src/validationinterface.h b/src/validationinterface.h index a494eb6990..7f13a29d23 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -69,7 +69,12 @@ struct CMainSignals { boost::signals2::signal<void (const uint256 &)> Inventory; /** Tells listeners to broadcast their data. */ boost::signals2::signal<void (int64_t nBestBlockTime, CConnman* connman)> Broadcast; - /** Notifies listeners of a block validation result */ + /** + * Notifies listeners of a block validation result. + * If the provided CValidationState IsValid, the provided block + * is guaranteed to be the current best block at the time the + * callback was generated (not necessarily now) + */ boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ boost::signals2::signal<void (boost::shared_ptr<CReserveScript>&)> ScriptForMining; diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index caca1248a1..4e13cbcaf4 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -30,6 +30,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) if (rc != 0) { zmqError("Unable to initialize ZMQ msg"); + va_end(args); return -1; } @@ -43,6 +44,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) { zmqError("Unable to send ZMQ msg"); zmq_msg_close(&msg); + va_end(args); return -1; } @@ -53,6 +55,7 @@ static int zmq_send_multipart(void *sock, const void* data, size_t size, ...) size = va_arg(args, size_t); } + va_end(args); return 0; } diff --git a/test/functional/assumevalid.py b/test/functional/assumevalid.py index c60c8e6d1a..da680a5d24 100755 --- a/test/functional/assumevalid.py +++ b/test/functional/assumevalid.py @@ -15,7 +15,7 @@ transactions: 2-101: bury that block with 100 blocks so the coinbase transaction output can be spent 102: a block containing a transaction spending the coinbase - transaction output. The transaction has an invalid signature. + transaction output. The transaction has an invalid signature. 103-2202: bury the bad block with just over two weeks' worth of blocks (2100 blocks) @@ -29,40 +29,34 @@ Start three nodes: block 200. node2 will reject block 102 since it's assumed valid, but it isn't buried by at least two weeks' work. """ +import time -from test_framework.mininode import * -from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import * -from test_framework.blocktools import create_block, create_coinbase +from test_framework.blocktools import (create_block, create_coinbase) from test_framework.key import CECKey -from test_framework.script import * +from test_framework.mininode import (CBlockHeader, + COutPoint, + CTransaction, + CTxIn, + CTxOut, + NetworkThread, + NodeConn, + SingleNodeConnCB, + msg_block, + msg_headers) +from test_framework.script import (CScript, OP_TRUE) +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import (start_node, p2p_port, assert_equal) class BaseNode(SingleNodeConnCB): def __init__(self): - SingleNodeConnCB.__init__(self) - self.last_inv = None - self.last_headers = None - self.last_block = None - self.last_getdata = None - self.block_announced = False - self.last_getheaders = None - self.disconnected = False - self.last_blockhash_announced = None - - def on_close(self, conn): - self.disconnected = True - - def wait_for_disconnect(self, timeout=60): - test_function = lambda: self.disconnected - assert(wait_until(test_function, timeout=timeout)) - return + super().__init__() def send_header_for_blocks(self, new_blocks): headers_message = msg_headers() - headers_message.headers = [ CBlockHeader(b) for b in new_blocks ] + headers_message.headers = [CBlockHeader(b) for b in new_blocks] self.send_message(headers_message) -class SendHeadersTest(BitcoinTestFramework): +class AssumeValidTest(BitcoinTestFramework): def __init__(self): super().__init__() self.setup_clean_chain = True @@ -72,8 +66,34 @@ class SendHeadersTest(BitcoinTestFramework): # Start node0. We don't start the other nodes yet since # we need to pre-mine a block with an invalid transaction # signature so we can pass in the block hash as assumevalid. - self.nodes = [] - self.nodes.append(start_node(0, self.options.tmpdir)) + self.nodes = [start_node(0, self.options.tmpdir)] + + def send_blocks_until_disconnected(self, node): + """Keep sending blocks to the node until we're disconnected.""" + for i in range(len(self.blocks)): + try: + node.send_message(msg_block(self.blocks[i])) + except IOError as e: + assert str(e) == 'Not connected, no pushbuf' + break + + def assert_blockchain_height(self, node, height): + """Wait until the blockchain is no longer advancing and verify it's reached the expected height.""" + last_height = node.getblock(node.getbestblockhash())['height'] + timeout = 10 + while True: + time.sleep(0.25) + current_height = node.getblock(node.getbestblockhash())['height'] + if current_height != last_height: + last_height = current_height + if timeout < 0: + assert False, "blockchain too short after timeout: %d" % current_height + timeout - 0.25 + continue + elif current_height > height: + assert False, "blockchain too long: %d" % current_height + elif current_height == height: + break def run_test(self): @@ -83,7 +103,7 @@ class SendHeadersTest(BitcoinTestFramework): connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], node0)) node0.add_connection(connections[0]) - NetworkThread().start() # Start up network handling in another thread + NetworkThread().start() # Start up network handling in another thread node0.wait_for_verack() # Build the blockchain @@ -120,7 +140,7 @@ class SendHeadersTest(BitcoinTestFramework): # Create a transaction spending the coinbase output with an invalid (null) signature tx = CTransaction() tx.vin.append(CTxIn(COutPoint(self.block1.vtx[0].sha256, 0), scriptSig=b"")) - tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE]))) + tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE]))) tx.calc_sha256() block102 = create_block(self.tip, create_coinbase(height), self.block_time) @@ -166,25 +186,19 @@ class SendHeadersTest(BitcoinTestFramework): node1.send_header_for_blocks(self.blocks[2000:]) node2.send_header_for_blocks(self.blocks[0:200]) - # Send 102 blocks to node0. Block 102 will be rejected. - for i in range(101): - node0.send_message(msg_block(self.blocks[i])) - node0.sync_with_ping() # make sure the most recent block is synced - node0.send_message(msg_block(self.blocks[101])) - assert_equal(self.nodes[0].getblock(self.nodes[0].getbestblockhash())['height'], 101) + # Send blocks to node0. Block 102 will be rejected. + self.send_blocks_until_disconnected(node0) + self.assert_blockchain_height(self.nodes[0], 101) - # Send 3102 blocks to node1. All blocks will be accepted. + # Send all blocks to node1. All blocks will be accepted. for i in range(2202): node1.send_message(msg_block(self.blocks[i])) - node1.sync_with_ping() # make sure the most recent block is synced + node1.sync_with_ping() # make sure the most recent block is synced assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202) - # Send 102 blocks to node2. Block 102 will be rejected. - for i in range(101): - node2.send_message(msg_block(self.blocks[i])) - node2.sync_with_ping() # make sure the most recent block is synced - node2.send_message(msg_block(self.blocks[101])) - assert_equal(self.nodes[2].getblock(self.nodes[2].getbestblockhash())['height'], 101) + # Send blocks to node2. Block 102 will be rejected. + self.send_blocks_until_disconnected(node2) + self.assert_blockchain_height(self.nodes[2], 101) if __name__ == '__main__': - SendHeadersTest().main() + AssumeValidTest().main() diff --git a/test/functional/bip68-sequence.py b/test/functional/bip68-sequence.py index 3ed6ebe044..89d42a710c 100755 --- a/test/functional/bip68-sequence.py +++ b/test/functional/bip68-sequence.py @@ -378,8 +378,8 @@ class BIP68Test(BitcoinTestFramework): # activation should happen at block height 432 (3 periods) min_activation_height = 432 height = self.nodes[0].getblockcount() - assert(height < 432) - self.nodes[0].generate(432-height) + assert(height < min_activation_height) + self.nodes[0].generate(min_activation_height-height) assert(get_bip9_status(self.nodes[0], 'csv')['status'] == 'active') sync_blocks(self.nodes) diff --git a/test/functional/bumpfee.py b/test/functional/bumpfee.py index 8f75e9ed4d..172e414188 100755 --- a/test/functional/bumpfee.py +++ b/test/functional/bumpfee.py @@ -2,7 +2,17 @@ # Copyright (c) 2016 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 the bumpfee RPC.""" +"""Test the bumpfee RPC. + +Verifies that the bumpfee RPC creates replacement transactions successfully when +its preconditions are met, and returns appropriate errors in other cases. + +This module consists of around a dozen individual test cases implemented in the +top-level functions named as test_<test_case_description>. The test functions +can be disabled or reordered if needed for debugging. If new test cases are +added in the the future, they should try to follow the same convention and not +make assumptions about execution order. +""" from segwit import send_to_witness from test_framework.test_framework import BitcoinTestFramework @@ -57,13 +67,13 @@ class BumpFeeTest(BitcoinTestFramework): self.log.info("Running tests") dest_address = peer_node.getnewaddress() - test_small_output_fails(rbf_node, dest_address) - test_dust_to_fee(rbf_node, dest_address) test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address) test_segwit_bumpfee_succeeds(rbf_node, dest_address) test_nonrbf_bumpfee_fails(peer_node, dest_address) test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address) test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address) + test_small_output_fails(rbf_node, dest_address) + test_dust_to_fee(rbf_node, dest_address) test_settxfee(rbf_node, dest_address) test_rebumping(rbf_node, dest_address) test_rebumping_not_replaceable(rbf_node, dest_address) @@ -74,7 +84,7 @@ class BumpFeeTest(BitcoinTestFramework): def test_simple_bumpfee_succeeds(rbf_node, peer_node, dest_address): - rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000}) + rbfid = spend_one_input(rbf_node, dest_address) rbftx = rbf_node.gettransaction(rbfid) sync_mempools((rbf_node, peer_node)) assert rbfid in rbf_node.getrawmempool() and rbfid in peer_node.getrawmempool() @@ -115,7 +125,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address): 'vout': 0, "sequence": BIP125_SEQUENCE_NUMBER }], {dest_address: Decimal("0.0005"), - get_change_address(rbf_node): Decimal("0.0003")}) + rbf_node.getrawchangeaddress(): Decimal("0.0003")}) rbfsigned = rbf_node.signrawtransaction(rbfraw) rbfid = rbf_node.sendrawtransaction(rbfsigned["hex"]) assert rbfid in rbf_node.getrawmempool() @@ -127,7 +137,7 @@ def test_segwit_bumpfee_succeeds(rbf_node, dest_address): def test_nonrbf_bumpfee_fails(peer_node, dest_address): # cannot replace a non RBF transaction (from node which did not enable RBF) - not_rbfid = create_fund_sign_send(peer_node, {dest_address: 0.00090000}) + not_rbfid = peer_node.sendtoaddress(dest_address, Decimal("0.00090000")) assert_raises_jsonrpc(-4, "not BIP 125 replaceable", peer_node.bumpfee, not_rbfid) @@ -155,7 +165,7 @@ def test_notmine_bumpfee_fails(rbf_node, peer_node, dest_address): def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address): # cannot bump fee if the transaction has a descendant # parent is send-to-self, so we don't have to check which output is change when creating the child tx - parent_id = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00050000}) + parent_id = spend_one_input(rbf_node, rbf_node_address) tx = rbf_node.createrawtransaction([{"txid": parent_id, "vout": 0}], {dest_address: 0.00020000}) tx = rbf_node.signrawtransaction(tx) txid = rbf_node.sendrawtransaction(tx["hex"]) @@ -164,58 +174,50 @@ def test_bumpfee_with_descendant_fails(rbf_node, rbf_node_address, dest_address) def test_small_output_fails(rbf_node, dest_address): # cannot bump fee with a too-small output - rbfid = spend_one_input(rbf_node, - Decimal("0.00100000"), - {dest_address: 0.00080000, - get_change_address(rbf_node): Decimal("0.00010000")}) - rbf_node.bumpfee(rbfid, {"totalFee": 20000}) + rbfid = spend_one_input(rbf_node, dest_address) + rbf_node.bumpfee(rbfid, {"totalFee": 50000}) - rbfid = spend_one_input(rbf_node, - Decimal("0.00100000"), - {dest_address: 0.00080000, - get_change_address(rbf_node): Decimal("0.00010000")}) - assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 20001}) + rbfid = spend_one_input(rbf_node, dest_address) + assert_raises_jsonrpc(-4, "Change output is too small", rbf_node.bumpfee, rbfid, {"totalFee": 50001}) def test_dust_to_fee(rbf_node, dest_address): # check that if output is reduced to dust, it will be converted to fee - # the bumped tx sets fee=9900, but it converts to 10,000 - rbfid = spend_one_input(rbf_node, - Decimal("0.00100000"), - {dest_address: 0.00080000, - get_change_address(rbf_node): Decimal("0.00010000")}) + # the bumped tx sets fee=49,900, but it converts to 50,000 + rbfid = spend_one_input(rbf_node, dest_address) fulltx = rbf_node.getrawtransaction(rbfid, 1) - bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 19900}) + bumped_tx = rbf_node.bumpfee(rbfid, {"totalFee": 49900}) full_bumped_tx = rbf_node.getrawtransaction(bumped_tx["txid"], 1) - assert_equal(bumped_tx["fee"], Decimal("0.00020000")) + assert_equal(bumped_tx["fee"], Decimal("0.00050000")) assert_equal(len(fulltx["vout"]), 2) assert_equal(len(full_bumped_tx["vout"]), 1) #change output is eliminated def test_settxfee(rbf_node, dest_address): # check that bumpfee reacts correctly to the use of settxfee (paytxfee) - # increase feerate by 2.5x, test that fee increased at least 2x - rbf_node.settxfee(Decimal("0.00001000")) - rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000}) + rbfid = spend_one_input(rbf_node, dest_address) rbftx = rbf_node.gettransaction(rbfid) - rbf_node.settxfee(Decimal("0.00002500")) + requested_feerate = Decimal("0.00025000") + rbf_node.settxfee(requested_feerate) bumped_tx = rbf_node.bumpfee(rbfid) - assert bumped_tx["fee"] > 2 * abs(rbftx["fee"]) + actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["size"] + # Assert that the difference between the requested feerate and the actual + # feerate of the bumped transaction is small. + assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate)) rbf_node.settxfee(Decimal("0.00000000")) # unset paytxfee def test_rebumping(rbf_node, dest_address): # check that re-bumping the original tx fails, but bumping the bumper succeeds - rbf_node.settxfee(Decimal("0.00001000")) - rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000}) - bumped = rbf_node.bumpfee(rbfid, {"totalFee": 1000}) - assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 2000}) - rbf_node.bumpfee(bumped["txid"], {"totalFee": 2000}) + rbfid = spend_one_input(rbf_node, dest_address) + bumped = rbf_node.bumpfee(rbfid, {"totalFee": 2000}) + assert_raises_jsonrpc(-4, "already bumped", rbf_node.bumpfee, rbfid, {"totalFee": 3000}) + rbf_node.bumpfee(bumped["txid"], {"totalFee": 3000}) def test_rebumping_not_replaceable(rbf_node, dest_address): # check that re-bumping a non-replaceable bump tx fails - rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000}) + rbfid = spend_one_input(rbf_node, dest_address) bumped = rbf_node.bumpfee(rbfid, {"totalFee": 10000, "replaceable": False}) assert_raises_jsonrpc(-4, "Transaction is not BIP 125 replaceable", rbf_node.bumpfee, bumped["txid"], {"totalFee": 20000}) @@ -223,7 +225,7 @@ def test_rebumping_not_replaceable(rbf_node, dest_address): def test_unconfirmed_not_spendable(rbf_node, rbf_node_address): # check that unconfirmed outputs from bumped transactions are not spendable - rbfid = create_fund_sign_send(rbf_node, {rbf_node_address: 0.00090000}) + rbfid = spend_one_input(rbf_node, rbf_node_address) rbftx = rbf_node.gettransaction(rbfid)["hex"] assert rbfid in rbf_node.getrawmempool() bumpid = rbf_node.bumpfee(rbfid)["txid"] @@ -258,7 +260,7 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address): def test_bumpfee_metadata(rbf_node, dest_address): - rbfid = rbf_node.sendtoaddress(dest_address, 0.00090000, "comment value", "to value") + rbfid = rbf_node.sendtoaddress(dest_address, Decimal("0.00100000"), "comment value", "to value") bumped_tx = rbf_node.bumpfee(rbfid) bumped_wtx = rbf_node.gettransaction(bumped_tx["txid"]) assert_equal(bumped_wtx["comment"], "comment value") @@ -266,43 +268,23 @@ def test_bumpfee_metadata(rbf_node, dest_address): def test_locked_wallet_fails(rbf_node, dest_address): - rbfid = create_fund_sign_send(rbf_node, {dest_address: 0.00090000}) + rbfid = spend_one_input(rbf_node, dest_address) rbf_node.walletlock() assert_raises_jsonrpc(-13, "Please enter the wallet passphrase with walletpassphrase first.", rbf_node.bumpfee, rbfid) -def create_fund_sign_send(node, outputs): - rawtx = node.createrawtransaction([], outputs) - fundtx = node.fundrawtransaction(rawtx) - signedtx = node.signrawtransaction(fundtx["hex"]) - txid = node.sendrawtransaction(signedtx["hex"]) - return txid - - -def spend_one_input(node, input_amount, outputs): - input = dict(sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == input_amount)) - rawtx = node.createrawtransaction([input], outputs) +def spend_one_input(node, dest_address): + tx_input = dict( + sequence=BIP125_SEQUENCE_NUMBER, **next(u for u in node.listunspent() if u["amount"] == Decimal("0.00100000"))) + rawtx = node.createrawtransaction( + [tx_input], {dest_address: Decimal("0.00050000"), + node.getrawchangeaddress(): Decimal("0.00049000")}) signedtx = node.signrawtransaction(rawtx) txid = node.sendrawtransaction(signedtx["hex"]) return txid -def get_change_address(node): - """Get a wallet change address. - - There is no wallet RPC to access unused change addresses, so this creates a - dummy transaction, calls fundrawtransaction to give add an input and change - output, then returns the change address.""" - dest_address = node.getnewaddress() - dest_amount = Decimal("0.00012345") - rawtx = node.createrawtransaction([], {dest_address: dest_amount}) - fundtx = node.fundrawtransaction(rawtx) - info = node.decoderawtransaction(fundtx["hex"]) - return next(address for out in info["vout"] - if out["value"] != dest_amount for address in out["scriptPubKey"]["addresses"]) - - def submit_block_with_tx(node, tx): ctx = CTransaction() ctx.deserialize(io.BytesIO(hex_str_to_bytes(tx))) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index fd330ef277..3bfc05d37b 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -322,8 +322,8 @@ class RawTransactionsTest(BitcoinTestFramework): #compare fee of a standard pubkeyhash transaction inputs = [] outputs = {self.nodes[1].getnewaddress():1.1} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1) @@ -338,8 +338,8 @@ class RawTransactionsTest(BitcoinTestFramework): #compare fee of a standard pubkeyhash transaction with multiple outputs inputs = [] outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendmany("", outputs) signedFee = self.nodes[0].getrawmempool(True)[txId]['fee'] @@ -364,8 +364,8 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [] outputs = {mSigObj:1.1} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) @@ -397,8 +397,8 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [] outputs = {mSigObj:1.1} - rawTx = self.nodes[0].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[0].fundrawtransaction(rawTx) + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[0].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[0].sendtoaddress(mSigObj, 1.1) @@ -432,8 +432,8 @@ class RawTransactionsTest(BitcoinTestFramework): oldBalance = self.nodes[1].getbalance() inputs = [] outputs = {self.nodes[1].getnewaddress():1.1} - rawTx = self.nodes[2].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[2].fundrawtransaction(rawTx) + rawtx = self.nodes[2].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[2].fundrawtransaction(rawtx) signedTx = self.nodes[2].signrawtransaction(fundedTx['hex']) txId = self.nodes[2].sendrawtransaction(signedTx['hex']) @@ -469,10 +469,10 @@ class RawTransactionsTest(BitcoinTestFramework): self.nodes[1].getnewaddress() inputs = [] outputs = {self.nodes[0].getnewaddress():1.1} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) # fund a transaction that requires a new key for the change output # creating the key must be impossible because the wallet is locked - assert_raises_jsonrpc(-4, "Insufficient funds", self.nodes[1].fundrawtransaction, rawtx) + assert_raises_jsonrpc(-4, "Keypool ran out, please call keypoolrefill first", self.nodes[1].fundrawtransaction, rawtx) #refill the keypool self.nodes[1].walletpassphrase("test", 100) @@ -484,8 +484,8 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [] outputs = {self.nodes[0].getnewaddress():1.1} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) #now we need to unlock self.nodes[1].walletpassphrase("test", 600) @@ -516,8 +516,8 @@ class RawTransactionsTest(BitcoinTestFramework): #fund a tx with ~20 small inputs inputs = [] outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) #create same transaction over sendtoaddress txId = self.nodes[1].sendmany("", outputs) @@ -548,8 +548,8 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [] outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04} - rawTx = self.nodes[1].createrawtransaction(inputs, outputs) - fundedTx = self.nodes[1].fundrawtransaction(rawTx) + rawtx = self.nodes[1].createrawtransaction(inputs, outputs) + fundedTx = self.nodes[1].fundrawtransaction(rawtx) fundedAndSignedTx = self.nodes[1].signrawtransaction(fundedTx['hex']) txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex']) self.sync_all() @@ -691,7 +691,6 @@ class RawTransactionsTest(BitcoinTestFramework): inputs = [] outputs = {self.nodes[2].getnewaddress(): value for value in (1.0, 1.1, 1.2, 1.3)} - keys = list(outputs.keys()) rawtx = self.nodes[3].createrawtransaction(inputs, outputs) result = [self.nodes[3].fundrawtransaction(rawtx), diff --git a/test/functional/import-rescan.py b/test/functional/import-rescan.py index 0218a46168..5be095e62d 100755 --- a/test/functional/import-rescan.py +++ b/test/functional/import-rescan.py @@ -22,7 +22,6 @@ happened previously. from test_framework.authproxy import JSONRPCException from test_framework.test_framework import BitcoinTestFramework from test_framework.util import (start_nodes, connect_nodes, sync_blocks, assert_equal, set_node_times) -from decimal import Decimal import collections import enum diff --git a/test/functional/multi_rpc.py b/test/functional/multi_rpc.py index 3b74bf1c46..a9701c548b 100755 --- a/test/functional/multi_rpc.py +++ b/test/functional/multi_rpc.py @@ -41,11 +41,9 @@ class HTTPBasicsTest (BitcoinTestFramework): authpair = url.username + ':' + url.password #New authpair generated via share/rpcuser tool - rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144" password = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM=" #Second authpair with different username - rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e" password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI=" authpairnew = "rt:"+password diff --git a/test/functional/rawtransactions.py b/test/functional/rawtransactions.py index 0374d8984a..d4c684136c 100755 --- a/test/functional/rawtransactions.py +++ b/test/functional/rawtransactions.py @@ -104,7 +104,6 @@ class RawTransactionsTest(BitcoinTestFramework): txId = self.nodes[0].sendtoaddress(mSigObj, 2.2) decTx = self.nodes[0].gettransaction(txId) rawTx = self.nodes[0].decoderawtransaction(decTx['hex']) - sPK = rawTx['vout'][0]['scriptPubKey']['hex'] self.sync_all() self.nodes[0].generate(1) self.sync_all() diff --git a/test/functional/rpcbind_test.py b/test/functional/rpcbind_test.py index 8720a345ce..efc36481d1 100755 --- a/test/functional/rpcbind_test.py +++ b/test/functional/rpcbind_test.py @@ -4,6 +4,9 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test running bitcoind with the -rpcbind and -rpcallowip options.""" +import socket +import sys + from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.netutil import * @@ -52,7 +55,9 @@ class RPCBindTest(BitcoinTestFramework): def run_test(self): # due to OS-specific network stats queries, this test works only on Linux - assert(sys.platform.startswith('linux')) + if not sys.platform.startswith('linux'): + self.log.warning("This test can only be run on linux. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) # find the first non-loopback interface for testing non_loopback_ip = None for name,ip in all_interfaces(): @@ -60,7 +65,16 @@ class RPCBindTest(BitcoinTestFramework): non_loopback_ip = ip break if non_loopback_ip is None: - assert(not 'This test requires at least one non-loopback IPv4 interface') + self.log.warning("This test requires at least one non-loopback IPv4 interface. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) + try: + s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) + s.connect(("::1",1)) + s.close + except OSError: + self.log.warning("This test requires IPv6 support. Skipping test.") + sys.exit(self.TEST_EXIT_SKIPPED) + self.log.info("Using interface %s for testing" % non_loopback_ip) defaultport = rpc_port(0) diff --git a/test/functional/segwit.py b/test/functional/segwit.py index 5b1fba8eec..a1fffcb81a 100755 --- a/test/functional/segwit.py +++ b/test/functional/segwit.py @@ -6,11 +6,10 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * -from test_framework.mininode import sha256, ripemd160, CTransaction, CTxIn, COutPoint, CTxOut, COIN +from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex from test_framework.address import script_to_p2sh, key_to_p2pkh -from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, hash160, OP_TRUE +from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE from io import BytesIO -from test_framework.mininode import ToHex, FromHex, COIN NODE_0 = 0 NODE_1 = 1 diff --git a/test/functional/smartfees.py b/test/functional/smartfees.py index 49f2df5c37..b7f4b86e7b 100755 --- a/test/functional/smartfees.py +++ b/test/functional/smartfees.py @@ -4,11 +4,10 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test fee estimation code.""" -from collections import OrderedDict from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE -from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, FromHex, COIN +from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, COIN # Construct 2 trivial P2SH's and the ScriptSigs that spend them # So we can create many many transactions without needing to spend diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py index dd7624d454..a08b03ed24 100644 --- a/test/functional/test_framework/socks5.py +++ b/test/functional/test_framework/socks5.py @@ -5,7 +5,6 @@ """Dummy Socks5 server for testing.""" import socket, threading, queue -import traceback, sys import logging logger = logging.getLogger("TestFramework.socks5") diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index fd2e803541..26a8aacb41 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -11,7 +11,6 @@ import sys import shutil import tempfile import time -import traceback from .util import ( initialize_chain, @@ -28,9 +27,12 @@ from .util import ( ) from .authproxy import JSONRPCException - class BitcoinTestFramework(object): + TEST_EXIT_PASSED = 0 + TEST_EXIT_FAILED = 1 + TEST_EXIT_SKIPPED = 77 + def __init__(self): self.num_nodes = 4 self.setup_clean_chain = False @@ -183,11 +185,11 @@ class BitcoinTestFramework(object): print("".join(deque(open(f), MAX_LINES_TO_PRINT))) if success: self.log.info("Tests successful") - sys.exit(0) + sys.exit(self.TEST_EXIT_PASSED) else: self.log.error("Test failed. Test logging available at %s/test_framework.log", self.options.tmpdir) logging.shutdown() - sys.exit(1) + sys.exit(self.TEST_EXIT_FAILED) def _start_logging(self): # Add logger and logging handlers diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 12eb92028f..e8d8908b13 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -24,6 +24,9 @@ import subprocess import tempfile import re +TEST_EXIT_PASSED = 0 +TEST_EXIT_SKIPPED = 77 + BASE_SCRIPTS= [ # Scripts that are run by the travis build process. # Longest test should go first, to favor running tests in parallel @@ -87,7 +90,7 @@ BASE_SCRIPTS= [ ZMQ_SCRIPTS = [ # ZMQ test can only be run if bitcoin was built with zmq-enabled. # call test_runner.py with -nozmq to explicitly exclude these tests. - "zmq_test.py"] + 'zmq_test.py'] EXTENDED_SCRIPTS = [ # These tests are not run by the travis build process. @@ -107,6 +110,7 @@ EXTENDED_SCRIPTS = [ 'p2p-feefilter.py', 'rpcbind_test.py', # vv Tests less than 30s vv + 'assumevalid.py', 'bip65-cltv.py', 'bip65-cltv-p2p.py', 'bipdersig-p2p.py', @@ -203,9 +207,9 @@ def main(): sys.exit(0) if args.help: - # Print help for test_runner.py, then print help of the first script and exit. + # Print help for test_runner.py, then print help of the first script (with args removed) and exit. parser.print_help() - subprocess.check_call((config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0]).split() + ['-h']) + subprocess.check_call([(config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0].split()[0])] + ['-h']) sys.exit(0) run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args) @@ -245,20 +249,20 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal job_queue = TestHandler(jobs, tests_dir, test_list, flags) max_len_name = len(max(test_list, key=len)) - results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0] + results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "STATUS ", "DURATION") + BOLD[0] for _ in range(len(test_list)): - (name, stdout, stderr, passed, duration) = job_queue.get_next() - all_passed = all_passed and passed + (name, stdout, stderr, status, duration) = job_queue.get_next() + all_passed = all_passed and status != "Failed" time_sum += duration print('\n' + BOLD[1] + name + BOLD[0] + ":") - print('' if passed else stdout + '\n', end='') + print('' if status == "Passed" else stdout + '\n', end='') print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='') - print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration)) + print("Status: %s%s%s, Duration: %s s\n" % (BOLD[1], status, BOLD[0], duration)) - results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration) + results += "%s | %s | %s s\n" % (name.ljust(max_len_name), status.ljust(7), duration) - results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0] + results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(7), time_sum) + BOLD[0] print(results) print("\nRuntime: %s s" % (int(time.time() - time0))) @@ -296,9 +300,10 @@ class TestHandler: port_seed = ["--portseed={}".format(len(self.test_list) + self.portseed_offset)] log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16) log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16) + test_argv = t.split() self.jobs.append((t, time.time(), - subprocess.Popen((self.tests_dir + t).split() + self.flags + port_seed, + subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + port_seed, universal_newlines=True, stdout=log_stdout, stderr=log_stderr), @@ -315,10 +320,15 @@ class TestHandler: log_out.seek(0), log_err.seek(0) [stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)] log_out.close(), log_err.close() - passed = stderr == "" and proc.returncode == 0 + if proc.returncode == TEST_EXIT_PASSED and stderr == "": + status = "Passed" + elif proc.returncode == TEST_EXIT_SKIPPED: + status = "Skipped" + else: + status = "Failed" self.num_running -= 1 self.jobs.remove(j) - return name, stdout, stderr, passed, int(time.time() - time0) + return name, stdout, stderr, status, int(time.time() - time0) print('.', end='', flush=True) diff --git a/test/functional/zmq_test.py b/test/functional/zmq_test.py index e6f18b0b93..9e27b46381 100755 --- a/test/functional/zmq_test.py +++ b/test/functional/zmq_test.py @@ -41,7 +41,6 @@ class ZMQTest (BitcoinTestFramework): topic = msg[0] assert_equal(topic, b"hashtx") body = msg[1] - nseq = msg[2] msgSequence = struct.unpack('<I', msg[-1])[-1] assert_equal(msgSequence, 0) #must be sequence 0 on hashtx |