]> arthur.barton.de Git - bup.git/commitdiff
Add vint tests and signed vint support via write_vint and read_vint.
authorRob Browning <rlb@defaultvalue.org>
Wed, 22 Sep 2010 01:34:55 +0000 (20:34 -0500)
committerAvery Pennarun <apenwarr@gmail.com>
Wed, 22 Sep 2010 02:24:20 +0000 (19:24 -0700)
Signed-off-by: Rob Browning <rlb@defaultvalue.org>
lib/bup/t/tvint.py [new file with mode: 0644]
lib/bup/vint.py

diff --git a/lib/bup/t/tvint.py b/lib/bup/t/tvint.py
new file mode 100644 (file)
index 0000000..1be4c42
--- /dev/null
@@ -0,0 +1,85 @@
+from bup import vint
+from wvtest import *
+from cStringIO import StringIO
+
+
+def encode_and_decode_vuint(x):
+    f = StringIO()
+    vint.write_vuint(f, x)
+    return vint.read_vuint(StringIO(f.getvalue()))
+
+
+@wvtest
+def test_vuint():
+    for x in (0, 1, 42, 128, 10**16):
+        WVPASSEQ(encode_and_decode_vuint(x), x)
+    WVEXCEPT(Exception, vint.write_vuint, StringIO(), -1)
+    WVEXCEPT(EOFError, vint.read_vuint, StringIO())
+
+
+def encode_and_decode_vint(x):
+    f = StringIO()
+    vint.write_vint(f, x)
+    return vint.read_vint(StringIO(f.getvalue()))
+
+
+@wvtest
+def test_vint():
+    values = (0, 1, 42, 64, 10**16)
+    for x in values:
+        WVPASSEQ(encode_and_decode_vint(x), x)
+    for x in [-x for x in values]:
+        WVPASSEQ(encode_and_decode_vint(x), x)
+    WVEXCEPT(EOFError, vint.read_vint, StringIO())
+
+
+def encode_and_decode_bvec(x):
+    f = StringIO()
+    vint.write_bvec(f, x)
+    return vint.read_bvec(StringIO(f.getvalue()))
+
+
+@wvtest
+def test_bvec():
+    values = ('', 'x', 'foo', '\0', '\0foo', 'foo\0bar\0')
+    for x in values:
+        WVPASSEQ(encode_and_decode_bvec(x), x)
+    WVEXCEPT(EOFError, vint.read_bvec, StringIO())
+    outf = StringIO()
+    for x in ('foo', 'bar', 'baz', 'bax'):
+        vint.write_bvec(outf, x)
+    inf = StringIO(outf.getvalue())
+    WVPASSEQ(vint.read_bvec(inf), 'foo')
+    WVPASSEQ(vint.read_bvec(inf), 'bar')
+    vint.skip_bvec(inf)
+    WVPASSEQ(vint.read_bvec(inf), 'bax')
+
+
+def pack_and_unpack(types, *values):
+    data = vint.pack(types, *values)
+    return vint.unpack(types, data)
+
+
+@wvtest
+def test_pack_and_unpack():
+    tests = [('', []),
+             ('s', ['foo']),
+             ('ss', ['foo', 'bar']),
+             ('sV', ['foo', 0]),
+             ('sv', ['foo', -1]),
+             ('V', [0]),
+             ('Vs', [0, 'foo']),
+             ('VV', [0, 1]),
+             ('Vv', [0, -1]),
+             ('v', [0]),
+             ('vs', [0, 'foo']),
+             ('vV', [0, 1]),
+             ('vv', [0, -1])]
+    for test in tests:
+        (types, values) = test
+        WVPASSEQ(pack_and_unpack(types, *values), values)
+    WVEXCEPT(Exception, vint.pack, 's')
+    WVEXCEPT(Exception, vint.pack, 's', 'foo', 'bar')
+    WVEXCEPT(Exception, vint.pack, 'x', 1)
+    WVEXCEPT(Exception, vint.unpack, 's', '')
+    WVEXCEPT(Exception, vint.unpack, 'x', '')
index 31e2dfa24731d50bb0edd288d148b473d6de8b88..8f7f58a6698ddc22a3d9a3959190c323d03e69dd 100644 (file)
@@ -42,6 +42,55 @@ def read_vuint(port):
     return result
 
 
+def write_vint(port, x):
+    # Sign is handled with the second bit of the first byte.  All else
+    # matches vuint.
+    if x == 0:
+        port.write('\0')
+    else:
+        if x < 0:
+            x = -x
+            sign_and_six_bits = (x & 0x3f) | 0x40
+        else:
+            sign_and_six_bits = x & 0x3f
+        x >>= 6
+        if x:
+            port.write(chr(0x80 | sign_and_six_bits))
+            write_vuint(port, x)
+        else:
+            port.write(chr(sign_and_six_bits))
+
+
+def read_vint(port):
+    c = port.read(1)
+    if c == '':
+        raise EOFError('encountered EOF while reading vint');
+    negative = False
+    result = 0
+    offset = 0
+    # Handle first byte with sign bit specially.
+    if c:
+        b = ord(c)
+        if b & 0x40:
+            negative = True
+        result |= (b & 0x3f)
+        if b & 0x80:
+            offset += 6
+            c = port.read(1)
+        else:
+            return -result if negative else result
+    while c:
+        b = ord(c)
+        if b & 0x80:
+            result |= ((b & 0x7f) << offset)
+            offset += 7
+            c = port.read(1)
+        else:
+            result |= (b << offset)
+            break
+    return -result if negative else result
+
+
 def write_bvec(port, x):
     write_vuint(port, len(x))
     port.write(x)
@@ -63,6 +112,8 @@ def pack(types, *args):
     for (type, value) in zip(types, args):
         if type == 'V':
             write_vuint(port, value)
+        elif type == 'v':
+            write_vint(port, value)
         elif type == 's':
             write_bvec(port, value)
         else:
@@ -76,6 +127,8 @@ def unpack(types, data):
     for type in types:
         if type == 'V':
             result.append(read_vuint(port))
+        elif type == 'v':
+            result.append(read_vint(port))
         elif type == 's':
             result.append(read_bvec(port))
         else: