# -*- coding: utf-8 -*-
## $Id: test_helpers.py 16818 2022-02-21 06:21:10Z henrik $
##
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import datetime
import os
import pytz
import shutil
import tempfile
import unittest
import doctest
from cStringIO import StringIO
from zope import schema
from zope.interface import Interface, Attribute, implements, implementer
from zope.security.testing import Principal, Participation
from zope.security.management import newInteraction, endInteraction
from waeup.kofa.utils import helpers
class IFakeObject(Interface):
"""Some marker interface."""
class FakeObject(object):
implements(IFakeObject)
class SimpleHelpersTestCase(unittest.TestCase):
# Tests for simple functions in `helpers`.
def test_product(self):
# the product will return zero without input
result1 = helpers.product([])
result2 = helpers.product([1,2,3])
result3 = helpers.product([], start=5)
result4 = helpers.product([1,2,3], start=5)
self.assertEqual(result1, 0)
self.assertEqual(result2, 6)
self.assertEqual(result3, 0)
self.assertEqual(result4, 30)
return
def test_attrs_to_fields_properties(self):
# we can omit single fields in order to retrieve properties
class IMyInterface(Interface):
attr1 = schema.Int(
title = u'Attribute 1', readonly = True, default = 110,
)
@helpers.attrs_to_fields
@implementer(IMyInterface)
class MyClass1(object):
@property
def attr1(self):
return 42
@implementer(IMyInterface)
class MyClass2(object):
@property
def attr1(self):
return 42
MyClass2 = helpers.attrs_to_fields(MyClass2, omit=['attr1'])
obj1 = MyClass1()
obj2 = MyClass2()
self.assertEqual(obj1.attr1, 110)
self.assertEqual(obj2.attr1, 42)
return
class RemoveFileOrDirectoryTestCase(unittest.TestCase):
def setUp(self):
self.dirpath = tempfile.mkdtemp()
self.filepath = os.path.join(self.dirpath, 'somefile')
self.non_file = os.path.join(self.dirpath, 'nonfile')
open(self.filepath, 'wb').write('Hi!')
return
def tearDown(self):
if os.path.exists(self.dirpath):
shutil.rmtree(self.dirpath)
return
def test_handle_not_existing_path(self):
result = helpers.remove_file_or_directory(self.non_file)
self.assertTrue(result is None)
return
def test_handle_dir(self):
helpers.remove_file_or_directory(self.dirpath)
self.assertFalse(
os.path.exists(self.dirpath)
)
return
def test_handle_file(self):
helpers.remove_file_or_directory(self.filepath)
self.assertFalse(
os.path.exists(self.filepath)
)
return
class CopyFileSystemTreeTestCase(unittest.TestCase):
# Test edge cases of copy_filesystem_tree().
#
# This is a typical case of tests not written as doctest as it is
# normally not interesting for developers and we only want to make
# sure everything works as expected.
def setUp(self):
self.existing_src = tempfile.mkdtemp()
self.filepath = os.path.join(self.existing_src, 'somefile')
open(self.filepath, 'wb').write('Hi!')
self.existing_dst = tempfile.mkdtemp()
self.not_existing_dir = tempfile.mkdtemp()
shutil.rmtree(self.not_existing_dir)
pass
def tearDown(self):
shutil.rmtree(self.existing_src)
shutil.rmtree(self.existing_dst)
pass
def test_source_and_dst_existing(self):
helpers.copy_filesystem_tree(self.existing_src, self.existing_dst)
self.assertTrue(
os.path.exists(
os.path.join(self.existing_dst, 'somefile')
)
)
return
def test_source_not_existing(self):
self.assertRaises(
ValueError,
helpers.copy_filesystem_tree,
self.not_existing_dir,
self.existing_dst
)
return
def test_dest_not_existing(self):
self.assertRaises(
ValueError,
helpers.copy_filesystem_tree,
self.existing_src,
self.not_existing_dir
)
return
def test_src_not_a_dir(self):
self.assertRaises(
ValueError,
helpers.copy_filesystem_tree,
self.filepath,
self.existing_dst
)
return
def test_dst_not_a_dir(self):
self.assertRaises(
ValueError,
helpers.copy_filesystem_tree,
self.existing_src,
self.filepath
)
return
class ReST2HTMLTestCase(unittest.TestCase):
def setUp(self):
self.expected = u'
\n\n\n
Some '
self.expected += u'test with \xfcmlaut
\n
'
return
def test_ascii_umlauts(self):
# Make sure we convert umlauts correctly to unicode.
source = 'Some test with ümlaut'
result = helpers.ReST2HTML(source)
self.assertEqual(result, self.expected)
def test_unicode_umlauts(self):
# Make sure we convert umlauts correctly to unicode.
source = u'Some test with ümlaut'
result = helpers.ReST2HTML(source)
self.assertEqual(result, self.expected)
def test_unicode_output_from_ascii(self):
source = 'Some test with ümlaut'
self.assertTrue(isinstance(helpers.ReST2HTML(source), unicode))
def test_unicode_output_from_unicode(self):
source = u'Some test with ümlaut'
self.assertTrue(isinstance(helpers.ReST2HTML(source), unicode))
class FactoryBaseTestCase(unittest.TestCase):
def test_ifaces(self):
# We test all relevant parts in the docstring. But the interfaces
# method has to be tested to please the coverage report as well.
factory = helpers.FactoryBase()
factory.factory = FakeObject
self.assertTrue(factory.getInterfaces()(IFakeObject))
return
class CurrentPrincipalTestCase(unittest.TestCase):
def tearDown(test):
endInteraction() # Just in case, one is still lingering around
def test_existing_principal(self):
# We can get the current principal if one is involved
principal = Principal('myprincipal')
newInteraction(Participation(principal))
result = helpers.get_current_principal()
self.assertTrue(result is principal)
def test_no_participation(self):
# Interactions without participation are handled correctly
newInteraction()
result = helpers.get_current_principal()
self.assertTrue(result is None)
def test_not_existing_principal(self):
# Missing interactions do not raise errors.
result = helpers.get_current_principal()
self.assertTrue(result is None)
class CmpFilesTestCase(unittest.TestCase):
def setUp(self):
self.workdir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.workdir)
def test_equal(self):
p1 = os.path.join(self.workdir, 'sample1')
p2 = os.path.join(self.workdir, 'sample2')
open(p1, 'wb').write('Hi!')
open(p2, 'wb').write('Hi!')
assert helpers.cmp_files(open(p1, 'r'), open(p2, 'r')) is True
def test_unequal(self):
p1 = os.path.join(self.workdir, 'sample1')
p2 = os.path.join(self.workdir, 'sample2')
open(p1, 'wb').write('Hi!')
open(p2, 'wb').write('Ho!')
assert helpers.cmp_files(open(p1, 'r'), open(p2, 'r')) is False
class FileSizeTestCase(unittest.TestCase):
def setUp(self):
self.workdir = tempfile.mkdtemp()
def tearDown(self):
shutil.rmtree(self.workdir)
def test_real_file(self):
# we can get the size of real files
path = os.path.join(self.workdir, 'sample.txt')
open(path, 'wb').write('My content')
self.assertEqual(
int(helpers.file_size(open(path, 'rb'))), 10)
return
def test_stringio_file(self):
# we can get the size of file-like objects
self.assertEqual(
helpers.file_size(StringIO('my sample content')), 17)
class IfaceNamesTestCase(unittest.TestCase):
def test_iface_names(self):
class I1(Interface):
foo = Attribute("""Some Foo""")
def bar(blah):
pass
i1_name = schema.TextLine(title=u'i1 name')
class I2(I1):
baz = schema.TextLine(title=u'some baz')
class I3(I2):
pass
result1 = helpers.iface_names(I3)
result2 = helpers.iface_names(I2)
result3 = helpers.iface_names(I1)
result4 = helpers.iface_names(I3, exclude_attribs=False)
result5 = helpers.iface_names(I3, exclude_methods=False)
result6 = helpers.iface_names(I3, omit='i1_name')
self.assertEqual(sorted(result1), ['baz', 'i1_name'])
self.assertEqual(sorted(result2), ['baz', 'i1_name'])
self.assertEqual(sorted(result3), ['i1_name'])
self.assertEqual(sorted(result4), ['baz', 'foo', 'i1_name'])
self.assertEqual(sorted(result5), ['bar', 'baz', 'i1_name'])
self.assertEqual(sorted(result6), ['baz'])
return
class DateTimeHelpersTestCase(unittest.TestCase):
def test_now(self):
tz_berlin = pytz.timezone('Europe/Berlin')
result1 = helpers.now()
result2 = helpers.now(tz_berlin)
self.assertEqual(result1.tzinfo, pytz.utc)
self.assertFalse(result2.tzinfo == pytz.utc)
self.assertFalse(result2.tzinfo is None)
return
def test_to_timezone(self):
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
tz_berlin = pytz.timezone('Europe/Berlin')
tz_lagos = pytz.timezone('Africa/Lagos')
dt1 = datetime.datetime(2012, 1, 1, 0, 0)
dt2 = datetime.datetime(2012, 1, 1, 0, 0, tzinfo=tz_berlin)
dt3 = datetime.datetime(2012, 6, 1, 0, 0, tzinfo=tz_lagos)
dt4 = datetime.datetime(2012, 6, 1, 0, 0, tzinfo=tz_berlin)
result1 = helpers.to_timezone(dt1)
result2 = helpers.to_timezone(dt1, pytz.utc)
result3 = helpers.to_timezone(dt2)
result4 = helpers.to_timezone(dt2, tz_lagos)
result5 = helpers.to_timezone(dt3, tz_berlin)
result6 = helpers.to_timezone(dt4, tz_lagos)
self.assertEqual(
result1.strftime(fmt), '2012-01-01 00:00:00 UTC+0000')
self.assertEqual(
result2.strftime(fmt), '2012-01-01 00:00:00 UTC+0000')
self.assertEqual(
result3.strftime(fmt), '2011-12-31 23:00:00 UTC+0000')
self.assertEqual(
result4.strftime(fmt), '2012-01-01 00:00:00 WAT+0100')
self.assertEqual(
result5.strftime(fmt), '2012-06-01 01:46:00 CEST+0200')
self.assertEqual(
result6.strftime(fmt), '2012-06-01 00:00:00 WAT+0100')
return
def test_to_timezone_no_dt(self):
# the to_timezone function copes with dates (!= datetimes)
d = datetime.date(2012, 12, 1)
result1 = helpers.to_timezone(d)
result2 = helpers.to_timezone(d, pytz.utc)
self.assertEqual(result1, d)
self.assertEqual(result2, d)
return
class GetFileFormatTestCase(unittest.TestCase):
# Tests for the get_fileformat helper.
def setUp(self):
self.valid_jpg_path = os.path.join(
os.path.dirname(__file__), 'sample_jpg_valid.jpg')
self.valid_jpg = open(self.valid_jpg_path, 'rb').read()
self.valid_png_path = os.path.join(
os.path.dirname(__file__), 'sample_png_valid.png')
self.valid_png = open(self.valid_png_path, 'rb').read()
self.valid_pdf_path = os.path.join(
os.path.dirname(__file__), 'sample_pdf_valid.pdf')
self.valid_pdf = open(self.valid_pdf_path, 'rb').read()
self.valid_fpm_path = os.path.join(
os.path.dirname(__file__), 'sample_fpm_valid.fpm')
self.valid_fpm = open(self.valid_fpm_path, 'rb').read()
return
def test_none(self):
# ``None`` is not a file and not a valid file format
self.assertEqual(helpers.get_fileformat(None), None)
return
def test_path_and_bytestream(self):
# get_fileformat accepts bytestreams and paths as arg.
self.assertEqual(
helpers.get_fileformat(None, self.valid_jpg), 'jpg')
self.assertEqual(
helpers.get_fileformat(self.valid_jpg_path), 'jpg')
# path is ignored when giving a bytestream
self.assertEqual(
helpers.get_fileformat('blah', self.valid_jpg), 'jpg')
return
def test_jpg(self):
# we recognize jpeg images.
self.assertEqual(
helpers.get_fileformat(self.valid_jpg_path), 'jpg')
self.assertEqual(
helpers.get_fileformat(None, self.valid_jpg), 'jpg')
return
def test_png(self):
# we recognize png images.
self.assertEqual(
helpers.get_fileformat(self.valid_png_path), 'png')
self.assertEqual(
helpers.get_fileformat(None, self.valid_png), 'png')
return
def test_pdf(self):
# we recognize pdf documents.
self.assertEqual(
helpers.get_fileformat(self.valid_pdf_path), 'pdf')
self.assertEqual(
helpers.get_fileformat(None, self.valid_pdf), 'pdf')
return
def test_fpm(self):
# we recognize fpm files.
# fpm files are binary fingerprint data produced by libfprint.
self.assertEqual(
helpers.get_fileformat(self.valid_fpm_path), 'fpm')
self.assertEqual(
helpers.get_fileformat(None, self.valid_fpm), 'fpm')
return
class MergeCSVFileTestCase(unittest.TestCase):
def setUp(self):
self.workdir = tempfile.mkdtemp()
self.path1 = os.path.join(self.workdir, 'myfile1')
self.path2 = os.path.join(self.workdir, 'myfile2')
self.result_path = None
return
def tearDown(self):
shutil.rmtree(self.workdir)
if self.result_path is not None and os.path.exists(self.result_path):
os.unlink(self.result_path)
return
def test_basic(self):
# we can merge very basic CSV files
open(self.path1, 'wb').write('name,age\nManfred,32\n')
open(self.path2, 'wb').write('name,age\nBarney,28\n')
self.result_path = helpers.merge_csv_files(self.path1, self.path2)
contents = open(self.result_path, 'r').read()
self.assertEqual(
contents,
'age,name\r\n'
'32,Manfred\r\n'
'28,Barney\r\n')
return
def test_different_col_order(self):
# if cols of both files have different order, that won't stop us
open(self.path1, 'wb').write('name,age\nManfred,32\n')
open(self.path2, 'wb').write('age,name\n28,Barney\n')
self.result_path = helpers.merge_csv_files(self.path1, self.path2)
contents = open(self.result_path, 'r').read()
self.assertEqual(
contents,
'age,name\r\n'
'32,Manfred\r\n'
'28,Barney\r\n')
return
def test_different_cols_at_all(self):
# also cols available only in one file will work.
open(self.path1, 'wb').write('name,age\nManfred,32\n')
open(self.path2, 'wb').write('name,age,buddy\nBarney,28,Manfred\n')
self.result_path = helpers.merge_csv_files(self.path1, self.path2)
contents = open(self.result_path, 'r').read()
self.assertEqual(
contents,
'age,buddy,name\r\n'
'32,,Manfred\r\n'
'28,Manfred,Barney\r\n')
return
def test_one_empty_input(self):
# we cope even with nearly empty input (one file with no data)
open(self.path1, 'wb').write('\n')
open(self.path2, 'wb').write('name,age\nManfred,32\n')
self.result_path = helpers.merge_csv_files(self.path1, self.path2)
contents = open(self.result_path, 'r').read()
self.assertEqual(
contents,
'age,name\r\n'
'32,Manfred\r\n')
return
def test_two_empty_inputs(self):
# we cope even with empty input (two files with no data)
open(self.path1, 'wb').write('\n')
open(self.path2, 'wb').write('\n')
self.result_path = helpers.merge_csv_files(self.path1, self.path2)
contents = open(self.result_path, 'r').read()
self.assertEqual(
contents, '\r\n')
return
class CheckCSVCharsetTestCase(unittest.TestCase):
def test_valid_data1(self):
csv = (
'col1,col2,col3\n'
'val1,val2,val3\n'
).splitlines()
self.assertEqual(helpers.check_csv_charset(csv), None)
def test_valid_data2(self):
csv = (
"code,title,title_prefix\n"
"FAC1,Faculty 1,faculty\n"
"FAC2,Faculty 2,institute\n"
"FAC3,Fäcülty 3,school\n"
).splitlines()
self.assertEqual(helpers.check_csv_charset(csv), None)
def test_invalid_data1(self):
csv = (
'col1,col2,col3\n' +
chr(0x92) + 'val1,val2,val3\n'
).splitlines()
self.assertEqual(helpers.check_csv_charset(csv), 1)
def test_invalid_data2(self):
csv = (
'some text that \n'
'\n' # this empty line will break
'is not a csv file\n' + chr(0x92) + '\n'
).splitlines()
self.assertEqual(helpers.check_csv_charset(csv), 2)
def test_invalid_data3(self):
csv = (
"code,title,title_prefix\n"
"FAC1,Faculty 1,faculty\n"
"FAC2,Faculty 2 ,institute\n"
"FAC3,Fäcülty 3,school\n"
).splitlines()
self.assertEqual(helpers.check_csv_charset(csv), None)
class MemInfoTestCase(unittest.TestCase):
def test_getsetattrs(self):
# we can set/get attributes of MemInfos
info = helpers.MemInfo()
self.assertRaises(
KeyError, info.__getattr__, 'foo')
info['foo'] = 'bar'
assert info.foo == 'bar'
info.bar = 'baz'
assert info.bar == 'baz'
def test_getattrs(self):
# we can del attributes
info = helpers.MemInfo()
info['foo'] = 'bar'
del info['foo']
self.assertRaises(
KeyError, info.__getattr__, 'foo')
info['bar'] = 'baz'
del info.bar
self.assertRaises(
KeyError, info.__getattr__, 'bar')
class GetMemInfoTestCase(unittest.TestCase):
@unittest.skipIf(
not os.path.exists('/proc/meminfo'),
reason="No /proc/meminfo found.")
def test_system(self):
info = helpers.get_meminfo()
assert isinstance(info, helpers.MemInfo)
def test_values(self):
sample_meminfo = os.path.join(
os.path.dirname(__file__), 'sample_meminfo')
info = helpers.get_meminfo(src=sample_meminfo)
assert info.Cached == 1013816
def test_invalid_src(self):
# we cope with invalid src files
info = helpers.get_meminfo(src="nOt-ExIsTiNg-FiLe")
assert info is None
class Html2dictTestCase(unittest.TestCase):
def test_html2dict(self):
assert helpers.html2dict(None) == {}
assert helpers.html2dict() == {}
assert helpers.html2dict(9) == {}
assert helpers.html2dict('Hello world') == {
'en': u'Hello world
'}
assert helpers.html2dict('Hello world>>de<Hallo Welt',
'en': u'Hello world
'}
class Rest2dictTestCase(unittest.TestCase):
def test_rest2dict(self):
assert helpers.rest2dict(None) == {}
assert helpers.rest2dict() == {}
assert helpers.rest2dict(9) == {}
assert helpers.rest2dict('Hello world') == {
'en': u''}
assert helpers.rest2dict('Hello world>>de<',
'en': u''}
def test_suite():
suite = unittest.TestSuite()
# Register local test cases...
for testcase in [
ReST2HTMLTestCase,
FactoryBaseTestCase,
CopyFileSystemTreeTestCase,
RemoveFileOrDirectoryTestCase,
CurrentPrincipalTestCase,
CmpFilesTestCase,
FileSizeTestCase,
IfaceNamesTestCase,
DateTimeHelpersTestCase,
GetFileFormatTestCase,
MergeCSVFileTestCase,
SimpleHelpersTestCase,
CheckCSVCharsetTestCase,
MemInfoTestCase,
GetMemInfoTestCase,
Html2dictTestCase,
Rest2dictTestCase,
]:
suite.addTests(
unittest.TestLoader().loadTestsFromTestCase(testcase)
)
# Add tests from docstrings in helpers.py...
suite.addTests(
doctest.DocTestSuite(
helpers,
optionflags = doctest.ELLIPSIS + doctest.REPORT_NDIFF,
)
)
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')