Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / dulwich / tests / compat / test_pack.py @ 959

History | View | Annotate | Download (6.36 KB)

1
# test_pack.py -- Compatibility tests for git packs.
2
# Copyright (C) 2010 Google, Inc.
3
#
4
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
5
# General Public License as public by the Free Software Foundation; version 2.0
6
# or (at your option) any later version. You can redistribute it and/or
7
# modify it under the terms of either of these two licenses.
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14
#
15
# You should have received a copy of the licenses; if not, see
16
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
17
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
18
# License, Version 2.0.
19
#
20

    
21
"""Compatibility tests for git packs."""
22

    
23

    
24
import binascii
25
import os
26
import re
27
import shutil
28
import tempfile
29

    
30
from dulwich.pack import (
31
    write_pack,
32
    )
33
from dulwich.objects import (
34
    Blob,
35
    )
36
from dulwich.tests import (
37
    SkipTest,
38
    )
39
from dulwich.tests.test_pack import (
40
    a_sha,
41
    pack1_sha,
42
    PackTests,
43
    )
44
from dulwich.tests.compat.utils import (
45
    require_git_version,
46
    run_git_or_fail,
47
    )
48

    
49
_NON_DELTA_RE = re.compile(b'non delta: (?P<non_delta>\d+) objects')
50

    
51
def _git_verify_pack_object_list(output):
52
    pack_shas = set()
53
    for line in output.splitlines():
54
        sha = line[:40]
55
        try:
56
            binascii.unhexlify(sha)
57
        except (TypeError, binascii.Error):
58
            continue  # non-sha line
59
        pack_shas.add(sha)
60
    return pack_shas
61

    
62

    
63
class TestPack(PackTests):
64
    """Compatibility tests for reading and writing pack files."""
65

    
66
    def setUp(self):
67
        require_git_version((1, 5, 0))
68
        super(TestPack, self).setUp()
69
        self._tempdir = tempfile.mkdtemp()
70
        self.addCleanup(shutil.rmtree, self._tempdir)
71

    
72
    def test_copy(self):
73
        with self.get_pack(pack1_sha) as origpack:
74
            self.assertSucceeds(origpack.index.check)
75
            pack_path = os.path.join(self._tempdir, "Elch")
76
            write_pack(pack_path, origpack.pack_tuples())
77
            output = run_git_or_fail(['verify-pack', '-v', pack_path])
78
            orig_shas = set(o.id for o in origpack.iterobjects())
79
            self.assertEqual(orig_shas, _git_verify_pack_object_list(output))
80

    
81
    def test_deltas_work(self):
82
        with self.get_pack(pack1_sha) as orig_pack:
83
            orig_blob = orig_pack[a_sha]
84
            new_blob = Blob()
85
            new_blob.data = orig_blob.data + b'x'
86
            all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None)]
87
        pack_path = os.path.join(self._tempdir, 'pack_with_deltas')
88
        write_pack(pack_path, all_to_pack, deltify=True)
89
        output = run_git_or_fail(['verify-pack', '-v', pack_path])
90
        self.assertEqual(set(x[0].id for x in all_to_pack),
91
                         _git_verify_pack_object_list(output))
92
        # We specifically made a new blob that should be a delta
93
        # against the blob a_sha, so make sure we really got only 3
94
        # non-delta objects:
95
        got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta'))
96
        self.assertEqual(
97
            3, got_non_delta,
98
            'Expected 3 non-delta objects, got %d' % got_non_delta)
99

    
100
    def test_delta_medium_object(self):
101
        # This tests an object set that will have a copy operation
102
        # 2**20 in size.
103
        with self.get_pack(pack1_sha) as orig_pack:
104
            orig_blob = orig_pack[a_sha]
105
            new_blob = Blob()
106
            new_blob.data = orig_blob.data + (b'x' * 2 ** 20)
107
            new_blob_2 = Blob()
108
            new_blob_2.data = new_blob.data + b'y'
109
            all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None),
110
                                                           (new_blob_2, None)]
111
        pack_path = os.path.join(self._tempdir, 'pack_with_deltas')
112
        write_pack(pack_path, all_to_pack, deltify=True)
113
        output = run_git_or_fail(['verify-pack', '-v', pack_path])
114
        self.assertEqual(set(x[0].id for x in all_to_pack),
115
                         _git_verify_pack_object_list(output))
116
        # We specifically made a new blob that should be a delta
117
        # against the blob a_sha, so make sure we really got only 3
118
        # non-delta objects:
119
        got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta'))
120
        self.assertEqual(
121
            3, got_non_delta,
122
            'Expected 3 non-delta objects, got %d' % got_non_delta)
123
        # We expect one object to have a delta chain length of two
124
        # (new_blob_2), so let's verify that actually happens:
125
        self.assertIn(b'chain length = 2', output)
126

    
127
    # This test is SUPER slow: over 80 seconds on a 2012-era
128
    # laptop. This is because SequenceMatcher is worst-case quadratic
129
    # on the input size. It's impractical to produce deltas for
130
    # objects this large, but it's still worth doing the right thing
131
    # when it happens.
132
    def test_delta_large_object(self):
133
        # This tests an object set that will have a copy operation
134
        # 2**25 in size. This is a copy large enough that it requires
135
        # two copy operations in git's binary delta format.
136
        raise SkipTest('skipping slow, large test')
137
        with self.get_pack(pack1_sha) as orig_pack:
138
            new_blob = Blob()
139
            new_blob.data = 'big blob' + ('x' * 2 ** 25)
140
            new_blob_2 = Blob()
141
            new_blob_2.data = new_blob.data + 'y'
142
            all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None),
143
                                                           (new_blob_2, None)]
144
        pack_path = os.path.join(self._tempdir, "pack_with_deltas")
145
        write_pack(pack_path, all_to_pack, deltify=True)
146
        output = run_git_or_fail(['verify-pack', '-v', pack_path])
147
        self.assertEqual(set(x[0].id for x in all_to_pack),
148
                         _git_verify_pack_object_list(output))
149
        # We specifically made a new blob that should be a delta
150
        # against the blob a_sha, so make sure we really got only 4
151
        # non-delta objects:
152
        got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta'))
153
        self.assertEqual(
154
            4, got_non_delta,
155
            'Expected 4 non-delta objects, got %d' % got_non_delta)