[Piglit] [PATCH 27/49] unittests: port compressed_backend_tests to pytest

Dylan Baker dylan at pnwbakers.com
Fri Jul 29 18:39:13 UTC 2016


Signed-off-by: Dylan Baker <dylanx.c.baker at intel.com>
---
 unittests/compressed_backend_tests.py            | 302 -----------------------
 unittests/framework/backends/__init__.py         |   0
 unittests/framework/backends/test_compression.py | 265 ++++++++++++++++++++
 3 files changed, 265 insertions(+), 302 deletions(-)
 delete mode 100644 unittests/compressed_backend_tests.py
 create mode 100644 unittests/framework/backends/__init__.py
 create mode 100644 unittests/framework/backends/test_compression.py

diff --git a/unittests/compressed_backend_tests.py b/unittests/compressed_backend_tests.py
deleted file mode 100644
index bf9af02..0000000
--- a/unittests/compressed_backend_tests.py
+++ /dev/null
@@ -1,302 +0,0 @@
-# Copyright (c) 2015 Intel Corporation
-
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-
-"""Tests for compressed backends.
-
-This modules tests for compression support. Most of the tests are fairly basic,
-aiming to verify that compression and decompression works as expected.
-
-"""
-
-from __future__ import (
-    absolute_import, division, print_function, unicode_literals
-)
-import os
-import functools
-
-import nose.tools as nt
-try:
-    import mock
-except ImportError:
-    from unittest import mock
-
-from . import utils
-from framework import results
-from framework.backends import compression, abstract
-
-# pylint: disable=line-too-long,protected-access
-
-# Helpers
-
-
-class _TestBackend(abstract.FileBackend):
-    """A class for testing backend compression."""
-    _file_extension = 'test_extension'
-
-    def initialize(self, *args, **kwargs):  # pylint: disable=unused-argument
-        os.mkdir(os.path.join(self._dest, 'tests'))
-
-    def finalize(self, *args, **kwargs): # pylint: disable=unused-argument
-        tests = os.path.join(self._dest, 'tests')
-        with self._write_final(os.path.join(self._dest, 'results.txt')) as f:
-            for file_ in os.listdir(tests):
-                with open(os.path.join(tests, file_), 'r') as t:
-                    f.write(t.read())
-
-    @staticmethod
-    def _write(f, name, data):  # pylint: disable=arguments-differ
-        f.write('{}: {}'.format(name, data))
-
-
-def _add_compression(value):
-    """Decorator that temporarily adds support for a compression method."""
-
-    def _wrapper(func):
-        """The actual wrapper."""
-
-        @functools.wraps(func)
-        def _inner(*args, **kwargs):
-            """The function called."""
-            compression.COMPRESSORS[value] = None
-            compression.DECOMPRESSORS[value] = None
-
-            try:
-                func(*args, **kwargs)
-            finally:
-                del compression.COMPRESSORS[value]
-                del compression.DECOMPRESSORS[value]
-
-        return _inner
-
-    return _wrapper
-
-
-def _test_compressor(mode):
-    """Helper to simplify testing compressors."""
-    func = compression.COMPRESSORS[mode]
-    with utils.nose.tempdir() as t:
-        with func(os.path.join(t, 'file')) as f:
-            f.write('foo')
-
-
-def _test_decompressor(mode):
-    """helper to simplify testing decompressors."""
-    func = compression.COMPRESSORS[mode]
-    dec = compression.DECOMPRESSORS[mode]
-
-    with utils.nose.tempdir() as t:
-        path = os.path.join(t, 'file')
-
-        with func(path) as f:
-            f.write('foo')
-
-        with dec(path) as f:
-            nt.eq_(f.read(), 'foo')
-
-
-def _test_extension():
-    """Create an final file and return the extension."""
-    with utils.nose.tempdir() as d:
-        obj = _TestBackend(d)
-        obj.initialize()
-        with obj.write_test('foo') as t:
-            t(results.TestResult('pass'))
-
-        obj.finalize()
-
-        for each in os.listdir(d):
-            if each.startswith('results.txt'):
-                name, ext = os.path.splitext(each)
-                if name.endswith('.'):
-                    raise utils.nose.TestFailure(
-                        'extra trailing "." in name "{}"'.format(name))
-                break
-        else:
-            raise utils.nose.TestFailure('No results file generated')
-
-    return ext
-
-
-# Tests
-
-
- at utils.nose.no_error
-def test_compress_none():
-    """framework.backends.compression: can compress to 'none'"""
-    _test_compressor('none')
-
-
-def test_decompress_none():
-    """framework.backends.compression: can decompress from 'none'"""
-    _test_decompressor('none')
-
-
-
- at _add_compression('foobar')
- at mock.patch.dict('os.environ', {'PIGLIT_COMPRESSION': 'foobar'})
-def testget_mode_env():
-    """framework.backends.compression.get_mode: uses PIGlIT_COMPRESSION environment variable"""
-    nt.eq_(compression.get_mode(), 'foobar')
-
-
- at _add_compression('foobar')
- at mock.patch.dict('os.environ', {}, True)
- at utils.piglit.set_piglit_conf(('core', 'compression', 'foobar'))
-def testget_mode_piglit_conf():
-    """framework.backends.compression.get_mode: uses piglit.conf [core]:compression value if env is unset"""
-    nt.eq_(compression.get_mode(), 'foobar')
-
-
- at mock.patch.dict('os.environ', {}, True)
- at utils.piglit.set_piglit_conf(('core', 'compression', None))
-def testget_mode_default():
-    """framework.backends.compression.get_mode: uses DEFAULT if env and piglit.conf are unset"""
-    nt.eq_(compression.get_mode(), compression.DEFAULT)
-
-
- at utils.nose.no_error
-def test_compress_gz():
-    """framework.backends.compression: can compress to 'gz'"""
-    _test_compressor('gz')
-
-
-def test_decompress_gz():
-    """framework.backends.compression: can decompress from 'gz'"""
-    _test_decompressor('gz')
-
-
- at mock.patch.dict('os.environ', {'PIGLIT_COMPRESSION': 'gz'})
-def test_gz_output():
-    """framework.backends: when using gz compression a gz file is created"""
-    nt.eq_(_test_extension(), '.gz')
-
-
- at utils.nose.no_error
-def test_compress_bz2():
-    """framework.backends.compression: can compress to 'bz2'"""
-    _test_compressor('bz2')
-
-
-def test_decompress_bz2():
-    """framework.backends.compression: can decompress from 'bz2'"""
-    _test_decompressor('bz2')
-
-
- at mock.patch.dict('os.environ', {'PIGLIT_COMPRESSION': 'bz2'})
-def test_bz2_output():
-    """framework.backends: when using bz2 compression a bz2 file is created"""
-    nt.eq_(_test_extension(), '.bz2')
-
-
- at utils.nose.Skip.backport(3.0, 'backports.lzma')
- at utils.nose.no_error
-def test_compress_xz_module():
-    """framework.backends.compression: can compress to 'xz' via module"""
-    _test_compressor('xz')
-
-
- at utils.nose.Skip.py3
- at utils.nose.Skip.module('backports.lzma', available=True)
- at utils.nose.Skip.binary('xz')
- at utils.nose.no_error
-def test_compress_xz_binary():
-    """framework.backends.compression: can compress to 'xz' via binary"""
-    _test_compressor('xz')
-
-
- at utils.nose.Skip.backport(3.0, 'backports.lzma')
-def test_decompress_xz_module():
-    """framework.backends.compression: can decompress from 'xz' via module"""
-    _test_decompressor('xz')
-
-
- at utils.nose.Skip.py3
- at utils.nose.Skip.module('backports.lzma', available=True)
- at utils.nose.Skip.binary('xz')
-def test_decompress_xz_binary():
-    """framework.backends.compression: can decompress from 'xz' via binary"""
-    _test_decompressor('xz')
-
-
- at utils.nose.Skip.backport(3.0, 'backports.lzma')
- at mock.patch.dict('os.environ', {'PIGLIT_COMPRESSION': 'xz'})
-def test_xz_output():
-    """framework.backends: when using xz compression a xz file is created"""
-    nt.eq_(_test_extension(), '.xz')
-
-
- at _add_compression('foobar')
- at mock.patch.dict('os.environ', {}, True)
- at utils.piglit.set_piglit_conf(('core', 'compression', 'foobar'))
-def test_update_piglit_conf():
-    """framework.backends.compression: The compression mode honors updates to piglit.conf.
-
-    the values in piglit.conf are subject to change. And the default
-    compression mode needs to be changed with them.
-
-    """
-    nt.eq_(compression.get_mode(), 'foobar')
-
-
- at utils.nose.Skip.py3
- at utils.nose.Skip.module('backports.lzma', available=False)
- at utils.nose.Skip.binary('xz')
- at mock.patch.dict('os.environ', {'PIGLIT_COMPRESSION': 'xz'})
- at utils.nose.test_in_tempdir
-def test_xz_shell_override():
-    """framework.backends.compression: the xz shell utility path can overwrite"""
-    with open('foo.json.xz', 'w') as f:
-        f.write('foo')
-
-    with compression.COMPRESSORS['xz']('foo.json') as f:
-        f.write('foobar')
-
-
- at utils.piglit.set_piglit_conf(('core', 'compression', 'bz2'))
-def test_write_compressed_one_suffix_bz2():
-    """backends.abstract.write_compressed: bz2 Does not duplicate compression suffixes
-    """
-    with utils.nose.tempdir() as d:
-        with abstract.write_compressed(os.path.join(d, 'results.txt.bz2')) as f:
-            f.write('foo')
-
-        nt.eq_(os.listdir(d)[0], 'results.txt.bz2')
-
-
- at utils.piglit.set_piglit_conf(('core', 'compression', 'gz'))
-def test_write_compressed_one_suffix_gz():
-    """backends.abstract.write_compressed: gz Does not duplicate compression suffixes
-    """
-    with utils.nose.tempdir() as d:
-        with abstract.write_compressed(os.path.join(d, 'results.txt.gz')) as f:
-            f.write('foo')
-
-        nt.eq_(os.listdir(d)[0], 'results.txt.gz')
-
-
- at utils.piglit.set_piglit_conf(('core', 'compression', 'gz'))
-def test_write_compressed_one_suffix_mixed():
-    """backends.abstract.write_compressed: does not generate two different compression suffixes
-    """
-    with utils.nose.tempdir() as d:
-        with abstract.write_compressed(os.path.join(d, 'results.txt.bz2')) as f:
-            f.write('foo')
-
-        nt.eq_(os.listdir(d)[0], 'results.txt.gz')
diff --git a/unittests/framework/backends/__init__.py b/unittests/framework/backends/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/unittests/framework/backends/test_compression.py b/unittests/framework/backends/test_compression.py
new file mode 100644
index 0000000..f7b400c
--- /dev/null
+++ b/unittests/framework/backends/test_compression.py
@@ -0,0 +1,265 @@
+# Copyright (c) 2015-2016 Intel Corporation
+
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+"""Tests for compression in file backends."""
+
+from __future__ import (
+    absolute_import, division, print_function, unicode_literals
+)
+import itertools
+import os
+import subprocess
+try:
+    import mock
+except ImportError:
+    from unittest import mock
+
+import pytest
+import six
+
+from framework import core
+from framework.backends import abstract
+from framework.backends import compression
+
+from .. import skip
+
+# pylint: disable=no-self-use,redefined-outer-name
+
+# Helpers
+
+
+def _has_lzma():
+    """Try to import backports.lzma, and return True if it exists, False if it
+    doesn't.
+    """
+    try:
+        import backports.lzma  # pylint: disable=unused-variable
+    except ImportError:
+        return False
+    return True
+
+
+def _has_xz_bin():
+    """Check for an xz binary."""
+    try:
+        subprocess.check_call(['xz', '--help'])
+    except subprocess.CalledProcessError:
+        return False
+    except OSError as e:  # pylint: disable=undefined-variable
+        if e.errno != 2:
+            raise
+        return False
+    return True
+
+
+requires_lzma = pytest.mark.skipif(  # pylint: disable=invalid-name
+    six.PY2 and not _has_lzma(),
+    reason="Python 2.x requires backports.lzma to run this test.")
+
+requires_xz_bin = pytest.mark.skipif(  # pylint: disable=invalid-name
+    _has_lzma() or not _has_xz_bin(),
+    reason="Python 2.x requires xz binary to run this test.")
+
+requires_any_lzma = pytest.mark.skipif(  # pylint: disable=invalid-name
+    six.PY2 and not (_has_lzma() or _has_xz_bin()),
+    reason="Python 2.x requires some form of xz compression to run this test.")
+
+
+ at pytest.yield_fixture
+def env():
+    with mock.patch.dict('os.environ'):
+        yield os.environ
+
+ at pytest.yield_fixture
+def config():
+    with mock.patch('framework.backends.compression.PIGLIT_CONFIG',
+                    new_callable=core.PiglitConfig) as conf:
+        conf.add_section('core')
+        yield conf
+
+ at pytest.yield_fixture
+def compressor():
+    """Workaround for yield_fixture not working with classes."""
+    class Compressor(object):
+        """Fixture to control the compressor/decompressor objects."""
+
+        def __init__(self):
+            self._mock_c = mock.patch.dict(
+                'framework.backends.compression.COMPRESSORS', clear=False)
+            self._mock_d = mock.patch.dict(
+                'framework.backends.compression.DECOMPRESSORS', clear=False)
+
+        def __enter__(self):
+            self._mock_c.start()
+            self._mock_d.start()
+            return self
+
+        def __exit__(self, type_, value, traceback):
+            self._mock_c.stop()
+            self._mock_d.stop()
+
+        def add(self, name, func):
+            assert name not in compression.COMPRESSORS
+            assert name not in compression.DECOMPRESSORS
+            compression.COMPRESSORS[name] = func
+            compression.DECOMPRESSORS[name] = func
+
+        def rm(self, name):  # pylint: disable=invalid-name
+            assert name in compression.COMPRESSORS
+            assert name in compression.DECOMPRESSORS
+            del compression.COMPRESSORS[name]
+            del compression.DECOMPRESSORS[name]
+
+    with Compressor() as c:
+        yield c
+
+
+# Tests
+
+
+ at pytest.mark.parametrize("mode", ['none', 'bz2', 'gz', requires_lzma('xz')])
+def test_compress(mode, tmpdir):
+    """Test that each compressor that we want works.
+
+    These only check using modules, that means on python2 this test will skip
+    unless backports.lzma is available, and it will not test the the xz binary
+    path.
+    """
+    func = compression.COMPRESSORS[mode]
+    testfile = tmpdir.join('test')
+    with func(six.text_type(testfile)) as f:
+        f.write('foo')
+
+
+ at pytest.mark.parametrize("mode", ['none', 'bz2', 'gz', requires_lzma('xz')])
+def test_decompress(mode, tmpdir):
+    """Test that each supported decompressor works.
+
+    See the docstring in test_compress.
+    """
+    comp = compression.COMPRESSORS[mode]
+    dec = compression.DECOMPRESSORS[mode]
+    testfile = tmpdir.join('test')
+
+    with comp(six.text_type(testfile)) as f:
+        f.write('foo')
+
+    with dec(six.text_type(testfile)) as f:
+        actual = f.read()
+
+    assert actual == 'foo'
+
+
+ at skip.posix
+ at skip.PY3
+ at requires_xz_bin
+class TestXZBin(object):
+    """Tests for the xz bin path on python2.x."""
+
+    def test_compress_xz_bin(self, tmpdir):
+        """Test python2 xz compression using the xz binary."""
+        func = compression.COMPRESSORS['xz']
+        testfile = tmpdir.join('test')
+        with func(six.text_type(testfile)) as f:
+            f.write('foo')
+
+    def test_decompress_xz_bin(self, tmpdir):
+        """Test python2 xz decompression using the xz binary."""
+        comp = compression.COMPRESSORS['xz']
+        dec = compression.DECOMPRESSORS['xz']
+        testfile = tmpdir.join('test')
+
+        with comp(six.text_type(testfile)) as f:
+            f.write('foo')
+
+        with dec(six.text_type(testfile)) as f:
+            actual = f.read()
+
+        assert actual == 'foo'
+
+
+class TestGetMode(object):
+    """Tests for the compression.get_mode function."""
+
+    def test_default(self, env, config):  # pylint: disable=unused-argument
+        """When neither the config file nor the environment sets a value for
+        compression the default value should be used.
+        """
+        env.clear()
+
+        assert compression.get_mode() == compression.DEFAULT
+
+    def test_env(self, env, config, compressor):
+        """Test that when env doesn't have a PIGLIT_COMPRESSION environment
+        varaible set, but the configuraiton has a compression method set that
+        it is used.
+        """
+        compressor.add('foo', None)
+        compressor.add('bar', None)
+        config.set('core', 'compression', 'foo')
+        env['PIGLIT_COMPRESSION'] = 'bar'
+
+        assert compression.get_mode() == 'bar'
+
+    def test_piglit_conf(self, env, config, compressor):
+        """Test that when env doesn't have a PIGLIT_COMPRESSION environment
+        varaible set, but the configuraiton has a compression method set that
+        it is used.
+        """
+        compressor.add('foobar', None)
+        config.set('core', 'compression', 'foobar')
+        env.clear()
+
+        assert compression.get_mode() == 'foobar'
+
+
+ at pytest.mark.parametrize("extension", ['bz2', 'gz', requires_any_lzma('xz')])
+def test_duplicate_extensions(extension, tmpdir, config):
+    """Tests that exersizes a bug that caused the compressed extension to be
+    duplicated in some cases.
+    """
+    tmpdir.chdir()
+    config.set('core', 'compression', extension)
+    expected = 'results.txt.' + extension
+
+    with abstract.write_compressed(expected) as f:
+        f.write('foo')
+
+    assert expected in os.listdir('.')
+
+
+ at pytest.mark.parametrize("orig,new", itertools.permutations(
+    ['bz2', 'gz', 'xz'], 2))
+def test_changed_extension(orig, new, tmpdir, config):
+    """Tests that exersizes a bug that caused two extensions to be present if
+    the compression method changed.
+    """
+    if 'xz' in [new, orig] and six.PY2 and not (_has_lzma() or _has_xz_bin()):
+        pytest.skip("There is no xz compressor available.")
+
+    tmpdir.chdir()
+    config.set('core', 'compression', six.text_type(new))
+
+    with abstract.write_compressed('results.txt.' + orig) as f:
+        f.write('foo')
+
+    assert 'results.txt.' + new in os.listdir('.')
+    assert 'results.txt.' + orig not in os.listdir('.')
+    assert 'results.txt.{}.{}'.format(orig, new) not in os.listdir('.')
-- 
2.9.0



More information about the Piglit mailing list