test_binascii.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. """Test the binascii C module."""
  2. from test import test_support
  3. import unittest
  4. import binascii
  5. import array
  6. # Note: "*_hex" functions are aliases for "(un)hexlify"
  7. b2a_functions = ['b2a_base64', 'b2a_hex', 'b2a_hqx', 'b2a_qp', 'b2a_uu',
  8. 'hexlify', 'rlecode_hqx']
  9. a2b_functions = ['a2b_base64', 'a2b_hex', 'a2b_hqx', 'a2b_qp', 'a2b_uu',
  10. 'unhexlify', 'rledecode_hqx']
  11. all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx']
  12. class BinASCIITest(unittest.TestCase):
  13. type2test = str
  14. # Create binary test data
  15. rawdata = "The quick brown fox jumps over the lazy dog.\r\n"
  16. # Be slow so we don't depend on other modules
  17. rawdata += "".join(map(chr, xrange(256)))
  18. rawdata += "\r\nHello world.\n"
  19. def setUp(self):
  20. self.data = self.type2test(self.rawdata)
  21. def test_exceptions(self):
  22. # Check module exceptions
  23. self.assertTrue(issubclass(binascii.Error, Exception))
  24. self.assertTrue(issubclass(binascii.Incomplete, Exception))
  25. def test_functions(self):
  26. # Check presence of all functions
  27. for name in all_functions:
  28. self.assertTrue(hasattr(getattr(binascii, name), '__call__'))
  29. self.assertRaises(TypeError, getattr(binascii, name))
  30. def test_returned_value(self):
  31. # Limit to the minimum of all limits (b2a_uu)
  32. MAX_ALL = 45
  33. raw = self.rawdata[:MAX_ALL]
  34. for fa, fb in zip(a2b_functions, b2a_functions):
  35. a2b = getattr(binascii, fa)
  36. b2a = getattr(binascii, fb)
  37. try:
  38. a = b2a(self.type2test(raw))
  39. res = a2b(self.type2test(a))
  40. except Exception, err:
  41. self.fail("{}/{} conversion raises {!r}".format(fb, fa, err))
  42. if fb == 'b2a_hqx':
  43. # b2a_hqx returns a tuple
  44. res, _ = res
  45. self.assertEqual(res, raw, "{}/{} conversion: "
  46. "{!r} != {!r}".format(fb, fa, res, raw))
  47. self.assertIsInstance(res, str)
  48. self.assertIsInstance(a, str)
  49. self.assertLess(max(ord(c) for c in a), 128)
  50. self.assertIsInstance(binascii.crc_hqx(raw, 0), int)
  51. self.assertIsInstance(binascii.crc32(raw), int)
  52. def test_base64valid(self):
  53. # Test base64 with valid data
  54. MAX_BASE64 = 57
  55. lines = []
  56. for i in range(0, len(self.rawdata), MAX_BASE64):
  57. b = self.type2test(self.rawdata[i:i+MAX_BASE64])
  58. a = binascii.b2a_base64(b)
  59. lines.append(a)
  60. res = ""
  61. for line in lines:
  62. a = self.type2test(line)
  63. b = binascii.a2b_base64(a)
  64. res = res + b
  65. self.assertEqual(res, self.rawdata)
  66. def test_base64invalid(self):
  67. # Test base64 with random invalid characters sprinkled throughout
  68. # (This requires a new version of binascii.)
  69. MAX_BASE64 = 57
  70. lines = []
  71. for i in range(0, len(self.data), MAX_BASE64):
  72. b = self.type2test(self.rawdata[i:i+MAX_BASE64])
  73. a = binascii.b2a_base64(b)
  74. lines.append(a)
  75. fillers = ""
  76. valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"
  77. for i in xrange(256):
  78. c = chr(i)
  79. if c not in valid:
  80. fillers += c
  81. def addnoise(line):
  82. noise = fillers
  83. ratio = len(line) // len(noise)
  84. res = ""
  85. while line and noise:
  86. if len(line) // len(noise) > ratio:
  87. c, line = line[0], line[1:]
  88. else:
  89. c, noise = noise[0], noise[1:]
  90. res += c
  91. return res + noise + line
  92. res = ""
  93. for line in map(addnoise, lines):
  94. a = self.type2test(line)
  95. b = binascii.a2b_base64(a)
  96. res += b
  97. self.assertEqual(res, self.rawdata)
  98. # Test base64 with just invalid characters, which should return
  99. # empty strings. TBD: shouldn't it raise an exception instead ?
  100. self.assertEqual(binascii.a2b_base64(self.type2test(fillers)), '')
  101. def test_uu(self):
  102. MAX_UU = 45
  103. lines = []
  104. for i in range(0, len(self.data), MAX_UU):
  105. b = self.type2test(self.rawdata[i:i+MAX_UU])
  106. a = binascii.b2a_uu(b)
  107. lines.append(a)
  108. res = ""
  109. for line in lines:
  110. a = self.type2test(line)
  111. b = binascii.a2b_uu(a)
  112. res += b
  113. self.assertEqual(res, self.rawdata)
  114. self.assertEqual(binascii.a2b_uu("\x7f"), "\x00"*31)
  115. self.assertEqual(binascii.a2b_uu("\x80"), "\x00"*32)
  116. self.assertEqual(binascii.a2b_uu("\xff"), "\x00"*31)
  117. self.assertRaises(binascii.Error, binascii.a2b_uu, "\xff\x00")
  118. self.assertRaises(binascii.Error, binascii.a2b_uu, "!!!!")
  119. self.assertRaises(binascii.Error, binascii.b2a_uu, 46*"!")
  120. # Issue #7701 (crash on a pydebug build)
  121. self.assertEqual(binascii.b2a_uu('x'), '!> \n')
  122. def test_crc_hqx(self):
  123. crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0)
  124. crc = binascii.crc_hqx(self.type2test(b" this string."), crc)
  125. self.assertEqual(crc, 14290)
  126. self.assertRaises(TypeError, binascii.crc_hqx)
  127. self.assertRaises(TypeError, binascii.crc_hqx, self.type2test(b''))
  128. def test_crc32(self):
  129. crc = binascii.crc32(self.type2test("Test the CRC-32 of"))
  130. crc = binascii.crc32(self.type2test(" this string."), crc)
  131. self.assertEqual(crc, 1571220330)
  132. self.assertRaises(TypeError, binascii.crc32)
  133. def test_hqx(self):
  134. # Perform binhex4 style RLE-compression
  135. # Then calculate the hexbin4 binary-to-ASCII translation
  136. rle = binascii.rlecode_hqx(self.data)
  137. a = binascii.b2a_hqx(self.type2test(rle))
  138. b, _ = binascii.a2b_hqx(self.type2test(a))
  139. res = binascii.rledecode_hqx(b)
  140. self.assertEqual(res, self.rawdata)
  141. def test_hex(self):
  142. # test hexlification
  143. s = '{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000'
  144. t = binascii.b2a_hex(self.type2test(s))
  145. u = binascii.a2b_hex(self.type2test(t))
  146. self.assertEqual(s, u)
  147. self.assertRaises(TypeError, binascii.a2b_hex, t[:-1])
  148. self.assertRaises(TypeError, binascii.a2b_hex, t[:-1] + 'q')
  149. # Verify the treatment of Unicode strings
  150. if test_support.have_unicode:
  151. self.assertEqual(binascii.hexlify(unicode('a', 'ascii')), '61')
  152. def test_qp(self):
  153. # A test for SF bug 534347 (segfaults without the proper fix)
  154. try:
  155. binascii.a2b_qp("", **{1:1})
  156. except TypeError:
  157. pass
  158. else:
  159. self.fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError")
  160. self.assertEqual(binascii.a2b_qp("= "), "= ")
  161. self.assertEqual(binascii.a2b_qp("=="), "=")
  162. self.assertEqual(binascii.a2b_qp("=AX"), "=AX")
  163. self.assertRaises(TypeError, binascii.b2a_qp, foo="bar")
  164. self.assertEqual(binascii.a2b_qp("=00\r\n=00"), "\x00\r\n\x00")
  165. self.assertEqual(
  166. binascii.b2a_qp("\xff\r\n\xff\n\xff"),
  167. "=FF\r\n=FF\r\n=FF"
  168. )
  169. self.assertEqual(
  170. binascii.b2a_qp("0"*75+"\xff\r\n\xff\r\n\xff"),
  171. "0"*75+"=\r\n=FF\r\n=FF\r\n=FF"
  172. )
  173. self.assertEqual(binascii.b2a_qp('\0\n'), '=00\n')
  174. self.assertEqual(binascii.b2a_qp('\0\n', quotetabs=True), '=00\n')
  175. self.assertEqual(binascii.b2a_qp('foo\tbar\t\n'), 'foo\tbar=09\n')
  176. self.assertEqual(binascii.b2a_qp('foo\tbar\t\n', quotetabs=True), 'foo=09bar=09\n')
  177. self.assertEqual(binascii.b2a_qp('.'), '=2E')
  178. self.assertEqual(binascii.b2a_qp('.\n'), '=2E\n')
  179. self.assertEqual(binascii.b2a_qp('a.\n'), 'a.\n')
  180. def test_empty_string(self):
  181. # A test for SF bug #1022953. Make sure SystemError is not raised.
  182. empty = self.type2test('')
  183. for func in all_functions:
  184. if func == 'crc_hqx':
  185. # crc_hqx needs 2 arguments
  186. binascii.crc_hqx(empty, 0)
  187. continue
  188. f = getattr(binascii, func)
  189. try:
  190. f(empty)
  191. except Exception, err:
  192. self.fail("{}({!r}) raises {!r}".format(func, empty, err))
  193. class ArrayBinASCIITest(BinASCIITest):
  194. def type2test(self, s):
  195. return array.array('c', s)
  196. class BytearrayBinASCIITest(BinASCIITest):
  197. type2test = bytearray
  198. class MemoryviewBinASCIITest(BinASCIITest):
  199. type2test = memoryview
  200. def test_main():
  201. test_support.run_unittest(BinASCIITest,
  202. ArrayBinASCIITest,
  203. BytearrayBinASCIITest,
  204. MemoryviewBinASCIITest)
  205. if __name__ == "__main__":
  206. test_main()