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 | 959 | jjdelcerro | # 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) |