|
5 | 5 |
|
6 | 6 | # Test for -rpcbind, as well as -rpcallowip and -rpcconnect
|
7 | 7 |
|
8 |
| -# TODO extend this test from the test framework (like all other tests) |
9 |
| - |
10 | 8 | import tempfile
|
11 | 9 | import traceback
|
12 | 10 |
|
| 11 | +from test_framework.test_framework import BitcoinTestFramework |
13 | 12 | from test_framework.util import *
|
14 | 13 | from test_framework.netutil import *
|
15 | 14 |
|
16 |
| -def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected): |
17 |
| - ''' |
18 |
| - Start a node with requested rpcallowip and rpcbind parameters, |
19 |
| - then try to connect, and check if the set of bound addresses |
20 |
| - matches the expected set. |
21 |
| - ''' |
22 |
| - expected = [(addr_to_hex(addr), port) for (addr, port) in expected] |
23 |
| - base_args = ['-disablewallet', '-nolisten'] |
24 |
| - if allow_ips: |
25 |
| - base_args += ['-rpcallowip=' + x for x in allow_ips] |
26 |
| - binds = ['-rpcbind='+addr for addr in addresses] |
27 |
| - nodes = start_nodes(self.num_nodes, tmpdir, [base_args + binds], connect_to) |
28 |
| - try: |
29 |
| - pid = bitcoind_processes[0].pid |
30 |
| - assert_equal(set(get_bind_addrs(pid)), set(expected)) |
31 |
| - finally: |
32 |
| - stop_nodes(nodes) |
33 |
| - wait_bitcoinds() |
34 |
| - |
35 |
| -def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport): |
36 |
| - ''' |
37 |
| - Start a node with rpcwallow IP, and request getinfo |
38 |
| - at a non-localhost IP. |
39 |
| - ''' |
40 |
| - base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] |
41 |
| - nodes = start_nodes(self.num_nodes, tmpdir, [base_args]) |
42 |
| - try: |
43 |
| - # connect to node through non-loopback interface |
44 |
| - url = "http://rt:rt@%s:%d" % (rpchost, rpcport,) |
45 |
| - node = get_rpc_proxy(url, 1) |
46 |
| - node.getinfo() |
47 |
| - finally: |
48 |
| - node = None # make sure connection will be garbage collected and closed |
49 |
| - stop_nodes(nodes) |
50 |
| - wait_bitcoinds() |
51 |
| - |
52 |
| - |
53 |
| -def run_test(tmpdir): |
54 |
| - assert(sys.platform.startswith('linux')) # due to OS-specific network stats queries, this test works only on Linux |
55 |
| - # find the first non-loopback interface for testing |
56 |
| - non_loopback_ip = None |
57 |
| - for name,ip in all_interfaces(): |
58 |
| - if ip != '127.0.0.1': |
59 |
| - non_loopback_ip = ip |
60 |
| - break |
61 |
| - if non_loopback_ip is None: |
62 |
| - assert(not 'This test requires at least one non-loopback IPv4 interface') |
63 |
| - print("Using interface %s for testing" % non_loopback_ip) |
| 15 | +class RPCBindTest(BitcoinTestFramework): |
64 | 16 |
|
65 |
| - defaultport = rpc_port(0) |
| 17 | + def __init__(self): |
| 18 | + super().__init__() |
| 19 | + self.setup_clean_chain = True |
| 20 | + self.num_nodes = 1 |
66 | 21 |
|
67 |
| - # check default without rpcallowip (IPv4 and IPv6 localhost) |
68 |
| - run_bind_test(tmpdir, None, '127.0.0.1', [], |
69 |
| - [('127.0.0.1', defaultport), ('::1', defaultport)]) |
70 |
| - # check default with rpcallowip (IPv6 any) |
71 |
| - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [], |
72 |
| - [('::0', defaultport)]) |
73 |
| - # check only IPv4 localhost (explicit) |
74 |
| - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], |
75 |
| - [('127.0.0.1', defaultport)]) |
76 |
| - # check only IPv4 localhost (explicit) with alternative port |
77 |
| - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], |
78 |
| - [('127.0.0.1', 32171)]) |
79 |
| - # check only IPv4 localhost (explicit) with multiple alternative ports on same host |
80 |
| - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], |
81 |
| - [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) |
82 |
| - # check only IPv6 localhost (explicit) |
83 |
| - run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'], |
84 |
| - [('::1', defaultport)]) |
85 |
| - # check both IPv4 and IPv6 localhost (explicit) |
86 |
| - run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], |
87 |
| - [('127.0.0.1', defaultport), ('::1', defaultport)]) |
88 |
| - # check only non-loopback interface |
89 |
| - run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip], |
90 |
| - [(non_loopback_ip, defaultport)]) |
91 |
| - |
92 |
| - # Check that with invalid rpcallowip, we are denied |
93 |
| - run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip, defaultport) |
94 |
| - try: |
95 |
| - run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip, defaultport) |
96 |
| - assert(not 'Connection not denied by rpcallowip as expected') |
97 |
| - except ValueError: |
| 22 | + def setup_network(self): |
98 | 23 | pass
|
99 | 24 |
|
100 |
| -def main(): |
101 |
| - import optparse |
102 |
| - |
103 |
| - parser = optparse.OptionParser(usage="%prog [options]") |
104 |
| - parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true", |
105 |
| - help="Leave bitcoinds and test.* datadir on exit or error") |
106 |
| - parser.add_option("--srcdir", dest="srcdir", default="../../src", |
107 |
| - help="Source directory containing bitcoind/bitcoin-cli (default: %default%)") |
108 |
| - parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"), |
109 |
| - help="Root directory for datadirs") |
110 |
| - (options, args) = parser.parse_args() |
111 |
| - |
112 |
| - os.environ['PATH'] = options.srcdir+":"+os.environ['PATH'] |
113 |
| - |
114 |
| - check_json_precision() |
115 |
| - |
116 |
| - success = False |
117 |
| - nodes = [] |
118 |
| - try: |
119 |
| - print("Initializing test directory "+options.tmpdir) |
120 |
| - if not os.path.isdir(options.tmpdir): |
121 |
| - os.makedirs(options.tmpdir) |
122 |
| - initialize_chain(options.tmpdir) |
123 |
| - |
124 |
| - run_test(options.tmpdir) |
125 |
| - |
126 |
| - success = True |
127 |
| - |
128 |
| - except AssertionError as e: |
129 |
| - print("Assertion failed: "+e.message) |
130 |
| - except Exception as e: |
131 |
| - print("Unexpected exception caught during testing: "+str(e)) |
132 |
| - traceback.print_tb(sys.exc_info()[2]) |
133 |
| - |
134 |
| - if not options.nocleanup: |
135 |
| - print("Cleaning up") |
136 |
| - wait_bitcoinds() |
137 |
| - shutil.rmtree(options.tmpdir) |
| 25 | + def setup_nodes(self): |
| 26 | + pass |
138 | 27 |
|
139 |
| - if success: |
140 |
| - print("Tests successful") |
141 |
| - sys.exit(0) |
142 |
| - else: |
143 |
| - print("Failed") |
144 |
| - sys.exit(1) |
| 28 | + def run_bind_test(self, allow_ips, connect_to, addresses, expected): |
| 29 | + ''' |
| 30 | + Start a node with requested rpcallowip and rpcbind parameters, |
| 31 | + then try to connect, and check if the set of bound addresses |
| 32 | + matches the expected set. |
| 33 | + ''' |
| 34 | + expected = [(addr_to_hex(addr), port) for (addr, port) in expected] |
| 35 | + base_args = ['-disablewallet', '-nolisten'] |
| 36 | + if allow_ips: |
| 37 | + base_args += ['-rpcallowip=' + x for x in allow_ips] |
| 38 | + binds = ['-rpcbind='+addr for addr in addresses] |
| 39 | + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to) |
| 40 | + try: |
| 41 | + pid = bitcoind_processes[0].pid |
| 42 | + assert_equal(set(get_bind_addrs(pid)), set(expected)) |
| 43 | + finally: |
| 44 | + stop_nodes(self.nodes) |
| 45 | + wait_bitcoinds() |
| 46 | + |
| 47 | + def run_allowip_test(self, allow_ips, rpchost, rpcport): |
| 48 | + ''' |
| 49 | + Start a node with rpcwallow IP, and request getinfo |
| 50 | + at a non-localhost IP. |
| 51 | + ''' |
| 52 | + base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips] |
| 53 | + self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args]) |
| 54 | + try: |
| 55 | + # connect to node through non-loopback interface |
| 56 | + node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0) |
| 57 | + node.getinfo() |
| 58 | + finally: |
| 59 | + node = None # make sure connection will be garbage collected and closed |
| 60 | + stop_nodes(self.nodes) |
| 61 | + wait_bitcoinds() |
| 62 | + |
| 63 | + def run_test(self): |
| 64 | + # due to OS-specific network stats queries, this test works only on Linux |
| 65 | + assert(sys.platform.startswith('linux')) |
| 66 | + # find the first non-loopback interface for testing |
| 67 | + non_loopback_ip = None |
| 68 | + for name,ip in all_interfaces(): |
| 69 | + if ip != '127.0.0.1': |
| 70 | + non_loopback_ip = ip |
| 71 | + break |
| 72 | + if non_loopback_ip is None: |
| 73 | + assert(not 'This test requires at least one non-loopback IPv4 interface') |
| 74 | + print("Using interface %s for testing" % non_loopback_ip) |
| 75 | + |
| 76 | + defaultport = rpc_port(0) |
| 77 | + |
| 78 | + # check default without rpcallowip (IPv4 and IPv6 localhost) |
| 79 | + self.run_bind_test(None, '127.0.0.1', [], |
| 80 | + [('127.0.0.1', defaultport), ('::1', defaultport)]) |
| 81 | + # check default with rpcallowip (IPv6 any) |
| 82 | + self.run_bind_test(['127.0.0.1'], '127.0.0.1', [], |
| 83 | + [('::0', defaultport)]) |
| 84 | + # check only IPv4 localhost (explicit) |
| 85 | + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'], |
| 86 | + [('127.0.0.1', defaultport)]) |
| 87 | + # check only IPv4 localhost (explicit) with alternative port |
| 88 | + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'], |
| 89 | + [('127.0.0.1', 32171)]) |
| 90 | + # check only IPv4 localhost (explicit) with multiple alternative ports on same host |
| 91 | + self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'], |
| 92 | + [('127.0.0.1', 32171), ('127.0.0.1', 32172)]) |
| 93 | + # check only IPv6 localhost (explicit) |
| 94 | + self.run_bind_test(['[::1]'], '[::1]', ['[::1]'], |
| 95 | + [('::1', defaultport)]) |
| 96 | + # check both IPv4 and IPv6 localhost (explicit) |
| 97 | + self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'], |
| 98 | + [('127.0.0.1', defaultport), ('::1', defaultport)]) |
| 99 | + # check only non-loopback interface |
| 100 | + self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip], |
| 101 | + [(non_loopback_ip, defaultport)]) |
| 102 | + |
| 103 | + # Check that with invalid rpcallowip, we are denied |
| 104 | + self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport) |
| 105 | + try: |
| 106 | + self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport) |
| 107 | + assert(not 'Connection not denied by rpcallowip as expected') |
| 108 | + except JSONRPCException: |
| 109 | + pass |
145 | 110 |
|
146 | 111 | if __name__ == '__main__':
|
147 |
| - main() |
| 112 | + RPCBindTest ().main () |
0 commit comments