summaryrefslogtreecommitdiffstats
path: root/tests/api
diff options
context:
space:
mode:
Diffstat (limited to 'tests/api')
-rw-r--r--tests/api/ApiProxy.py70
-rw-r--r--tests/api/ApiTester.py37
-rw-r--r--tests/api/__init__.py0
-rw-r--r--tests/api/test_JSONBackend.py52
-rw-r--r--tests/api/test_WebSocketBackend.py35
-rw-r--r--tests/api/test_api.py50
-rw-r--r--tests/api/test_noargs.py29
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