rpc: Handle -named argument parsing where '=' character is used

This commit is contained in:
zaidmstrr
2025-06-27 15:49:58 +05:30
parent 65e909dfdd
commit 694f04e2bd
3 changed files with 199 additions and 65 deletions

View File

@@ -17,30 +17,40 @@ def parse_string(s):
assert s[-1] == '"'
return s[1:-1]
def process_mapping(fname):
"""Find and parse conversion table in implementation file `fname`."""
cmds = []
string_params = []
in_rpcs = False
with open(fname, "r", encoding="utf8") as f:
for line in f:
line = line.rstrip()
if not in_rpcs:
if line == 'static const CRPCConvertParam vRPCConvertParams[] =':
if re.match(r'static const CRPCConvertParam vRPCConvertParams\[] =', line):
in_rpcs = True
else:
if line.startswith('};'):
in_rpcs = False
elif '{' in line and '"' in line:
m = re.search(r'{ *("[^"]*"), *([0-9]+) *, *("[^"]*") *(, \/\*also_string=\*\/true *)?},', line)
assert m, 'No match to table expression: %s' % line
name = parse_string(m.group(1))
idx = int(m.group(2))
argname = parse_string(m.group(3))
cmds.append((name, idx, argname))
assert not in_rpcs and cmds
return cmds
# Match lines with ParamFormat::STRING
m_string = re.search(r'{ *("[^"]*") *, *([0-9]+) *, *("[^"]*") *, *ParamFormat::STRING *},?', line)
if m_string:
name = parse_string(m_string.group(1))
idx = int(m_string.group(2))
argname = parse_string(m_string.group(3))
string_params.append((name, idx, argname))
continue
# Match lines with ParamFormat::JSON and ParamFormat::JSON_OR_STRING
m_json = re.search(r'{ *("[^"]*") *, *([0-9]+) *, *("[^"]*") *(?:, *ParamFormat::(JSON_OR_STRING|JSON))? *},?', line)
if m_json:
name = parse_string(m_json.group(1))
idx = int(m_json.group(2))
argname = parse_string(m_json.group(3))
cmds.append((name, idx, argname))
assert not in_rpcs
return cmds, string_params
class HelpRpcTest(BitcoinTestFramework):
def set_test_params(self):
@@ -49,6 +59,7 @@ class HelpRpcTest(BitcoinTestFramework):
def run_test(self):
self.test_client_conversion_table()
self.test_client_string_conversion_table()
self.test_categories()
self.dump_help()
if self.is_wallet_compiled():
@@ -56,7 +67,7 @@ class HelpRpcTest(BitcoinTestFramework):
def test_client_conversion_table(self):
file_conversion_table = os.path.join(self.config["environment"]["SRCDIR"], 'src', 'rpc', 'client.cpp')
mapping_client = process_mapping(file_conversion_table)
mapping_client, _ = process_mapping(file_conversion_table)
# Ignore echojson in client table
mapping_client = [m for m in mapping_client if m[0] != 'echojson']
@@ -85,6 +96,29 @@ class HelpRpcTest(BitcoinTestFramework):
# Only allow dummy and psbt to fail consistency check
assert argname in ['dummy', "psbt"], ('WARNING: conversion mismatch for argument named %s (%s)' % (argname, list(zip(all_methods_by_argname[argname], converts_by_argname[argname]))))
def test_client_string_conversion_table(self):
file_conversion_table = os.path.join(self.config["environment"]["SRCDIR"], 'src', 'rpc', 'client.cpp')
_, string_params_client = process_mapping(file_conversion_table)
mapping_server = self.nodes[0].help("dump_all_command_conversions")
server_tuples = {tuple(m[:3]) for m in mapping_server}
# Filter string parameters based on wallet compilation status
if self.is_wallet_compiled():
# Check that every entry in string parameters exists on the server
stale_entries = [entry for entry in string_params_client if entry not in server_tuples]
if stale_entries:
raise AssertionError(f"String parameters contains entries not present on the server: {stale_entries}")
filtered_string_params = string_params_client
else:
available_string_params = [entry for entry in string_params_client if entry in server_tuples]
filtered_string_params = available_string_params
# Validate that all entries are legitimate server parameters
server_method_param_tuples = {(m[0], m[1], m[2]) for m in mapping_server}
invalid_entries = [entry for entry in filtered_string_params if entry not in server_method_param_tuples]
if invalid_entries:
raise AssertionError(f"String parameters contains invalid entries: {invalid_entries}")
def test_categories(self):
node = self.nodes[0]
@@ -128,6 +162,5 @@ class HelpRpcTest(BitcoinTestFramework):
self.restart_node(0, extra_args=['-nowallet=1'])
assert 'getnewaddress ( "label" "address_type" )' in self.nodes[0].help('getnewaddress')
if __name__ == '__main__':
HelpRpcTest(__file__).main()