1
# Copyright (C) 2008, 2009 Canonical Ltd
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
"""Tests for the pyrex extension of groupcompress"""
19
from bzrlib import tests
21
from bzrlib import groupcompress
24
class _CompiledGroupCompress(tests.Feature):
28
import bzrlib._groupcompress_pyx
34
def feature_name(self):
35
return 'bzrlib._groupcompress_pyx'
37
CompiledGroupCompress = _CompiledGroupCompress()
42
which is meant to be matched
49
which is meant to differ from
56
which is meant to be matched
60
at the end of the file
66
common with the next text
70
some more bit of text, that
72
common with the previous text
73
and has some extra text
79
has some in common with the previous text
80
and has some extra text
82
common with the next text
86
class Test_GroupCompress(tests.TestCase):
87
"""Direct tests for the compiled extension."""
90
super(Test_GroupCompress, self).setUp()
91
self.requireFeature(CompiledGroupCompress)
92
from bzrlib import _groupcompress_pyx
93
self._gc_module = _groupcompress_pyx
96
class TestMakeAndApplyDelta(Test_GroupCompress):
99
super(TestMakeAndApplyDelta, self).setUp()
100
self.make_delta = self._gc_module.make_delta
101
self.apply_delta = self._gc_module.apply_delta
103
def test_make_delta_is_typesafe(self):
104
self.make_delta('a string', 'another string')
105
self.assertRaises(TypeError,
106
self.make_delta, 'a string', object())
107
self.assertRaises(TypeError,
108
self.make_delta, 'a string', u'not a string')
109
self.assertRaises(TypeError,
110
self.make_delta, object(), 'a string')
111
self.assertRaises(TypeError,
112
self.make_delta, u'not a string', 'a string')
114
def test_make_noop_delta(self):
115
ident_delta = self.make_delta(_text1, _text1)
116
self.assertEqual('MM\x90M', ident_delta)
117
ident_delta = self.make_delta(_text2, _text2)
118
self.assertEqual('NN\x90N', ident_delta)
119
ident_delta = self.make_delta(_text3, _text3)
120
self.assertEqual('\x87\x01\x87\x01\x90\x87', ident_delta)
122
def test_make_delta(self):
123
delta = self.make_delta(_text1, _text2)
124
self.assertEqual('MN\x90/\x1fdiffer from\nagainst other text\n', delta)
125
delta = self.make_delta(_text2, _text1)
126
self.assertEqual('NM\x90/\x1ebe matched\nagainst other text\n', delta)
127
delta = self.make_delta(_text3, _text1)
128
self.assertEqual('\x87\x01M\x90M', delta)
129
delta = self.make_delta(_text3, _text2)
130
self.assertEqual('\x87\x01N\x90/\x1fdiffer from\nagainst other text\n',
133
def test_apply_delta_is_typesafe(self):
134
self.apply_delta(_text1, 'MM\x90M')
135
self.assertRaises(TypeError,
136
self.apply_delta, object(), 'MM\x90M')
137
self.assertRaises(TypeError,
138
self.apply_delta, unicode(_text1), 'MM\x90M')
139
self.assertRaises(TypeError,
140
self.apply_delta, _text1, u'MM\x90M')
141
self.assertRaises(TypeError,
142
self.apply_delta, _text1, object())
144
def test_apply_delta(self):
145
target = self.apply_delta(_text1,
146
'MN\x90/\x1fdiffer from\nagainst other text\n')
147
self.assertEqual(_text2, target)
148
target = self.apply_delta(_text2,
149
'NM\x90/\x1ebe matched\nagainst other text\n')
150
self.assertEqual(_text1, target)
153
class TestDeltaIndex(Test_GroupCompress):
156
di = self._gc_module.DeltaIndex('test text\n')
157
self.assertEqual('DeltaIndex(1, 10)', repr(di))
159
def test_make_delta(self):
160
di = self._gc_module.DeltaIndex(_text1)
161
delta = di.make_delta(_text2)
162
self.assertEqual('MN\x90/\x1fdiffer from\nagainst other text\n', delta)
164
def test_delta_against_multiple_sources(self):
165
di = self._gc_module.DeltaIndex()
166
di.add_source(_first_text, 0)
167
self.assertEqual(len(_first_text), di._source_offset)
168
di.add_source(_second_text, 0)
169
self.assertEqual(len(_first_text) + len(_second_text), di._source_offset)
170
delta = di.make_delta(_third_text)
171
result = self._gc_module.apply_delta(_first_text + _second_text, delta)
172
self.assertEqualDiff(_third_text, result)
173
self.assertEqual('\xac\x01\x85\x01\x90\x14\x0chas some in '
174
'\x91v6\x03and\x91d"\x91:\n', delta)
176
def test_delta_with_offsets(self):
177
di = self._gc_module.DeltaIndex()
178
di.add_source(_first_text, 5)
179
self.assertEqual(len(_first_text) + 5, di._source_offset)
180
di.add_source(_second_text, 10)
181
self.assertEqual(len(_first_text) + len(_second_text) + 15,
183
delta = di.make_delta(_third_text)
184
self.assertIsNot(None, delta)
185
result = self._gc_module.apply_delta(
186
'12345' + _first_text + '1234567890' + _second_text, delta)
187
self.assertIsNot(None, result)
188
self.assertEqualDiff(_third_text, result)
189
self.assertEqual('\xbb\x01\x85\x01\x91\x05\x14\x0chas some in '
190
'\x91\x856\x03and\x91s"\x91?\n', delta)
192
def test_delta_with_delta_bytes(self):
193
di = self._gc_module.DeltaIndex()
194
di.add_source(_first_text, 0)
195
self.assertEqual(len(_first_text), di._source_offset)
196
delta = di.make_delta(_second_text)
197
self.assertEqual('Dh\tsome more\x91\x019'
198
'&previous text\nand has some extra text\n', delta)
199
di.add_delta_source(delta, 0)
200
self.assertEqual(len(_first_text) + len(delta), di._source_offset)
201
third_delta = di.make_delta(_third_text)
202
result = self._gc_module.apply_delta(_first_text + delta, third_delta)
203
self.assertEqualDiff(_third_text, result)
204
# We should be able to match against the 'previous text\nand has some...'
205
# that was part of the delta bytes
206
# Note that we don't match the 'common with the', because it isn't long
207
# enough to match in the original text, and those bytes are not present
208
# in the delta for the second text.
209
self.assertEqual('z\x85\x01\x90\x14\x1chas some in common with the '
210
'\x91T&\x03and\x91\x18,', third_delta)