[Tests] Shutdown test daemon cleanly using rpc. (needed for Windows)
Escape backslashes in config path for test daemon startup.
This commit is contained in:
parent
3dca30343f
commit
209716f7cd
|
@ -19,7 +19,9 @@ from twisted.trial import unittest
|
||||||
import deluge.configmanager
|
import deluge.configmanager
|
||||||
import deluge.core.preferencesmanager
|
import deluge.core.preferencesmanager
|
||||||
import deluge.log
|
import deluge.log
|
||||||
|
from deluge.common import get_localhost_auth
|
||||||
from deluge.error import DelugeError
|
from deluge.error import DelugeError
|
||||||
|
from deluge.ui.client import client
|
||||||
|
|
||||||
# This sets log level to critical, so use log.critical() to debug while running unit tests
|
# This sets log level to critical, so use log.critical() to debug while running unit tests
|
||||||
deluge.log.setup_logger('none')
|
deluge.log.setup_logger('none')
|
||||||
|
@ -94,12 +96,19 @@ class ReactorOverride:
|
||||||
|
|
||||||
class ProcessOutputHandler(protocol.ProcessProtocol):
|
class ProcessOutputHandler(protocol.ProcessProtocol):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, script, callbacks, logfile=None, print_stdout=True, print_stderr=True
|
self,
|
||||||
|
script,
|
||||||
|
shutdown_func,
|
||||||
|
callbacks,
|
||||||
|
logfile=None,
|
||||||
|
print_stdout=True,
|
||||||
|
print_stderr=True,
|
||||||
):
|
):
|
||||||
"""Executes a script and handle the process' output to stdout and stderr.
|
"""Executes a script and handle the process' output to stdout and stderr.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
script (str): The script to execute.
|
script (str): The script to execute.
|
||||||
|
shutdown_func (func): A function which will gracefully stop the called script.
|
||||||
callbacks (list): Callbacks to trigger if the expected output if found.
|
callbacks (list): Callbacks to trigger if the expected output if found.
|
||||||
logfile (str, optional): Filename to wrote the process' output.
|
logfile (str, optional): Filename to wrote the process' output.
|
||||||
print_stderr (bool): Print the process' stderr output to stdout.
|
print_stderr (bool): Print the process' stderr output to stdout.
|
||||||
|
@ -108,6 +117,7 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
|
||||||
"""
|
"""
|
||||||
self.callbacks = callbacks
|
self.callbacks = callbacks
|
||||||
self.script = script
|
self.script = script
|
||||||
|
self.shutdown_func = shutdown_func
|
||||||
self.log_output = ''
|
self.log_output = ''
|
||||||
self.stderr_out = ''
|
self.stderr_out = ''
|
||||||
self.logfile = logfile
|
self.logfile = logfile
|
||||||
|
@ -127,6 +137,7 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
|
||||||
with open(self.logfile, 'w') as f:
|
with open(self.logfile, 'w') as f:
|
||||||
f.write(self.log_output)
|
f.write(self.log_output)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
def kill(self):
|
def kill(self):
|
||||||
"""Kill the running process.
|
"""Kill the running process.
|
||||||
|
|
||||||
|
@ -139,8 +150,13 @@ class ProcessOutputHandler(protocol.ProcessProtocol):
|
||||||
self.killed = True
|
self.killed = True
|
||||||
self._kill_watchdogs()
|
self._kill_watchdogs()
|
||||||
self.quit_d = Deferred()
|
self.quit_d = Deferred()
|
||||||
self.transport.signalProcess('INT')
|
shutdown = self.shutdown_func()
|
||||||
return self.quit_d
|
shutdown.addTimeout(5, reactor)
|
||||||
|
try:
|
||||||
|
yield shutdown
|
||||||
|
except Exception:
|
||||||
|
self.transport.signalProcess('TERM')
|
||||||
|
yield self.quit_d
|
||||||
|
|
||||||
def _kill_watchdogs(self):
|
def _kill_watchdogs(self):
|
||||||
""""Cancel all watchdogs"""
|
""""Cancel all watchdogs"""
|
||||||
|
@ -216,7 +232,7 @@ def start_core(
|
||||||
Args:
|
Args:
|
||||||
listen_port (int, optional): The port the daemon listens for client connections.
|
listen_port (int, optional): The port the daemon listens for client connections.
|
||||||
logfile (str, optional): Logfile name to write the output from the process.
|
logfile (str, optional): Logfile name to write the output from the process.
|
||||||
timeout (int): If none of the callbacks have been triggered before the imeout, the process is killed.
|
timeout (int): If none of the callbacks have been triggered before the timeout, the process is killed.
|
||||||
timeout_msg (str): The message to print when the timeout expires.
|
timeout_msg (str): The message to print when the timeout expires.
|
||||||
custom_script (str): Extra python code to insert into the daemon process script.
|
custom_script (str): Extra python code to insert into the daemon process script.
|
||||||
print_stderr (bool): If the output from the process' stderr should be printed to stdout.
|
print_stderr (bool): If the output from the process' stderr should be printed to stdout.
|
||||||
|
@ -251,7 +267,7 @@ except Exception:
|
||||||
import traceback
|
import traceback
|
||||||
sys.stderr.write('Exception raised:\\n %%s' %% traceback.format_exc())
|
sys.stderr.write('Exception raised:\\n %%s' %% traceback.format_exc())
|
||||||
""" % {
|
""" % {
|
||||||
'dir': config_directory,
|
'dir': config_directory.replace('\\', '\\\\'),
|
||||||
'port': listen_port,
|
'port': listen_port,
|
||||||
'script': custom_script,
|
'script': custom_script,
|
||||||
}
|
}
|
||||||
|
@ -286,20 +302,29 @@ except Exception:
|
||||||
if extra_callbacks:
|
if extra_callbacks:
|
||||||
callbacks.extend(extra_callbacks)
|
callbacks.extend(extra_callbacks)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def shutdown_daemon():
|
||||||
|
username, password = get_localhost_auth()
|
||||||
|
yield client.connect(
|
||||||
|
'localhost', listen_port, username=username, password=password
|
||||||
|
)
|
||||||
|
yield client.daemon.shutdown()
|
||||||
|
|
||||||
process_protocol = start_process(
|
process_protocol = start_process(
|
||||||
daemon_script, callbacks, logfile, print_stdout, print_stderr
|
daemon_script, shutdown_daemon, callbacks, logfile, print_stdout, print_stderr
|
||||||
)
|
)
|
||||||
return default_core_cb['deferred'], process_protocol
|
return default_core_cb['deferred'], process_protocol
|
||||||
|
|
||||||
|
|
||||||
def start_process(
|
def start_process(
|
||||||
script, callbacks, logfile=None, print_stdout=True, print_stderr=True
|
script, shutdown_func, callbacks, logfile=None, print_stdout=True, print_stderr=True
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Starts an external python process which executes the given script.
|
Starts an external python process which executes the given script.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
script (str): The content of the script to execute.
|
script (str): The content of the script to execute.
|
||||||
|
shutdown_func (func): A function which will gracefully end the called script.
|
||||||
callbacks (list): list of dictionaries specifying callbacks.
|
callbacks (list): list of dictionaries specifying callbacks.
|
||||||
logfile (str, optional): Logfile name to write the output from the process.
|
logfile (str, optional): Logfile name to write the output from the process.
|
||||||
print_stderr (bool): If the output from the process' stderr should be printed to stdout.
|
print_stderr (bool): If the output from the process' stderr should be printed to stdout.
|
||||||
|
@ -321,7 +346,12 @@ def start_process(
|
||||||
"""
|
"""
|
||||||
cwd = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
cwd = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||||
process_protocol = ProcessOutputHandler(
|
process_protocol = ProcessOutputHandler(
|
||||||
script.encode('utf8'), callbacks, logfile, print_stdout, print_stderr
|
script.encode('utf8'),
|
||||||
|
shutdown_func,
|
||||||
|
callbacks,
|
||||||
|
logfile,
|
||||||
|
print_stdout,
|
||||||
|
print_stderr,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add timeouts to deferreds
|
# Add timeouts to deferreds
|
||||||
|
|
Loading…
Reference in New Issue