Skip to content

Commit cf2cecb

Browse files
author
MarcoFalke
committed
Merge #8400: [qa]: enable rpcbind_test
9bbb414 [qa]: enable rpcbind_test (whythat) 0ff4375 [qa]: add parsing for '<host>:<port>' argument form to rpc_url() (whythat)
2 parents 6caf3ee + 9bbb414 commit cf2cecb

File tree

3 files changed

+102
-129
lines changed

3 files changed

+102
-129
lines changed

qa/pull-tester/rpc-tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
'txn_clone.py --mineblock',
160160
'forknotify.py',
161161
'invalidateblock.py',
162-
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
162+
'rpcbind_test.py',
163163
'smartfees.py',
164164
'maxblocksinflight.py',
165165
'p2p-acceptblock.py',

qa/rpc-tests/rpcbind_test.py

Lines changed: 92 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -5,143 +5,108 @@
55

66
# Test for -rpcbind, as well as -rpcallowip and -rpcconnect
77

8-
# TODO extend this test from the test framework (like all other tests)
9-
108
import tempfile
119
import traceback
1210

11+
from test_framework.test_framework import BitcoinTestFramework
1312
from test_framework.util import *
1413
from test_framework.netutil import *
1514

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):
6416

65-
defaultport = rpc_port(0)
17+
def __init__(self):
18+
super().__init__()
19+
self.setup_clean_chain = True
20+
self.num_nodes = 1
6621

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):
9823
pass
9924

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
13827

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
145110

146111
if __name__ == '__main__':
147-
main()
112+
RPCBindTest ().main ()

qa/rpc-tests/test_framework/util.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,15 @@ def rpc_auth_pair(n):
171171

172172
def rpc_url(i, rpchost=None):
173173
rpc_u, rpc_p = rpc_auth_pair(i)
174-
return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, rpchost or '127.0.0.1', rpc_port(i))
174+
host = '127.0.0.1'
175+
port = rpc_port(i)
176+
if rpchost:
177+
parts = rpchost.split(':')
178+
if len(parts) == 2:
179+
host, port = parts
180+
else:
181+
host = rpchost
182+
return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port))
175183

176184
def wait_for_bitcoind_start(process, url, i):
177185
'''

0 commit comments

Comments
 (0)