diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/CrypterPluginTester.py | 81 | ||||
-rw-r--r-- | tests/HosterPluginTester.py | 152 | ||||
-rwxr-xr-x | tests/clonedigger.sh | 2 | ||||
-rw-r--r-- | tests/config/db.version | 1 | ||||
-rw-r--r-- | tests/config/plugin.conf | 138 | ||||
-rw-r--r-- | tests/config/pyload.conf.org | 75 | ||||
-rw-r--r-- | tests/config/pyload.db.org | bin | 0 -> 13312 bytes | |||
-rw-r--r-- | tests/crypterlinks.txt | 5 | ||||
-rw-r--r-- | tests/helper/BenchmarkTest.py | 66 | ||||
-rw-r--r-- | tests/helper/PluginTester.py | 151 | ||||
-rw-r--r-- | tests/helper/Stubs.py | 130 | ||||
-rw-r--r-- | tests/helper/__init__.py | 0 | ||||
-rwxr-xr-x | tests/hosterlinks.txt | 50 | ||||
-rwxr-xr-x | tests/nosetests.sh | 5 | ||||
-rwxr-xr-x | tests/plugin_tests.sh | 7 | ||||
-rwxr-xr-x | tests/pyflakes.sh | 5 | ||||
-rwxr-xr-x | tests/quit_pyload.sh | 7 | ||||
-rwxr-xr-x | tests/run_pyload.sh | 17 | ||||
-rwxr-xr-x | tests/sloccount.sh | 2 | ||||
-rw-r--r-- | tests/test_api.py | 24 | ||||
-rw-r--r-- | tests/test_backends.py (renamed from tests/test_json.py) | 25 | ||||
-rw-r--r-- | tests/test_configparser.py | 48 | ||||
-rw-r--r-- | tests/test_database.py | 194 | ||||
-rw-r--r-- | tests/test_filemanager.py | 214 | ||||
-rw-r--r-- | tests/test_interactionManager.py | 58 | ||||
-rw-r--r-- | tests/test_syntax.py | 43 |
26 files changed, 1480 insertions, 20 deletions
diff --git a/tests/CrypterPluginTester.py b/tests/CrypterPluginTester.py new file mode 100644 index 000000000..67e5ddebc --- /dev/null +++ b/tests/CrypterPluginTester.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- + +from os.path import dirname, join +from nose.tools import nottest + +from logging import log, DEBUG + +from helper.Stubs import Core +from helper.PluginTester import PluginTester + +from module.plugins.Base import Fail +from module.utils import accumulate, to_int + +class CrypterPluginTester(PluginTester): + @nottest + def test_plugin(self, name, url, flag): + + print "%s: %s" % (name, url.encode("utf8")) + log(DEBUG, "%s: %s", name, url.encode("utf8")) + + plugin = self.core.pluginManager.getPluginClass(name) + p = plugin(self.core, None, "") + self.thread.plugin = p + + try: + result = p._decrypt([url]) + + if to_int(flag): + assert to_int(flag) == len(result) + + except Exception, e: + if isinstance(e, Fail) and flag == "fail": + pass + else: + raise + + +# setup methods + +c = Core() + +f = open(join(dirname(__file__), "crypterlinks.txt")) +links = [x.strip() for x in f.readlines()] +urls = [] +flags = {} + +for l in links: + if not l or l.startswith("#"): continue + if l.startswith("http"): + if "||" in l: + l, flag = l.split("||") + flags[l] = flag + + urls.append(l) + +h, crypter = c.pluginManager.parseUrls(urls) +plugins = accumulate(crypter) +for plugin, urls in plugins.iteritems(): + + def meta_class(plugin): + class _testerClass(CrypterPluginTester): + pass + _testerClass.__name__ = plugin + return _testerClass + + _testerClass = meta_class(plugin) + + for i, url in enumerate(urls): + def meta(plugin, url, flag, sig): + def _test(self): + self.test_plugin(plugin, url, flag) + + _test.func_name = sig + return _test + + sig = "test_LINK%d" % i + setattr(_testerClass, sig, meta(plugin, url, flags.get(url, None), sig)) + print url + + locals()[plugin] = _testerClass + del _testerClass diff --git a/tests/HosterPluginTester.py b/tests/HosterPluginTester.py new file mode 100644 index 000000000..627494a3f --- /dev/null +++ b/tests/HosterPluginTester.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- + +from os.path import dirname +from logging import log, DEBUG +from hashlib import md5 +from time import time +from shutil import move +import codecs + +from nose.tools import nottest + +from helper.Stubs import Core +from helper.PluginTester import PluginTester + +from module.datatypes.PyFile import PyFile +from module.plugins.Base import Fail +from module.utils import accumulate +from module.utils.fs import save_join, join, exists, listdir, remove, stat + +DL_DIR = join("Downloads", "tmp") + +class HosterPluginTester(PluginTester): + files = {} + + def setUp(self): + PluginTester.setUp(self) + for f in self.files: + if exists(save_join(DL_DIR, f)): remove(save_join(DL_DIR, f)) + + # folder for reports + report = join("tmp", self.__class__.__name__) + if exists(report): + for f in listdir(report): + remove(join(report, f)) + + + @nottest + def test_plugin(self, name, url, flag): + # Print to stdout to see whats going on + print "%s: %s, %s" % (name, url.encode("utf8"), flag) + log(DEBUG, "%s: %s, %s", name, url.encode("utf8"), flag) + + # url and plugin should be only important thing + pyfile = PyFile(self.core, -1, url, url, 0, 0, "", name, 0, 0) + pyfile.initPlugin() + + self.thread.pyfile = pyfile + self.thread.plugin = pyfile.plugin + + try: + a = time() + pyfile.plugin.preprocessing(self.thread) + + log(DEBUG, "downloading took %ds" % (time() - a)) + log(DEBUG, "size %d kb" % (pyfile.size / 1024)) + + if flag == "offline": + raise Exception("No offline Exception raised.") + + if pyfile.name not in self.files: + raise Exception("Filename %s not recognized." % pyfile.name) + + if not exists(save_join(DL_DIR, pyfile.name)): + raise Exception("File %s does not exists." % pyfile.name) + + hash = md5() + f = open(save_join(DL_DIR, pyfile.name), "rb") + while True: + buf = f.read(4096) + if not buf: break + hash.update(buf) + f.close() + + if hash.hexdigest() != self.files[pyfile.name]: + log(DEBUG, "Hash is %s" % hash.hexdigest()) + + size = stat(f.name).st_size + if size < 1024 * 1024 * 10: # 10MB + # Copy for debug report + log(DEBUG, "Downloaded file copied to report") + move(f.name, join("tmp", plugin, f.name)) + + raise Exception("Hash does not match.") + + + + except Exception, e: + if isinstance(e, Fail) and flag == "fail": + pass + elif isinstance(e, Fail) and flag == "offline" and e.message == "offline": + pass + else: + raise + + +# setup methods + +c = Core() + +# decode everything as unicode +f = codecs.open(join(dirname(__file__), "hosterlinks.txt"), "r", "utf_8") +links = [x.strip() for x in f.readlines()] +urls = [] +flags = {} + +for l in links: + if not l or l.startswith("#"): continue + if l.startswith("http"): + if "||" in l: + l, flag = l.split("||") + flags[l] = str(flag.strip()) + urls.append(l) + + elif len(l.rsplit(" ", 1)) == 2: + name, hash = l.rsplit(" ", 1) + HosterPluginTester.files[name] = str(hash) + +hoster, c = c.pluginManager.parseUrls(urls) + +plugins = accumulate(hoster) +for plugin, urls in plugins.iteritems(): + # closure functions to retain local scope + def meta_class(plugin): + class _testerClass(HosterPluginTester): + pass + _testerClass.__name__ = plugin + return _testerClass + + _testerClass = meta_class(plugin) + + for i, url in enumerate(urls): + def meta(__plugin, url, flag, sig): + def _test(self): + self.test_plugin(__plugin, url, flag) + + _test.func_name = sig + return _test + + tmp_flag = flags.get(url, None) + if flags.get(url, None): + sig = "test_LINK%d_%s" % (i, tmp_flag) + else: + sig = "test_LINK%d" % i + + # set test method + setattr(_testerClass, sig, meta(plugin, url, tmp_flag, sig)) + + + #register class + locals()[plugin] = _testerClass + # remove from locals, or tested twice + del _testerClass diff --git a/tests/clonedigger.sh b/tests/clonedigger.sh new file mode 100755 index 000000000..93c1cb323 --- /dev/null +++ b/tests/clonedigger.sh @@ -0,0 +1,2 @@ +#!/bin/bash +clonedigger -o cpd.xml --cpd-output --fast --ignore-dir=lib --ignore-dir=remote module diff --git a/tests/config/db.version b/tests/config/db.version new file mode 100644 index 000000000..bf0d87ab1 --- /dev/null +++ b/tests/config/db.version @@ -0,0 +1 @@ +4
\ No newline at end of file diff --git a/tests/config/plugin.conf b/tests/config/plugin.conf new file mode 100644 index 000000000..5e7ee3858 --- /dev/null +++ b/tests/config/plugin.conf @@ -0,0 +1,138 @@ +version: 2 + +[MultiuploadCom] +preferedHoster = multiupload +ignoredHoster = + +[SerienjunkiesOrg] +preferredHoster = RapidshareCom,UploadedTo,NetloadIn,FilefactoryCom,FreakshareNet,FilebaseTo,MegauploadCom,HotfileCom,DepositfilesCom,EasyshareCom,KickloadCom +changeName = True + +[EmbeduploadCom] +preferedHoster = embedupload +ignoredHoster = + +[MultiloadCz] +usedHoster = +ignoredHoster = + +[WiiReloadedOrg] +changeName = True + +[Xdcc] +nick = pyload +ident = pyloadident +realname = pyloadreal + +[UlozTo] +reuseCaptcha = True +captchaUser = +captchaNb = + +[YoutubeCom] +quality = hd +fmt = 0 +.mp4 = True +.flv = True +.webm = False +.3gp = False + +[RapidshareCom] +server = None + +[VeehdCom] +filename_spaces = False +replacement_char = _ + +[RealdebridCom] +https = False + +[ClickAndLoad] +activated = True +extern = False + +[ExtractArchive] +activated = True +fullpath = True +overwrite = True +passwordfile = unrar_passwords.txt +deletearchive = False +subfolder = False +destination = +queue = True +renice = 0 + +[CaptchaTrader] +activated = True +username = +force = False +passkey = + +[MergeFiles] +activated = False + +[IRCInterface] +activated = False +host = Enter your server here! +port = 6667 +ident = pyload-irc +realname = pyload-irc +nick = pyLoad-IRC +owner = Enter your nick here! +info_file = False +info_pack = True +captcha = True + +[Ev0InFetcher] +activated = False +interval = 10 +queue = False +shows = +quality = xvid +hoster = NetloadIn,RapidshareCom,MegauploadCom,HotfileCom + +[EasybytezCom] +activated = False +includeHoster = +excludeHoster = + +[XMPPInterface] +activated = False +jid = user@exmaple-jabber-server.org +pw = +tls = False +owners = me@icq-gateway.org;some@msn-gateway.org +info_file = False +info_pack = True +captcha = True + +[RehostTo] +activated = False + +[MultiHoster] +activated = True + +[MultiHome] +activated = False +interfaces = None + +[MultishareCz] +activated = False +includeHoster = +excludeHoster = rapidshare.com|uloz.to + +[HotFolder] +activated = False +folder = container +watch_file = False +keep = True +file = links.txt + +[ExternalScripts] +activated = True + +[UpdateManager] +activated = True +interval = 360 +debug = False + diff --git a/tests/config/pyload.conf.org b/tests/config/pyload.conf.org new file mode 100644 index 000000000..7fb1c8c87 --- /dev/null +++ b/tests/config/pyload.conf.org @@ -0,0 +1,75 @@ +version: 2 + +[remote] +nolocalauth = False +activated = True +port = 7227 +listenaddr = 127.0.0.1 + +[log] +log_size = 100 +log_folder = Logs +file_log = False +log_count = 5 +log_rotate = True + +[permission] +group = users +change_dl = False +change_file = False +user = user +file = 0644 +change_group = False +folder = 0755 +change_user = False + +[general] +language = en +download_folder = Downloads +checksum = False +folder_per_package = True +debug_mode = True +min_free_space = 200 +renice = 0 + +[ssl] +cert = ssl.crt +activated = False +key = ssl.key + +[webinterface] +template = default +activated = True +prefix = +server = builtin +host = 127.0.0.1 +https = False +port = 8001 + +[proxy] +username = +proxy = False +address = localhost +password = +type = http +port = 7070 + +[reconnect] +endTime = 0:00 +activated = False +method = ./reconnect.sh +startTime = 0:00 + +[download] +max_downloads = 3 +limit_speed = False +interface = +skip_existing = False +max_speed = -1 +ipv6 = False +chunks = 3 + +[downloadTime] +start = 0:00 +end = 0:00 + diff --git a/tests/config/pyload.db.org b/tests/config/pyload.db.org Binary files differnew file mode 100644 index 000000000..d340531c5 --- /dev/null +++ b/tests/config/pyload.db.org diff --git a/tests/crypterlinks.txt b/tests/crypterlinks.txt new file mode 100644 index 000000000..4ff651888 --- /dev/null +++ b/tests/crypterlinks.txt @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +# Crypter links, append ||fail or ||#N to mark error or number of expected results (single links+packages) + +http://www.filesonic.com/folder/19906605||2 diff --git a/tests/helper/BenchmarkTest.py b/tests/helper/BenchmarkTest.py new file mode 100644 index 000000000..d28c52959 --- /dev/null +++ b/tests/helper/BenchmarkTest.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +from time import time + + +class BenchmarkTest: + + bench = [] + results = {} + + @classmethod + def timestamp(cls, name, a): + t = time() + r = cls.results.get(name, []) + r.append((t-a) * 1000) + cls.results[name] = r + + @classmethod + def benchmark(cls, n=1): + + print "Benchmarking %s" % cls.__name__ + print + + for i in range(n): + cls.collect_results() + + if "setUpClass" in cls.results: + cls.bench.insert(0, "setUpClass") + + if "tearDownClass" in cls.results: + cls.bench.append("tearDownClass") + + length = str(max([len(k) for k in cls.bench]) + 1) + total = 0 + + for k in cls.bench: + v = cls.results[k] + + if len(v) > 1: + print ("%" + length +"s: %s | average: %.2f ms") % (k, ", ".join(["%.2f" % x for x in v]), sum(v)/len(v)) + total += sum(v)/len(v) + else: + print ("%" + length +"s: %.2f ms") % (k, v[0]) + total += v[0] + + print "\ntotal: %.2f ms" % total + + + @classmethod + def collect_results(cls): + if hasattr(cls, "setUpClass"): + a = time() + cls.setUpClass() + cls.timestamp("setUpClass", a) + + obj = cls() + + for f in cls.bench: + a = time() + getattr(obj, "test_" + f)() + cls.timestamp(f, a) + + if hasattr(cls, "tearDownClass"): + a = time() + cls.tearDownClass() + cls.timestamp("tearDownClass", a)
\ No newline at end of file diff --git a/tests/helper/PluginTester.py b/tests/helper/PluginTester.py new file mode 100644 index 000000000..ef61385be --- /dev/null +++ b/tests/helper/PluginTester.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- + +from unittest import TestCase +from os import makedirs, remove +from os.path import exists, join, expanduser +from shutil import move +from sys import exc_clear, exc_info +from logging import log, DEBUG +from time import sleep, time +from random import randint +from glob import glob + +from pycurl import LOW_SPEED_TIME, FORM_FILE +from json import loads + +from Stubs import Thread, Core, noop + +from module.network.RequestFactory import getRequest, getURL +from module.plugins.Hoster import Hoster, Abort, Fail + +def _wait(self): + """ waits the time previously set """ + self.waiting = True + + waittime = self.pyfile.waitUntil - time() + log(DEBUG, "waiting %ss" % waittime) + + if self.wantReconnect and waittime > 300: + raise Fail("Would wait for reconnect %ss" % waittime) + elif waittime > 300: + raise Fail("Would wait %ss" % waittime) + + while self.pyfile.waitUntil > time(): + sleep(1) + if self.pyfile.abort: raise Abort + + self.waiting = False + self.pyfile.setStatus("starting") + +Hoster.wait = _wait + + +def decryptCaptcha(self, url, get={}, post={}, cookies=False, forceUser=False, imgtype='jpg', + result_type='textual'): + img = self.load(url, get=get, post=post, cookies=cookies) + + id = ("%.2f" % time())[-6:].replace(".", "") + temp_file = open(join("tmp", "tmpCaptcha_%s_%s.%s" % (self.__name__, id, imgtype)), "wb") + temp_file.write(img) + temp_file.close() + + Ocr = self.core.pluginManager.loadClass("captcha", self.__name__) + + if Ocr: + log(DEBUG, "Using tesseract for captcha") + sleep(randint(3000, 5000) / 1000.0) + if self.pyfile.abort: raise Abort + + ocr = Ocr() + result = ocr.get_captcha(temp_file.name) + else: + log(DEBUG, "Using ct for captcha") + # put username and passkey into two lines in ct.conf + conf = join(expanduser("~"), "ct.conf") + if not exists(conf): raise Exception("CaptchaTrader config %s not found." % conf) + f = open(conf, "rb") + req = getRequest() + + #raise timeout threshold + req.c.setopt(LOW_SPEED_TIME, 80) + + try: + json = req.load("http://captchatrader.com/api/submit", + post={"api_key": "9f65e7f381c3af2b076ea680ae96b0b7", + "username": f.readline().strip(), + "password": f.readline().strip(), + "value": (FORM_FILE, temp_file.name), + "type": "file"}, multipart=True) + finally: + f.close() + req.close() + + response = loads(json) + log(DEBUG, str(response)) + result = response[1] + + self.cTask = response[0] + + return result + +Hoster.decryptCaptcha = decryptCaptcha + + +def respond(ticket, value): + conf = join(expanduser("~"), "ct.conf") + f = open(conf, "rb") + try: + getURL("http://captchatrader.com/api/respond", + post={"is_correct": value, + "username": f.readline().strip(), + "password": f.readline().strip(), + "ticket": ticket}) + except Exception, e : + print "CT Exception:", e + log(DEBUG, str(e)) + finally: + f.close() + + + +def invalidCaptcha(self): + log(DEBUG, "Captcha invalid") + if self.cTask: + respond(self.cTask, 0) + +Hoster.invalidCaptcha = invalidCaptcha + +def correctCaptcha(self): + log(DEBUG, "Captcha correct") + if self.cTask: + respond(self.cTask, 1) + +Hoster.correctCaptcha = correctCaptcha + +Hoster.checkForSameFiles = noop + +class PluginTester(TestCase): + @classmethod + def setUpClass(cls): + cls.core = Core() + name = "%s.%s" % (cls.__module__, cls.__name__) + for f in glob(join(name, "debug_*")): + remove(f) + + # Copy debug report to attachment dir for jenkins + @classmethod + def tearDownClass(cls): + name = "%s.%s" % (cls.__module__, cls.__name__) + if not exists(name): makedirs(name) + for f in glob("debug_*"): + move(f, join(name, f)) + + def setUp(self): + self.thread = Thread(self.core) + exc_clear() + + def tearDown(self): + exc = exc_info() + if exc != (None, None, None): + debug = self.thread.writeDebugReport() + log(DEBUG, debug) diff --git a/tests/helper/Stubs.py b/tests/helper/Stubs.py new file mode 100644 index 000000000..5c44cfb58 --- /dev/null +++ b/tests/helper/Stubs.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- + +import sys +from os.path import abspath, dirname, join +from time import strftime +from traceback import format_exc + +sys.path.append(abspath(join(dirname(__file__), "..", "..", "module", "lib"))) +sys.path.append(abspath(join(dirname(__file__), "..", ".."))) + +import __builtin__ + +from module.datatypes.PyPackage import PyPackage +from module.threads.BaseThread import BaseThread +from module.config.ConfigParser import ConfigParser +from module.network.RequestFactory import RequestFactory +from module.PluginManager import PluginManager +from module.common.JsEngine import JsEngine + +from logging import log, DEBUG, INFO, WARN, ERROR + + +# Do nothing +def noop(*args, **kwargs): + pass + +ConfigParser.save = noop + +class LogStub: + def debug(self, *args): + log(DEBUG, *args) + + def info(self, *args): + log(INFO, *args) + + def error(self, *args): + log(ERROR, *args) + + def warning(self, *args): + log(WARN, *args) + + +class NoLog: + def debug(self, *args): + pass + + def info(self, *args): + pass + + def error(self, *args): + log(ERROR, *args) + + def warning(self, *args): + log(WARN, *args) + + +class Core: + def __init__(self): + self.log = NoLog() + + self.api = self.core = self + self.threadManager = self + self.debug = True + self.captcha = True + self.config = ConfigParser() + self.pluginManager = PluginManager(self) + self.requestFactory = RequestFactory(self) + __builtin__.pyreq = self.requestFactory + self.accountManager = AccountManager() + self.addonManager = AddonManager() + self.eventManager = self.interActionManager = NoopClass() + self.js = JsEngine() + self.cache = {} + self.packageCache = {} + + self.log = LogStub() + + def getServerVersion(self): + return "TEST_RUNNER on %s" % strftime("%d %h %Y") + + def path(self, path): + return path + + def updateLink(self, *args): + pass + + def updatePackage(self, *args): + pass + + def processingIds(self, *args): + return [] + + def getPackage(self, id): + return PyPackage(self, 0, "tmp", "tmp", "", "", 0, 0) + + def print_exc(self): + log(ERROR, format_exc()) + + +class NoopClass: + def __getattr__(self, item): + return noop + +class AddonManager(NoopClass): + def activePlugins(self): + return [] + +class AccountManager: + + def getAccountForPlugin(self, name): + return None + +class Thread(BaseThread): + def __init__(self, core): + BaseThread.__init__(self, core) + self.plugin = None + + + def writeDebugReport(self): + if hasattr(self, "pyfile"): + dump = BaseThread.writeDebugReport(self, self.plugin.__name__, pyfile=self.pyfile) + else: + dump = BaseThread.writeDebugReport(self, self.plugin.__name__, plugin=self.plugin) + + return dump + +__builtin__._ = lambda x: x +__builtin__.pypath = abspath(join(dirname(__file__), "..", "..")) +__builtin__.addonManager = AddonManager() +__builtin__.pyreq = None diff --git a/tests/helper/__init__.py b/tests/helper/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/tests/helper/__init__.py diff --git a/tests/hosterlinks.txt b/tests/hosterlinks.txt new file mode 100755 index 000000000..70dcc44f6 --- /dev/null +++ b/tests/hosterlinks.txt @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +# Valid files, with md5 hash +# Please only use files around 5-15 MB and with explicit permission for redistribution + +http://download.pyload.org/random.bin +random.bin d76505d0869f9f928a17d42d66326307 +Mořská želva ( Зелёная черепаха .&+ 綠蠵龜 _@- Đồi mồi dứa ).tar 932212256dc0b0a1e71c0944eef633a4 +Mořská_želva_(_Зелёная_черепаха_.&+_綠蠵龜__@-_Đồi_mồi_dứa_).tar 932212256dc0b0a1e71c0944eef633a4 + +# Hoster links, append ||offline or ||fail to mark your expectation + +http://netload.in/datei9XirAJZs79/random.bin.htm +http://rapidshare.com/files/445996776/random.bin +http://hotfile.com/dl/101569859/2e01f04/random.bin.html +http://www.megaupload.com/?d=1JZLOP3B +http://www.shragle.com/files/f899389b/random.bin +http://www10.zippyshare.com/v/76557688/file.html +http://yourfiles.to/?d=312EC6E911 +http://depositfiles.com/files/k8la98953 +http://uploading.com/files/3896f5a1/random.bin/ + + +http://ul.to/file/o41isx||offline +http://www.4shared.com/file/-O5CBhQV/random.html||offline +http://www.4shared.com/file/-O5CBhQV/random.html||offline +http://www.fileserve.com/file/MxjZXjX||offline +http://www.share-online.biz/download.php?id=PTCOX1GL6XAH||offline +http://dl.free.fr/d4aL5dyXY||offline +http://files.mail.ru/32EW66||offline +http://www.shragle.com/files/f899389b/random.bin||offline + + +# Hoster links with fancy unicode filenames: +http://vs3iaw.1fichier.com/fr/ +http://www.4shared.com/file/rQltf2Fr/Mosk_elva___Зелная_черепаха___.html +http://bezvadata.cz/stahnout/99273_morska-zelva-.-d-i-m-i-d-a-.tar +http://www.crocko.com/A524453DA89841B4BFC4FB9125D6F186/ +http://czshare.com/2483034/zelva +http://www.easybytez.com/etvhltkg0d05 +http://www.filejungle.com/f/qX5fxT/ +http://fp.io/43798f2b/ +http://www.filesonic.com/file/yU2cU6s +http://www.fshare.vn/file/A7H8LSTP7Z/ +http://ifile.it/muwgivz +http://letitbit.net/download/67793.60a7d3745791db7271a6e6c92cfe/Mořská_želva_(_Зелёная_черепаха_.___綠蠵龜___-_Đồi_mồi_dứa_).tar.html +http://www.mediafire.com/file/n09th58z1x5r585 +http://www.quickshare.cz/stahnout-soubor/676150:morska-zelva----_-oi-moi-dua-tar_6MB +http://www.uloz.to/12553820/morska-zelva-oi-moi-dua-tar +http://www.wupload.com/file/2642593407/
\ No newline at end of file diff --git a/tests/nosetests.sh b/tests/nosetests.sh new file mode 100755 index 000000000..c68861b90 --- /dev/null +++ b/tests/nosetests.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +NS=nosetests +which nosetests2 > /dev/null && NS=nosetests2 +$NS tests/ --with-coverage --with-xunit --cover-package=module --cover-erase +coverage xml diff --git a/tests/plugin_tests.sh b/tests/plugin_tests.sh new file mode 100755 index 000000000..be06c0dc5 --- /dev/null +++ b/tests/plugin_tests.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +NS=nosetests +which nosetests2 > /dev/null && NS=nosetests2 +# must be executed within tests dir +cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +$NS HosterPluginTester.py CrypterPluginTester.py -s --with-xunit --with-coverage --cover-erase --cover-package=module.plugins --with-id +coverage xml diff --git a/tests/pyflakes.sh b/tests/pyflakes.sh new file mode 100755 index 000000000..0c7e03891 --- /dev/null +++ b/tests/pyflakes.sh @@ -0,0 +1,5 @@ +#!/bin/bash +find -name '*.py' |egrep -v '^.(/tests/|/module/lib)'|xargs pyflakes > pyflakes.log || : +# Filter warnings and strip ./ from path +cat pyflakes.log | awk -F\: '{printf "%s:%s: [E]%s\n", $1, $2, $3}' | grep -i -E -v "'_'|pypath|webinterface|pyreq|hookmanager" > pyflakes.txt +sed -i 's/^.\///g' pyflakes.txt diff --git a/tests/quit_pyload.sh b/tests/quit_pyload.sh new file mode 100755 index 000000000..e466bcb31 --- /dev/null +++ b/tests/quit_pyload.sh @@ -0,0 +1,7 @@ +#!/bin/bash +PYTHON=python +which python2 > /dev/null && PYTHON=python2 +$PYTHON pyLoadCore.py --configdir=tests/config --quit +if [ -d userplugins ]; then + rm -r userplugins +fi
\ No newline at end of file diff --git a/tests/run_pyload.sh b/tests/run_pyload.sh new file mode 100755 index 000000000..66498cd10 --- /dev/null +++ b/tests/run_pyload.sh @@ -0,0 +1,17 @@ +#/usr/bin/env bash +cp tests/config/pyload.db.org tests/config/pyload.db +cp tests/config/pyload.conf.org tests/config/pyload.conf + +PYTHON=python +which python2 > /dev/null && PYTHON=python2 + +touch pyload.out +$PYTHON pyLoadCore.py -d --configdir=tests/config > pyload.out 2> pyload.err & + +for i in {1..30}; do + grep 8001 pyload.out > /dev/null && echo "pyLoad started" && break + sleep 1 +done + +echo "pyLoad start script finished" + diff --git a/tests/sloccount.sh b/tests/sloccount.sh new file mode 100755 index 000000000..0dab4164e --- /dev/null +++ b/tests/sloccount.sh @@ -0,0 +1,2 @@ +#!/bin/bash +sloccount --duplicates --wide --details module > sloccount.sc diff --git a/tests/test_api.py b/tests/test_api.py index f8901f731..0171b46bb 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,20 +1,18 @@ -# -*- coding: utf-8 -*- -from module.common import APIExerciser -from nose.tools import nottest +from unittest import TestCase +from pyLoadCore import Core +from module.common.APIExerciser import APIExerciser -class TestApi: +class TestApi(TestCase): - def __init__(self): - self.api = APIExerciser.APIExerciser(None, True, "TestUser", "pwhere") + @classmethod + def setUpClass(cls): + cls.core = Core() + cls.core.start(False, False, True) - def test_login(self): - assert self.api.api.login("crapp", "wrong pw") is False - - #takes really long, only test when needed - @nottest def test_random(self): + api = APIExerciser(self.core) - for i in range(0, 100): - self.api.testAPI() + for i in range(2000): + api.testAPI() diff --git a/tests/test_json.py b/tests/test_backends.py index ff56e8f5a..71ccedd2f 100644 --- a/tests/test_json.py +++ b/tests/test_backends.py @@ -1,14 +1,30 @@ # -*- coding: utf-8 -*- + from urllib import urlencode from urllib2 import urlopen, HTTPError from json import loads from logging import log +from module.common import APIExerciser + url = "http://localhost:8001/api/%s" -class TestJson: +class TestBackends(): + + def setUp(self): + u = urlopen(url % "login", data=urlencode({"username": "TestUser", "password": "sometestpw"})) + self.key = loads(u.read()) + assert self.key is not False + + def test_random(self): + api = APIExerciser.APIExerciser(None, True, "TestUser", "sometestpw") + + assert api.api.login("crapp", "wrong pw") is False + + for i in range(0, 1000): + api.testAPI() def call(self, name, post=None): if not post: post = {} @@ -16,11 +32,6 @@ class TestJson: u = urlopen(url % name, data=urlencode(post)) return loads(u.read()) - def setUp(self): - u = urlopen(url % "login", data=urlencode({"username": "TestUser", "password": "pwhere"})) - self.key = loads(u.read()) - assert self.key is not False - def test_wronglogin(self): u = urlopen(url % "login", data=urlencode({"username": "crap", "password": "wrongpw"})) assert loads(u.read()) is False @@ -45,4 +56,4 @@ class TestJson: except HTTPError, e: assert e.code == 404 else: - assert False
\ No newline at end of file + assert False diff --git a/tests/test_configparser.py b/tests/test_configparser.py new file mode 100644 index 000000000..d797c7912 --- /dev/null +++ b/tests/test_configparser.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +from collections import defaultdict +from helper.Stubs import Core + +from module.database import DatabaseBackend +from module.config.ConfigParser import ConfigParser + +# TODO +class TestConfigParser(): + + @classmethod + def setUpClass(cls): + cls.db = DatabaseBackend(Core()) + cls.db.manager = cls.db.core + cls.db.manager.statusMsg = defaultdict(lambda: "statusmsg") + cls.config = ConfigParser() + cls.db.setup() + cls.db.clearAllConfigs() + + + def test_db(self): + + self.db.saveConfig("plugin", "some value", 0) + self.db.saveConfig("plugin", "some other value", 1) + + assert self.db.loadConfig("plugin", 0) == "some value" + assert self.db.loadConfig("plugin", 1) == "some other value" + + d = self.db.loadAllConfigs() + assert d[0]["plugin"] == "some value" + + self.db.deleteConfig("plugin") + + assert not self.db.loadAllConfigs() + + + def test_dict(self): + + assert self.config["general"]["language"] + self.config["general"]["language"] = "de" + assert self.config["general"]["language"] == "de" + + def test_config(self): + pass + + def test_userconfig(self): + pass
\ No newline at end of file diff --git a/tests/test_database.py b/tests/test_database.py new file mode 100644 index 000000000..b7408e213 --- /dev/null +++ b/tests/test_database.py @@ -0,0 +1,194 @@ +# -*- coding: utf-8 -*- + +from collections import defaultdict + +from helper.Stubs import Core +from helper.BenchmarkTest import BenchmarkTest + +from module.database import DatabaseBackend + +# disable asyncronous queries +DatabaseBackend.async = DatabaseBackend.queue + +from random import choice + +class TestDatabase(BenchmarkTest): + bench = ["insert", "insert_links", "insert_many", "get_packages", + "get_files", "get_files_queued", "get_package_childs", "get_package_files", + "get_package_data", "get_file_data", "find_files", "collector", "purge"] + pids = None + fids = None + owner = 123 + pstatus = 0 + + @classmethod + def setUpClass(cls): + cls.pids = [-1] + cls.fids = [] + + cls.db = DatabaseBackend(Core()) + cls.db.manager = cls.db.core + cls.db.manager.statusMsg = defaultdict(lambda: "statusmsg") + + cls.db.setup() + cls.db.purgeAll() + + @classmethod + def tearDownClass(cls): + cls.db.purgeAll() + cls.db.shutdown() + + # benchmarker ignore setup + def setUp(self): + self.db.purgeAll() + self.pids = [-1] + self.fids = [] + + self.test_insert(20) + self.test_insert_many() + self.fids = self.db.getAllFiles().keys() + + + def test_insert(self, n=200): + for i in range(n): + pid = self.db.addPackage("name", "folder", choice(self.pids), "password", "site", "comment", self.pstatus, + self.owner) + self.pids.append(pid) + + def test_insert_links(self): + for i in range(10000): + fid = self.db.addLink("url %s" % i, "name", "plugin", choice(self.pids), self.owner) + self.fids.append(fid) + + def test_insert_many(self): + for pid in self.pids: + self.db.addLinks([("url %s" % i, "plugin") for i in range(50)], pid, self.owner) + + def test_get_packages(self): + packs = self.db.getAllPackages() + n = len(packs) + assert n == len(self.pids) - 1 + + print "Fetched %d packages" % n + self.assert_pack(choice(packs.values())) + + def test_get_files(self): + files = self.db.getAllFiles() + n = len(files) + assert n >= len(self.pids) + + print "Fetched %d files" % n + self.assert_file(choice(files.values())) + + def test_get_files_queued(self): + files = self.db.getAllFiles(unfinished=True) + print "Fetched %d files queued" % len(files) + + def test_delete(self): + pid = choice(self.pids) + self.db.deletePackage(pid) + self.pids.remove(pid) + + def test_get_package_childs(self): + pid = choice(self.pids) + packs = self.db.getAllPackages(root=pid) + + print "Package %d has %d packages" % (pid, len(packs)) + self.assert_pack(choice(packs.values())) + + def test_get_package_files(self): + pid = choice(self.pids) + files = self.db.getAllFiles(package=pid) + + print "Package %d has %d files" % (pid, len(files)) + self.assert_file(choice(files.values())) + + def test_get_package_data(self, stats=False): + pid = choice(self.pids) + p = self.db.getPackageInfo(pid, stats) + self.assert_pack(p) + # test again with stat + if not stats: + self.test_get_package_data(True) + + def test_get_file_data(self): + fid = choice(self.fids) + f = self.db.getFileInfo(fid) + self.assert_file(f) + + def test_find_files(self): + files = self.db.getAllFiles(search="1") + print "Found %s files" % len(files) + f = choice(files.values()) + + assert "1" in f.name + + def test_collector(self): + self.db.saveCollector(0, "data") + assert self.db.retrieveCollector(0) == "data" + self.db.deleteCollector(0) + + def test_purge(self): + self.db.purgeLinks() + + + def test_user_context(self): + self.db.purgeAll() + + p1 = self.db.addPackage("name", "folder", 0, "password", "site", "comment", self.pstatus, 0) + self.db.addLink("url", "name", "plugin", p1, 0) + p2 = self.db.addPackage("name", "folder", 0, "password", "site", "comment", self.pstatus, 1) + self.db.addLink("url", "name", "plugin", p2, 1) + + assert len(self.db.getAllPackages(owner=0)) == 1 == len(self.db.getAllFiles(owner=0)) + assert len(self.db.getAllPackages(root=0, owner=0)) == 1 == len(self.db.getAllFiles(package=p1, owner=0)) + assert len(self.db.getAllPackages(owner=1)) == 1 == len(self.db.getAllFiles(owner=1)) + assert len(self.db.getAllPackages(root=0, owner=1)) == 1 == len(self.db.getAllFiles(package=p2, owner=1)) + assert len(self.db.getAllPackages()) == 2 == len(self.db.getAllFiles()) + + self.db.deletePackage(p1, 1) + assert len(self.db.getAllPackages(owner=0)) == 1 == len(self.db.getAllFiles(owner=0)) + self.db.deletePackage(p1, 0) + assert len(self.db.getAllPackages(owner=1)) == 1 == len(self.db.getAllFiles(owner=1)) + self.db.deletePackage(p2) + + assert len(self.db.getAllPackages()) == 0 + + def test_count(self): + self.db.purgeAll() + + assert self.db.filecount() == 0 + assert self.db.queuecount() == 0 + assert self.db.proccesscount() == 0 + + def assert_file(self, f): + try: + assert f is not None + self.assert_int(f, ("fid", "status", "size", "media", "fileorder", "added", "package", "owner")) + assert f.status in range(5) + assert f.owner == self.owner + assert f.media in range(1024) + assert f.package in self.pids + assert f.added > 10 ** 6 # date is usually big integer + except: + print f + raise + + def assert_pack(self, p): + try: + assert p is not None + self.assert_int(p, ("pid", "root", "added", "status", "packageorder", "owner")) + assert p.pid in self.pids + assert p.owner == self.owner + assert p.status in range(5) + assert p.root in self.pids + assert p.added > 10 ** 6 + except: + print p + raise + + def assert_int(self, obj, list): + for attr in list: assert type(getattr(obj, attr)) == int + +if __name__ == "__main__": + TestDatabase.benchmark()
\ No newline at end of file diff --git a/tests/test_filemanager.py b/tests/test_filemanager.py new file mode 100644 index 000000000..f5bdd9df3 --- /dev/null +++ b/tests/test_filemanager.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- + +from random import choice + +from helper.Stubs import Core +from helper.BenchmarkTest import BenchmarkTest + +from module.database import DatabaseBackend +# disable asyncronous queries +DatabaseBackend.async = DatabaseBackend.queue + +from module.FileManager import FileManager + +class TestFileManager(BenchmarkTest): + bench = ["add_packages", "add_files", "get_files_root", "get", + "get_package_content", "get_package_tree", + "order_package", "order_files", "move"] + + pids = [-1] + count = 100 + + @classmethod + def setUpClass(cls): + c = Core() + # db needs seperate initialisation + cls.db = c.db = DatabaseBackend(c) + cls.db.setup() + cls.db.purgeAll() + + cls.m = cls.db.manager = FileManager(c) + + @classmethod + def tearDownClass(cls): + cls.db.purgeAll() + cls.db.shutdown() + + + # benchmarker ignore setup + def setUp(self): + self.db.purgeAll() + self.pids = [-1] + + self.count = 20 + self.test_add_packages() + self.test_add_files() + + def test_add_packages(self): + for i in range(100): + pid = self.m.addPackage("name", "folder", choice(self.pids), "", "", "", False) + self.pids.append(pid) + + if -1 in self.pids: + self.pids.remove(-1) + + def test_add_files(self): + for pid in self.pids: + self.m.addLinks([("plugin %d" % i, "url %s" % i) for i in range(self.count)], pid) + + count = self.m.getQueueCount() + files = self.count * len(self.pids) + # in test runner files get added twice + assert count == files or count == files * 2 + + def test_get(self): + info = self.m.getPackageInfo(choice(self.pids)) + assert info.stats.linkstotal == self.count + + fid = choice(info.fids) + f = self.m.getFile(fid) + assert f.fid in self.m.files + + f.name = "new name" + f.sync() + finfo = self.m.getFileInfo(fid) + assert finfo is not None + assert finfo.name == "new name" + + p = self.m.getPackage(choice(self.pids)) + assert p is not None + assert p.pid in self.m.packages + p.sync() + + p.delete() + + self.m.getTree(-1, True, False) + + + def test_get_files_root(self): + view = self.m.getTree(-1, True, False) + + for pid in self.pids: + assert pid in view.packages + + assert len(view.packages) == len(self.pids) + + p = choice(view.packages.values()) + assert len(p.fids) == self.count + assert p.stats.linkstotal == self.count + + + def test_get_package_content(self): + view = self.m.getTree(choice(self.pids), False, False) + p = view.root + + assert len(view.packages) == len(p.pids) + for pid in p.pids: assert pid in view.packages + + def test_get_package_tree(self): + view = self.m.getTree(choice(self.pids), True, False) + for pid in view.root.pids: assert pid in view.packages + for fid in view.root.fids: assert fid in view.files + + def test_delete(self): + self.m.deleteFile(self.count * 5) + self.m.deletePackage(choice(self.pids)) + + def test_order_package(self): + parent = self.m.addPackage("order", "", -1, "", "", "", False) + self.m.addLinks([("url", "plugin") for i in range(100)], parent) + + pids = [self.m.addPackage("c", "", parent, "", "", "", False) for i in range(5)] + v = self.m.getTree(parent, False, False) + self.assert_ordered(pids, 0, 5, v.root.pids, v.packages, True) + + pid = v.packages.keys()[0] + self.assert_pack_ordered(parent, pid, 3) + self.assert_pack_ordered(parent, pid, 0) + self.assert_pack_ordered(parent, pid, 0) + self.assert_pack_ordered(parent, pid, 4) + pid = v.packages.keys()[2] + self.assert_pack_ordered(parent, pid, 4) + self.assert_pack_ordered(parent, pid, 3) + self.assert_pack_ordered(parent, pid, 2) + + + def test_order_files(self): + parent = self.m.addPackage("order", "", -1, "", "", "", False) + self.m.addLinks([("url", "plugin") for i in range(100)], parent) + v = self.m.getTree(parent, False, False) + + fids = v.root.fids[10:20] + v = self.assert_files_ordered(parent, fids, 0) + + fids = v.root.fids[20:30] + + self.m.orderFiles(fids, parent, 99) + v = self.m.getTree(parent, False, False) + assert fids[-1] == v.root.fids[-1] + assert fids[0] == v.root.fids[90] + self.assert_ordered(fids, 90, 100, v.root.fids, v.files) + + fids = v.root.fids[80:] + v = self.assert_files_ordered(parent, fids, 20) + + self.m.orderFiles(fids, parent, 80) + v = self.m.getTree(parent, False, False) + self.assert_ordered(fids, 61, 81, v.root.fids, v.files) + + fids = v.root.fids[50:51] + self.m.orderFiles(fids, parent, 99) + v = self.m.getTree(parent, False, False) + self.assert_ordered(fids, 99, 100, v.root.fids, v.files) + + fids = v.root.fids[50:51] + v = self.assert_files_ordered(parent, fids, 0) + + + def assert_files_ordered(self, parent, fids, pos): + fs = [self.m.getFile(choice(fids)) for i in range(5)] + self.m.orderFiles(fids, parent, pos) + v = self.m.getTree(parent, False, False) + self.assert_ordered(fids, pos, pos+len(fids), v.root.fids, v.files) + + return v + + def assert_pack_ordered(self, parent, pid, pos): + self.m.orderPackage(pid, pos) + v = self.m.getTree(parent, False, False) + self.assert_ordered([pid], pos, pos+1, v.root.pids, v.packages, True) + + # assert that ordering is total, complete with no gaps + def assert_ordered(self, part, start, end, data, dict, pack=False): + assert data[start:end] == part + if pack: + assert sorted([p.packageorder for p in dict.values()]) == range(len(dict)) + assert [dict[pid].packageorder for pid in part] == range(start, end) + else: + assert sorted([f.fileorder for f in dict.values()]) == range(len(dict)) + assert [dict[fid].fileorder for fid in part] == range(start, end) + + + def test_move(self): + + pid = self.pids[-1] + pid2 = self.pids[1] + + self.m.movePackage(pid, -1) + v = self.m.getTree(-1, False, False) + + assert v.root.pids[-1] == pid + assert sorted([p.packageorder for p in v.packages.values()]) == range(len(v.packages)) + + v = self.m.getTree(pid, False, False) + fids = v.root.fids[10:20] + self.m.moveFiles(fids, pid2) + v = self.m.getTree(pid2, False, False) + + assert sorted([f.fileorder for f in v.files.values()]) == range(len(v.files)) + assert len(v.files) == self.count + len(fids) + + + +if __name__ == "__main__": + TestFileManager.benchmark()
\ No newline at end of file diff --git a/tests/test_interactionManager.py b/tests/test_interactionManager.py new file mode 100644 index 000000000..920d84b9d --- /dev/null +++ b/tests/test_interactionManager.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- + +from unittest import TestCase +from helper.Stubs import Core + +from module.Api import Input, Output +from module.interaction.InteractionManager import InteractionManager + +class TestInteractionManager(TestCase): + + @classmethod + def setUpClass(cls): + cls.core = Core() + + def setUp(self): + self.im = InteractionManager(self.core) + + + def test_notifications(self): + + n = self.im.createNotification("test", "notify") + assert self.im.getNotifications() == [n] + + for i in range(10): + self.im.createNotification("title", "test") + + assert len(self.im.getNotifications()) == 11 + + + def test_captcha(self): + assert self.im.getTask() is None + + t = self.im.newCaptchaTask("1", "", "") + assert t.output == Output.Captcha + self.im.handleTask(t) + assert t is self.im.getTask() + + t2 = self.im.newCaptchaTask("2", "", "") + self.im.handleTask(t2) + + assert self.im.getTask(Output.Query) is None + assert self.im.getTask() is t + + self.im.removeTask(t) + assert self.im.getTask() is t2 + + self.im.getTaskByID(t2.iid) + assert self.im.getTask() is None + + + def test_query(self): + assert self.im.getTask() is None + t = self.im.newQueryTask(Input.Text, None, "text") + assert t.description == "text" + self.im.handleTask(t) + + assert self.im.getTask(Output.Query) is t + assert self.im.getTask(Output.Captcha) is None
\ No newline at end of file diff --git a/tests/test_syntax.py b/tests/test_syntax.py new file mode 100644 index 000000000..a4cc53ee5 --- /dev/null +++ b/tests/test_syntax.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +from os import walk +from os.path import abspath, dirname, join + +from unittest import TestCase + +PATH = abspath(join(dirname(abspath(__file__)), "..", "")) + +# needed to register globals +from helper import Stubs + +class TestSyntax(TestCase): + pass + + +for path, dirs, files in walk(join(PATH, "module")): + + for f in files: + if not f.endswith(".py") or f.startswith("__"): continue + fpath = join(path, f) + pack = fpath.replace(PATH, "")[1:-3] #replace / and .py + imp = pack.replace("/", ".") + packages = imp.split(".") + #__import__(imp) + + # to much sideeffect when importing + if "web" in packages or "lib" in packages: continue + if "ThriftTest" in packages: continue + + # currying + def meta(imp, sig): + def _test(self=None): + __import__(imp) + + _test.func_name = sig + return _test + + # generate test methods + sig = "test_%s_%s" % (packages[-2], packages[-1]) + + + setattr(TestSyntax, sig, meta(imp, sig))
\ No newline at end of file |