Skip to content

Commit

Permalink
PluginResourceManager: add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-Kamina committed Jul 17, 2024
1 parent 62584c1 commit 742ac7f
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 0 deletions.
71 changes: 71 additions & 0 deletions deluge/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@
import os
import sys
import traceback
from pathlib import Path
from unittest import mock

import pytest
import pytest_twisted
from twisted.internet import defer, protocol, reactor
from twisted.internet.defer import Deferred
from twisted.internet.error import CannotListenError

import deluge.component as component
import deluge.configmanager
import deluge.core.preferencesmanager
import deluge.log
import deluge.pluginmanagerbase
from deluge.common import get_localhost_auth
from deluge.error import DelugeError
from deluge.ui.client import Client
Expand All @@ -39,6 +43,14 @@ def get_test_data_file(filename):
return os.path.join(os.path.join(os.path.dirname(__file__), 'data'), filename)


def plugin_search_dir(self):
basedir = get_test_data_file('')
test_plugin_wheels = list(Path(basedir).glob('*.whl'))
plugin_dir = [basedir] + [str(i) for i in test_plugin_wheels]
print(f'plugin_search_dir(): plugin_dir is: {plugin_dir}')
return plugin_dir


def todo_test(caller):
# If we are using the delugereporter we can set todo mark on the test
# Without the delugereporter the todo would print a stack trace, so in
Expand Down Expand Up @@ -66,6 +78,65 @@ def callback(value):
return watchdog


@mock.patch('deluge.pluginmanagerbase.PluginManagerBase.get_plugin_dirs', plugin_search_dir)
@pytest.mark.usefixtures('config_dir')
class TestPluginManager(
deluge.pluginmanagerbase.PluginManagerBase, component.Component
):
"""For testing the PluginManager and PluginResourceManager."""

def __init__(self, core):
component.Component.__init__(self, 'TestPluginManager')

self.status_fields = {}

# Call the PluginManagerBase constructor
deluge.pluginmanagerbase.PluginManagerBase.__init__(
self, 'core.conf', 'deluge.plugin.core'
)

def start(self):
# Enable plugins that are enabled in the config
self.enable_plugins()

def stop(self):
# Disable all enabled plugins
self.disable_plugins()

def shutdown(self):
self.stop()

def update_plugins(self):
for plugin in self.plugins:
if hasattr(self.plugins[plugin], 'update'):
try:
self.plugins[plugin].update()
except Exception as ex:
deluge.log.critical(ex)

def enable_plugin(self, name):
d = defer.succeed(True)
if name not in self.plugins:
d = deluge.pluginmanagerbase.PluginManagerBase.enable_plugin(self, name)

def on_enable_plugin(result):
return result

d.addBoth(on_enable_plugin)
return d

def disable_plugin(self, name):
d = defer.succeed(True)
if name in self.plugins:
d = deluge.pluginmanagerbase.PluginManagerBase.disable_plugin(self, name)

def on_disable_plugin(result):
return result

d.addBoth(on_disable_plugin)
return d


class ReactorOverride:
"""Class used to patch reactor while running unit tests
to avoid starting and stopping the twisted reactor
Expand Down
9 changes: 9 additions & 0 deletions deluge/tests/test_plugin_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@
# See LICENSE for more details.
#

from unittest import mock

from deluge.pluginmanagerbase import PluginManagerBase

from . import common


class TestPluginManagerBase:
@mock.patch('deluge.pluginmanagerbase.PluginManagerBase.get_plugin_dirs', common.plugin_search_dir)
def test_scan_for_plugins(self):
pm = PluginManagerBase('core.conf', 'deluge.plugin.core')
assert 'plugin_resources_test' in pm.available_plugins

def test_get_plugin_info(self):
pm = PluginManagerBase('core.conf', 'deluge.plugin.core')
for p in pm.get_available_plugins():
Expand Down
122 changes: 122 additions & 0 deletions deluge/tests/test_plugin_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#
# Copyright (C) 2024 Gregorio Litenstein <[email protected]>
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#

import os
from unittest import mock

import deluge.component as component
from deluge.conftest import BaseTestCase
from deluge.core.core import Core
from deluge.core.rpcserver import RPCServer
from deluge.plugin_resource_manager import PluginResourceManager
from deluge.pluginmanagerbase import PluginManagerBase

from . import common

common.disable_new_release_check()


@mock.patch('deluge.core.pluginmanager.PluginManager', common.TestPluginManager)
class TestPluginResourceManager(BaseTestCase):
test_plugin_js = b'''/**
* Script: plugin_resources_test.js
* The client-side javascript code for the plugin_resources_test plugin.
*
* Copyright:
* (C) Gregorio Litenstein 2024 <[email protected]>
*
* This file is part of plugin_resources_test and is licensed under GNU GPL 3.0, or
* later, with the additional special exception to link portions of this
* program with the OpenSSL library. See LICENSE for more details.
*/
plugin_resources_testPlugin = Ext.extend(Deluge.Plugin, {
constructor: function(config) {
config = Ext.apply({
name: 'plugin_resources_test'
}, config);
plugin_resources_testPlugin.superclass.constructor.call(this, config);
},
onDisable: function() {
deluge.preferences.removePage(this.prefsPage);
},
onEnable: function() {
this.prefsPage = deluge.preferences.addPage(
new Deluge.ux.preferences.plugin_resources_testPage());
}
});
new plugin_resources_testPlugin();
'''

def set_up(self):
self.rpcserver = RPCServer(listen=False)
self.core: Core = Core()
self.core.config.config['lsd'] = False
self.core.config.config['enabled_plugins'] = []
self.listen_port = 51242
return component.start()

def tear_down(self):
def on_shutdown(result):
del self.rpcserver
del self.core

return component.shutdown().addCallback(on_shutdown)

async def test_resource_filename(self):
self.core.pluginmanager.scan_for_plugins()
await self.core.pluginmanager.enable_plugin('plugin_resources_test')
js_file_path = PluginResourceManager.resource_filename(
'deluge_plugin_resources_test', 'data/plugin_resources_test.js'
)
assert os.path.isfile(js_file_path)
with open(js_file_path, 'rb') as readfile:
contents = readfile.read()
assert contents == self.test_plugin_js

async def test_reuse_previously_extracted_file(self):
def get_js_file():
js_file = PluginResourceManager.resource_filename(
'deluge_plugin_resources_test', 'data/plugin_resources_test.js'
)
yield js_file

self.core.pluginmanager.scan_for_plugins()
await self.core.pluginmanager.enable_plugin('plugin_resources_test')
js_file_path = ''
for i in range(5):
del i
if not js_file_path:
js_file_path = next(get_js_file())
assert next(get_js_file()) == js_file_path and os.path.isfile(js_file_path)

async def test_update_path_if_file_deleted(self):
self.core.pluginmanager.scan_for_plugins()
await self.core.pluginmanager.enable_plugin('plugin_resources_test')
js_file_path = PluginResourceManager.resource_filename(
'deluge_plugin_resources_test', 'data/plugin_resources_test.js'
)
assert os.path.isfile(js_file_path)
os.remove(js_file_path)
assert not os.path.isfile(js_file_path)
js_file_path_new = PluginResourceManager.resource_filename(
'deluge_plugin_resources_test', 'data/plugin_resources_test.js'
)
assert js_file_path != js_file_path_new and os.path.isfile(js_file_path_new)

async def test_clean_files_on_disable_plugin(self):
self.core.pluginmanager.scan_for_plugins()
await self.core.pluginmanager.enable_plugin('plugin_resources_test')
js_file_path = PluginResourceManager.resource_filename(
'deluge_plugin_resources_test', 'data/plugin_resources_test.js'
)
assert os.path.isfile(js_file_path)
await self.core.pluginmanager.disable_plugin('plugin_resources_test')
assert not os.path.isfile(js_file_path)
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ per-file-ignores =
deluge/**/gtkui/*.py: E402
deluge/plugins/Stats/deluge_stats/graph.py: E402
deluge/plugin_resource_manager.py: N813
deluge/tests/test_plugin_resources.py: F401, E501
deluge/tests/test_plugin_metadata.py: E501
deluge/tests/common.py: E501
setup.py : E402
# loop variable shares name with imported function
deluge/common.py : F402
Expand Down

0 comments on commit 742ac7f

Please sign in to comment.