"""Test the binascii C module.""" import unittest import binascii import array import re import sys from test.support import bigmemtest, _1G, _4G, check_impl_detail from test.support.hypothesis_helper import hypothesis # Note: "*_hex" functions are aliases for "(un)hexlify" b2a_functions = ['b2a_ascii85', 'b2a_base32', 'b2a_base64', 'b2a_base85', 'b2a_hex', 'b2a_qp', 'b2a_uu', 'hexlify'] a2b_functions = ['a2b_ascii85', 'a2b_base32', 'a2b_base64', 'a2b_base85', 'a2b_hex', 'a2b_qp', 'a2b_uu', 'unhexlify'] all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx'] class BinASCIITest(unittest.TestCase): type2test = bytes # Create binary test data rawdata = b"The quick brown fox jumps over the lazy dog.\r\n" # Be slow so we don't depend on other modules rawdata += bytes(range(256)) rawdata += b'\0'*32 rawdata += b' '*32 rawdata += b"\r\nHello world.\n" def setUp(self): self.data = self.type2test(self.rawdata) def assertConversion(self, original, converted, restored, **kwargs): self.assertIsInstance(original, bytes) self.assertIsInstance(converted, bytes) self.assertIsInstance(restored, bytes) if converted: self.assertLess(max(converted), 128) self.assertEqual(original, restored, msg=f'{self.type2test=} {kwargs=}') def test_exceptions(self): # Check module exceptions self.assertIsSubclass(binascii.Error, Exception) self.assertIsSubclass(binascii.Incomplete, Exception) def test_constants(self): self.assertEqual(binascii.BASE64_ALPHABET, b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' b'abcdefghijklmnopqrstuvwxyz' b'0123456789+/') self.assertEqual(binascii.URLSAFE_BASE64_ALPHABET, binascii.BASE64_ALPHABET[:-2] + b'-_') self.assertEqual(binascii.UU_ALPHABET, bytes(range(32, 32+64))) self.assertEqual(binascii.CRYPT_ALPHABET, b'./0123456789' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' b'abcdefghijklmnopqrstuvwxyz') self.assertEqual(binascii.BINHEX_ALPHABET, b'!"#$%&\'()*+,-012345689' b'@ABCDEFGHIJKLMNPQRSTUVXYZ[' b'`abcdefhijklmpqr') self.assertEqual(binascii.BASE85_ALPHABET, b'0123456789' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' b'abcdefghijklmnopqrstuvwxyz' b'!#$%&()*+-;<=>?@^_`{|}~') self.assertEqual(binascii.ASCII85_ALPHABET, bytes(range(33, 33+85))) self.assertEqual(binascii.Z85_ALPHABET, b'0123456789' b'abcdefghijklmnopqrstuvwxyz' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' b'.-:+=^!/*?&<>()[]{}@%$#') self.assertEqual(binascii.BASE32_ALPHABET, b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') self.assertEqual(binascii.BASE32HEX_ALPHABET, b'0123456789ABCDEFGHIJKLMNOPQRSTUV') def test_functions(self): # Check presence of all functions for name in all_functions: self.assertHasAttr(getattr(binascii, name), '__call__') self.assertRaises(TypeError, getattr(binascii, name)) def test_returned_value(self): # Limit to the minimum of all limits (b2a_uu) MAX_ALL = 45 raw = self.rawdata[:MAX_ALL] for fa, fb in zip(a2b_functions, b2a_functions): a2b = getattr(binascii, fa) b2a = getattr(binascii, fb) try: a = b2a(self.type2test(raw)) res = a2b(self.type2test(a)) except Exception as err: self.fail("{}/{} conversion raises {!r}".format(fb, fa, err)) self.assertEqual(res, raw, "{}/{} conversion: " "{!r} != {!r}".format(fb, fa, res, raw)) self.assertConversion(raw, a, res) self.assertIsInstance(binascii.crc_hqx(raw, 0), int) self.assertIsInstance(binascii.crc32(raw), int) def test_base64valid(self): # Test base64 with valid data MAX_BASE64 = 57 lines = [] for i in range(0, len(self.rawdata), MAX_BASE64): b = self.type2test(self.rawdata[i:i+MAX_BASE64]) a = binascii.b2a_base64(b) lines.append(a) res = bytes() for line in lines: a = self.type2test(line) b = binascii.a2b_base64(a) res += b self.assertEqual(res, self.rawdata) def test_base64invalid(self): # Test base64 with random invalid characters sprinkled throughout # (This requires a new version of binascii.) MAX_BASE64 = 57 lines = [] for i in range(0, len(self.data), MAX_BASE64): b = self.type2test(self.rawdata[i:i+MAX_BASE64]) a = binascii.b2a_base64(b) lines.append(a) fillers = bytearray() valid = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" for i in range(256): if i not in valid: fillers.append(i) def addnoise(line): noise = fillers ratio = len(line) // len(noise) res = bytearray() while line and noise: if len(line) // len(noise) > ratio: c, line = line[0], line[1:] else: c, noise = noise[0], noise[1:] res.append(c) return res + noise + line res = bytearray() for line in map(addnoise, lines): a = self.type2test(line) b = binascii.a2b_base64(a) res += b self.assertEqual(res, self.rawdata) # Test base64 with just invalid characters, which should return # empty strings. TBD: shouldn't it raise an exception instead ? self.assertEqual(binascii.a2b_base64(self.type2test(fillers)), b'') def test_base64_bad_padding(self): # Test malformed padding def _assertRegexTemplate(assert_regex, data, non_strict_mode_expected_result): data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base64(data, strict_mode=True) self.assertEqual(binascii.a2b_base64(data, strict_mode=False), non_strict_mode_expected_result) self.assertEqual(binascii.a2b_base64(data, strict_mode=True, ignorechars=b'='), non_strict_mode_expected_result) self.assertEqual(binascii.a2b_base64(data), non_strict_mode_expected_result) def assertLeadingPadding(*args): _assertRegexTemplate(r'(?i)Leading padding', *args) def assertDiscontinuousPadding(*args): _assertRegexTemplate(r'(?i)Discontinuous padding', *args) def assertExcessPadding(*args): _assertRegexTemplate(r'(?i)Excess padding', *args) def assertInvalidLength(*args): _assertRegexTemplate(r'(?i)Invalid.+number of data characters', *args) assertExcessPadding(b'ab===', b'i') assertExcessPadding(b'ab====', b'i') assertExcessPadding(b'abc==', b'i\xb7') assertExcessPadding(b'abc===', b'i\xb7') assertExcessPadding(b'abc====', b'i\xb7') assertExcessPadding(b'abc=====', b'i\xb7') assertLeadingPadding(b'=', b'') assertLeadingPadding(b'==', b'') assertLeadingPadding(b'===', b'') assertLeadingPadding(b'====', b'') assertLeadingPadding(b'=====', b'') assertLeadingPadding(b'=abcd', b'i\xb7\x1d') assertLeadingPadding(b'==abcd', b'i\xb7\x1d') assertLeadingPadding(b'===abcd', b'i\xb7\x1d') assertLeadingPadding(b'====abcd', b'i\xb7\x1d') assertLeadingPadding(b'=====abcd', b'i\xb7\x1d') assertInvalidLength(b'a=b==', b'i') assertInvalidLength(b'a=bc=', b'i\xb7') assertInvalidLength(b'a=bc==', b'i\xb7') assertInvalidLength(b'a=bcd', b'i\xb7\x1d') assertInvalidLength(b'a=bcd=', b'i\xb7\x1d') assertDiscontinuousPadding(b'ab=c=', b'i\xb7') assertDiscontinuousPadding(b'ab=cd', b'i\xb7\x1d') assertDiscontinuousPadding(b'ab=cd==', b'i\xb7\x1d') assertExcessPadding(b'abcd=', b'i\xb7\x1d') assertExcessPadding(b'abcd==', b'i\xb7\x1d') assertExcessPadding(b'abcd===', b'i\xb7\x1d') assertExcessPadding(b'abcd====', b'i\xb7\x1d') assertExcessPadding(b'abcd=====', b'i\xb7\x1d') assertExcessPadding(b'abcd==', b'i\xb7\x1d') assertExcessPadding(b'abcd===', b'i\xb7\x1d') assertExcessPadding(b'abcd====', b'i\xb7\x1d') assertExcessPadding(b'abcd=====', b'i\xb7\x1d') assertExcessPadding(b'abcd=efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd==efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd===efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd====efgh', b'i\xb7\x1dy\xf8!') assertExcessPadding(b'abcd=====efgh', b'i\xb7\x1dy\xf8!') def test_base64_invalidchars(self): # Test non-base64 data exceptions def assertNonBase64Data(data, expected, ignorechars): data = self.type2test(data) assert_regex = r'(?i)Only base64 data' self.assertEqual(binascii.a2b_base64(data), expected) with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base64(data, strict_mode=True) with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base64(data, ignorechars=b'') self.assertEqual(binascii.a2b_base64(data, ignorechars=ignorechars), expected) self.assertEqual(binascii.a2b_base64(data, strict_mode=False, ignorechars=b''), expected) assertNonBase64Data(b'\nab==', b'i', ignorechars=b'\n') assertNonBase64Data(b'ab:(){:|:&};:==', b'i', ignorechars=b':;(){}|&') assertNonBase64Data(b'a\nb==', b'i', ignorechars=b'\n') assertNonBase64Data(b'a\x00b==', b'i', ignorechars=b'\x00') assertNonBase64Data(b'ab:==', b'i', ignorechars=b':') assertNonBase64Data(b'ab=:=', b'i', ignorechars=b':') assertNonBase64Data(b'ab==:', b'i', ignorechars=b':') assertNonBase64Data(b'abc=:', b'i\xb7', ignorechars=b':') assertNonBase64Data(b'ab==\n', b'i', ignorechars=b'\n') assertNonBase64Data(b'a\nb==', b'i', ignorechars=bytearray(b'\n')) assertNonBase64Data(b'a\nb==', b'i', ignorechars=memoryview(b'\n')) # Same cell in the cache: '\r' >> 3 == '\n' >> 3. data = self.type2test(b'\r\n') with self.assertRaises(binascii.Error): binascii.a2b_base64(data, ignorechars=b'\r') self.assertEqual(binascii.a2b_base64(data, ignorechars=b'\r\n'), b'') # Same bit mask in the cache: '*' & 31 == '\n' & 31. data = self.type2test(b'*\n') with self.assertRaises(binascii.Error): binascii.a2b_base64(data, ignorechars=b'*') self.assertEqual(binascii.a2b_base64(data, ignorechars=b'*\n'), b'') data = self.type2test(b'a\nb==') with self.assertRaises(TypeError): binascii.a2b_base64(data, ignorechars='') with self.assertRaises(TypeError): binascii.a2b_base64(data, ignorechars=[]) with self.assertRaises(TypeError): binascii.a2b_base64(data, ignorechars=None) def test_base64_excess_data(self): # Test excess data exceptions def assertExcessData(data, expected): assert_regex = r'(?i)Excess data' data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base64(data, strict_mode=True) self.assertEqual(binascii.a2b_base64(data, strict_mode=False), expected) self.assertEqual(binascii.a2b_base64(data, strict_mode=True, ignorechars=b'='), expected) self.assertEqual(binascii.a2b_base64(data), expected) assertExcessData(b'ab==c=', b'i\xb7') assertExcessData(b'ab==cd', b'i\xb7\x1d') assertExcessData(b'abc=d', b'i\xb7\x1d') def test_base64errors(self): # Test base64 with invalid padding def assertIncorrectPadding(data, strict_mode=True): data = self.type2test(data) with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): binascii.a2b_base64(data) with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): binascii.a2b_base64(data, strict_mode=False) if strict_mode: with self.assertRaisesRegex(binascii.Error, r'(?i)Incorrect padding'): binascii.a2b_base64(data, strict_mode=True) assertIncorrectPadding(b'ab') assertIncorrectPadding(b'ab=') assertIncorrectPadding(b'abc') assertIncorrectPadding(b'abcdef') assertIncorrectPadding(b'abcdef=') assertIncorrectPadding(b'abcdefg') assertIncorrectPadding(b'a=b=', strict_mode=False) assertIncorrectPadding(b'a\nb=', strict_mode=False) # Test base64 with invalid number of valid characters (1 mod 4) def assertInvalidLength(data, strict_mode=True): n_data_chars = len(re.sub(br'[^A-Za-z0-9/+]', br'', data)) data = self.type2test(data) expected_errmsg_re = \ r'(?i)Invalid.+number of data characters.+' + str(n_data_chars) with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): binascii.a2b_base64(data) with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): binascii.a2b_base64(data, strict_mode=False) if strict_mode: with self.assertRaisesRegex(binascii.Error, expected_errmsg_re): binascii.a2b_base64(data, strict_mode=True) assertInvalidLength(b'a') assertInvalidLength(b'a=') assertInvalidLength(b'a==') assertInvalidLength(b'a===') assertInvalidLength(b'a' * 5) assertInvalidLength(b'a' * (4 * 87 + 1)) assertInvalidLength(b'A\tB\nC ??DE', # only 5 valid characters strict_mode=False) def test_base64_alphabet(self): alphabet = (b'!"#$%&\'()*+,-012345689@' b'ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr') data = self.type2test(self.rawdata) encoded = binascii.b2a_base64(data, alphabet=alphabet) trans = bytes.maketrans(binascii.BASE64_ALPHABET, alphabet) expected = binascii.b2a_base64(data).translate(trans) self.assertEqual(encoded, expected) self.assertEqual(binascii.a2b_base64(encoded, alphabet=alphabet), self.rawdata) self.assertEqual(binascii.b2a_base64(data, alphabet=self.type2test(alphabet)), expected) data = self.type2test(b'') self.assertEqual(binascii.b2a_base64(data, alphabet=alphabet), b'\n') self.assertEqual(binascii.a2b_base64(data, alphabet=alphabet), b'') for func in binascii.b2a_base64, binascii.a2b_base64: with self.assertRaises(TypeError): func(data, alphabet=None) with self.assertRaises(TypeError): func(data, alphabet=alphabet.decode()) with self.assertRaises(ValueError): func(data, alphabet=alphabet[:-1]) with self.assertRaises(ValueError): func(data, alphabet=alphabet+b'?') with self.assertRaises(TypeError): binascii.a2b_base64(data, alphabet=bytearray(alphabet)) def test_ascii85_valid(self): # Test Ascii85 with valid data ASCII85_PREFIX = b"<~" ASCII85_SUFFIX = b"~>" # Interleave blocks of 4 null bytes and 4 spaces into test data rawdata = bytearray() rawlines, i = [], 0 for k in range(1, len(self.rawdata) + 1): b = b"\0\0\0\0" if k & 1 else b" " b = b + self.rawdata[i:i + k] b = b" " if k & 1 else b"\0\0\0\0" rawdata += b rawlines.append(b) i += k if i >= len(self.rawdata): break # Test core parameter combinations params = (False, False), (False, True), (True, False), (True, True) for foldspaces, adobe in params: lines = [] for rawline in rawlines: b = self.type2test(rawline) a = binascii.b2a_ascii85(b, foldspaces=foldspaces, adobe=adobe) lines.append(a) res = bytearray() for line in lines: a = self.type2test(line) b = binascii.a2b_ascii85(a, foldspaces=foldspaces, adobe=adobe) res += b self.assertEqual(res, rawdata) # Test decoding inputs with length 1 mod 5 params = [ (b"a", False, False, b"", b""), (b"xbw", False, False, b"wx", b""), (b"<~c~>", False, True, b"", b""), (b"{d ~>", False, True, b" {", b""), (b"ye", True, False, b"", b" "), (b"z\x01y\x00f", True, False, b"\x00\x01", b"\x00\x00\x00\x00 "), (b"<~FCfN8yg~>", True, True, b"", b"test "), (b"FE;\x03#8zFCf\x02N8yh~>", True, True, b"\x02\x03", b"tset\x00\x00\x00\x00test "), ] for a, foldspaces, adobe, ignorechars, b in params: kwargs = {"foldspaces": foldspaces, "adobe": adobe, "ignorechars": ignorechars} self.assertEqual(binascii.a2b_ascii85(self.type2test(a), **kwargs), b) def test_ascii85_invalid(self): # Test Ascii85 with invalid characters interleaved lines, i = [], 0 for k in range(1, len(self.rawdata) + 1): b = self.type2test(self.rawdata[i:i + k]) a = binascii.b2a_ascii85(b) lines.append(a) i += k if i >= len(self.rawdata): break fillers = bytearray() valid = b"!\"#$%&'()*+,-./0123456789:;<=>?@" \ b"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu" + b"z" for i in range(256): if i not in valid: fillers.append(i) def addnoise(line): res = bytearray() for i in range(len(line)): res.append(line[i]) for j in range(i, len(fillers), len(line)): res.append(fillers[j]) return res res = bytearray() for line in map(addnoise, lines): a = self.type2test(line) b = binascii.a2b_ascii85(a, ignorechars=fillers) res += b self.assertEqual(res, self.rawdata) # Test Ascii85 with only invalid characters fillers = self.type2test(fillers) b = binascii.a2b_ascii85(fillers, ignorechars=fillers) self.assertEqual(b, b"") def test_ascii85_errors(self): def _assertRegexTemplate(assert_regex, data, **kwargs): with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_ascii85(self.type2test(data), **kwargs) def assertMissingDelimiter(data): _assertRegexTemplate(r"(?i)end with b'~>'", data, adobe=True) def assertOverflow(data): _assertRegexTemplate(r"(?i)Ascii85 overflow", data) def assertInvalidSpecial(data): _assertRegexTemplate(r"(?i)'[yz]'.+5-tuple", data, foldspaces=True) def assertInvalidChar(data, **kwargs): _assertRegexTemplate(r"(?i)Non-Ascii85 digit", data, **kwargs) # Test Ascii85 with missing delimiters assertMissingDelimiter(b"") assertMissingDelimiter(b"a") assertMissingDelimiter(b"<~") assertMissingDelimiter(b"<~!~") assertMissingDelimiter(b"<~abc>") assertMissingDelimiter(b"<~has delimiter but not terminal~> !") # Test Ascii85 with out-of-range encoded value assertOverflow(b"t") assertOverflow(b"s9") assertOverflow(b"s8X") assertOverflow(b"s8W.") assertOverflow(b's8W-"') assertOverflow(b"s8W-!u") assertOverflow(b"s8W-!s8W-!zs8X") # Test Ascii85 with misplaced short form groups assertInvalidSpecial(b"ay") assertInvalidSpecial(b"az") assertInvalidSpecial(b"aby") assertInvalidSpecial(b"ayz") assertInvalidSpecial(b"abcz") assertInvalidSpecial(b"abcdy") assertInvalidSpecial(b"y!and!z!then!!y") # Test Ascii85 with non-ignored invalid characters assertInvalidChar(b"j\n") assertInvalidChar(b" ", ignorechars=b"") assertInvalidChar(b" valid\x02until\x03", ignorechars=b"\x00\x01\x02\x04") assertInvalidChar(b"\tFCb", ignorechars=b"\n") assertInvalidChar(b"xxxB\nP\thU'D v/F+", ignorechars=b" \n\tv") def test_ascii85_wrapcol(self): # Test Ascii85 splitting lines def assertEncode(a_expected, data, n, adobe=False): b = self.type2test(data) a = binascii.b2a_ascii85(b, adobe=adobe, wrapcol=n) self.assertEqual(a, a_expected) def assertDecode(data, b_expected, adobe=False): a = self.type2test(data) b = binascii.a2b_ascii85(a, adobe=adobe, ignorechars=b"\n") self.assertEqual(b, b_expected) tests = [ (b"", 0, b"", b"<~~>"), (b"", 1, b"", b"<~\n~>"), (b"a", 0, b"@/", b"<~@/~>"), (b"a", 1, b"@\n/", b"<~\n@/\n~>"), (b"a", 2, b"@/", b"<~\n@/\n~>"), (b"a", 3, b"@/", b"<~@\n/~>"), (b"a", 4, b"@/", b"<~@/\n~>"), (b"a", 5, b"@/", b"<~@/\n~>"), (b"a", 6, b"@/", b"<~@/~>"), (b"a", 7, b"@/", b"<~@/~>"), (b"a", 123, b"@/", b"<~@/~>"), (b"this is a test", 7, b"FD,B0+D\nGm>@3BZ\n'F*%", b"<~FD,B0\n+DGm>@3\nBZ'F*%\n~>"), (b"a test!!!!!!! ", 11, b"@3BZ'F*&QK+\nX&!P+WqmM+9", b"<~@3BZ'F*&Q\nK+X&!P+WqmM\n+9~>"), (b"\0" * 56, 7, b"zzzzzzz\nzzzzzzz", b"<~zzzzz\nzzzzzzz\nzz~>"), ] for b, n, a, a_wrap in tests: assertEncode(a, b, n) assertEncode(a_wrap, b, n, adobe=True) assertDecode(a, b) assertDecode(a_wrap, b, adobe=True) def test_ascii85_pad(self): # Test Ascii85 with encode padding rawdata = b"n1n3tee\n ch@rAcTer$" for i in range(1, len(rawdata) + 1): padding = -i % 4 b = rawdata[:i] a_pad = binascii.b2a_ascii85(self.type2test(b), pad=True) b_pad = binascii.a2b_ascii85(self.type2test(a_pad)) b_pad_expected = b + b"\0" * padding self.assertEqual(b_pad, b_pad_expected) # Test Ascii85 short form groups with encode padding def assertShortPad(data, expected, **kwargs): data = self.type2test(data) res = binascii.b2a_ascii85(data, **kwargs) self.assertEqual(res, expected) assertShortPad(b"\0", b"!!", pad=False) assertShortPad(b"\0", b"z", pad=True) assertShortPad(b"\0" * 2, b"z", pad=True) assertShortPad(b"\0" * 3, b"z", pad=True) assertShortPad(b"\0" * 4, b"z", pad=True) assertShortPad(b"\0" * 5, b"zz", pad=True) assertShortPad(b"\0" * 6, b"z!!!") assertShortPad(b" " * 7, b"y+", foldspaces=True, adobe=True, pad=True) assertShortPad(b"\0\0\0\0abcd \0\0", b"<~z@:E_Wy\nz~>", foldspaces=True, adobe=True, wrapcol=9, pad=True) def test_ascii85_ignorechars(self): # Test Ascii85 with ignored characters def assertIgnore(data, expected, ignorechars=b"", **kwargs): data = self.type2test(data) ignore = self.type2test(ignorechars) with self.assertRaisesRegex(binascii.Error, r"(?i)Non-Ascii85 digit"): binascii.a2b_ascii85(data, **kwargs) res = binascii.a2b_ascii85(data, ignorechars=ignorechars, **kwargs) self.assertEqual(res, expected) assertIgnore(b"\n", b"", ignorechars=b"\n") assertIgnore(b"<~ ~>", b"", ignorechars=b" ", adobe=True) assertIgnore(b"z|z", b"\0" * 8, ignorechars=b"|||") # repeats don't matter assertIgnore(b"zz!!|", b"\0" * 9, ignorechars=b"|!z") # ignore only if invalid assertIgnore(b"<~B P~@~>", b"hi", ignorechars=b" <~>", adobe=True) assertIgnore(b"zy}", b"\0\0\0\0", ignorechars=b"zy}") assertIgnore(b"zy}", b"\0\0\0\0 ", ignorechars=b"zy}", foldspaces=True) def test_base85_valid(self): # Test base85 with valid data lines, i = [], 0 for k in range(1, len(self.rawdata) + 1): b = self.type2test(self.rawdata[i:i + k]) a = binascii.b2a_base85(b) lines.append(a) i += k if i >= len(self.rawdata): break res = bytes() for line in lines: a = self.type2test(line) b = binascii.a2b_base85(a) res += b self.assertEqual(res, self.rawdata) # Test decoding inputs with different length self.assertEqual(binascii.a2b_base85(self.type2test(b'a')), b'') self.assertEqual(binascii.a2b_base85(self.type2test(b'a')), b'') self.assertEqual(binascii.a2b_base85(self.type2test(b'ab')), b'q') self.assertEqual(binascii.a2b_base85(self.type2test(b'abc')), b'qa') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcd')), b'qa\x9e') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcde')), b'qa\x9e\xb6') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcdef')), b'qa\x9e\xb6') self.assertEqual(binascii.a2b_base85(self.type2test(b'abcdefg')), b'qa\x9e\xb6\x81') def test_base85_errors(self): def _assertRegexTemplate(assert_regex, data, **kwargs): with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base85(self.type2test(data), **kwargs) def assertNonBase85Data(data): _assertRegexTemplate(r"(?i)bad base85 character", data) def assertOverflow(data): _assertRegexTemplate(r"(?i)base85 overflow", data) assertNonBase85Data(b"\xda") assertNonBase85Data(b"00\0\0") assertNonBase85Data(b"Z )*") assertNonBase85Data(b"bY*jNb0Hyq\n") # Test base85 with out-of-range encoded value assertOverflow(b"}") assertOverflow(b"|O") assertOverflow(b"|Nt") assertOverflow(b"|NsD") assertOverflow(b"|NsC1") assertOverflow(b"|NsC0~") assertOverflow(b"|NsC0|NsC0|NsD0") def test_base85_pad(self): # Test base85 with encode padding rawdata = b"n1n3Tee\n ch@rAc\te\r$" for i in range(1, len(rawdata) + 1): padding = -i % 4 b = rawdata[:i] a_pad = binascii.b2a_base85(self.type2test(b), pad=True) b_pad = binascii.a2b_base85(self.type2test(a_pad)) b_pad_expected = b + b"\0" * padding self.assertEqual(b_pad, b_pad_expected) def test_base85_alphabet(self): alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz' b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#') data = self.type2test(self.rawdata) encoded = binascii.b2a_base85(data, alphabet=alphabet) trans = bytes.maketrans(binascii.BASE85_ALPHABET, alphabet) expected = binascii.b2a_base85(data).translate(trans) self.assertEqual(encoded, expected) self.assertEqual(binascii.a2b_base85(encoded, alphabet=alphabet), self.rawdata) self.assertEqual(binascii.b2a_base85(data, alphabet=self.type2test(alphabet)), expected) data = self.type2test(b'') self.assertEqual(binascii.b2a_base85(data, alphabet=alphabet), b'') self.assertEqual(binascii.a2b_base85(data, alphabet=alphabet), b'') for func in binascii.b2a_base85, binascii.a2b_base85: with self.assertRaises(TypeError): func(data, alphabet=None) with self.assertRaises(TypeError): func(data, alphabet=alphabet.decode()) with self.assertRaises(ValueError): func(data, alphabet=alphabet[:-1]) with self.assertRaises(ValueError): func(data, alphabet=alphabet+b'?') with self.assertRaises(TypeError): binascii.a2b_base64(data, alphabet=bytearray(alphabet)) def test_base32_valid(self): # Test base32 with valid data lines = [] step = 0 i = 0 while i < len(self.rawdata): b = self.type2test(self.rawdata[i:i + step]) a = binascii.b2a_base32(b) lines.append(a) i += step step += 1 res = bytes() for line in lines: a = self.type2test(line) b = binascii.a2b_base32(a) res += b self.assertEqual(res, self.rawdata) def test_base32_errors(self): def _fixPadding(data): fixed = data.replace(b"=", b"") len_8 = len(fixed) % 8 p = 8 - len_8 if len_8 else 0 return fixed + b"=" * p def _assertRegexTemplate(assert_regex, data, good_padding_result=None): with self.assertRaisesRegex(binascii.Error, assert_regex): binascii.a2b_base32(self.type2test(data)) if good_padding_result: fixed = self.type2test(_fixPadding(data)) self.assertEqual(binascii.a2b_base32(fixed), good_padding_result) def assertNonBase32Data(*args): _assertRegexTemplate(r"(?i)Only base32 data", *args) def assertExcessData(*args): _assertRegexTemplate(r"(?i)Excess data", *args) def assertExcessPadding(*args): _assertRegexTemplate(r"(?i)Excess padding", *args) def assertLeadingPadding(*args): _assertRegexTemplate(r"(?i)Leading padding", *args) def assertIncorrectPadding(*args): _assertRegexTemplate(r"(?i)Incorrect padding", *args) def assertDiscontinuousPadding(*args): _assertRegexTemplate(r"(?i)Discontinuous padding", *args) def assertInvalidLength(*args): _assertRegexTemplate(r"(?i)Invalid.+number of data characters", *args) assertNonBase32Data(b"a") assertNonBase32Data(b"AA-") assertNonBase32Data(b"ABCDE==!") assertNonBase32Data(b"ab:(){:|:&};:==") assertExcessData(b"AB======C") assertExcessData(b"AB======CD") assertExcessData(b"ABCD====E") assertExcessData(b"ABCDE===FGH") assertExcessData(b"ABCDEFG=H") assertExcessData(b"432Z====55555555") assertExcessData(b"BE======EF", b"\t\x08") assertExcessData(b"BEEF====C", b"\t\x08Q") assertExcessData(b"BEEFC===AK", b"\t\x08Q\x01") assertExcessData(b"BEEFCAK=E", b"\t\x08Q\x01D") assertExcessPadding(b"BE=======", b"\t") assertExcessPadding(b"BE========", b"\t") assertExcessPadding(b"BEEF=====", b"\t\x08") assertExcessPadding(b"BEEF======", b"\t\x08") assertExcessPadding(b"BEEFC====", b"\t\x08Q") assertExcessPadding(b"BEEFC=====", b"\t\x08Q") assertExcessPadding(b"BEEFCAK==", b"\t\x08Q\x01") assertExcessPadding(b"BEEFCAK===", b"\t\x08Q\x01") assertExcessPadding(b"BEEFCAKE=", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE==", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE===", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE====", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE=====", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE======", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE=======", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE========", b"\t\x08Q\x01D") assertExcessPadding(b"BEEFCAKE=========", b"\t\x08Q\x01D") assertLeadingPadding(b"=", b"") assertLeadingPadding(b"==", b"") assertLeadingPadding(b"===", b"") assertLeadingPadding(b"====", b"") assertLeadingPadding(b"=====", b"") assertLeadingPadding(b"======", b"") assertLeadingPadding(b"=======", b"") assertLeadingPadding(b"========", b"") assertLeadingPadding(b"=========", b"") assertLeadingPadding(b"=BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"==BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"===BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"====BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"=====BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"======BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"=======BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"========BEEFCAKE", b"\t\x08Q\x01D") assertLeadingPadding(b"=========BEEFCAKE", b"\t\x08Q\x01D") assertIncorrectPadding(b"AB") assertIncorrectPadding(b"ABCD") assertIncorrectPadding(b"ABCDE") assertIncorrectPadding(b"ABCDEFG") assertIncorrectPadding(b"BE=", b"\t") assertIncorrectPadding(b"BE==", b"\t") assertIncorrectPadding(b"BE===", b"\t") assertIncorrectPadding(b"BE====", b"\t") assertIncorrectPadding(b"BE=====", b"\t") assertIncorrectPadding(b"BEEF=", b"\t\x08") assertIncorrectPadding(b"BEEF==", b"\t\x08") assertIncorrectPadding(b"BEEF===", b"\t\x08") assertIncorrectPadding(b"BEEFC=", b"\t\x08Q") assertIncorrectPadding(b"BEEFC==", b"\t\x08Q") assertDiscontinuousPadding(b"BE=EF===", b"\t\x08") assertDiscontinuousPadding(b"BE==EF==", b"\t\x08") assertDiscontinuousPadding(b"BEEF=C==", b"\t\x08Q") assertDiscontinuousPadding(b"BEEFC=AK", b"\t\x08Q\x01") assertInvalidLength(b"A") assertInvalidLength(b"ABC") assertInvalidLength(b"ABCDEF") assertInvalidLength(b"A=") assertInvalidLength(b"A==") assertInvalidLength(b"A===") assertInvalidLength(b"A====") assertInvalidLength(b"A=====") assertInvalidLength(b"A======") assertInvalidLength(b"ABC=") assertInvalidLength(b"ABC==") assertInvalidLength(b"ABC===") assertInvalidLength(b"ABC====") assertInvalidLength(b"ABCDEF=") assertInvalidLength(b"B=E=====", b"\t") assertInvalidLength(b"B==E====", b"\t") assertInvalidLength(b"BEE=F===", b"\t\x08") assertInvalidLength(b"BEE==F==", b"\t\x08") assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01") assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01") def test_base32_alphabet(self): alphabet = b'0Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9JjKk' data = self.type2test(self.rawdata) encoded = binascii.b2a_base32(data, alphabet=alphabet) trans = bytes.maketrans(binascii.BASE32_ALPHABET, alphabet) expected = binascii.b2a_base32(data).translate(trans) self.assertEqual(encoded, expected) self.assertEqual(binascii.a2b_base32(encoded, alphabet=alphabet), self.rawdata) self.assertEqual(binascii.b2a_base32(data, alphabet=self.type2test(alphabet)), expected) data = self.type2test(b'') self.assertEqual(binascii.b2a_base32(data, alphabet=alphabet), b'') self.assertEqual(binascii.a2b_base32(data, alphabet=alphabet), b'') for func in binascii.b2a_base32, binascii.a2b_base32: with self.assertRaises(TypeError): func(data, alphabet=None) with self.assertRaises(TypeError): func(data, alphabet=alphabet.decode()) with self.assertRaises(ValueError): func(data, alphabet=alphabet[:-1]) with self.assertRaises(ValueError): func(data, alphabet=alphabet+b'?') with self.assertRaises(TypeError): binascii.a2b_base32(data, alphabet=bytearray(alphabet)) def test_uu(self): MAX_UU = 45 for backtick in (True, False): lines = [] for i in range(0, len(self.data), MAX_UU): b = self.type2test(self.rawdata[i:i+MAX_UU]) a = binascii.b2a_uu(b, backtick=backtick) lines.append(a) res = bytes() for line in lines: a = self.type2test(line) b = binascii.a2b_uu(a) res += b self.assertEqual(res, self.rawdata) self.assertEqual(binascii.a2b_uu(b"\x7f"), b"\x00"*31) self.assertEqual(binascii.a2b_uu(b"\x80"), b"\x00"*32) self.assertEqual(binascii.a2b_uu(b"\xff"), b"\x00"*31) self.assertRaises(binascii.Error, binascii.a2b_uu, b"\xff\x00") self.assertRaises(binascii.Error, binascii.a2b_uu, b"!!!!") self.assertRaises(binascii.Error, binascii.b2a_uu, 46*b"!") # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') self.assertEqual(binascii.b2a_uu(b''), b' \n') self.assertEqual(binascii.b2a_uu(b'', backtick=True), b'`\n') self.assertEqual(binascii.a2b_uu(b' \n'), b'') self.assertEqual(binascii.a2b_uu(b'`\n'), b'') self.assertEqual(binascii.b2a_uu(b'\x00Cat'), b'$ $-A= \n') self.assertEqual(binascii.b2a_uu(b'\x00Cat', backtick=True), b'$`$-A=```\n') self.assertEqual(binascii.a2b_uu(b'$`$-A=```\n'), binascii.a2b_uu(b'$ $-A= \n')) with self.assertRaises(TypeError): binascii.b2a_uu(b"", True) @hypothesis.given( binary=hypothesis.strategies.binary(max_size=45), backtick=hypothesis.strategies.booleans(), ) def test_b2a_roundtrip(self, binary, backtick): converted = binascii.b2a_uu(self.type2test(binary), backtick=backtick) restored = binascii.a2b_uu(self.type2test(converted)) self.assertConversion(binary, converted, restored, backtick=backtick) def test_crc_hqx(self): crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0) crc = binascii.crc_hqx(self.type2test(b" this string."), crc) self.assertEqual(crc, 14290) self.assertRaises(TypeError, binascii.crc_hqx) self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b'')) for crc in 0, 1, 0x1234, 0x12345, 0x12345678, -1: self.assertEqual(binascii.crc_hqx(self.type2test(b''), crc), crc & 0xffff) def test_crc32(self): crc = binascii.crc32(self.type2test(b"Test the CRC-32 of")) crc = binascii.crc32(self.type2test(b" this string."), crc) self.assertEqual(crc, 1571220330) self.assertRaises(TypeError, binascii.crc32) def test_hex(self): # test hexlification s = b'{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' t = binascii.b2a_hex(self.type2test(s)) u = binascii.a2b_hex(self.type2test(t)) self.assertEqual(s, u) self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1]) self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1] + b'q') self.assertRaises(binascii.Error, binascii.a2b_hex, bytes([255, 255])) self.assertRaises(binascii.Error, binascii.a2b_hex, b'0G') self.assertRaises(binascii.Error, binascii.a2b_hex, b'0g') self.assertRaises(binascii.Error, binascii.a2b_hex, b'G0') self.assertRaises(binascii.Error, binascii.a2b_hex, b'g0') # Confirm that b2a_hex == hexlify and a2b_hex == unhexlify self.assertEqual(binascii.hexlify(self.type2test(s)), t) self.assertEqual(binascii.unhexlify(self.type2test(t)), u) @hypothesis.given(binary=hypothesis.strategies.binary()) def test_hex_roundtrip(self, binary): converted = binascii.hexlify(self.type2test(binary)) restored = binascii.unhexlify(self.type2test(converted)) self.assertConversion(binary, converted, restored) def test_hex_separator(self): """Test that hexlify and b2a_hex are binary versions of bytes.hex.""" # Logic of separators is tested in test_bytes.py. This checks that # arg parsing works and exercises the direct to bytes object code # path within pystrhex.c. s = b'{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' self.assertEqual(binascii.hexlify(self.type2test(s)), s.hex().encode('ascii')) expected8 = s.hex('.', 8).encode('ascii') self.assertEqual(binascii.hexlify(self.type2test(s), '.', 8), expected8) expected1 = s.hex(':').encode('ascii') self.assertEqual(binascii.b2a_hex(self.type2test(s), ':'), expected1) def test_qp(self): type2test = self.type2test a2b_qp = binascii.a2b_qp b2a_qp = binascii.b2a_qp a2b_qp(data=b"", header=False) # Keyword arguments allowed # A test for SF bug 534347 (segfaults without the proper fix) try: a2b_qp(b"", **{1:1}) except TypeError: pass else: self.fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError") self.assertEqual(a2b_qp(type2test(b"=")), b"") self.assertEqual(a2b_qp(type2test(b"= ")), b"= ") self.assertEqual(a2b_qp(type2test(b"==")), b"=") self.assertEqual(a2b_qp(type2test(b"=\nAB")), b"AB") self.assertEqual(a2b_qp(type2test(b"=\r\nAB")), b"AB") self.assertEqual(a2b_qp(type2test(b"=\rAB")), b"") # ? self.assertEqual(a2b_qp(type2test(b"=\rAB\nCD")), b"CD") # ? self.assertEqual(a2b_qp(type2test(b"=AB")), b"\xab") self.assertEqual(a2b_qp(type2test(b"=ab")), b"\xab") self.assertEqual(a2b_qp(type2test(b"=AX")), b"=AX") self.assertEqual(a2b_qp(type2test(b"=XA")), b"=XA") self.assertEqual(a2b_qp(type2test(b"=AB")[:-1]), b"=A") self.assertEqual(a2b_qp(type2test(b'_')), b'_') self.assertEqual(a2b_qp(type2test(b'_'), header=True), b' ') self.assertRaises(TypeError, b2a_qp, foo="bar") self.assertEqual(a2b_qp(type2test(b"=00\r\n=00")), b"\x00\r\n\x00") self.assertEqual(b2a_qp(type2test(b"\xff\r\n\xff\n\xff")), b"=FF\r\n=FF\r\n=FF") self.assertEqual(b2a_qp(type2test(b"0"*75+b"\xff\r\n\xff\r\n\xff")), b"0"*75+b"=\r\n=FF\r\n=FF\r\n=FF") self.assertEqual(b2a_qp(type2test(b'\x7f')), b'=7F') self.assertEqual(b2a_qp(type2test(b'=')), b'=3D') self.assertEqual(b2a_qp(type2test(b'_')), b'_') self.assertEqual(b2a_qp(type2test(b'_'), header=True), b'=5F') self.assertEqual(b2a_qp(type2test(b'x y'), header=True), b'x_y') self.assertEqual(b2a_qp(type2test(b'x '), header=True), b'x=20') self.assertEqual(b2a_qp(type2test(b'x y'), header=True, quotetabs=True), b'x=20y') self.assertEqual(b2a_qp(type2test(b'x\ty'), header=True), b'x\ty') self.assertEqual(b2a_qp(type2test(b' ')), b'=20') self.assertEqual(b2a_qp(type2test(b'\t')), b'=09') self.assertEqual(b2a_qp(type2test(b' x')), b' x') self.assertEqual(b2a_qp(type2test(b'\tx')), b'\tx') self.assertEqual(b2a_qp(type2test(b' x')[:-1]), b'=20') self.assertEqual(b2a_qp(type2test(b'\tx')[:-1]), b'=09') self.assertEqual(b2a_qp(type2test(b'\0')), b'=00') self.assertEqual(b2a_qp(type2test(b'\0\n')), b'=00\n') self.assertEqual(b2a_qp(type2test(b'\0\n'), quotetabs=True), b'=00\n') self.assertEqual(b2a_qp(type2test(b'x y\tz')), b'x y\tz') self.assertEqual(b2a_qp(type2test(b'x y\tz'), quotetabs=True), b'x=20y=09z') self.assertEqual(b2a_qp(type2test(b'x y\tz'), istext=False), b'x y\tz') self.assertEqual(b2a_qp(type2test(b'x \ny\t\n')), b'x=20\ny=09\n') self.assertEqual(b2a_qp(type2test(b'x \ny\t\n'), quotetabs=True), b'x=20\ny=09\n') self.assertEqual(b2a_qp(type2test(b'x \ny\t\n'), istext=False), b'x =0Ay\t=0A') self.assertEqual(b2a_qp(type2test(b'x \ry\t\r')), b'x \ry\t\r') self.assertEqual(b2a_qp(type2test(b'x \ry\t\r'), quotetabs=True), b'x=20\ry=09\r') self.assertEqual(b2a_qp(type2test(b'x \ry\t\r'), istext=False), b'x =0Dy\t=0D') self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n')), b'x=20\r\ny=09\r\n') self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n'), quotetabs=True), b'x=20\r\ny=09\r\n') self.assertEqual(b2a_qp(type2test(b'x \r\ny\t\r\n'), istext=False), b'x =0D=0Ay\t=0D=0A') self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1]), b'x \r') self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1]), b'x\t\r') self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1], quotetabs=True), b'x=20\r') self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1], quotetabs=True), b'x=09\r') self.assertEqual(b2a_qp(type2test(b'x \r\n')[:-1], istext=False), b'x =0D') self.assertEqual(b2a_qp(type2test(b'x\t\r\n')[:-1], istext=False), b'x\t=0D') self.assertEqual(b2a_qp(type2test(b'.')), b'=2E') self.assertEqual(b2a_qp(type2test(b'.\n')), b'=2E\n') self.assertEqual(b2a_qp(type2test(b'.\r')), b'=2E\r') self.assertEqual(b2a_qp(type2test(b'.\0')), b'=2E=00') self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n') self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E') @hypothesis.given( binary=hypothesis.strategies.binary(), quotetabs=hypothesis.strategies.booleans(), istext=hypothesis.strategies.booleans(), header=hypothesis.strategies.booleans(), ) def test_b2a_qp_a2b_qp_round_trip(self, binary, quotetabs, istext, header): converted = binascii.b2a_qp( self.type2test(binary), quotetabs=quotetabs, istext=istext, header=header, ) restored = binascii.a2b_qp(self.type2test(converted), header=header) self.assertConversion(binary, converted, restored, quotetabs=quotetabs, istext=istext, header=header) def test_empty_string(self): # A test for SF bug #1022953. Make sure SystemError is not raised. empty = self.type2test(b'') for func in all_functions: if func == 'crc_hqx': # crc_hqx needs 2 arguments binascii.crc_hqx(empty, 0) continue f = getattr(binascii, func) try: f(empty) except Exception as err: self.fail("{}({!r}) raises {!r}".format(func, empty, err)) def test_unicode_b2a(self): # Unicode strings are not accepted by b2a_* functions. for func in set(all_functions) - set(a2b_functions): try: self.assertRaises(TypeError, getattr(binascii, func), "test") except Exception as err: self.fail('{}("test") raises {!r}'.format(func, err)) # crc_hqx needs 2 arguments self.assertRaises(TypeError, binascii.crc_hqx, "test", 0) def test_unicode_a2b(self): # Unicode strings are accepted by a2b_* functions. MAX_ALL = 45 raw = self.rawdata[:MAX_ALL] for fa, fb in zip(a2b_functions, b2a_functions): a2b = getattr(binascii, fa) b2a = getattr(binascii, fb) try: a = b2a(self.type2test(raw)) binary_res = a2b(a) a = a.decode('ascii') res = a2b(a) except Exception as err: self.fail("{}/{} conversion raises {!r}".format(fb, fa, err)) self.assertEqual(res, raw, "{}/{} conversion: " "{!r} != {!r}".format(fb, fa, res, raw)) self.assertEqual(res, binary_res) self.assertIsInstance(res, bytes) # non-ASCII string self.assertRaises(ValueError, a2b, "\x80") def test_b2a_base64_newline(self): # Issue #25357: test newline parameter b = self.type2test(b'hello') self.assertEqual(binascii.b2a_base64(b), b'aGVsbG8=\n') self.assertEqual(binascii.b2a_base64(b, newline=True), b'aGVsbG8=\n') self.assertEqual(binascii.b2a_base64(b, newline=False), b'aGVsbG8=') b = self.type2test(b'') self.assertEqual(binascii.b2a_base64(b), b'\n') self.assertEqual(binascii.b2a_base64(b, newline=True), b'\n') self.assertEqual(binascii.b2a_base64(b, newline=False), b'') def test_b2a_base64_wrapcol(self): b = self.type2test(b'www.python.org') self.assertEqual(binascii.b2a_base64(b), b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=0), b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=76), b'd3d3LnB5dGhvbi5vcmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'd3d3LnB5\ndGhvbi5v\ncmc=') self.assertEqual(binascii.b2a_base64(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize), b'd3d3LnB5dGhvbi5vcmc=\n') if check_impl_detail(): self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize*2), b'd3d3LnB5dGhvbi5vcmc=\n') with self.assertRaises(OverflowError): binascii.b2a_base64(b, wrapcol=2**1000) with self.assertRaises(ValueError): binascii.b2a_base64(b, wrapcol=-8) with self.assertRaises(TypeError): binascii.b2a_base64(b, wrapcol=8.0) with self.assertRaises(TypeError): binascii.b2a_base64(b, wrapcol='8') b = self.type2test(b'') self.assertEqual(binascii.b2a_base64(b), b'\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=0), b'\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'\n') self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'') @hypothesis.given( binary=hypothesis.strategies.binary(), newline=hypothesis.strategies.booleans(), ) def test_base64_roundtrip(self, binary, newline): converted = binascii.b2a_base64(self.type2test(binary), newline=newline) restored = binascii.a2b_base64(self.type2test(converted)) self.assertConversion(binary, converted, restored, newline=newline) def test_c_contiguity(self): m = memoryview(bytearray(b'noncontig')) noncontig_writable = m[::-2] with self.assertRaises(BufferError): binascii.b2a_hex(noncontig_writable) class ArrayBinASCIITest(BinASCIITest): def type2test(self, s): return array.array('B', list(s)) class BytearrayBinASCIITest(BinASCIITest): type2test = bytearray class MemoryviewBinASCIITest(BinASCIITest): type2test = memoryview class ChecksumBigBufferTestCase(unittest.TestCase): """bpo-38256 - check that inputs >=4 GiB are handled correctly.""" @bigmemtest(size=_4G + 4, memuse=1, dry_run=False) def test_big_buffer(self, size): data = b"nyan" * (_1G + 1) self.assertEqual(binascii.crc32(data), 1044521549) if __name__ == "__main__": unittest.main()