Rev 3912: Start adding permutation tests for _groupcompress_py and _groupcompress_pyx in http://bzr.arbash-meinel.com/branches/bzr/brisbane/vilajam

John Arbash Meinel john at arbash-meinel.com
Wed Mar 25 20:58:38 GMT 2009


At http://bzr.arbash-meinel.com/branches/bzr/brisbane/vilajam

------------------------------------------------------------
revno: 3912
revision-id: john at arbash-meinel.com-20090325205816-m8rellryp3b7u4f0
parent: john at arbash-meinel.com-20090325202406-d3na661pqwtw75dx
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: vilajam
timestamp: Wed 2009-03-25 15:58:16 -0500
message:
  Start adding permutation tests for _groupcompress_py and _groupcompress_pyx
  We need to implement make_delta() for the python version.
  (maybe, but it would be a good test for apply_delta, which we *do* care about)
-------------- next part --------------
=== modified file 'bzrlib/_groupcompress_py.py'
--- a/bzrlib/_groupcompress_py.py	2009-03-25 20:24:06 +0000
+++ b/bzrlib/_groupcompress_py.py	2009-03-25 20:58:16 +0000
@@ -57,6 +57,83 @@
         except KeyError:
             return None
 
+    def _get_longest_match(self, pos, max_pos, locations):
+        """Get the longest possible match for the current position."""
+        range_start = pos
+        range_len = 0
+        copy_ends = None
+        while pos < max_pos:
+            if locations is None:
+                locations = self.get_idx_matches(pos)
+            if locations is None:
+                # No more matches, just return whatever we have, but we know that
+                # this last position is not going to match anything
+                pos += 1
+                break
+            else:
+                if copy_ends is None:
+                    # We are starting a new range
+                    copy_ends = [loc + 1 for loc in locations]
+                    range_len = 1
+                    locations = None # Consumed
+                else:
+                    # We are currently in the middle of a match
+                    next_locations = set(copy_ends).intersection(locations)
+                    if len(next_locations):
+                        # range continues
+                        copy_ends = [loc + 1 for loc in next_locations]
+                        range_len += 1
+                        locations = None # Consumed
+                    else:
+                        # But we are done with this match, we should be
+                        # starting a new one, though. We will pass back
+                        # 'locations' so that we don't have to do another
+                        # lookup.
+                        break
+            pos += 1
+        if copy_ends is None:
+            return None, pos, locations
+        return (((min(copy_ends) - range_len, range_start, range_len)),
+                pos, locations)
+
+    def get_matching_blocks(self, lines, soft=False):
+        """Return the ranges in lines which match self.lines.
+
+        :param lines: lines to compress
+        :return: A list of (old_start, new_start, length) tuples which reflect
+            a region in self.lines that is present in lines.  The last element
+            of the list is always (old_len, new_len, 0) to provide a end point
+            for generating instructions from the matching blocks list.
+        """
+        result = []
+        pos = 0
+        self.set_right_lines(lines)
+        locations = None
+        max_pos = len(lines)
+        result_append = result.append
+        min_match_bytes = 10
+        if soft:
+            min_match_bytes = 200
+        while pos < max_pos:
+            block, pos, locations = self._get_longest_match(pos, max_pos,
+                                                            locations)
+            if block is not None:
+                # Check to see if we are matching fewer than 5 characters,
+                # which is turned into a simple 'insert', rather than a copy
+                # If we have more than 5 lines, we definitely have more than 5
+                # chars
+                if block[-1] < min_match_bytes:
+                    # This block may be a 'short' block, check
+                    old_start, new_start, range_len = block
+                    matched_bytes = sum(map(len,
+                        lines[new_start:new_start + range_len]))
+                    if matched_bytes < min_match_bytes:
+                        block = None
+            if block is not None:
+                result_append(block)
+        result_append((len(self.lines), len(lines), 0))
+        return result
+
     def _get_matching_lines(self):
         """Return a dictionary showing matching lines."""
         matching = {}
@@ -87,42 +164,11 @@
         self._right_lines = lines
 
 
-def _get_longest_match(equivalence_table, pos, max_pos, locations):
-    """Get the longest possible match for the current position."""
-    range_start = pos
-    range_len = 0
-    copy_ends = None
-    while pos < max_pos:
-        if locations is None:
-            locations = equivalence_table.get_idx_matches(pos)
-        if locations is None:
-            # No more matches, just return whatever we have, but we know that
-            # this last position is not going to match anything
-            pos += 1
-            break
-        else:
-            if copy_ends is None:
-                # We are starting a new range
-                copy_ends = [loc + 1 for loc in locations]
-                range_len = 1
-                locations = None # Consumed
-            else:
-                # We are currently in the middle of a match
-                next_locations = set(copy_ends).intersection(locations)
-                if len(next_locations):
-                    # range continues
-                    copy_ends = [loc + 1 for loc in next_locations]
-                    range_len += 1
-                    locations = None # Consumed
-                else:
-                    # But we are done with this match, we should be
-                    # starting a new one, though. We will pass back 'locations'
-                    # so that we don't have to do another lookup.
-                    break
-        pos += 1
-    if copy_ends is None:
-        return None, pos, locations
-    return ((min(copy_ends) - range_len, range_start, range_len)), pos, locations
+
+def make_delta(source_bytes, target_bytes):
+    """Create a delta from source to target."""
+    line_locations = EquivalenceTable([])
+    return None
 
 
 def apply_delta(basis, delta):

=== modified file 'bzrlib/groupcompress.py'
--- a/bzrlib/groupcompress.py	2009-03-25 20:24:06 +0000
+++ b/bzrlib/groupcompress.py	2009-03-25 20:58:16 +0000
@@ -845,45 +845,6 @@
         self.lines = self.line_locations.lines
         self._present_prefixes = set()
 
-    def get_matching_blocks(self, lines, soft=False):
-        """Return the ranges in lines which match self.lines.
-
-        :param lines: lines to compress
-        :return: A list of (old_start, new_start, length) tuples which reflect
-            a region in self.lines that is present in lines.  The last element
-            of the list is always (old_len, new_len, 0) to provide a end point
-            for generating instructions from the matching blocks list.
-        """
-        result = []
-        pos = 0
-        line_locations = self.line_locations
-        line_locations.set_right_lines(lines)
-        locations = None
-        max_pos = len(lines)
-        result_append = result.append
-        min_match_bytes = 10
-        if soft:
-            min_match_bytes = 200
-        while pos < max_pos:
-            block, pos, locations = _get_longest_match(line_locations, pos,
-                                                       max_pos, locations)
-            if block is not None:
-                # Check to see if we are matching fewer than 5 characters,
-                # which is turned into a simple 'insert', rather than a copy
-                # If we have more than 5 lines, we definitely have more than 5
-                # chars
-                if block[-1] < min_match_bytes:
-                    # This block may be a 'short' block, check
-                    old_start, new_start, range_len = block
-                    matched_bytes = sum(map(len,
-                        lines[new_start:new_start + range_len]))
-                    if matched_bytes < min_match_bytes:
-                        block = None
-            if block is not None:
-                result_append(block)
-        result_append((len(self.lines), len(lines), 0))
-        return result
-
     # FIXME: implement nostore_sha
     def compress(self, key, bytes, expected_sha, nostore_sha=None, soft=False):
         """Compress lines with label key.
@@ -921,7 +882,7 @@
         # reserved for content type, content length, source_len, target_len
         out_lines = ['', '', '', '']
         index_lines = [False, False, False, False]
-        blocks = self.get_matching_blocks(new_lines, soft=soft)
+        blocks = self.line_locations.get_matching_blocks(new_lines, soft=soft)
         current_line_num = 0
         # We either copy a range (while there are reusable lines) or we
         # insert new lines. To find reusable lines we traverse
@@ -2031,7 +1992,6 @@
 from bzrlib._groupcompress_py import (
     apply_delta,
     EquivalenceTable,
-    _get_longest_match,
     )
 try:
     from bzrlib._groupcompress_pyx import (

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2009-03-25 17:29:07 +0000
+++ b/bzrlib/tests/__init__.py	2009-03-25 20:58:16 +0000
@@ -2931,7 +2931,7 @@
                    'bzrlib.tests.per_repository_reference',
                    'bzrlib.tests.test__chk_map',
                    'bzrlib.tests.test__dirstate_helpers',
-                   'bzrlib.tests.test__groupcompress_pyx',
+                   'bzrlib.tests.test__groupcompress',
                    'bzrlib.tests.test__walkdirs_win32',
                    'bzrlib.tests.test_ancestry',
                    'bzrlib.tests.test_annotate',

=== renamed file 'bzrlib/tests/test__groupcompress_pyx.py' => 'bzrlib/tests/test__groupcompress.py'
--- a/bzrlib/tests/test__groupcompress_pyx.py	2009-03-24 19:36:34 +0000
+++ b/bzrlib/tests/test__groupcompress.py	2009-03-25 20:58:16 +0000
@@ -16,12 +16,28 @@
 
 """Tests for the pyrex extension of groupcompress"""
 
-from bzrlib import tests
-
-from bzrlib import groupcompress
-
-
-class _CompiledGroupCompress(tests.Feature):
+from bzrlib import (
+    groupcompress,
+    _groupcompress_py,
+    tests,
+    )
+
+
+def load_tests(standard_tests, module, loader):
+    """Parameterize tests for view-aware vs not."""
+    to_adapt, result = tests.split_suite_by_condition(
+        standard_tests, tests.condition_isinstance(TestMakeAndApplyDelta))
+    scenarios = [
+        ('python', {'_gc_module': _groupcompress_py}),
+        ]
+    if CompiledGroupCompressFeature.available():
+        from bzrlib import _groupcompress_pyx
+        scenarios.append(('C',
+            {'_gc_module': _groupcompress_pyx}))
+    return tests.multiply_tests(to_adapt, scenarios, result)
+
+
+class _CompiledGroupCompressFeature(tests.Feature):
 
     def _probe(self):
         try:
@@ -34,7 +50,7 @@
     def feature_name(self):
         return 'bzrlib._groupcompress_pyx'
 
-CompiledGroupCompress = _CompiledGroupCompress()
+CompiledGroupCompressFeature = _CompiledGroupCompressFeature()
 
 _text1 = """\
 This is a bit
@@ -93,17 +109,9 @@
 same rabin hash
 """
 
-class Test_GroupCompress(tests.TestCase):
-    """Direct tests for the compiled extension."""
-
-    def setUp(self):
-        super(Test_GroupCompress, self).setUp()
-        self.requireFeature(CompiledGroupCompress)
-        from bzrlib import _groupcompress_pyx
-        self._gc_module = _groupcompress_pyx
-
-
-class TestMakeAndApplyDelta(Test_GroupCompress):
+class TestMakeAndApplyDelta(tests.TestCase):
+
+    _gc_module = None # Set by load_tests
 
     def setUp(self):
         super(TestMakeAndApplyDelta, self).setUp()
@@ -160,7 +168,16 @@
         self.assertEqual(_text1, target)
 
 
-class TestDeltaIndex(Test_GroupCompress):
+class TestDeltaIndex(tests.TestCase):
+
+    def setUp(self):
+        super(TestDeltaIndex, self).setUp()
+        # This test isn't multiplied, because we only have DeltaIndex for the
+        # compiled form
+        # We call this here, because _test_needs_features happens after setUp
+        self.requireFeature(CompiledGroupCompressFeature)
+        from bzrlib import _groupcompress_pyx
+        self._gc_module = _groupcompress_pyx
 
     def test_repr(self):
         di = self._gc_module.DeltaIndex('test text\n')

=== modified file 'bzrlib/tests/test_groupcompress.py'
--- a/bzrlib/tests/test_groupcompress.py	2009-03-25 20:24:06 +0000
+++ b/bzrlib/tests/test_groupcompress.py	2009-03-25 20:58:16 +0000
@@ -26,10 +26,7 @@
     versionedfile,
     )
 from bzrlib.osutils import sha_string
-from bzrlib.tests import (
-    TestCaseWithTransport,
-    multiply_tests,
-    )
+from bzrlib.tests.test__groupcompress import CompiledGroupCompressFeature
 
 
 def load_tests(standard_tests, module, loader):
@@ -39,25 +36,10 @@
     scenarios = [
         ('python', {'compressor': groupcompress.PythonGroupCompressor}),
         ]
-    if CompiledGroupcompressFeature.available():
+    if CompiledGroupCompressFeature.available():
         scenarios.append(('C',
             {'compressor': groupcompress.PyrexGroupCompressor}))
-    return multiply_tests(to_adapt, scenarios, result)
-
-
-class _CompiledGroupcompressFeature(tests.Feature):
-
-    def _probe(self):
-        try:
-            import bzrlib._groupcompress_pyx
-        except ImportError:
-            return False
-        return True
-
-    def feature_name(self):
-        return "bzrlib._groupcompress_pyx"
-
-CompiledGroupcompressFeature = _CompiledGroupcompressFeature()
+    return tests.multiply_tests(to_adapt, scenarios, result)
 
 
 class TestGroupCompressor(tests.TestCase):
@@ -140,7 +122,7 @@
 
 class TestPyrexGroupCompressor(TestGroupCompressor):
 
-    _test_needs_features = [CompiledGroupcompressFeature]
+    _test_needs_features = [CompiledGroupCompressFeature]
     compressor = groupcompress.PyrexGroupCompressor
 
     def test_stats(self):



More information about the bazaar-commits mailing list