From 32d98f0a876af041c149af8a6df1ba35354c8af4 Mon Sep 17 00:00:00 2001 From: darosior Date: Sun, 15 Sep 2019 15:19:28 +0200 Subject: [PATCH] plugins: refactor the tests for dynamic plugins This adapts the test to the new 'plugin' command: no more sleeping, since we are synchronous ! This tests the timeout by increasing the 'slowinit' plugin sleep duration at init reception. This adds a broken plugin to make sure we won't crash because of a misbehaving plugin (unmet dependency is the most common case). --- tests/plugins/broken.py | 19 +++++++++++++++++++ tests/plugins/slow_init.py | 2 +- tests/test_plugin.py | 34 +++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 16 deletions(-) create mode 100755 tests/plugins/broken.py diff --git a/tests/plugins/broken.py b/tests/plugins/broken.py new file mode 100755 index 000000000..28b871c88 --- /dev/null +++ b/tests/plugins/broken.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +"""Simple plugin to test that lightningd doesnt crash if it starts a +misbehaving plugin via RPC. +""" + +from lightning import Plugin +import an_unexistent_module_that_will_make_me_crash + +plugin = Plugin(dynamic=False) + + +@plugin.init() +def init(options, configuration, plugin): + plugin.log("broken.py initializing {}".format(configuration)) + # We need to actually use the import to pass source checks.. + an_unexistent_module_that_will_make_me_crash.hello() + + +plugin.run() diff --git a/tests/plugins/slow_init.py b/tests/plugins/slow_init.py index 4be95ced8..91945d7df 100755 --- a/tests/plugins/slow_init.py +++ b/tests/plugins/slow_init.py @@ -8,7 +8,7 @@ plugin = Plugin() @plugin.init() def init(options, configuration, plugin): plugin.log("slow_init.py initializing {}".format(configuration)) - time.sleep(1) + time.sleep(2) plugin.run() diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 6f2b85b18..53e9474df 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -94,11 +94,10 @@ def test_plugin_dir(node_factory): def test_plugin_slowinit(node_factory): - """Tests the 'plugin' RPC command when init is slow""" + """Tests that the 'plugin' RPC command times out if plugin doesnt respond""" n = node_factory.get_node() n.rpc.plugin_start(os.path.join(os.getcwd(), "tests/plugins/slow_init.py")) - n.daemon.wait_for_log("slow_init.py initializing.* 'startup': False") # It's not actually configured yet, see what happens; # make sure 'rescan' and 'list' controls dont crash @@ -116,42 +115,47 @@ def test_plugin_command(node_factory): assert(len(cmd) == 0) # Add the 'contrib/plugins' test dir - time.sleep(2) n.rpc.plugin_startdir(directory=os.path.join(os.getcwd(), "contrib/plugins")) - n.daemon.wait_for_log(r"Plugin helloworld.py initialized") # Make sure that the 'hello' command from the helloworld.py plugin # is now available. cmd = [hlp for hlp in n.rpc.help()["help"] if "hello" in hlp["command"]] assert(len(cmd) == 1) - # Make sure 'rescan' and 'list' controls dont crash + # Make sure 'rescan' and 'list' subcommands dont crash n.rpc.plugin_rescan() n.rpc.plugin_list() - time.sleep(1) # Make sure the plugin behaves normally after stop and restart - n.rpc.plugin_stop(plugin="helloworld.py") + assert("Successfully stopped helloworld.py." == n.rpc.plugin_stop(plugin="helloworld.py")['']) n.daemon.wait_for_log(r"Killing plugin: helloworld.py") - time.sleep(1) n.rpc.plugin_start(plugin=os.path.join(os.getcwd(), "contrib/plugins/helloworld.py")) n.daemon.wait_for_log(r"Plugin helloworld.py initialized") assert("Hello world" == n.rpc.call(method="hello")) # Now stop the helloworld plugin - n.rpc.plugin_stop(plugin="helloworld.py") + assert("Successfully stopped helloworld.py." == n.rpc.plugin_stop(plugin="helloworld.py")['']) n.daemon.wait_for_log(r"Killing plugin: helloworld.py") - time.sleep(1) # Make sure that the 'hello' command from the helloworld.py plugin # is not available anymore. cmd = [hlp for hlp in n.rpc.help()["help"] if "hello" in hlp["command"]] assert(len(cmd) == 0) - # Test that we cannot stop a plugin with 'dynamic' set to False in + # Test that we cannot start a plugin with 'dynamic' set to False in # getmanifest - n.rpc.plugin_start(plugin=os.path.join(os.getcwd(), "tests/plugins/static.py")) - n.daemon.wait_for_log(r"Static plugin initialized.") - with pytest.raises(RpcError, match=r"plugin cannot be managed when lightningd is up"): - n.rpc.plugin_stop(plugin="static.py") + with pytest.raises(RpcError, match=r"Not a dynamic plugin"): + n.rpc.plugin_start(plugin=os.path.join(os.getcwd(), "tests/plugins/static.py")) + + # Test that we cannot stop a started plugin with 'dynamic' flag set to + # False + n2 = node_factory.get_node(options={ + "plugin": os.path.join(os.getcwd(), "tests/plugins/static.py") + }) + with pytest.raises(RpcError, match=r"static.py cannot be managed when lightningd is up"): + n2.rpc.plugin_stop(plugin="static.py") + + # Test that we don't crash when starting a broken plugin + with pytest.raises(RpcError, match=r"Timed out while waiting for plugin response"): + n2.rpc.plugin_start(plugin=os.path.join(os.getcwd(), "tests/plugins/broken.py")) def test_plugin_disable(node_factory):