diff options
Diffstat (limited to 'tests/api')
-rw-r--r-- | tests/api/ApiProxy.py | 70 | ||||
-rw-r--r-- | tests/api/ApiTester.py | 37 | ||||
-rw-r--r-- | tests/api/__init__.py | 0 | ||||
-rw-r--r-- | tests/api/test_JSONBackend.py | 52 | ||||
-rw-r--r-- | tests/api/test_WebSocketBackend.py | 35 | ||||
-rw-r--r-- | tests/api/test_api.py | 50 | ||||
-rw-r--r-- | tests/api/test_noargs.py | 29 |
7 files changed, 273 insertions, 0 deletions
diff --git a/tests/api/ApiProxy.py b/tests/api/ApiProxy.py new file mode 100644 index 000000000..0da79a204 --- /dev/null +++ b/tests/api/ApiProxy.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- + + +from pyload.remote.apitypes_debug import classes, methods + +from tests.helper.config import credentials + +class ApiProxy: + """ Proxy that does type checking on the api """ + + def __init__(self, api, user=credentials[0], pw=credentials[1]): + self.api = api + self.user = user + self.pw = pw + + if user and pw is not None: + self.api.login(user, pw) + + def assert_type(self, result, type): + if not type: return # void + try: + # Complex attribute + if isinstance(type, tuple): + # Optional result + if type[0] is None: + # Only check if not None + if result is not None: self.assert_type(result, type[1]) + + # List + elif type[0] == list: + assert isinstance(result, list) + for item in result: + self.assert_type(item, type[1]) + # Dict + elif type[0] == dict: + assert isinstance(result, dict) + for k, v in result.iteritems(): + self.assert_type(k, type[1]) + self.assert_type(v, type[2]) + + # Struct - Api class + elif hasattr(result, "__name__") and result.__name__ in classes: + for attr, atype in zip(result.__slots__, classes[result.__name__]): + self.assert_type(getattr(result, attr), atype) + else: # simple object + assert isinstance(result, type) + except AssertionError: + print "Assertion for %s as %s failed" % (result, type) + raise + + + def call(self, func, *args, **kwargs): + result = getattr(self.api, func)(*args, **kwargs) + self.assert_type(result, methods[func]) + + return result + + + def __getattr__(self, item): + def call(*args, **kwargs): + return self.call(item, *args, **kwargs) + + return call + +if __name__ == "__main__": + + from pyload.remote.JSONClient import JSONClient + + api = ApiProxy(JSONClient(), "User", "test") + api.getServerVersion()
\ No newline at end of file diff --git a/tests/api/ApiTester.py b/tests/api/ApiTester.py new file mode 100644 index 000000000..e9a185947 --- /dev/null +++ b/tests/api/ApiTester.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- + +from pyload.remote.JSONClient import JSONClient +from pyload.remote.WSClient import WSClient + +from tests.helper.config import webAddress, wsAddress + +from ApiProxy import ApiProxy + +class ApiTester: + + tester= [] + + @classmethod + def register(cls, tester): + cls.tester.append(tester) + + @classmethod + def get_methods(cls): + """ All available methods for testing """ + methods = [] + for t in cls.tester: + methods.extend(getattr(t, attr) for attr in dir(t) if attr.startswith("test_")) + return methods + + def __init__(self): + ApiTester.register(self) + self.api = None + + def setApi(self, api): + self.api = api + + def enableJSON(self): + self.api = ApiProxy(JSONClient(webAddress)) + + def enableWS(self): + self.api = ApiProxy(WSClient(wsAddress)) diff --git a/tests/api/__init__.py b/tests/api/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/api/__init__.py diff --git a/tests/api/test_JSONBackend.py b/tests/api/test_JSONBackend.py new file mode 100644 index 000000000..d13d6709f --- /dev/null +++ b/tests/api/test_JSONBackend.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +from nose.tools import raises, assert_equal + +from requests.auth import HTTPBasicAuth +import requests + +import json + +from pyload.remote.apitypes import Forbidden +from pyload.remote.JSONClient import JSONClient + +from tests.helper.config import credentials, webAddress + +class TestJSONBackend: + + def setUp(self): + self.client = JSONClient(webAddress) + + def test_login(self): + self.client.login(*credentials) + self.client.getServerVersion() + self.client.logout() + + def test_wronglogin(self): + ret = self.client.login("WrongUser", "wrongpw") + assert ret is False + + def test_httpauth(self): + # cheap http auth + ret = requests.get(webAddress + "/getServerVersion", auth=HTTPBasicAuth(*credentials)) + assert_equal(ret.status_code, 200) + assert ret.text + + def test_jsonbody(self): + payload = {'section': 'webinterface', 'option': 'port'} + headers = {'content-type': 'application/json'} + + ret = requests.get(webAddress + "/getConfigValue", headers=headers, + auth=HTTPBasicAuth(*credentials), data=json.dumps(payload)) + + assert_equal(ret.status_code, 200) + assert ret.text + + @raises(Forbidden) + def test_access(self): + self.client.getServerVersion() + + @raises(AttributeError) + def test_unknown_method(self): + self.client.login(*credentials) + self.client.sdfdsg()
\ No newline at end of file diff --git a/tests/api/test_WebSocketBackend.py b/tests/api/test_WebSocketBackend.py new file mode 100644 index 000000000..a9288104f --- /dev/null +++ b/tests/api/test_WebSocketBackend.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +from nose.tools import raises + +from pyload.remote.apitypes import Forbidden +from pyload.remote.WSClient import WSClient + +from tests.helper.config import credentials, wsAddress + +class TestWebSocketBackend: + + def setUp(self): + self.client = WSClient(wsAddress) + self.client.connect() + + def tearDown(self): + self.client.close() + + def test_login(self): + self.client.login(*credentials) + self.client.getServerVersion() + self.client.logout() + + def test_wronglogin(self): + ret = self.client.login("WrongUser", "wrongpw") + assert ret is False + + @raises(Forbidden) + def test_access(self): + self.client.getServerVersion() + + @raises(AttributeError) + def test_unknown_method(self): + self.client.login(*credentials) + self.client.sdfdsg() diff --git a/tests/api/test_api.py b/tests/api/test_api.py new file mode 100644 index 000000000..668470fe4 --- /dev/null +++ b/tests/api/test_api.py @@ -0,0 +1,50 @@ +from unittest import TestCase +from random import choice + +from pyload.Core import Core + +from ApiTester import ApiTester + + +class TestAPI(TestCase): + """ + Test all available testers randomly and on all backends + """ + _multiprocess_can_split_ = True + core = None + + #TODO: parallel testing + @classmethod + def setUpClass(cls): + from test_noargs import TestNoArgs + + cls.core = Core() + cls.core.start(False, False, True) + for Test in (TestNoArgs,): + t = Test() + t.enableJSON() + t = Test() + t.enableWS() + t = Test() + t.setApi(cls.core.api) + + cls.methods = ApiTester.get_methods() + + @classmethod + def tearDownClass(cls): + cls.core.shutdown() + + def test_random(self, n=10000): + for i in range(n): + func = choice(self.methods) + func() + + def test_random2(self, n): + self.test_random(n) + + def test_random3(self, n): + self.test_random(n) + + def test_random4(self, n): + self.test_random(n) + diff --git a/tests/api/test_noargs.py b/tests/api/test_noargs.py new file mode 100644 index 000000000..e84946e45 --- /dev/null +++ b/tests/api/test_noargs.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- + +import inspect + +from ApiTester import ApiTester + +from pyload.remote.apitypes import Iface + +IGNORE = ('quit', 'restart') + +class TestNoArgs(ApiTester): + def setUp(self): + self.enableJSON() + +# Setup test_methods dynamically, only these which require no arguments +for name in dir(Iface): + if name.startswith("_") or name in IGNORE: continue + + spec = inspect.getargspec(getattr(Iface, name)) + if len(spec.args) == 1 and (not spec.varargs or len(spec.varargs) == 0): + def meta_test(name): #retain local scope + def test(self): + getattr(self.api, name)() + test.func_name = "test_%s" % name + return test + + setattr(TestNoArgs, "test_%s" % name, meta_test(name)) + + del meta_test
\ No newline at end of file |