[UI] Add tests for ui_entry

This commit is contained in:
bendikro 2016-04-29 00:13:28 +02:00 committed by Calum Lind
parent d5294d5733
commit bb0e699619
7 changed files with 84 additions and 26 deletions

View File

@ -66,12 +66,12 @@ class Core(CorePluginBase):
try: try:
self.server = component.get("DelugeWeb") self.server = component.get("DelugeWeb")
except KeyError: except KeyError:
self.server = server.DelugeWeb() self.server = server.DelugeWeb(daemon=False)
self.server.port = self.config["port"] self.server.port = self.config["port"]
self.server.https = self.config["ssl"] self.server.https = self.config["ssl"]
try: try:
self.server.start(standalone=False) self.server.start()
except CannotListenError as ex: except CannotListenError as ex:
log.warn("Failed to start WebUI server: %s", ex) log.warn("Failed to start WebUI server: %s", ex)
raise raise

View File

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
import mock
import pytest
import deluge.component as component
from deluge.ui import ui_entry
from . import common
from .basetest import BaseTestCase
@pytest.mark.gtkui
class UIEntryTestCase(BaseTestCase):
def set_up(self):
common.set_tmp_config_dir()
return component.start()
def tear_down(self):
return component.shutdown()
def test_start_gtkui(self):
import deluge.ui.gtkui.gtkui
import sys
self.patch(sys, "argv", ['./deluge', "--ui", 'gtk'])
with mock.patch.object(deluge.ui.gtkui.gtkui.GtkUI, 'start', autospec=True):
ui_entry.start_ui()
def test_start_console(self):
import sys
self.patch(sys, "argv", ['./deluge', "--ui", 'console'])
with mock.patch('deluge.ui.console.main.ConsoleUI'):
ui_entry.start_ui()
def test_start_webserver(self):
import sys
from deluge.ui.web.server import DelugeWeb
self.patch(sys, "argv", ['./deluge', "--ui", 'web', '--do-not-daemonize'])
class DelugeWebMock(DelugeWeb):
def __init__(self, *args, **kwargs):
kwargs["daemon"] = False
DelugeWeb.__init__(self, *args, **kwargs)
import deluge.ui.web.server
self.patch(deluge.ui.web.server, 'DelugeWeb', DelugeWebMock)
ui_entry.start_ui()

View File

@ -64,7 +64,7 @@ class WebAPITestCase(BaseTestCase, DaemonBase):
config_defaults["port"] = self.webserver_listen_port config_defaults["port"] = self.webserver_listen_port
self.config = configmanager.ConfigManager("web.conf", config_defaults) self.config = configmanager.ConfigManager("web.conf", config_defaults)
self.deluge_web = DelugeWeb() self.deluge_web = DelugeWeb(daemon=False)
host = list(self.deluge_web.web_api.host_list["hosts"][0]) host = list(self.deluge_web.web_api.host_list["hosts"][0])
host[2] = self.listen_port host[2] = self.listen_port

View File

@ -28,7 +28,7 @@ try:
reactor = gtk2reactor.install() reactor = gtk2reactor.install()
except ReactorAlreadyInstalledError as ex: except ReactorAlreadyInstalledError as ex:
# Running unit tests so trial already installed a rector # Running unit tests so trial already installed a rector
pass from twisted.internet import reactor
import deluge.common import deluge.common
import deluge.component as component import deluge.component as component
@ -151,7 +151,8 @@ class Gtk(UI):
def run(options): def run(options):
try: try:
GtkUI(options) gtkui = GtkUI(options)
gtkui.start()
except Exception as ex: except Exception as ex:
log.exception(ex) log.exception(ex)
raise raise
@ -250,19 +251,20 @@ class GtkUI(object):
# daemon_bps: time, bytes_sent, bytes_recv # daemon_bps: time, bytes_sent, bytes_recv
self.daemon_bps = (0, 0, 0) self.daemon_bps = (0, 0, 0)
self.rpc_stats = LoopingCall(self.print_rpc_stats) self.rpc_stats = LoopingCall(self.print_rpc_stats)
self.closing = False
# Twisted catches signals to terminate, so have it call a pre_shutdown method. # Twisted catches signals to terminate, so have it call a pre_shutdown method.
reactor.addSystemEventTrigger("before", "gtkui_close", self.close) reactor.addSystemEventTrigger("before", "gtkui_close", self.close)
reactor.callWhenRunning(self._on_reactor_start)
self.closing = False
def gtkui_sigint_handler(num, frame): def gtkui_sigint_handler(num, frame):
log.debug("SIGINT signal caught - firing event: 'gtkui_close'") log.debug("SIGINT signal caught - firing event: 'gtkui_close'")
reactor.callLater(0, reactor.fireSystemEvent, 'gtkui_close') reactor.callLater(0, reactor.fireSystemEvent, 'gtkui_close')
signal.signal(signal.SIGINT, gtkui_sigint_handler) signal.signal(signal.SIGINT, gtkui_sigint_handler)
def start(self):
reactor.callWhenRunning(self._on_reactor_start)
# Initialize gdk threading # Initialize gdk threading
gtk.gdk.threads_enter() gtk.gdk.threads_enter()
reactor.run() reactor.run()

View File

@ -74,6 +74,7 @@ class IPCClientFactory(ClientFactory):
class IPCInterface(component.Component): class IPCInterface(component.Component):
def __init__(self, args): def __init__(self, args):
component.Component.__init__(self, "IPCInterface") component.Component.__init__(self, "IPCInterface")
self.listener = None
ipc_dir = get_config_dir("ipc") ipc_dir = get_config_dir("ipc")
if not os.path.exists(ipc_dir): if not os.path.exists(ipc_dir):
os.makedirs(ipc_dir) os.makedirs(ipc_dir)
@ -91,7 +92,7 @@ class IPCInterface(component.Component):
self.factory.protocol = IPCProtocolServer self.factory.protocol = IPCProtocolServer
import random import random
port = random.randrange(20000, 65535) port = random.randrange(20000, 65535)
reactor.listenTCP(port, self.factory) self.listener = reactor.listenTCP(port, self.factory)
# Store the port number in the socket file # Store the port number in the socket file
open(socket, "w").write(str(port)) open(socket, "w").write(str(port))
# We need to process any args when starting this process # We need to process any args when starting this process
@ -132,7 +133,7 @@ class IPCInterface(component.Component):
try: try:
self.factory = Factory() self.factory = Factory()
self.factory.protocol = IPCProtocolServer self.factory.protocol = IPCProtocolServer
reactor.listenUNIX(socket, self.factory, wantPID=True) self.listener = reactor.listenUNIX(socket, self.factory, wantPID=True)
except twisted.internet.error.CannotListenError as ex: except twisted.internet.error.CannotListenError as ex:
log.info("Deluge is already running! Sending arguments to running instance...") log.info("Deluge is already running! Sending arguments to running instance...")
self.factory = IPCClientFactory() self.factory = IPCClientFactory()
@ -160,6 +161,8 @@ class IPCInterface(component.Component):
if windows_check(): if windows_check():
import win32api import win32api
win32api.CloseHandle(self.mutex) win32api.CloseHandle(self.mutex)
if self.listener:
return self.listener.stopListening()
def process_args(args): def process_args(args):

View File

@ -532,8 +532,17 @@ class TopLevel(resource.Resource):
class DelugeWeb(component.Component): class DelugeWeb(component.Component):
def __init__(self, options=None): def __init__(self, options=None, daemon=True):
super(DelugeWeb, self).__init__("DelugeWeb") """
Setup the DelugeWeb server.
Args:
options (argparse.Namespace): The web server options.
daemon (bool): If True run web server as a seperate daemon process (starts a twisted
reactor). If False shares the process and twisted reactor from WebUI plugin or tests.
"""
component.Component.__init__(self, "DelugeWeb", depend=["Web"])
self.config = configmanager.ConfigManager("web.conf", CONFIG_DEFAULTS) self.config = configmanager.ConfigManager("web.conf", CONFIG_DEFAULTS)
self.config.run_converter((0, 1), 2, self._migrate_config_1_to_2) self.config.run_converter((0, 1), 2, self._migrate_config_1_to_2)
self.config.register_set_function("language", self._on_language_changed) self.config.register_set_function("language", self._on_language_changed)
@ -567,7 +576,7 @@ class DelugeWeb(component.Component):
self.web_utils = WebUtils() self.web_utils = WebUtils()
self.auth = Auth(self.config) self.auth = Auth(self.config)
self.standalone = True self.daemon = daemon
# Initalize the plugins # Initalize the plugins
self.plugins = PluginManager() self.plugins = PluginManager()
@ -594,22 +603,14 @@ class DelugeWeb(component.Component):
return 1 return 1
SetConsoleCtrlHandler(win_handler) SetConsoleCtrlHandler(win_handler)
def start(self, standalone=True): def start(self):
""" """
Start the DelugeWeb server Start the DelugeWeb server
When running WebUI plugin, the server must not try to start
the twisted reactor.
Args:
standalone (bool): Whether the server runs as a standalone process
If standalone, start twisted reactor.
""" """
if self.socket: if self.socket:
log.warn("DelugeWeb is already running and cannot be started") log.warn("DelugeWeb is already running and cannot be started")
return return
self.standalone = standalone
log.info("Starting webui server at PID %s", os.getpid()) log.info("Starting webui server at PID %s", os.getpid())
if self.https: if self.https:
self.start_ssl() self.start_ssl()
@ -618,7 +619,7 @@ class DelugeWeb(component.Component):
component.get("Web").enable() component.get("Web").enable()
if self.standalone: if self.daemon:
reactor.run() reactor.run()
def start_normal(self): def start_normal(self):
@ -641,7 +642,10 @@ class DelugeWeb(component.Component):
def stop(self): def stop(self):
log.info("Shutting down webserver") log.info("Shutting down webserver")
component.get("Web").disable() try:
component.get("Web").disable()
except KeyError:
pass
self.plugins.disable_plugins() self.plugins.disable_plugins()
log.debug("Saving configuration file") log.debug("Saving configuration file")
@ -657,7 +661,7 @@ class DelugeWeb(component.Component):
def shutdown(self, *args): def shutdown(self, *args):
self.stop() self.stop()
if self.standalone and reactor.running: if self.daemon and reactor.running:
reactor.stop() reactor.stop()
def _migrate_config_1_to_2(self, config): def _migrate_config_1_to_2(self, config):

View File

@ -60,7 +60,7 @@ class Web(UI):
self.server.install_signal_handlers() self.server.install_signal_handlers()
self.server.start() self.server.start()
except CannotListenError as ex: except CannotListenError as ex:
log.error("%s \nCheck that deluge-web or webui plugin are not already running.", ex) log.error("%s \nCheck that deluge-web or webui plugin is not already running.", ex)
except Exception as ex: except Exception as ex:
log.exception(ex) log.exception(ex)
raise raise