5
5
"""Test bitcoin-cli"""
6
6
7
7
from decimal import Decimal
8
+ import re
8
9
9
10
from test_framework .blocktools import COINBASE_MATURITY
10
11
from test_framework .test_framework import BitcoinTestFramework
29
30
WALLET_NOT_LOADED = 'Requested wallet does not exist or is not loaded'
30
31
WALLET_NOT_SPECIFIED = 'Wallet file not specified'
31
32
33
+
34
+ def cli_get_info_string_to_dict (cli_get_info_string ):
35
+ """Helper method to convert human-readable -getinfo into a dictionary"""
36
+ cli_get_info = {}
37
+ lines = cli_get_info_string .splitlines ()
38
+ line_idx = 0
39
+ ansi_escape = re .compile (r'(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]' )
40
+ while line_idx < len (lines ):
41
+ # Remove ansi colour code
42
+ line = ansi_escape .sub ('' , lines [line_idx ])
43
+ if "Balances" in line :
44
+ # When "Balances" appears in a line, all of the following lines contain "balance: wallet" until an empty line
45
+ cli_get_info ["Balances" ] = {}
46
+ while line_idx < len (lines ) and not (lines [line_idx + 1 ] == '' ):
47
+ line_idx += 1
48
+ balance , wallet = lines [line_idx ].strip ().split (" " )
49
+ # Remove right justification padding
50
+ wallet = wallet .strip ()
51
+ if wallet == '""' :
52
+ # Set default wallet("") to empty string
53
+ wallet = ''
54
+ cli_get_info ["Balances" ][wallet ] = balance .strip ()
55
+ elif ": " in line :
56
+ key , value = line .split (": " )
57
+ if key == 'Wallet' and value == '""' :
58
+ # Set default wallet("") to empty string
59
+ value = ''
60
+ if key == "Proxy" and value == "N/A" :
61
+ # Set N/A to empty string to represent no proxy
62
+ value = ''
63
+ cli_get_info [key .strip ()] = value .strip ()
64
+ line_idx += 1
65
+ return cli_get_info
66
+
67
+
32
68
class TestBitcoinCli (BitcoinTestFramework ):
33
69
def set_test_params (self ):
34
70
self .setup_clean_chain = True
@@ -67,37 +103,43 @@ def run_test(self):
67
103
self .log .info ("Test -getinfo with arguments fails" )
68
104
assert_raises_process_error (1 , "-getinfo takes no arguments" , self .nodes [0 ].cli ('-getinfo' ).help )
69
105
106
+ self .log .info ("Test -getinfo with -color=never does not return ANSI escape codes" )
107
+ assert "\u001b [0m" not in self .nodes [0 ].cli ('-getinfo' , '-color=never' ).send_cli ()
108
+
109
+ self .log .info ("Test -getinfo with -color=always returns ANSI escape codes" )
110
+ assert "\u001b [0m" in self .nodes [0 ].cli ('-getinfo' , '-color=always' ).send_cli ()
111
+
112
+ self .log .info ("Test -getinfo with invalid value for -color option" )
113
+ assert_raises_process_error (1 , "Invalid value for -color option. Valid values: always, auto, never." , self .nodes [0 ].cli ('-getinfo' , '-color=foo' ).send_cli )
114
+
70
115
self .log .info ("Test -getinfo returns expected network and blockchain info" )
71
116
if self .is_wallet_compiled ():
72
117
self .nodes [0 ].encryptwallet (password )
73
- cli_get_info = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
118
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
119
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
120
+
74
121
network_info = self .nodes [0 ].getnetworkinfo ()
75
122
blockchain_info = self .nodes [0 ].getblockchaininfo ()
76
- assert_equal (cli_get_info ['version' ], network_info ['version' ])
77
- assert_equal (cli_get_info ['blocks' ], blockchain_info ['blocks' ])
78
- assert_equal (cli_get_info ['headers' ], blockchain_info ['headers' ])
79
- assert_equal (cli_get_info ['timeoffset' ], network_info ['timeoffset' ])
80
- assert_equal (
81
- cli_get_info ['connections' ],
82
- {
83
- 'in' : network_info ['connections_in' ],
84
- 'out' : network_info ['connections_out' ],
85
- 'total' : network_info ['connections' ]
86
- }
87
- )
88
- assert_equal (cli_get_info ['proxy' ], network_info ['networks' ][0 ]['proxy' ])
89
- assert_equal (cli_get_info ['difficulty' ], blockchain_info ['difficulty' ])
90
- assert_equal (cli_get_info ['chain' ], blockchain_info ['chain' ])
123
+ assert_equal (int (cli_get_info ['Version' ]), network_info ['version' ])
124
+ assert_equal (cli_get_info ['Verification progress' ], "%.4f%%" % (blockchain_info ['verificationprogress' ] * 100 ))
125
+ assert_equal (int (cli_get_info ['Blocks' ]), blockchain_info ['blocks' ])
126
+ assert_equal (int (cli_get_info ['Headers' ]), blockchain_info ['headers' ])
127
+ assert_equal (int (cli_get_info ['Time offset (s)' ]), network_info ['timeoffset' ])
128
+ expected_network_info = f"in { network_info ['connections_in' ]} , out { network_info ['connections_out' ]} , total { network_info ['connections' ]} "
129
+ assert_equal (cli_get_info ["Network" ], expected_network_info )
130
+ assert_equal (cli_get_info ['Proxy' ], network_info ['networks' ][0 ]['proxy' ])
131
+ assert_equal (Decimal (cli_get_info ['Difficulty' ]), blockchain_info ['difficulty' ])
132
+ assert_equal (cli_get_info ['Chain' ], blockchain_info ['chain' ])
91
133
92
134
if self .is_wallet_compiled ():
93
135
self .log .info ("Test -getinfo and bitcoin-cli getwalletinfo return expected wallet info" )
94
- assert_equal (cli_get_info ['balance' ] , BALANCE )
95
- assert 'balances ' not in cli_get_info . keys ()
136
+ assert_equal (Decimal ( cli_get_info ['Balance' ]) , BALANCE )
137
+ assert 'Balances ' not in cli_get_info_string
96
138
wallet_info = self .nodes [0 ].getwalletinfo ()
97
- assert_equal (cli_get_info ['keypoolsize' ] , wallet_info ['keypoolsize' ])
98
- assert_equal (cli_get_info ['unlocked_until' ] , wallet_info ['unlocked_until' ])
99
- assert_equal (cli_get_info ['paytxfee' ] , wallet_info ['paytxfee' ])
100
- assert_equal (cli_get_info ['relayfee' ] , network_info ['relayfee' ])
139
+ assert_equal (int ( cli_get_info ['Keypool size' ]) , wallet_info ['keypoolsize' ])
140
+ assert_equal (int ( cli_get_info ['Unlocked until' ]) , wallet_info ['unlocked_until' ])
141
+ assert_equal (Decimal ( cli_get_info ['Transaction fee rate (- paytxfee) (BTC/kvB)' ]) , wallet_info ['paytxfee' ])
142
+ assert_equal (Decimal ( cli_get_info ['Min tx relay fee rate (BTC/kvB)' ]) , network_info ['relayfee' ])
101
143
assert_equal (self .nodes [0 ].cli .getwalletinfo (), wallet_info )
102
144
103
145
# Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.
@@ -120,44 +162,57 @@ def run_test(self):
120
162
121
163
self .log .info ("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance" )
122
164
for i in range (len (wallets )):
123
- cli_get_info = self .nodes [0 ].cli ('-getinfo' , '-rpcwallet={}' .format (wallets [i ])).send_cli ()
124
- assert 'balances' not in cli_get_info .keys ()
125
- assert_equal (cli_get_info ['balance' ], amounts [i ])
165
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' , '-rpcwallet={}' .format (wallets [i ])).send_cli ()
166
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
167
+ assert 'Balances' not in cli_get_info_string
168
+ assert_equal (cli_get_info ["Wallet" ], wallets [i ])
169
+ assert_equal (Decimal (cli_get_info ['Balance' ]), amounts [i ])
126
170
127
171
self .log .info ("Test -getinfo with multiple wallets and -rpcwallet=non-existing-wallet returns no balances" )
128
- cli_get_info_keys = self .nodes [0 ].cli ('-getinfo' , '-rpcwallet=does-not-exist' ).send_cli (). keys ()
129
- assert 'balance ' not in cli_get_info_keys
130
- assert 'balances ' not in cli_get_info_keys
172
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' , '-rpcwallet=does-not-exist' ).send_cli ()
173
+ assert 'Balance ' not in cli_get_info_string
174
+ assert 'Balances ' not in cli_get_info_string
131
175
132
176
self .log .info ("Test -getinfo with multiple wallets returns all loaded wallet names and balances" )
133
177
assert_equal (set (self .nodes [0 ].listwallets ()), set (wallets ))
134
- cli_get_info = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
135
- assert 'balance' not in cli_get_info .keys ()
136
- assert_equal (cli_get_info ['balances' ], {k : v for k , v in zip (wallets , amounts )})
178
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
179
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
180
+ assert 'Balance' not in cli_get_info
181
+ for k , v in zip (wallets , amounts ):
182
+ assert_equal (Decimal (cli_get_info ['Balances' ][k ]), v )
137
183
138
184
# Unload the default wallet and re-verify.
139
185
self .nodes [0 ].unloadwallet (wallets [0 ])
140
186
assert wallets [0 ] not in self .nodes [0 ].listwallets ()
141
- cli_get_info = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
142
- assert 'balance' not in cli_get_info .keys ()
143
- assert_equal (cli_get_info ['balances' ], {k : v for k , v in zip (wallets [1 :], amounts [1 :])})
187
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
188
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
189
+ assert 'Balance' not in cli_get_info
190
+ assert 'Balances' in cli_get_info_string
191
+ for k , v in zip (wallets [1 :], amounts [1 :]):
192
+ assert_equal (Decimal (cli_get_info ['Balances' ][k ]), v )
193
+ assert wallets [0 ] not in cli_get_info
144
194
145
195
self .log .info ("Test -getinfo after unloading all wallets except a non-default one returns its balance" )
146
196
self .nodes [0 ].unloadwallet (wallets [2 ])
147
197
assert_equal (self .nodes [0 ].listwallets (), [wallets [1 ]])
148
- cli_get_info = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
149
- assert 'balances' not in cli_get_info .keys ()
150
- assert_equal (cli_get_info ['balance' ], amounts [1 ])
198
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' ).send_cli ()
199
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
200
+ assert 'Balances' not in cli_get_info_string
201
+ assert_equal (cli_get_info ['Wallet' ], wallets [1 ])
202
+ assert_equal (Decimal (cli_get_info ['Balance' ]), amounts [1 ])
151
203
152
204
self .log .info ("Test -getinfo with -rpcwallet=remaining-non-default-wallet returns only its balance" )
153
- cli_get_info = self .nodes [0 ].cli ('-getinfo' , rpcwallet2 ).send_cli ()
154
- assert 'balances' not in cli_get_info .keys ()
155
- assert_equal (cli_get_info ['balance' ], amounts [1 ])
205
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' , rpcwallet2 ).send_cli ()
206
+ cli_get_info = cli_get_info_string_to_dict (cli_get_info_string )
207
+ assert 'Balances' not in cli_get_info_string
208
+ assert_equal (cli_get_info ['Wallet' ], wallets [1 ])
209
+ assert_equal (Decimal (cli_get_info ['Balance' ]), amounts [1 ])
156
210
157
211
self .log .info ("Test -getinfo with -rpcwallet=unloaded wallet returns no balances" )
158
- cli_get_info_keys = self .nodes [0 ].cli ('-getinfo' , rpcwallet3 ).send_cli ().keys ()
159
- assert 'balance' not in cli_get_info_keys
160
- assert 'balances' not in cli_get_info_keys
212
+ cli_get_info_string = self .nodes [0 ].cli ('-getinfo' , rpcwallet3 ).send_cli ()
213
+ cli_get_info_keys = cli_get_info_string_to_dict (cli_get_info_string )
214
+ assert 'Balance' not in cli_get_info_keys
215
+ assert 'Balances' not in cli_get_info_string
161
216
162
217
# Test bitcoin-cli -generate.
163
218
n1 = 3
0 commit comments