| from __future__ import print_function |
| import filecmp |
| import glob |
| import itertools |
| import os |
| import sys |
| import sysconfig |
| import tempfile |
| import unittest |
| |
| |
| project_dir = os.path.abspath(os.path.join(__file__, '..', '..', '..')) |
| test_dir = os.getenv("BROTLI_TESTS_PATH") |
| BRO_ARGS = [os.getenv("BROTLI_WRAPPER")] |
| |
| # Fallbacks |
| if test_dir is None: |
| test_dir = os.path.join(project_dir, 'tests') |
| if BRO_ARGS[0] is None: |
| python_exe = sys.executable or 'python' |
| bro_path = os.path.join(project_dir, 'python', 'bro.py') |
| BRO_ARGS = [python_exe, bro_path] |
| |
| # Get the platform/version-specific build folder. |
| # By default, the distutils build base is in the same location as setup.py. |
| platform_lib_name = 'lib.{platform}-{version[0]}.{version[1]}'.format( |
| platform=sysconfig.get_platform(), version=sys.version_info) |
| build_dir = os.path.join(project_dir, 'bin', platform_lib_name) |
| |
| # Prepend the build folder to sys.path and the PYTHONPATH environment variable. |
| if build_dir not in sys.path: |
| sys.path.insert(0, build_dir) |
| TEST_ENV = os.environ.copy() |
| if 'PYTHONPATH' not in TEST_ENV: |
| TEST_ENV['PYTHONPATH'] = build_dir |
| else: |
| TEST_ENV['PYTHONPATH'] = build_dir + os.pathsep + TEST_ENV['PYTHONPATH'] |
| |
| TESTDATA_DIR = os.path.join(test_dir, 'testdata') |
| |
| TESTDATA_FILES = [ |
| 'empty', # Empty file |
| '10x10y', # Small text |
| 'alice29.txt', # Large text |
| 'random_org_10k.bin', # Small data |
| 'mapsdatazrh', # Large data |
| 'ukkonooa', # Poem |
| 'cp1251-utf16le', # Codepage 1251 table saved in UTF16-LE encoding |
| 'cp852-utf8', # Codepage 852 table saved in UTF8 encoding |
| ] |
| |
| # Some files might be missing in a lightweight sources pack. |
| TESTDATA_PATH_CANDIDATES = [ |
| os.path.join(TESTDATA_DIR, f) for f in TESTDATA_FILES |
| ] |
| |
| TESTDATA_PATHS = [ |
| path for path in TESTDATA_PATH_CANDIDATES if os.path.isfile(path) |
| ] |
| |
| TESTDATA_PATHS_FOR_DECOMPRESSION = glob.glob( |
| os.path.join(TESTDATA_DIR, '*.compressed')) |
| |
| TEMP_DIR = tempfile.mkdtemp() |
| |
| |
| def get_temp_compressed_name(filename): |
| return os.path.join(TEMP_DIR, os.path.basename(filename + '.bro')) |
| |
| |
| def get_temp_uncompressed_name(filename): |
| return os.path.join(TEMP_DIR, os.path.basename(filename + '.unbro')) |
| |
| |
| def bind_method_args(method, *args, **kwargs): |
| return lambda self: method(self, *args, **kwargs) |
| |
| |
| def generate_test_methods(test_case_class, |
| for_decompression=False, |
| variants=None): |
| # Add test methods for each test data file. This makes identifying problems |
| # with specific compression scenarios easier. |
| if for_decompression: |
| paths = TESTDATA_PATHS_FOR_DECOMPRESSION |
| else: |
| paths = TESTDATA_PATHS |
| opts = [] |
| if variants: |
| opts_list = [] |
| for k, v in variants.items(): |
| opts_list.append([r for r in itertools.product([k], v)]) |
| for o in itertools.product(*opts_list): |
| opts_name = '_'.join([str(i) for i in itertools.chain(*o)]) |
| opts_dict = dict(o) |
| opts.append([opts_name, opts_dict]) |
| else: |
| opts.append(['', {}]) |
| for method in [m for m in dir(test_case_class) if m.startswith('_test')]: |
| for testdata in paths: |
| for (opts_name, opts_dict) in opts: |
| f = os.path.splitext(os.path.basename(testdata))[0] |
| name = 'test_{method}_{options}_{file}'.format( |
| method=method, options=opts_name, file=f) |
| func = bind_method_args( |
| getattr(test_case_class, method), testdata, **opts_dict) |
| setattr(test_case_class, name, func) |
| |
| |
| class TestCase(unittest.TestCase): |
| |
| def tearDown(self): |
| for f in TESTDATA_PATHS: |
| try: |
| os.unlink(get_temp_compressed_name(f)) |
| except OSError: |
| pass |
| try: |
| os.unlink(get_temp_uncompressed_name(f)) |
| except OSError: |
| pass |
| |
| def assertFilesMatch(self, first, second): |
| self.assertTrue( |
| filecmp.cmp(first, second, shallow=False), |
| 'File {} differs from {}'.format(first, second)) |