138
132
self.apply_delta_to_source = self._gc_module.apply_delta_to_source
140
134
def test_make_delta_is_typesafe(self):
141
self.make_delta(b'a string', b'another string')
135
self.make_delta('a string', 'another string')
143
137
def _check_make_delta(string1, string2):
144
138
self.assertRaises(TypeError, self.make_delta, string1, string2)
146
_check_make_delta(b'a string', object())
147
_check_make_delta(b'a string', u'not a string')
148
_check_make_delta(object(), b'a string')
149
_check_make_delta(u'not a string', b'a string')
140
_check_make_delta('a string', object())
141
_check_make_delta('a string', u'not a string')
142
_check_make_delta(object(), 'a string')
143
_check_make_delta(u'not a string', 'a string')
151
145
def test_make_noop_delta(self):
152
146
ident_delta = self.make_delta(_text1, _text1)
153
self.assertEqual(b'M\x90M', ident_delta)
147
self.assertEqual('M\x90M', ident_delta)
154
148
ident_delta = self.make_delta(_text2, _text2)
155
self.assertEqual(b'N\x90N', ident_delta)
149
self.assertEqual('N\x90N', ident_delta)
156
150
ident_delta = self.make_delta(_text3, _text3)
157
self.assertEqual(b'\x87\x01\x90\x87', ident_delta)
151
self.assertEqual('\x87\x01\x90\x87', ident_delta)
159
153
def assertDeltaIn(self, delta1, delta2, delta):
160
154
"""Make sure that the delta bytes match one of the expectations."""
161
155
# In general, the python delta matcher gives different results than the
162
156
# pyrex delta matcher. Both should be valid deltas, though.
163
157
if delta not in (delta1, delta2):
164
self.fail(b"Delta bytes:\n"
158
self.fail("Delta bytes:\n"
168
162
% (delta, delta1, delta2))
170
164
def test_make_delta(self):
171
165
delta = self.make_delta(_text1, _text2)
172
166
self.assertDeltaIn(
173
b'N\x90/\x1fdiffer from\nagainst other text\n',
174
b'N\x90\x1d\x1ewhich is meant to differ from\n\x91:\x13',
167
'N\x90/\x1fdiffer from\nagainst other text\n',
168
'N\x90\x1d\x1ewhich is meant to differ from\n\x91:\x13',
176
170
delta = self.make_delta(_text2, _text1)
177
171
self.assertDeltaIn(
178
b'M\x90/\x1ebe matched\nagainst other text\n',
179
b'M\x90\x1d\x1dwhich is meant to be matched\n\x91;\x13',
172
'M\x90/\x1ebe matched\nagainst other text\n',
173
'M\x90\x1d\x1dwhich is meant to be matched\n\x91;\x13',
181
175
delta = self.make_delta(_text3, _text1)
182
self.assertEqual(b'M\x90M', delta)
176
self.assertEqual('M\x90M', delta)
183
177
delta = self.make_delta(_text3, _text2)
184
178
self.assertDeltaIn(
185
b'N\x90/\x1fdiffer from\nagainst other text\n',
186
b'N\x90\x1d\x1ewhich is meant to differ from\n\x91:\x13',
179
'N\x90/\x1fdiffer from\nagainst other text\n',
180
'N\x90\x1d\x1ewhich is meant to differ from\n\x91:\x13',
189
183
def test_make_delta_with_large_copies(self):
457
451
class TestCopyInstruction(tests.TestCase):
459
453
def assertEncode(self, expected, offset, length):
460
data = _groupcompress_py.encode_copy_instruction(offset, length)
461
self.assertEqual(expected, data)
454
bytes = _groupcompress_py.encode_copy_instruction(offset, length)
455
if expected != bytes:
456
self.assertEqual([hex(ord(e)) for e in expected],
457
[hex(ord(b)) for b in bytes])
463
def assertDecode(self, exp_offset, exp_length, exp_newpos, data, pos):
464
cmd = indexbytes(data, pos)
459
def assertDecode(self, exp_offset, exp_length, exp_newpos, bytes, pos):
460
cmd = ord(bytes[pos])
466
out = _groupcompress_py.decode_copy_instruction(data, cmd, pos)
462
out = _groupcompress_py.decode_copy_instruction(bytes, cmd, pos)
467
463
self.assertEqual((exp_offset, exp_length, exp_newpos), out)
469
465
def test_encode_no_length(self):
470
self.assertEncode(b'\x80', 0, 64*1024)
471
self.assertEncode(b'\x81\x01', 1, 64*1024)
472
self.assertEncode(b'\x81\x0a', 10, 64*1024)
473
self.assertEncode(b'\x81\xff', 255, 64*1024)
474
self.assertEncode(b'\x82\x01', 256, 64*1024)
475
self.assertEncode(b'\x83\x01\x01', 257, 64*1024)
476
self.assertEncode(b'\x8F\xff\xff\xff\xff', 0xFFFFFFFF, 64*1024)
477
self.assertEncode(b'\x8E\xff\xff\xff', 0xFFFFFF00, 64*1024)
478
self.assertEncode(b'\x8D\xff\xff\xff', 0xFFFF00FF, 64*1024)
479
self.assertEncode(b'\x8B\xff\xff\xff', 0xFF00FFFF, 64*1024)
480
self.assertEncode(b'\x87\xff\xff\xff', 0x00FFFFFF, 64*1024)
481
self.assertEncode(b'\x8F\x04\x03\x02\x01', 0x01020304, 64*1024)
466
self.assertEncode('\x80', 0, 64*1024)
467
self.assertEncode('\x81\x01', 1, 64*1024)
468
self.assertEncode('\x81\x0a', 10, 64*1024)
469
self.assertEncode('\x81\xff', 255, 64*1024)
470
self.assertEncode('\x82\x01', 256, 64*1024)
471
self.assertEncode('\x83\x01\x01', 257, 64*1024)
472
self.assertEncode('\x8F\xff\xff\xff\xff', 0xFFFFFFFF, 64*1024)
473
self.assertEncode('\x8E\xff\xff\xff', 0xFFFFFF00, 64*1024)
474
self.assertEncode('\x8D\xff\xff\xff', 0xFFFF00FF, 64*1024)
475
self.assertEncode('\x8B\xff\xff\xff', 0xFF00FFFF, 64*1024)
476
self.assertEncode('\x87\xff\xff\xff', 0x00FFFFFF, 64*1024)
477
self.assertEncode('\x8F\x04\x03\x02\x01', 0x01020304, 64*1024)
483
479
def test_encode_no_offset(self):
484
self.assertEncode(b'\x90\x01', 0, 1)
485
self.assertEncode(b'\x90\x0a', 0, 10)
486
self.assertEncode(b'\x90\xff', 0, 255)
487
self.assertEncode(b'\xA0\x01', 0, 256)
488
self.assertEncode(b'\xB0\x01\x01', 0, 257)
489
self.assertEncode(b'\xB0\xff\xff', 0, 0xFFFF)
480
self.assertEncode('\x90\x01', 0, 1)
481
self.assertEncode('\x90\x0a', 0, 10)
482
self.assertEncode('\x90\xff', 0, 255)
483
self.assertEncode('\xA0\x01', 0, 256)
484
self.assertEncode('\xB0\x01\x01', 0, 257)
485
self.assertEncode('\xB0\xff\xff', 0, 0xFFFF)
490
486
# Special case, if copy == 64KiB, then we store exactly 0
491
487
# Note that this puns with a copy of exactly 0 bytes, but we don't care
492
488
# about that, as we would never actually copy 0 bytes
493
self.assertEncode(b'\x80', 0, 64*1024)
489
self.assertEncode('\x80', 0, 64*1024)
495
491
def test_encode(self):
496
self.assertEncode(b'\x91\x01\x01', 1, 1)
497
self.assertEncode(b'\x91\x09\x0a', 9, 10)
498
self.assertEncode(b'\x91\xfe\xff', 254, 255)
499
self.assertEncode(b'\xA2\x02\x01', 512, 256)
500
self.assertEncode(b'\xB3\x02\x01\x01\x01', 258, 257)
501
self.assertEncode(b'\xB0\x01\x01', 0, 257)
492
self.assertEncode('\x91\x01\x01', 1, 1)
493
self.assertEncode('\x91\x09\x0a', 9, 10)
494
self.assertEncode('\x91\xfe\xff', 254, 255)
495
self.assertEncode('\xA2\x02\x01', 512, 256)
496
self.assertEncode('\xB3\x02\x01\x01\x01', 258, 257)
497
self.assertEncode('\xB0\x01\x01', 0, 257)
502
498
# Special case, if copy == 64KiB, then we store exactly 0
503
499
# Note that this puns with a copy of exactly 0 bytes, but we don't care
504
500
# about that, as we would never actually copy 0 bytes
505
self.assertEncode(b'\x81\x0a', 10, 64*1024)
501
self.assertEncode('\x81\x0a', 10, 64*1024)
507
503
def test_decode_no_length(self):
508
504
# If length is 0, it is interpreted as 64KiB
509
505
# The shortest possible instruction is a copy of 64KiB from offset 0
510
self.assertDecode(0, 65536, 1, b'\x80', 0)
511
self.assertDecode(1, 65536, 2, b'\x81\x01', 0)
512
self.assertDecode(10, 65536, 2, b'\x81\x0a', 0)
513
self.assertDecode(255, 65536, 2, b'\x81\xff', 0)
514
self.assertDecode(256, 65536, 2, b'\x82\x01', 0)
515
self.assertDecode(257, 65536, 3, b'\x83\x01\x01', 0)
516
self.assertDecode(0xFFFFFFFF, 65536, 5, b'\x8F\xff\xff\xff\xff', 0)
517
self.assertDecode(0xFFFFFF00, 65536, 4, b'\x8E\xff\xff\xff', 0)
518
self.assertDecode(0xFFFF00FF, 65536, 4, b'\x8D\xff\xff\xff', 0)
519
self.assertDecode(0xFF00FFFF, 65536, 4, b'\x8B\xff\xff\xff', 0)
520
self.assertDecode(0x00FFFFFF, 65536, 4, b'\x87\xff\xff\xff', 0)
521
self.assertDecode(0x01020304, 65536, 5, b'\x8F\x04\x03\x02\x01', 0)
506
self.assertDecode(0, 65536, 1, '\x80', 0)
507
self.assertDecode(1, 65536, 2, '\x81\x01', 0)
508
self.assertDecode(10, 65536, 2, '\x81\x0a', 0)
509
self.assertDecode(255, 65536, 2, '\x81\xff', 0)
510
self.assertDecode(256, 65536, 2, '\x82\x01', 0)
511
self.assertDecode(257, 65536, 3, '\x83\x01\x01', 0)
512
self.assertDecode(0xFFFFFFFF, 65536, 5, '\x8F\xff\xff\xff\xff', 0)
513
self.assertDecode(0xFFFFFF00, 65536, 4, '\x8E\xff\xff\xff', 0)
514
self.assertDecode(0xFFFF00FF, 65536, 4, '\x8D\xff\xff\xff', 0)
515
self.assertDecode(0xFF00FFFF, 65536, 4, '\x8B\xff\xff\xff', 0)
516
self.assertDecode(0x00FFFFFF, 65536, 4, '\x87\xff\xff\xff', 0)
517
self.assertDecode(0x01020304, 65536, 5, '\x8F\x04\x03\x02\x01', 0)
523
519
def test_decode_no_offset(self):
524
self.assertDecode(0, 1, 2, b'\x90\x01', 0)
525
self.assertDecode(0, 10, 2, b'\x90\x0a', 0)
526
self.assertDecode(0, 255, 2, b'\x90\xff', 0)
527
self.assertDecode(0, 256, 2, b'\xA0\x01', 0)
528
self.assertDecode(0, 257, 3, b'\xB0\x01\x01', 0)
529
self.assertDecode(0, 65535, 3, b'\xB0\xff\xff', 0)
520
self.assertDecode(0, 1, 2, '\x90\x01', 0)
521
self.assertDecode(0, 10, 2, '\x90\x0a', 0)
522
self.assertDecode(0, 255, 2, '\x90\xff', 0)
523
self.assertDecode(0, 256, 2, '\xA0\x01', 0)
524
self.assertDecode(0, 257, 3, '\xB0\x01\x01', 0)
525
self.assertDecode(0, 65535, 3, '\xB0\xff\xff', 0)
530
526
# Special case, if copy == 64KiB, then we store exactly 0
531
527
# Note that this puns with a copy of exactly 0 bytes, but we don't care
532
528
# about that, as we would never actually copy 0 bytes
533
self.assertDecode(0, 65536, 1, b'\x80', 0)
529
self.assertDecode(0, 65536, 1, '\x80', 0)
535
531
def test_decode(self):
536
self.assertDecode(1, 1, 3, b'\x91\x01\x01', 0)
537
self.assertDecode(9, 10, 3, b'\x91\x09\x0a', 0)
538
self.assertDecode(254, 255, 3, b'\x91\xfe\xff', 0)
539
self.assertDecode(512, 256, 3, b'\xA2\x02\x01', 0)
540
self.assertDecode(258, 257, 5, b'\xB3\x02\x01\x01\x01', 0)
541
self.assertDecode(0, 257, 3, b'\xB0\x01\x01', 0)
532
self.assertDecode(1, 1, 3, '\x91\x01\x01', 0)
533
self.assertDecode(9, 10, 3, '\x91\x09\x0a', 0)
534
self.assertDecode(254, 255, 3, '\x91\xfe\xff', 0)
535
self.assertDecode(512, 256, 3, '\xA2\x02\x01', 0)
536
self.assertDecode(258, 257, 5, '\xB3\x02\x01\x01\x01', 0)
537
self.assertDecode(0, 257, 3, '\xB0\x01\x01', 0)
543
539
def test_decode_not_start(self):
544
self.assertDecode(1, 1, 6, b'abc\x91\x01\x01def', 3)
545
self.assertDecode(9, 10, 5, b'ab\x91\x09\x0ade', 2)
546
self.assertDecode(254, 255, 6, b'not\x91\xfe\xffcopy', 3)
540
self.assertDecode(1, 1, 6, 'abc\x91\x01\x01def', 3)
541
self.assertDecode(9, 10, 5, 'ab\x91\x09\x0ade', 2)
542
self.assertDecode(254, 255, 6, 'not\x91\xfe\xffcopy', 3)
549
545
class TestBase128Int(tests.TestCase):
560
556
self._gc_module.decode_base128_int(bytes))
562
558
def test_encode(self):
563
self.assertEqualEncode(b'\x01', 1)
564
self.assertEqualEncode(b'\x02', 2)
565
self.assertEqualEncode(b'\x7f', 127)
566
self.assertEqualEncode(b'\x80\x01', 128)
567
self.assertEqualEncode(b'\xff\x01', 255)
568
self.assertEqualEncode(b'\x80\x02', 256)
569
self.assertEqualEncode(b'\xff\xff\xff\xff\x0f', 0xFFFFFFFF)
559
self.assertEqualEncode('\x01', 1)
560
self.assertEqualEncode('\x02', 2)
561
self.assertEqualEncode('\x7f', 127)
562
self.assertEqualEncode('\x80\x01', 128)
563
self.assertEqualEncode('\xff\x01', 255)
564
self.assertEqualEncode('\x80\x02', 256)
565
self.assertEqualEncode('\xff\xff\xff\xff\x0f', 0xFFFFFFFF)
571
567
def test_decode(self):
572
self.assertEqualDecode(1, 1, b'\x01')
573
self.assertEqualDecode(2, 1, b'\x02')
574
self.assertEqualDecode(127, 1, b'\x7f')
575
self.assertEqualDecode(128, 2, b'\x80\x01')
576
self.assertEqualDecode(255, 2, b'\xff\x01')
577
self.assertEqualDecode(256, 2, b'\x80\x02')
578
self.assertEqualDecode(0xFFFFFFFF, 5, b'\xff\xff\xff\xff\x0f')
568
self.assertEqualDecode(1, 1, '\x01')
569
self.assertEqualDecode(2, 1, '\x02')
570
self.assertEqualDecode(127, 1, '\x7f')
571
self.assertEqualDecode(128, 2, '\x80\x01')
572
self.assertEqualDecode(255, 2, '\xff\x01')
573
self.assertEqualDecode(256, 2, '\x80\x02')
574
self.assertEqualDecode(0xFFFFFFFF, 5, '\xff\xff\xff\xff\x0f')
580
576
def test_decode_with_trailing_bytes(self):
581
self.assertEqualDecode(1, 1, b'\x01abcdef')
582
self.assertEqualDecode(127, 1, b'\x7f\x01')
583
self.assertEqualDecode(128, 2, b'\x80\x01abcdef')
584
self.assertEqualDecode(255, 2, b'\xff\x01\xff')
577
self.assertEqualDecode(1, 1, '\x01abcdef')
578
self.assertEqualDecode(127, 1, '\x7f\x01')
579
self.assertEqualDecode(128, 2, '\x80\x01abcdef')
580
self.assertEqualDecode(255, 2, '\xff\x01\xff')