55"""Test bitcoin-cli"""
66
77from decimal import Decimal
8+ import re
89
910from test_framework .blocktools import COINBASE_MATURITY
1011from test_framework .test_framework import BitcoinTestFramework
2930WALLET_NOT_LOADED = 'Requested wallet does not exist or is not loaded'
3031WALLET_NOT_SPECIFIED = 'Wallet file not specified'
3132
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+
3268class TestBitcoinCli (BitcoinTestFramework ):
3369 def set_test_params (self ):
3470 self .setup_clean_chain = True
@@ -67,37 +103,43 @@ def run_test(self):
67103 self .log .info ("Test -getinfo with arguments fails" )
68104 assert_raises_process_error (1 , "-getinfo takes no arguments" , self .nodes [0 ].cli ('-getinfo' ).help )
69105
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+
70115 self .log .info ("Test -getinfo returns expected network and blockchain info" )
71116 if self .is_wallet_compiled ():
72117 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+
74121 network_info = self .nodes [0 ].getnetworkinfo ()
75122 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' ])
91133
92134 if self .is_wallet_compiled ():
93135 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
96138 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' ])
101143 assert_equal (self .nodes [0 ].cli .getwalletinfo (), wallet_info )
102144
103145 # Setup to test -getinfo, -generate, and -rpcwallet= with multiple wallets.
@@ -120,44 +162,57 @@ def run_test(self):
120162
121163 self .log .info ("Test -getinfo with multiple wallets and -rpcwallet returns specified wallet balance" )
122164 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 ])
126170
127171 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
131175
132176 self .log .info ("Test -getinfo with multiple wallets returns all loaded wallet names and balances" )
133177 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 )
137183
138184 # Unload the default wallet and re-verify.
139185 self .nodes [0 ].unloadwallet (wallets [0 ])
140186 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
144194
145195 self .log .info ("Test -getinfo after unloading all wallets except a non-default one returns its balance" )
146196 self .nodes [0 ].unloadwallet (wallets [2 ])
147197 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 ])
151203
152204 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 ])
156210
157211 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
161216
162217 # Test bitcoin-cli -generate.
163218 n1 = 3
0 commit comments