From c10e385612654246fea16cb32b9826af35bd8eb7 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 21 Jul 2022 14:40:10 +0930 Subject: [PATCH] commando: add stress test, fix memleak report. Signed-off-by: Rusty Russell --- plugins/commando.c | 6 +++++- tests/test_plugin.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/plugins/commando.c b/plugins/commando.c index 9cfe41147..c2b32239e 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -452,8 +452,11 @@ static void handle_incmd(struct node_id *peer, incmd = find_commando(incoming_commands, peer, NULL); /* Don't let them buffer multiple commands: discard old. */ - if (incmd && incmd->id != idnum) + if (incmd && incmd->id != idnum) { + plugin_log(plugin, LOG_DBG, "New cmd from %s, replacing old", + node_id_to_hexstr(tmpctx, peer)); incmd = tal_free(incmd); + } if (!incmd) { incmd = tal(plugin, struct commando); @@ -705,6 +708,7 @@ static struct command_result *json_commando(struct command *cmd, tal_free(peer); tal_free(method); tal_free(cparams); + tal_free(rune); return send_more_cmd(cmd, NULL, NULL, outgoing); } diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 87341b38e..92157a50c 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -2804,3 +2804,36 @@ def test_commando_rune(node_factory): 'rune': rune['rune'], 'method': cmd, 'params': params}) + + +@pytest.mark.slow_test +def test_commando_stress(node_factory, executor): + """Stress test to slam commando with many large queries""" + nodes = node_factory.get_nodes(5) + + rune = nodes[0].rpc.commando_rune()['rune'] + for n in nodes[1:]: + n.connect(nodes[0]) + + futs = [] + for i in range(1000): + node = random.choice(nodes[1:]) + futs.append(executor.submit(node.rpc.call, method='commando', + payload={'peer_id': nodes[0].info['id'], + 'rune': rune, + 'method': 'invoice', + 'params': {'amount_msat': 'any', + 'label': 'label{}'.format(i), + 'description': 'A' * 200000, + 'deschashonly': True}})) + discards = 0 + for f in futs: + try: + f.result(TIMEOUT) + except RpcError as e: + assert(e.error['code'] == 0x4c50) + assert(e.error['message'] == "Invalid JSON") + discards += 1 + + # Should have exactly one discard msg from each discard + nodes[0].daemon.wait_for_logs([r"New cmd from .*, replacing old"] * discards)