mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
pytest: test rpc_command hook chain
This commit is contained in:
parent
316457a1de
commit
d753ee27a2
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
This plugin is used to test the `rpc_command` hook.
|
This plugin is used to test the chained `rpc_command` hook.
|
||||||
"""
|
"""
|
||||||
from pyln.client import Plugin
|
from pyln.client import Plugin
|
||||||
|
|
||||||
@ -12,15 +12,11 @@ def on_rpc_command(plugin, rpc_command, **kwargs):
|
|||||||
request = rpc_command
|
request = rpc_command
|
||||||
if request["method"] == "invoice":
|
if request["method"] == "invoice":
|
||||||
# Replace part of this command
|
# Replace part of this command
|
||||||
request["params"]["description"] = "A plugin modified this description"
|
request["params"]["description"] = "rpc_command_1 modified this description"
|
||||||
return {"replace": request}
|
return {"replace": request}
|
||||||
elif request["method"] == "listfunds":
|
elif request["method"] == "listfunds":
|
||||||
# Return a custom result to the command
|
# Return a custom result to the command
|
||||||
return {"return": {"result": ["Custom result"]}}
|
return {"return": {"result": ["Custom rpc_command_1 result"]}}
|
||||||
elif request["method"] == "sendpay":
|
|
||||||
# Don't allow this command to be executed
|
|
||||||
return {"return": {"error": {"code": -1,
|
|
||||||
"message": "You cannot do this"}}}
|
|
||||||
elif request["method"] == "help":
|
elif request["method"] == "help":
|
||||||
request["method"] = "autocleaninvoice"
|
request["method"] = "autocleaninvoice"
|
||||||
return {"replace": request}
|
return {"replace": request}
|
24
tests/plugins/rpc_command_2.py
Executable file
24
tests/plugins/rpc_command_2.py
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
This plugin is used to test the chained `rpc_command` hook.
|
||||||
|
"""
|
||||||
|
from pyln.client import Plugin
|
||||||
|
|
||||||
|
plugin = Plugin()
|
||||||
|
|
||||||
|
|
||||||
|
@plugin.hook("rpc_command")
|
||||||
|
def on_rpc_command(plugin, rpc_command, **kwargs):
|
||||||
|
request = rpc_command
|
||||||
|
if request["method"] == "invoice":
|
||||||
|
# Replace part of this command
|
||||||
|
request["params"]["description"] = "rpc_command_2 modified this description"
|
||||||
|
return {"replace": request}
|
||||||
|
elif request["method"] == "sendpay":
|
||||||
|
# Don't allow this command to be executed
|
||||||
|
return {"return": {"error": {"code": -1,
|
||||||
|
"message": "rpc_command_2 cannot do this"}}}
|
||||||
|
return {"result": "continue"}
|
||||||
|
|
||||||
|
|
||||||
|
plugin.run()
|
@ -16,6 +16,7 @@ import ast
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
|
import random
|
||||||
import re
|
import re
|
||||||
import signal
|
import signal
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@ -1339,28 +1340,42 @@ def test_sendpay_notifications_nowaiter(node_factory):
|
|||||||
|
|
||||||
|
|
||||||
def test_rpc_command_hook(node_factory):
|
def test_rpc_command_hook(node_factory):
|
||||||
"""Test the `sensitive_command` hook"""
|
"""Test the `rpc_command` hook chain"""
|
||||||
plugin = os.path.join(os.getcwd(), "tests/plugins/rpc_command.py")
|
plugin = [
|
||||||
|
os.path.join(os.getcwd(), "tests/plugins/rpc_command_1.py"),
|
||||||
|
os.path.join(os.getcwd(), "tests/plugins/rpc_command_2.py")
|
||||||
|
]
|
||||||
l1 = node_factory.get_node(options={"plugin": plugin})
|
l1 = node_factory.get_node(options={"plugin": plugin})
|
||||||
|
|
||||||
# Usage of "sendpay" has been restricted by the plugin
|
# rpc_command_2 plugin restricts using "sendpay"
|
||||||
with pytest.raises(RpcError, match=r"You cannot do this"):
|
with pytest.raises(RpcError, match=r"rpc_command_2 cannot do this"):
|
||||||
l1.rpc.call("sendpay")
|
l1.rpc.call("sendpay")
|
||||||
|
|
||||||
# The plugin replaces a call made for the "invoice" command
|
# Both plugins will replace calls made for the "invoice" command
|
||||||
|
# The first will win, for the second a warning should be logged
|
||||||
invoice = l1.rpc.invoice(10**6, "test_side", "test_input")
|
invoice = l1.rpc.invoice(10**6, "test_side", "test_input")
|
||||||
decoded = l1.rpc.decodepay(invoice["bolt11"])
|
decoded = l1.rpc.decodepay(invoice["bolt11"])
|
||||||
assert decoded["description"] == "A plugin modified this description"
|
assert decoded["description"] == "rpc_command_1 modified this description"
|
||||||
|
l1.daemon.wait_for_log("rpc_command hook 'invoice' already modified, ignoring.")
|
||||||
|
|
||||||
# The plugin sends a custom response to "listfunds"
|
# rpc_command_1 plugin sends a custom response to "listfunds"
|
||||||
funds = l1.rpc.listfunds()
|
funds = l1.rpc.listfunds()
|
||||||
assert funds[0] == "Custom result"
|
assert funds[0] == "Custom rpc_command_1 result"
|
||||||
|
|
||||||
# Test command redirection to a plugin
|
# Test command redirection to a plugin
|
||||||
l1.rpc.call('help', [0])
|
l1.rpc.call('help', [0])
|
||||||
|
|
||||||
# Test command which removes plugin itself!
|
# Check the 'already modified' warning is not logged on just 'continue'
|
||||||
l1.rpc.plugin_stop('rpc_command.py')
|
assert not l1.daemon.is_in_log("rpc_command hook 'listfunds' already modified, ignoring.")
|
||||||
|
|
||||||
|
# Tests removing a chained hook in random order.
|
||||||
|
# Note: This will get flaky by design if theres a problem.
|
||||||
|
if bool(random.getrandbits(1)):
|
||||||
|
l1.rpc.plugin_stop('rpc_command_2.py')
|
||||||
|
l1.rpc.plugin_stop('rpc_command_1.py')
|
||||||
|
else:
|
||||||
|
l1.rpc.plugin_stop('rpc_command_1.py')
|
||||||
|
l1.rpc.plugin_stop('rpc_command_2.py')
|
||||||
|
|
||||||
|
|
||||||
def test_libplugin(node_factory):
|
def test_libplugin(node_factory):
|
||||||
|
Loading…
Reference in New Issue
Block a user