[bmap-tools] [PATCH 2/4] test_compat: improve backward compatibility test

Artem Bityutskiy dedekind1 at gmail.com
Mon Nov 4 10:28:53 EST 2013


From: Artem Bityutskiy <artem.bityutskiy at intel.com>

Currently 'test_compat' verifies that BmapCopy handles all the older bmap file
formats. This patch adds a check that older BmapCopy implementations are able
to handle all the compatible bmap file formats.

The reason for this test is that I once screwed it up with version 1.4: it had
incompatible changes, and older versions of BmapCopy crash with 1.4. If I had
this test-suite, I would add the new bmap format file to 'tests/test-data', and
the mistake would be caought right away.

Change-Id: I62ac407fb9cfe3b7158853ce09d5402cf85785de
Signed-off-by: Artem Bityutskiy <artem.bityutskiy at intel.com>
---
 tests/test_compat.py | 147 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 109 insertions(+), 38 deletions(-)

diff --git a/tests/test_compat.py b/tests/test_compat.py
index d0ba703..ea8e606 100644
--- a/tests/test_compat.py
+++ b/tests/test_compat.py
@@ -12,15 +12,29 @@
 # General Public License for more details.
 
 """
-This unit test verifies that BmapCopy can handle all the bmap file formats and
-have no backward-compatibility problems.
+This unit test verifies various compatibility aspects of the BmapCopy module:
+    * current BmapCopy has to handle all the older bmap formats
+    * older BmapCopy have to handle all the newer compatible bmap formats
 """
 
+# Disable the following pylint recommendations:
+#   *  Too many public methods - R0904
+# pylint: disable=R0904
+
 import os
 import shutil
 import tempfile
 from tests import helpers
-from bmaptools import TransRead
+from bmaptools import TransRead, BmapCopy
+
+# Test image file name
+_IMAGE_NAME = "test.image.gz"
+# Test bmap file names template
+_BMAP_TEMPL = "test.image.bmap.v"
+# Name of the subdirectory where test data are stored
+_TEST_DATA_SUBDIR = "test-data"
+# Name of the subdirectory where old BmapCopy modules are stored
+_OLDCODEBASE_SUBDIR = "oldcodebase"
 
 # This is a work-around for Centos 6
 try:
@@ -29,50 +43,107 @@ except ImportError:
     import unittest
 
 class TestCreateCopy(unittest.TestCase):
-    """
-    The test class for this unit tests which executes the '_do_test()' function
-    for various bmap file formats.
-    """
+    """The test class for this unit test."""
 
     def test(self):
-        """
-        The test entry point. Executes the '_do_test()' function for various
-        bmap file formats.
-        """
-
-        image_name = "test.image.gz"
-        bmap_name  = "test.image.bmap.v"
-        test_data_dir = "test-data"
-
-        test_data_dir = os.path.join(os.path.dirname(__file__), test_data_dir)
-        image_path = os.path.join(test_data_dir, image_name)
+        """The test entry point."""
 
+        test_data_dir = os.path.join(os.path.dirname(__file__),
+                                     _TEST_DATA_SUBDIR)
+        image_path = os.path.join(test_data_dir, _IMAGE_NAME)
 
-        # Get the list of bmap files to test
-        bmap_paths = []
-        for direntry in os.listdir(test_data_dir):
-            direntry_path = os.path.join(test_data_dir, direntry)
-            if os.path.isfile(direntry_path) and direntry.startswith(bmap_name):
-                bmap_paths.append(direntry_path)
+        # Construct the list of bmap files to test
+        self._bmap_paths = []
+        for dentry in os.listdir(test_data_dir):
+            dentry_path = os.path.join(test_data_dir, dentry)
+            if os.path.isfile(dentry_path) and dentry.startswith(_BMAP_TEMPL):
+                self._bmap_paths.append(dentry_path)
 
         # Create and open a temporary file for uncompressed image and its copy
-        f_image = tempfile.NamedTemporaryFile("wb+", prefix=image_name,
-                                              suffix=".image")
-        f_copy = tempfile.NamedTemporaryFile("wb+", prefix=image_name,
-                                             suffix=".copy")
+        self._f_image = tempfile.NamedTemporaryFile("wb+", prefix=_IMAGE_NAME,
+                                                   suffix=".image")
+        self._f_copy = tempfile.NamedTemporaryFile("wb+", prefix=_IMAGE_NAME,
+                                                  suffix=".copy")
 
-        # Create an ucompressed version of the image file
+        # Uncompress the test image into 'self._f_image'
         f_tmp_img = TransRead.TransRead(image_path)
-        shutil.copyfileobj(f_tmp_img, f_image)
+        shutil.copyfileobj(f_tmp_img, self._f_image)
         f_tmp_img.close()
-        f_image.flush()
+        self._f_image.flush()
+
+        image_chksum = helpers.calculate_chksum(self._f_image.name)
+        image_size = os.path.getsize(self._f_image.name)
+
+        # Test the current version of BmapCopy
+        for bmap_path in self._bmap_paths:
+            helpers.copy_and_verify_image(image_path, self._f_copy.name,
+                                          bmap_path, image_chksum,
+                                          image_size)
+
+        # Test the older versions of BmapCopy
+        self._test_older_bmapcopy()
+
+        self._f_copy.close()
+        self._f_image.close()
+
+    def _test_older_bmapcopy(self):
+        """Test older than the current versions of the BmapCopy class."""
+
+        def import_module(searched_module):
+            """Search and import a module by its name."""
+
+            modref = __import__(searched_module)
+            for name in searched_module.split(".")[1:]:
+                modref = getattr(modref, name)
+            return modref
+
+        oldcodebase_dir = os.path.join(os.path.dirname(__file__),
+                                       _OLDCODEBASE_SUBDIR)
+
+        # Construct the list of old BmapCopy modules
+        old_modules = []
+        for dentry in os.listdir(oldcodebase_dir):
+            if dentry.startswith("BmapCopy") and dentry.endswith(".py"):
+                old_modules.append("tests." + _OLDCODEBASE_SUBDIR + "."
+                                   + dentry[:-3])
+
+        for old_module in old_modules:
+            modref = import_module(old_module)
+
+            for bmap_path in self._bmap_paths:
+                self._do_test_older_bmapcopy(bmap_path, modref)
+
+    def _do_test_older_bmapcopy(self, bmap_path, modref):
+        """
+        Test an older version of BmapCopy class, referenced to by the 'modref'
+        argument. The 'bmap_path' argument is the bmap file path to test with.
+        """
+
+        # Get a reference to the older BmapCopy class object to test with
+        old_bmapcopy_class = getattr(modref, "BmapCopy")
+        supported_ver = getattr(modref, "SUPPORTED_BMAP_VERSION")
+
+        f_bmap = open(bmap_path, "r")
 
-        image_chksum = helpers.calculate_chksum(f_image.name)
-        image_size = os.path.getsize(f_image.name)
+        # Find the version of the bmap file. The easiest is to simply use the
+        # latest BmapCopy.
+        bmapcopy = BmapCopy.BmapCopy(self._f_image, self._f_copy, f_bmap)
+        bmap_version = bmapcopy.bmap_version
+        bmap_version_major = bmapcopy.bmap_version_major
 
-        for bmap_path in bmap_paths:
-            helpers.copy_and_verify_image(image_path, f_copy.name, bmap_path,
-                                          image_chksum, image_size)
+        try:
+            if supported_ver >= bmap_version:
+                writer = old_bmapcopy_class(self._f_image, self._f_copy, f_bmap)
+                writer.copy(True, True)
+        except:
+            if supported_ver >= bmap_version_major:
+                # The BmapCopy which we are testing is supposed to support this
+                # version of bmap file format. However, bmap format version 1.4
+                # was a screw-up, because it actually had incompatible changes,
+                # so old versions of BmapCopy are supposed to fail.
+                if not (supported_ver == 1 and bmap_version == "1.4"):
+                    print("Module \"%s\" failed to handle \"%s\"" %
+                          (modref.__name__, bmap_path))
+                    raise
 
-        f_copy.close()
-        f_image.close()
+        f_bmap.close()
-- 
1.8.1.4




More information about the Bmap-tools mailing list