diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py
index de3182bd8b..e9ade03cda 100644
--- a/src/calibre/test_build.py
+++ b/src/calibre/test_build.py
@@ -12,303 +12,217 @@ __docformat__ = 'restructuredtext en'
Test a binary calibre build to ensure that all needed binary images/libraries have loaded.
'''
-import os, ctypes, sys
+import os, ctypes, sys, unittest
from calibre.constants import plugins, iswindows, islinux, isosx
-def fprint(*args, **kwargs):
- print(*args, **kwargs)
- sys.stdout.flush()
+class BuildTest(unittest.TestCase):
-def test_dlls():
- import win32api
- base = win32api.GetDllDirectory()
- errors = []
- for x in os.listdir(base):
- if x.lower().endswith('.dll'):
- try:
- ctypes.WinDLL(os.path.join(base, x))
- except Exception as err:
- errors.append('Failed to load DLL %s with error: %s' % (x, err))
- fprint(errors[-1])
- if errors:
- fprint('Loading %d dll(s) failed!' % len(errors))
- raise SystemExit(1)
- fprint('DLLs OK!')
+ @unittest.skipUnless(iswindows, 'DLL loading needs testing only on windows')
+ def test_dlls(self):
+ import win32api
+ base = win32api.GetDllDirectory()
+ for x in os.listdir(base):
+ if x.lower().endswith('.dll'):
+ try:
+ ctypes.WinDLL(os.path.join(base, x))
+ except Exception as err:
+ self.assertTrue(False, 'Failed to load DLL %s with error: %s' % (x, err))
+ @unittest.skipUnless(islinux, 'DBUS only used on linux')
+ def test_dbus(self):
+ import dbus
+ bus = dbus.SystemBus()
+ self.assertTrue(bus.list_names(), 'Failed to list names on the system bus')
+ bus = dbus.SessionBus()
+ self.assertTrue(bus.list_names(), 'Failed to list names on the session bus')
+ del bus
-def test_dbus():
- import dbus
- bus = dbus.SystemBus()
- if not bus.list_names():
- raise ValueError('Failed to list names on the system bus')
- bus = dbus.SessionBus()
- if not bus.list_names():
- raise ValueError('Failed to list names on the session bus')
- del bus
- fprint('dbus OK!')
+ def test_regex(self):
+ import regex
+ self.assertEqual(regex.findall(r'(?i)(a)(b)', 'ab cd AB 1a1b'), [('a', 'b'), ('A', 'B')])
-def test_regex():
- import regex
- if regex.findall(r'(?i)(a)(b)', 'ab cd AB 1a1b') != [('a', 'b'), ('A', 'B')]:
- raise ValueError('regex module failed on a simple search')
- fprint('regex OK!')
+ def test_lzma(self):
+ from lzma.xz import test_lzma2
+ test_lzma2()
-def test_lzma():
- from lzma.xz import test_lzma2
- test_lzma2()
- fprint('lzma OK!')
+ def test_html5lib(self):
+ import html5lib.html5parser # noqa
+ from html5lib import parse # noqa
-def test_html5lib():
- import html5lib.html5parser # noqa
- from html5lib import parse # noqa
- fprint('html5lib OK!')
+ def test_spell(self):
+ from calibre.spell.dictionary import test_dictionaries
+ test_dictionaries()
-def test_spell():
- from calibre.spell.dictionary import test_dictionaries
- test_dictionaries()
- fprint('hunspell OK!')
+ def test_plugins(self):
+ for name in plugins:
+ mod, err = plugins[name]
+ self.assertFalse(err or not mod, 'Failed to load plugin: ' + name + ' with error:\n' + err)
-def test_plugins():
- bad = []
- for name in plugins:
- mod, err = plugins[name]
- if err or not mod:
- bad.append((name, err))
- if bad:
- for name, err in bad:
- fprint('Failed to load plugin:', name, 'with error:\n', err, '\n')
- raise SystemExit(1)
- fprint('Loaded all plugins successfully!')
+ def test_lxml(self):
+ from calibre.utils.cleantext import test_clean_xml_chars
+ test_clean_xml_chars()
+ from lxml import etree
+ raw = ''
+ root = etree.fromstring(raw)
+ self.assertEqual(etree.tostring(root), raw)
-def test_lxml():
- from calibre.utils.cleantext import test_clean_xml_chars
- test_clean_xml_chars()
- from lxml import etree
- raw = ''
- root = etree.fromstring(raw)
- if etree.tostring(root) == raw:
- fprint('lxml OK!')
- else:
- raise RuntimeError('lxml failed')
+ def test_certgen(self):
+ from calibre.utils.certgen import create_key_pair
+ create_key_pair()
-def test_certgen():
- from calibre.utils.certgen import create_key_pair
- create_key_pair()
+ @unittest.skipUnless(isosx, 'FSEvents only present on OS X')
+ def test_fsevents(self):
+ from fsevents import Observer, Stream
+ del Observer, Stream
-def test_fsevents():
- from fsevents import Observer, Stream
- del Observer, Stream
- fprint('macfsevents OK!')
+ @unittest.skipUnless(iswindows, 'winutil is windows only')
+ def test_winutil(self):
+ from calibre.constants import plugins
+ winutil = plugins['winutil'][0]
+ for x in winutil.argv():
+ self.assertTrue(isinstance(x, unicode), 'argv() not returning unicode string')
-def test_winutil():
- from calibre.constants import plugins
- winutil = plugins['winutil'][0]
- for x in winutil.argv():
- if not isinstance(x, unicode):
- raise ValueError('argv() not returning unicode string')
- fprint('winutil OK!')
+ def test_sqlite(self):
+ import sqlite3
+ conn = sqlite3.connect(':memory:')
+ from calibre.library.sqlite import load_c_extensions
+ self.assertTrue(load_c_extensions(conn, True), 'Failed to load sqlite extension')
-def test_sqlite():
- import sqlite3
- conn = sqlite3.connect(':memory:')
- from calibre.library.sqlite import load_c_extensions
- if not load_c_extensions(conn, True):
- raise RuntimeError('Failed to load sqlite extension')
- fprint('sqlite OK!')
+ def test_apsw(self):
+ import apsw
+ conn = apsw.Connection(':memory:')
+ conn.close()
-def test_apsw():
- import apsw
- conn = apsw.Connection(':memory:')
- conn.close()
- fprint('apsw OK!')
+ def test_qt(self):
+ # Must be run before QApplication is constructed
+ # Test that the image formats are available without a QApplication being
+ # constructed
+ from calibre.utils.img import image_from_data, image_to_data, test
+ data = I('blank.png', allow_user_override=False, data=True)
+ img = image_from_data(data)
+ image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
+ for fmt in 'png bmp jpeg'.split():
+ d = image_to_data(img, fmt=fmt)
+ image_from_data(d)
+ # Run the imaging tests
+ test()
-def test_image_formats():
- # Must be run before QApplication is constructed
- # Test that the image formats are available without a QApplication being
- # constructed
- from calibre.utils.img import image_from_data, image_to_data, test
- data = I('blank.png', allow_user_override=False, data=True)
- img = image_from_data(data)
- image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True))
- for fmt in 'png bmp jpeg'.split():
- d = image_to_data(img, fmt=fmt)
- image_from_data(d)
- # Run the imaging tests
- test()
+ from calibre.gui2 import Application
+ from PyQt5.Qt import (QImageReader, QNetworkAccessManager, QFontDatabase)
+ from PyQt5.QtWebKitWidgets import QWebView
+ os.environ.pop('DISPLAY', None)
+ app = Application([], headless=islinux)
+ self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig')
+ fmts = set(map(unicode, QImageReader.supportedImageFormats()))
+ testf = set(['jpg', 'png', 'svg', 'ico', 'gif'])
+ self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load its image plugins")
+ QWebView()
+ del QWebView
+ na = QNetworkAccessManager()
+ self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl')
+ del na
+ del app
-def test_qt():
- test_image_formats()
- from calibre.gui2 import Application
- from PyQt5.Qt import (QImageReader, QNetworkAccessManager, QFontDatabase)
- from PyQt5.QtWebKitWidgets import QWebView
- os.environ.pop('DISPLAY', None)
- app = Application([], headless=islinux)
- if len(QFontDatabase().families()) < 5:
- raise RuntimeError('The QPA headless plugin is not able to locate enough system fonts via fontconfig')
- fmts = set(map(unicode, QImageReader.supportedImageFormats()))
- testf = set(['jpg', 'png', 'svg', 'ico', 'gif'])
- if testf.intersection(fmts) != testf:
- raise RuntimeError(
- "Qt doesn't seem to be able to load its image plugins")
- QWebView()
- del QWebView
- na = QNetworkAccessManager()
- if not hasattr(na, 'sslErrors'):
- raise RuntimeError('Qt not compiled with openssl')
- del na
- del app
- fprint('Qt OK!')
-
-def test_imaging():
- from PIL import Image
- try:
- import _imaging, _imagingmath, _imagingft
+ def test_imaging(self):
+ from PIL import Image
+ try:
+ import _imaging, _imagingmath, _imagingft
+ _imaging, _imagingmath, _imagingft
+ except ImportError:
+ from PIL import _imaging, _imagingmath, _imagingft
_imaging, _imagingmath, _imagingft
- except ImportError:
- from PIL import _imaging, _imagingmath, _imagingft
- _imaging, _imagingmath, _imagingft
- i = Image.open(I('lt.png', allow_user_override=False))
- if i.size < (20, 20):
- raise RuntimeError('PIL choked!')
- fprint('PIL OK!')
+ i = Image.open(I('lt.png', allow_user_override=False))
+ self.assertGreaterEqual(i.size, (20, 20))
-def test_file_dialog_helper():
- from calibre.gui2.win_file_dialogs import test
- test()
- print('File dialog helper OK!')
+ @unittest.skipUnless(iswindows, 'File dialog helper only used on windows')
+ def test_file_dialog_helper(self):
+ from calibre.gui2.win_file_dialogs import test
+ test()
-def test_unrar():
- from calibre.utils.unrar import test_basic
- test_basic()
- fprint('Unrar OK!')
+ def test_unrar(self):
+ from calibre.utils.unrar import test_basic
+ test_basic()
-def test_icu():
- fprint('Testing ICU')
- from calibre.utils.icu_test import test_build
- test_build()
- fprint('ICU OK!')
+ @unittest.skipUnless(iswindows, 'WPD is windows only')
+ def test_wpd(self):
+ wpd = plugins['wpd'][0]
+ try:
+ wpd.init('calibre', 1, 1, 1)
+ except wpd.NoWPD:
+ pass
+ else:
+ wpd.uninit()
-def test_dukpy():
- fprint('Testing dukpy')
- from duktape import test_build
- test_build()
- fprint('dukpy OK!')
+ def test_tinycss_tokenizer(self):
+ from tinycss.tokenizer import c_tokenize_flat
+ self.assertIsNotNone(c_tokenize_flat, 'tinycss C tokenizer not loaded')
-def test_wpd():
- wpd = plugins['wpd'][0]
- try:
- wpd.init('calibre', 1, 1, 1)
- except wpd.NoWPD:
- fprint('This computer does not have WPD')
- else:
- wpd.uninit()
- fprint('WPD OK!')
-
-def test_tokenizer():
- fprint('Testing tinycss tokenizer')
- from tinycss.tokenizer import c_tokenize_flat
- if c_tokenize_flat is None:
- raise ValueError('tinycss C tokenizer not loaded')
- import tinycss.tests.main as m
- if getattr(m, '__file__', None) and os.path.exists(m.__file__):
- m.run_tests(for_build=True)
- fprint('tinycss tokenizer OK!')
-
-def test_executables():
- from calibre.utils.ipc.launch import Worker
- if getattr(sys, 'frozen', False):
+ @unittest.skipUnless(getattr(sys, 'frozen', False), 'Only makes sense to test executables in frozen builds')
+ def test_executables(self):
+ from calibre.utils.ipc.launch import Worker
+ from calibre.ebooks.pdf.pdftohtml import PDFTOHTML
w = Worker({})
- if not os.path.exists(w.executable):
- raise SystemExit('calibre-parallel (%s) does not exist' % w.executable)
- if not os.path.exists(w.gui_executable):
- raise SystemExit('calibre-parallel-gui (%s) does not exist' % w.gui_executable)
+ self.assertTrue(os.path.exists(w.executable), 'calibre-parallel (%s) does not exist' % w.executable)
+ self.assertTrue(os.path.exists(w.gui_executable), 'calibre-parallel-gui (%s) does not exist' % w.gui_executable)
+ self.assertTrue(os.path.exists(PDFTOHTML), 'pdftohtml (%s) does not exist' % PDFTOHTML)
if iswindows:
from calibre.devices.usbms.device import eject_exe
- if not os.path.exists(eject_exe()):
- raise SystemExit('calibre-eject.exe (%s) does not exist' % eject_exe())
- from calibre.ebooks.pdf.pdftohtml import PDFTOHTML
- if not os.path.exists(PDFTOHTML):
- raise SystemExit('pdftohtml (%s) does not exist' % PDFTOHTML)
+ self.assertTrue(os.path.exists(eject_exe()), 'calibre-eject.exe (%s) does not exist' % eject_exe())
- fprint('executables OK!')
+ def test_netifaces(self):
+ import netifaces
+ self.assertGreaterEqual(netifaces.interfaces(), 1, 'netifaces could find no network interfaces')
-def test_netifaces():
- import netifaces
- if len(netifaces.interfaces()) < 1:
- raise ValueError('netifaces could find no network interfaces')
- fprint('netifaces OK!')
+ def test_psutil(self):
+ import psutil
+ psutil.Process(os.getpid())
-def test_psutil():
- import psutil
- psutil.Process(os.getpid())
- fprint('psutil OK!')
+ def test_podofo(self):
+ from calibre.utils.podofo import test_podofo as dotest
+ dotest()
-def test_podofo():
- from calibre.utils.podofo import test_podofo as dotest
- dotest()
- fprint('podofo OK!')
+ @unittest.skipIf(iswindows, 'readline not available on windows')
+ def test_terminal(self):
+ import readline
+ del readline
-def test_terminal():
- import readline
- del readline
- fprint('readline OK!')
+ def test_markdown(self):
+ from calibre.ebooks.markdown import Markdown
+ Markdown(extensions=['extra'])
+ from calibre.library.comments import sanitize_html
+ sanitize_html(b'''xxx
''')
-def test_markdown():
- from calibre.ebooks.markdown import Markdown
- Markdown(extensions=['extra'])
- from calibre.library.comments import sanitize_html
- sanitize_html(b'''xxx
''')
- fprint('Markdown OK!')
+ def test_image_compression(self):
+ from calibre.utils.img import test
+ test()
-def test_image_compression():
- from calibre.utils.img import test
- test()
- fprint('Image compression OK!')
+ def test_openssl(self):
+ import ssl
+ ssl.PROTOCOL_TLSv1_2
+ if isosx:
+ cafile = ssl.get_default_verify_paths().cafile
+ if not cafile or not cafile.endswith('/mozilla-ca-certs.pem') or not os.access(cafile, os.R_OK):
+ self.assert_('Mozilla CA certs not loaded')
-def test_openssl():
- import ssl
- ssl.PROTOCOL_TLSv1_2
- if isosx:
- cafile = ssl.get_default_verify_paths().cafile
- if not cafile or not cafile.endswith('/mozilla-ca-certs.pem') or not os.access(cafile, os.R_OK):
- raise ValueError('Mozilla CA certs not loaded')
- fprint('SSL OK!')
+def find_tests():
+ ans = unittest.defaultTestLoader.loadTestsFromTestCase(BuildTest)
+ from calibre.utils.icu_test import find_tests
+ import duktape.tests as dtests
+ ans.addTests(find_tests())
+ ans.addTests(unittest.defaultTestLoader.loadTestsFromModule(dtests))
+ from tinycss.tests.main import find_tests
+ ans.addTests(find_tests())
+ return ans
+
+class TestRunner(unittest.main):
+
+ def createTests(self):
+ self.test = find_tests()
def test():
- if iswindows:
- test_dlls()
- test_plugins()
- test_executables()
- test_image_compression()
- test_lzma()
- test_dukpy()
- test_spell()
- test_lxml()
- test_openssl()
- test_sqlite()
- test_apsw()
- test_imaging()
- test_unrar()
- test_certgen()
- test_icu()
- test_qt()
- test_html5lib()
- test_regex()
- test_tokenizer()
- test_netifaces()
- test_psutil()
- test_podofo()
- test_markdown()
- if islinux:
- test_dbus()
- if iswindows:
- test_wpd()
- test_winutil()
- test_file_dialog_helper()
- else:
- test_terminal()
- if isosx:
- test_fsevents()
+ result = TestRunner(verbosity=2, buffer=True, catchbreak=True, failfast=True, argv=sys.argv[:1], exit=False).result
+ if not result.wasSuccessful():
+ raise SystemExit(1)
if __name__ == '__main__':
test()