Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | """Test the binascii C module.""" |
2 | ||
3 | from test import test_support | |
4 | import unittest | |
5 | import binascii | |
6 | ||
7 | class BinASCIITest(unittest.TestCase): | |
8 | ||
9 | # Create binary test data | |
10 | data = "The quick brown fox jumps over the lazy dog.\r\n" | |
11 | # Be slow so we don't depend on other modules | |
12 | data += "".join(map(chr, xrange(256))) | |
13 | data += "\r\nHello world.\n" | |
14 | ||
15 | def test_exceptions(self): | |
16 | # Check module exceptions | |
17 | self.assert_(issubclass(binascii.Error, Exception)) | |
18 | self.assert_(issubclass(binascii.Incomplete, Exception)) | |
19 | ||
20 | def test_functions(self): | |
21 | # Check presence of all functions | |
22 | funcs = [] | |
23 | for suffix in "base64", "hqx", "uu", "hex": | |
24 | prefixes = ["a2b_", "b2a_"] | |
25 | if suffix == "hqx": | |
26 | prefixes.extend(["crc_", "rlecode_", "rledecode_"]) | |
27 | for prefix in prefixes: | |
28 | name = prefix + suffix | |
29 | self.assert_(callable(getattr(binascii, name))) | |
30 | self.assertRaises(TypeError, getattr(binascii, name)) | |
31 | for name in ("hexlify", "unhexlify"): | |
32 | self.assert_(callable(getattr(binascii, name))) | |
33 | self.assertRaises(TypeError, getattr(binascii, name)) | |
34 | ||
35 | def test_base64valid(self): | |
36 | # Test base64 with valid data | |
37 | MAX_BASE64 = 57 | |
38 | lines = [] | |
39 | for i in range(0, len(self.data), MAX_BASE64): | |
40 | b = self.data[i:i+MAX_BASE64] | |
41 | a = binascii.b2a_base64(b) | |
42 | lines.append(a) | |
43 | res = "" | |
44 | for line in lines: | |
45 | b = binascii.a2b_base64(line) | |
46 | res = res + b | |
47 | self.assertEqual(res, self.data) | |
48 | ||
49 | def test_base64invalid(self): | |
50 | # Test base64 with random invalid characters sprinkled throughout | |
51 | # (This requires a new version of binascii.) | |
52 | MAX_BASE64 = 57 | |
53 | lines = [] | |
54 | for i in range(0, len(self.data), MAX_BASE64): | |
55 | b = self.data[i:i+MAX_BASE64] | |
56 | a = binascii.b2a_base64(b) | |
57 | lines.append(a) | |
58 | ||
59 | fillers = "" | |
60 | valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/" | |
61 | for i in xrange(256): | |
62 | c = chr(i) | |
63 | if c not in valid: | |
64 | fillers += c | |
65 | def addnoise(line): | |
66 | noise = fillers | |
67 | ratio = len(line) // len(noise) | |
68 | res = "" | |
69 | while line and noise: | |
70 | if len(line) // len(noise) > ratio: | |
71 | c, line = line[0], line[1:] | |
72 | else: | |
73 | c, noise = noise[0], noise[1:] | |
74 | res += c | |
75 | return res + noise + line | |
76 | res = "" | |
77 | for line in map(addnoise, lines): | |
78 | b = binascii.a2b_base64(line) | |
79 | res += b | |
80 | self.assertEqual(res, self.data) | |
81 | ||
82 | # Test base64 with just invalid characters, which should return | |
83 | # empty strings. TBD: shouldn't it raise an exception instead ? | |
84 | self.assertEqual(binascii.a2b_base64(fillers), '') | |
85 | ||
86 | def test_uu(self): | |
87 | MAX_UU = 45 | |
88 | lines = [] | |
89 | for i in range(0, len(self.data), MAX_UU): | |
90 | b = self.data[i:i+MAX_UU] | |
91 | a = binascii.b2a_uu(b) | |
92 | lines.append(a) | |
93 | res = "" | |
94 | for line in lines: | |
95 | b = binascii.a2b_uu(line) | |
96 | res += b | |
97 | self.assertEqual(res, self.data) | |
98 | ||
99 | self.assertEqual(binascii.a2b_uu("\x7f"), "\x00"*31) | |
100 | self.assertEqual(binascii.a2b_uu("\x80"), "\x00"*32) | |
101 | self.assertEqual(binascii.a2b_uu("\xff"), "\x00"*31) | |
102 | self.assertRaises(binascii.Error, binascii.a2b_uu, "\xff\x00") | |
103 | self.assertRaises(binascii.Error, binascii.a2b_uu, "!!!!") | |
104 | ||
105 | self.assertRaises(binascii.Error, binascii.b2a_uu, 46*"!") | |
106 | ||
107 | def test_crc32(self): | |
108 | crc = binascii.crc32("Test the CRC-32 of") | |
109 | crc = binascii.crc32(" this string.", crc) | |
110 | self.assertEqual(crc, 1571220330) | |
111 | ||
112 | self.assertRaises(TypeError, binascii.crc32) | |
113 | ||
114 | # The hqx test is in test_binhex.py | |
115 | ||
116 | def test_hex(self): | |
117 | # test hexlification | |
118 | s = '{s\005\000\000\000worldi\002\000\000\000s\005\000\000\000helloi\001\000\000\0000' | |
119 | t = binascii.b2a_hex(s) | |
120 | u = binascii.a2b_hex(t) | |
121 | self.assertEqual(s, u) | |
122 | self.assertRaises(TypeError, binascii.a2b_hex, t[:-1]) | |
123 | self.assertRaises(TypeError, binascii.a2b_hex, t[:-1] + 'q') | |
124 | ||
125 | # Verify the treatment of Unicode strings | |
126 | if test_support.have_unicode: | |
127 | self.assertEqual(binascii.hexlify(unicode('a', 'ascii')), '61') | |
128 | ||
129 | def test_qp(self): | |
130 | # A test for SF bug 534347 (segfaults without the proper fix) | |
131 | try: | |
132 | binascii.a2b_qp("", **{1:1}) | |
133 | except TypeError: | |
134 | pass | |
135 | else: | |
136 | self.fail("binascii.a2b_qp(**{1:1}) didn't raise TypeError") | |
137 | self.assertEqual(binascii.a2b_qp("= "), "") | |
138 | self.assertEqual(binascii.a2b_qp("=="), "=") | |
139 | self.assertEqual(binascii.a2b_qp("=AX"), "=AX") | |
140 | self.assertRaises(TypeError, binascii.b2a_qp, foo="bar") | |
141 | self.assertEqual(binascii.a2b_qp("=00\r\n=00"), "\x00\r\n\x00") | |
142 | self.assertEqual( | |
143 | binascii.b2a_qp("\xff\r\n\xff\n\xff"), | |
144 | "=FF\r\n=FF\r\n=FF" | |
145 | ) | |
146 | self.assertEqual( | |
147 | binascii.b2a_qp("0"*75+"\xff\r\n\xff\r\n\xff"), | |
148 | "0"*75+"=\r\n=FF\r\n=FF\r\n=FF" | |
149 | ) | |
150 | ||
151 | def test_empty_string(self): | |
152 | # A test for SF bug #1022953. Make sure SystemError is not raised. | |
153 | for n in ['b2a_qp', 'a2b_hex', 'b2a_base64', 'a2b_uu', 'a2b_qp', | |
154 | 'b2a_hex', 'unhexlify', 'hexlify', 'crc32', 'b2a_hqx', | |
155 | 'a2b_hqx', 'a2b_base64', 'rlecode_hqx', 'b2a_uu', | |
156 | 'rledecode_hqx']: | |
157 | f = getattr(binascii, n) | |
158 | f('') | |
159 | binascii.crc_hqx('', 0) | |
160 | ||
161 | def test_main(): | |
162 | test_support.run_unittest(BinASCIITest) | |
163 | ||
164 | if __name__ == "__main__": | |
165 | test_main() |