diff --git a/test/functional/forknotify.py b/test/functional/forknotify.py deleted file mode 100755 --- a/test/functional/forknotify.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2014-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 -alertnotify -# -"""Test the -alertnotify option.""" - -import os -import time - -from test_framework.test_framework import BitcoinTestFramework - - -class ForkNotifyTest(BitcoinTestFramework): - def set_test_params(self): - self.num_nodes = 2 - - def setup_network(self): - self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") - with open(self.alert_filename, 'w', encoding='utf8'): - pass # Just open then close to create zero-length file - self.extra_args = [["-blockversion=2", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""], - ["-blockversion=211"]] - super().setup_network() - - def run_test(self): - # Mine 51 up-version blocks - self.nodes[1].generate(51) - self.sync_all() - # -alertnotify should trigger on the 51'st, - # but mine and sync another to give - # -alertnotify time to write - self.nodes[1].generate(1) - self.sync_all() - - # Give bitcoind 10 seconds to write the alert notification - timeout = 10.0 - while timeout > 0: - if os.path.exists(self.alert_filename) and os.path.getsize(self.alert_filename): - break - time.sleep(0.1) - timeout -= 0.1 - else: - assert False, "-alertnotify did not warn of up-version blocks" - - with open(self.alert_filename, 'r', encoding='utf8') as f: - alert_text = f.read() - - # Mine more up-version blocks, should not get more alerts: - self.nodes[1].generate(1) - self.sync_all() - self.nodes[1].generate(1) - self.sync_all() - - with open(self.alert_filename, 'r', encoding='utf8') as f: - alert_text2 = f.read() - - if alert_text != alert_text2: - raise AssertionError( - "-alertnotify excessive warning of up-version blocks") - - -if __name__ == '__main__': - ForkNotifyTest().main() diff --git a/test/functional/notifications.py b/test/functional/notifications.py new file mode 100755 --- /dev/null +++ b/test/functional/notifications.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +# Copyright (c) 2014-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 -alertnotify, -blocknotify and -walletnotify options.""" +import os + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, wait_until, connect_nodes_bi + + +class NotificationsTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 2 + self.setup_clean_chain = True + + def setup_network(self): + self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt") + self.block_filename = os.path.join(self.options.tmpdir, "blocks.txt") + self.tx_filename = os.path.join( + self.options.tmpdir, "transactions.txt") + + # -alertnotify and -blocknotify on node0, walletnotify on node1 + self.extra_args = [["-blockversion=2", + "-alertnotify=echo %%s >> %s" % self.alert_filename, + "-blocknotify=echo %%s >> %s" % self.block_filename], + ["-blockversion=211", + "-rescan", + "-walletnotify=echo %%s >> %s" % self.tx_filename]] + super().setup_network() + + def run_test(self): + self.log.info("test -blocknotify") + block_count = 10 + blocks = self.nodes[1].generate(block_count) + + # wait at most 10 seconds for expected file size before reading the content + wait_until(lambda: os.path.isfile(self.block_filename) and os.stat( + self.block_filename).st_size >= (block_count * 65), timeout=10) + + # file content should equal the generated blocks hashes + with open(self.block_filename, 'r') as f: + assert_equal(sorted(blocks), sorted(f.read().splitlines())) + + self.log.info("test -walletnotify") + # wait at most 10 seconds for expected file size before reading the content + wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat( + self.tx_filename).st_size >= (block_count * 65), timeout=10) + + # file content should equal the generated transaction hashes + txids_rpc = list( + map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) + with open(self.tx_filename, 'r') as f: + assert_equal(sorted(txids_rpc), sorted(f.read().splitlines())) + os.remove(self.tx_filename) + + self.log.info("test -walletnotify after rescan") + # restart node to rescan to force wallet notifications + self.restart_node(1) + connect_nodes_bi(self.nodes, 0, 1) + + wait_until(lambda: os.path.isfile(self.tx_filename) and os.stat( + self.tx_filename).st_size >= (block_count * 65), timeout=10) + + # file content should equal the generated transaction hashes + txids_rpc = list( + map(lambda t: t['txid'], self.nodes[1].listtransactions("*", block_count))) + with open(self.tx_filename, 'r') as f: + assert_equal(sorted(txids_rpc), sorted(f.read().splitlines())) + + # Mine another 41 up-version blocks. -alertnotify should trigger on the 51st. + self.log.info("test -alertnotify") + self.nodes[1].generate(41) + self.sync_all() + + # Give bitcoind 10 seconds to write the alert notification + wait_until(lambda: os.path.isfile(self.alert_filename) + and os.path.getsize(self.alert_filename), timeout=10) + + with open(self.alert_filename, 'r', encoding='utf8') as f: + alert_text = f.read() + + # Mine more up-version blocks, should not get more alerts: + self.nodes[1].generate(2) + self.sync_all() + + with open(self.alert_filename, 'r', encoding='utf8') as f: + alert_text2 = f.read() + + self.log.info( + "-alertnotify should not continue notifying for more unknown version blocks") + assert_equal(alert_text, alert_text2) + + +if __name__ == '__main__': + NotificationsTest().main() diff --git a/test/functional/timing.json b/test/functional/timing.json --- a/test/functional/timing.json +++ b/test/functional/timing.json @@ -1,7 +1,7 @@ [ { "name": "abandonconflict.py", - "time": 14 + "time": 25 }, { "name": "abc-checkdatasig-activation.py", @@ -9,15 +9,15 @@ }, { "name": "abc-cmdline.py", - "time": 9 + "time": 11 }, { "name": "abc-high_priority_transaction.py", - "time": 11 + "time": 10 }, { "name": "abc-magnetic-anomaly-activation.py", - "time": 8 + "time": 14 }, { "name": "abc-mempool-accept-txn.py", @@ -25,55 +25,55 @@ }, { "name": "abc-p2p-compactblocks.py", - "time": 165 + "time": 170 }, { "name": "abc-p2p-fullblocktest.py", - "time": 52 + "time": 65 }, { "name": "abc-replay-protection.py", - "time": 13 + "time": 5 }, { "name": "abc-rpc.py", - "time": 4 + "time": 2 }, { "name": "abc-transaction-ordering.py", - "time": 8 + "time": 13 }, { "name": "assumevalid.py", - "time": 29 + "time": 12 }, { "name": "bip65-cltv-p2p.py", - "time": 16 + "time": 6 }, { "name": "bip68-112-113-p2p.py", - "time": 26 + "time": 24 }, { "name": "bip68-sequence.py", - "time": 29 + "time": 28 }, { "name": "bipdersig-p2p.py", - "time": 15 + "time": 5 }, { "name": "bitcoin_cli.py", - "time": 3 + "time": 16 }, { "name": "blockchain.py", - "time": 8 + "time": 30 }, { "name": "dbcrash.py", - "time": 1320 + "time": 1109 }, { "name": "decodescript.py", @@ -89,63 +89,59 @@ }, { "name": "disconnect_ban.py", - "time": 20 + "time": 10 }, { "name": "example_test.py", - "time": 4 - }, - { - "name": "forknotify.py", - "time": 17 + "time": 16 }, { "name": "fundrawtransaction.py", - "time": 43 + "time": 56 }, { "name": "getblocktemplate_longpoll.py", - "time": 73 + "time": 69 }, { "name": "getchaintips.py", - "time": 6 + "time": 19 }, { "name": "httpbasics.py", - "time": 16 + "time": 25 }, { "name": "import-rescan.py", - "time": 18 + "time": 43 }, { "name": "importmulti.py", - "time": 14 + "time": 23 }, { "name": "importprunedfunds.py", - "time": 4 + "time": 31 }, { "name": "invalidateblock.py", - "time": 13 + "time": 9 }, { "name": "invalidblockrequest.py", - "time": 4 + "time": 14 }, { "name": "invalidtxrequest.py", - "time": 4 + "time": 16 }, { "name": "keypool-topup.py", - "time": 31 + "time": 17 }, { "name": "keypool.py", - "time": 20 + "time": 10 }, { "name": "listsinceblock.py", @@ -153,79 +149,83 @@ }, { "name": "listtransactions.py", - "time": 26 + "time": 11 }, { "name": "maxuploadtarget.py", - "time": 55 + "time": 58 }, { "name": "mempool_limit.py", - "time": 22 + "time": 18 }, { "name": "mempool_packages.py", - "time": 29 + "time": 36 }, { "name": "mempool_persist.py", - "time": 20 + "time": 40 }, { "name": "mempool_reorg.py", - "time": 8 + "time": 17 }, { "name": "mempool_resurrect_test.py", - "time": 30 + "time": 3 }, { "name": "mempool_spendcoinbase.py", - "time": 16 + "time": 3 }, { "name": "merkle_blocks.py", - "time": 5 + "time": 4 }, { "name": "minchainwork.py", - "time": 7 + "time": 6 }, { "name": "mining.py", - "time": 17 + "time": 6 }, { "name": "multi_rpc.py", - "time": 5 + "time": 6 }, { "name": "multiwallet.py", - "time": 8 + "time": 20 }, { "name": "net.py", "time": 3 }, + { + "name": "notifications.py", + "time": 12 + }, { "name": "nulldummy.py", "time": 3 }, { "name": "p2p-acceptblock.py", - "time": 15 + "time": 6 }, { "name": "p2p-compactblocks.py", - "time": 29 + "time": 24 }, { "name": "p2p-feefilter.py", - "time": 41 + "time": 65 }, { "name": "p2p-fullblocktest.py", - "time": 182 + "time": 155 }, { "name": "p2p-leaktests.py", @@ -237,7 +237,7 @@ }, { "name": "p2p-timeouts.py", - "time": 65 + "time": 64 }, { "name": "preciousblock.py", @@ -245,39 +245,39 @@ }, { "name": "prioritise_transaction.py", - "time": 40 + "time": 12 }, { "name": "proxy_test.py", - "time": 5 + "time": 6 }, { "name": "pruning.py", - "time": 1515 + "time": 1248 }, { "name": "rawtransactions.py", - "time": 14 + "time": 10 }, { "name": "receivedby.py", - "time": 16 + "time": 8 }, { "name": "reindex.py", - "time": 14 + "time": 15 }, { "name": "resendwallettransactions.py", - "time": 5 + "time": 7 }, { "name": "rest.py", - "time": 22 + "time": 20 }, { "name": "rpcbind_test.py", - "time": 25 + "time": 39 }, { "name": "rpcnamedargs.py", @@ -285,7 +285,7 @@ }, { "name": "sendheaders.py", - "time": 27 + "time": 26 }, { "name": "signmessages.py", @@ -293,58 +293,58 @@ }, { "name": "signrawtransactions.py", - "time": 3 + "time": 2 }, { "name": "txn_clone.py", - "time": 7 + "time": 6 }, { "name": "txn_clone.py --mineblock", - "time": 7 + "time": 22 }, { "name": "txn_doublespend.py", - "time": 7 + "time": 21 }, { "name": "txn_doublespend.py --mineblock", - "time": 6 + "time": 7 }, { "name": "uptime.py", - "time": 3 + "time": 2 }, { "name": "wallet-accounts.py", - "time": 11 + "time": 10 }, { "name": "wallet-dump.py", - "time": 37 + "time": 8 }, { "name": "wallet-encryption.py", - "time": 15 + "time": 18 }, { "name": "wallet-hd.py", - "time": 132 + "time": 66 }, { "name": "wallet.py", - "time": 57 + "time": 41 }, { "name": "walletbackup.py", - "time": 154 + "time": 84 }, { "name": "zapwallettxes.py", - "time": 12 + "time": 13 }, { "name": "zmq_test.py", "time": 6 } ] \ No newline at end of file