Skip to content

Commit

Permalink
pytest: test rpc_command hook chain
Browse files Browse the repository at this point in the history
  • Loading branch information
m-schmoock committed Feb 11, 2021
1 parent b13284a commit 0bcc8ac
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 17 deletions.
10 changes: 3 additions & 7 deletions tests/plugins/rpc_command.py → tests/plugins/rpc_command_1.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/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

Expand All @@ -12,15 +12,11 @@ def on_rpc_command(plugin, rpc_command, **kwargs):
request = rpc_command
if request["method"] == "invoice":
# 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}
elif request["method"] == "listfunds":
# Return a custom result to the command
return {"return": {"result": ["Custom result"]}}
elif request["method"] == "sendpay":
# Don't allow this command to be executed
return {"return": {"error": {"code": -1,
"message": "You cannot do this"}}}
return {"return": {"result": ["Custom rpc_command_1 result"]}}
elif request["method"] == "help":
request["method"] = "autocleaninvoice"
return {"replace": request}
Expand Down
24 changes: 24 additions & 0 deletions tests/plugins/rpc_command_2.py
Original file line number Diff line number Diff line change
@@ -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()
35 changes: 25 additions & 10 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import json
import os
import pytest
import random
import re
import signal
import sqlite3
Expand Down Expand Up @@ -1332,28 +1333,42 @@ def test_sendpay_notifications_nowaiter(node_factory):


def test_rpc_command_hook(node_factory):
"""Test the `sensitive_command` hook"""
plugin = os.path.join(os.getcwd(), "tests/plugins/rpc_command.py")
"""Test the `rpc_command` hook chain"""
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})

# Usage of "sendpay" has been restricted by the plugin
with pytest.raises(RpcError, match=r"You cannot do this"):
# rpc_command_2 plugin restricts using "sendpay"
with pytest.raises(RpcError, match=r"rpc_command_2 cannot do this"):
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")
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()
assert funds[0] == "Custom result"
assert funds[0] == "Custom rpc_command_1 result"

# Test command redirection to a plugin
l1.rpc.call('help', [0])

# Test command which removes plugin itself!
l1.rpc.plugin_stop('rpc_command.py')
# Check the 'already modified' warning is not logged on just 'continue'
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):
Expand Down

0 comments on commit 0bcc8ac

Please sign in to comment.