Merge pull request #743 from tahoe-lafs/3342-more-tests-for-base32-base62

Fixes https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3343
This commit is contained in:
Itamar Turner-Trauring 2020-07-14 13:41:20 -04:00 committed by GitHub
commit db41d5af6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 67 additions and 35 deletions

0
newsfragments/3343.other Normal file
View File

View File

@ -222,7 +222,7 @@ class ValidatedReadBucketProxy(log.PrefixingLogMixin):
UEB"""
precondition(share_hash_tree[0] is not None, share_hash_tree)
prefix = "%d-%s-%s" % (sharenum, bucket,
base32.b2a_l(share_hash_tree[0][:8], 60))
base32.b2a(share_hash_tree[0][:8])[:12])
log.PrefixingLogMixin.__init__(self,
facility="tahoe.immutable.download",
prefix=prefix)
@ -465,7 +465,7 @@ class Checker(log.PrefixingLogMixin):
monitor):
assert precondition(isinstance(verifycap, CHKFileVerifierURI), verifycap, type(verifycap))
prefix = "%s" % base32.b2a_l(verifycap.get_storage_index()[:8], 60)
prefix = "%s" % base32.b2a(verifycap.get_storage_index()[:8])[:12]
log.PrefixingLogMixin.__init__(self, facility="tahoe.immutable.checker", prefix=prefix)
self._verifycap = verifycap

View File

@ -43,7 +43,7 @@ class ShareFinder(object):
self.overdue_timers = {}
self._storage_index = verifycap.storage_index
self._si_prefix = base32.b2a_l(self._storage_index[:8], 60)
self._si_prefix = base32.b2a(self._storage_index[:8])[:12]
self._node_logparent = logparent
self._download_status = download_status
self._lp = log.msg(format="ShareFinder[si=%(si)s] starting",

View File

@ -44,7 +44,7 @@ class DownloadNode(object):
assert isinstance(verifycap, uri.CHKFileVerifierURI)
self._verifycap = verifycap
self._storage_broker = storage_broker
self._si_prefix = base32.b2a_l(verifycap.storage_index[:8], 60)
self._si_prefix = base32.b2a(verifycap.storage_index[:8])[:12]
self.running = True
if terminator:
terminator.register(self) # calls self.stop() at stopService()

View File

@ -298,7 +298,7 @@ class BucketReader(Referenceable):
def __repr__(self):
return "<%s %s %s>" % (self.__class__.__name__,
base32.b2a_l(self.storage_index[:8], 60),
base32.b2a(self.storage_index[:8])[:12],
self.shnum)
def remote_read(self, offset, length):

View File

@ -0,0 +1,37 @@
"""
Tests for allmydata.util.base32.
"""
import base64
from twisted.trial import unittest
from hypothesis import (
strategies as st,
given,
)
from allmydata.util import base32
class Base32(unittest.TestCase):
@given(input_bytes=st.binary(max_size=100))
def test_a2b_b2a_match_Pythons(self, input_bytes):
encoded = base32.b2a(input_bytes)
x = base64.b32encode(input_bytes).rstrip(b"=").lower()
self.failUnlessEqual(encoded, x)
self.assertIsInstance(encoded, bytes)
self.assertTrue(base32.could_be_base32_encoded(encoded))
self.assertEqual(base32.a2b(encoded), input_bytes)
def test_b2a(self):
self.failUnlessEqual(base32.b2a(b"\x12\x34"), b"ci2a")
def test_b2a_or_none(self):
self.failUnlessEqual(base32.b2a_or_none(None), None)
self.failUnlessEqual(base32.b2a_or_none(b"\x12\x34"), b"ci2a")
def test_a2b(self):
self.failUnlessEqual(base32.a2b(b"ci2a"), b"\x12\x34")
self.failUnlessRaises(AssertionError, base32.a2b, b"b0gus")
self.assertFalse(base32.could_be_base32_encoded(b"b0gus"))

View File

@ -1,9 +1,16 @@
import random, unittest
from past.builtins import chr as byteschr
from hypothesis import (
strategies as st,
given,
)
from allmydata.util import base62, mathutil
def insecurerandstr(n):
return ''.join(map(chr, map(random.randrange, [0]*n, [256]*n)))
return b''.join(map(byteschr, map(random.randrange, [0]*n, [256]*n)))
class T(unittest.TestCase):
def _test_num_octets_that_encode_to_this_many_chars(self, chars, octets):
@ -14,6 +21,10 @@ class T(unittest.TestCase):
bs2=base62.a2b(ascii)
assert bs2 == bs, "bs2: %s:%s, bs: %s:%s, ascii: %s:%s" % (len(bs2), repr(bs2), len(bs), repr(bs), len(ascii), repr(ascii))
@given(input_bytes=st.binary(max_size=100))
def test_roundtrip(self, input_bytes):
self._test_ende(input_bytes)
def test_num_octets_that_encode_to_this_many_chars(self):
return self._test_num_octets_that_encode_to_this_many_chars(2, 1)
return self._test_num_octets_that_encode_to_this_many_chars(3, 2)
@ -21,19 +32,19 @@ class T(unittest.TestCase):
return self._test_num_octets_that_encode_to_this_many_chars(6, 4)
def test_ende_0x00(self):
return self._test_ende('\x00')
return self._test_ende(b'\x00')
def test_ende_0x01(self):
return self._test_ende('\x01')
return self._test_ende(b'\x01')
def test_ende_0x0100(self):
return self._test_ende('\x01\x00')
return self._test_ende(b'\x01\x00')
def test_ende_0x000000(self):
return self._test_ende('\x00\x00\x00')
return self._test_ende(b'\x00\x00\x00')
def test_ende_0x010000(self):
return self._test_ende('\x01\x00\x00')
return self._test_ende(b'\x01\x00\x00')
def test_ende_randstr(self):
return self._test_ende(insecurerandstr(2**4))

View File

@ -36,25 +36,6 @@ def sha256(data):
return binascii.hexlify(hashlib.sha256(data).digest())
class Base32(unittest.TestCase):
def test_b2a_matches_Pythons(self):
import base64
y = "\x12\x34\x45\x67\x89\x0a\xbc\xde\xf0"
x = base64.b32encode(y)
while x and x[-1] == '=':
x = x[:-1]
x = x.lower()
self.failUnlessEqual(base32.b2a(y), x)
def test_b2a(self):
self.failUnlessEqual(base32.b2a("\x12\x34"), "ci2a")
def test_b2a_or_none(self):
self.failUnlessEqual(base32.b2a_or_none(None), None)
self.failUnlessEqual(base32.b2a_or_none("\x12\x34"), "ci2a")
def test_a2b(self):
self.failUnlessEqual(base32.a2b("ci2a"), "\x12\x34")
self.failUnlessRaises(AssertionError, base32.a2b, "b0gus")
class IDLib(unittest.TestCase):
def test_nodeid_b2a(self):
self.failUnlessEqual(idlib.nodeid_b2a("\x00"*20), "a"*32)

View File

@ -52,13 +52,13 @@ def b2a(os):
@return the contents of os in base-32 encoded form
"""
return b2a_l(os, len(os)*8)
return _b2a_l(os, len(os)*8)
def b2a_or_none(os):
if os is not None:
return b2a(os)
def b2a_l(os, lengthinbits):
def _b2a_l(os, lengthinbits):
"""
@param os the data to be encoded (a string)
@param lengthinbits the number of bits of data in os to be encoded
@ -204,9 +204,9 @@ def a2b(cs):
precondition(could_be_base32_encoded(cs), "cs is required to be possibly base32 encoded data.", cs=cs)
precondition(isinstance(cs, six.binary_type), cs)
return a2b_l(cs, num_octets_that_encode_to_this_many_quintets(len(cs))*8)
return _a2b_l(cs, num_octets_that_encode_to_this_many_quintets(len(cs))*8)
def a2b_l(cs, lengthinbits):
def _a2b_l(cs, lengthinbits):
"""
@param lengthinbits the number of bits of data in encoded into cs
@ -261,5 +261,8 @@ def a2b_l(cs, lengthinbits):
pos = pos * 256
assert len(octets) == numoctets, "len(octets): %s, numoctets: %s, octets: %s" % (len(octets), numoctets, octets,)
res = ''.join(map(chr, octets))
precondition(b2a_l(res, lengthinbits) == cs, "cs is required to be the canonical base-32 encoding of some data.", b2a(res), res=res, cs=cs)
precondition(_b2a_l(res, lengthinbits) == cs, "cs is required to be the canonical base-32 encoding of some data.", b2a(res), res=res, cs=cs)
return res
__all__ = ["b2a", "a2b", "b2a_or_none", "BASE32CHAR_3bits", "BASE32CHAR_1bits", "BASE32CHAR", "BASE32STR_anybytes", "could_be_base32_encoded"]