summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_base64.py
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-11-17 22:52:25 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-11-17 22:52:25 (GMT)
commit6dd0d461a4e1f3d02784598f1efae185c0bf06bc (patch)
treee7d206e3137b2590ce10ef579c0b58441cc679bd /Lib/test/test_base64.py
parent1a048f93bb62ef1b301de8aa8e422e864db2f423 (diff)
downloadcpython-6dd0d461a4e1f3d02784598f1efae185c0bf06bc.zip
cpython-6dd0d461a4e1f3d02784598f1efae185c0bf06bc.tar.gz
cpython-6dd0d461a4e1f3d02784598f1efae185c0bf06bc.tar.bz2
Issue #17618: Add Base85 and Ascii85 encoding/decoding to the base64 module.
Diffstat (limited to 'Lib/test/test_base64.py')
-rw-r--r--Lib/test/test_base64.py254
1 files changed, 252 insertions, 2 deletions
diff --git a/Lib/test/test_base64.py b/Lib/test/test_base64.py
index 54f392d..b9738dd 100644
--- a/Lib/test/test_base64.py
+++ b/Lib/test/test_base64.py
@@ -100,9 +100,13 @@ class BaseXYTestCase(unittest.TestCase):
def check_other_types(self, f, bytes_data, expected):
eq = self.assertEqual
- eq(f(bytearray(bytes_data)), expected)
+ b = bytearray(bytes_data)
+ eq(f(b), expected)
+ # The bytearray wasn't mutated
+ eq(b, bytes_data)
eq(f(memoryview(bytes_data)), expected)
eq(f(array('B', bytes_data)), expected)
+ # XXX why is b64encode hardcoded here?
self.check_nonbyte_element_format(base64.b64encode, bytes_data)
self.check_multidimensional(base64.b64encode, bytes_data)
@@ -359,12 +363,258 @@ class BaseXYTestCase(unittest.TestCase):
eq(base64.b16decode(array('B', b"0102abcdef"), True),
b'\x01\x02\xab\xcd\xef')
+ def test_a85encode(self):
+ eq = self.assertEqual
+
+ tests = {
+ b'': b'',
+ b"www.python.org": b'GB\\6`E-ZP=Df.1GEb>',
+ bytes(range(255)): b"""!!*-'"9eu7#RLhG$k3[W&.oNg'GVB"(`=52*$$"""
+ b"""(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cE"""
+ b"""H9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbN"""
+ b"""G^4U^I!pHnJ:W<)KS>/9Ll%"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TU"""
+ b"""nsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg"GZd"""
+ b"""*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq"ad`"""
+ b"""r;HT""",
+ b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ b"0123456789!@#0^&*();:<>,. []{}":
+ b'@:E_WAS,RgBkhF"D/O92EH6,BF`qtRH$VbC6UX@47n?3D92&&T'
+ b":Jand;cHat='/U/0JP==1c70M3&r-I,;<FN.OZ`-3]oSW/g+A(H[P",
+ b"no padding..": b'DJpY:@:Wn_DJ(RS',
+ b"zero compression\0\0\0\0": b'H=_,8+Cf>,E,oN2F(oQ1z',
+ b"zero compression\0\0\0": b'H=_,8+Cf>,E,oN2F(oQ1!!!!',
+ b"Boundary:\0\0\0\0": b'6>q!aA79M(3WK-[!!',
+ b"Space compr: ": b';fH/TAKYK$D/aMV+<VdL',
+ b'\xff': b'rr',
+ b'\xff'*2: b's8N',
+ b'\xff'*3: b's8W*',
+ b'\xff'*4: b's8W-!',
+ }
+
+ for data, res in tests.items():
+ eq(base64.a85encode(data), res, data)
+ eq(base64.a85encode(data, adobe=False), res, data)
+ eq(base64.a85encode(data, adobe=True), b'<~' + res + b'~>', data)
+
+ self.check_other_types(base64.a85encode, b"www.python.org",
+ b'GB\\6`E-ZP=Df.1GEb>')
+
+ self.assertRaises(TypeError, base64.a85encode, "")
+
+ eq(base64.a85encode(b"www.python.org", wrapcol=7, adobe=False),
+ b'GB\\6`E-\nZP=Df.1\nGEb>')
+ eq(base64.a85encode(b"\0\0\0\0www.python.org", wrapcol=7, adobe=False),
+ b'zGB\\6`E\n-ZP=Df.\n1GEb>')
+ eq(base64.a85encode(b"www.python.org", wrapcol=7, adobe=True),
+ b'<~GB\\6`\nE-ZP=Df\n.1GEb>\n~>')
+
+ eq(base64.a85encode(b' '*8, foldspaces=True, adobe=False), b'yy')
+ eq(base64.a85encode(b' '*7, foldspaces=True, adobe=False), b'y+<Vd')
+ eq(base64.a85encode(b' '*6, foldspaces=True, adobe=False), b'y+<U')
+ eq(base64.a85encode(b' '*5, foldspaces=True, adobe=False), b'y+9')
+
+ def test_b85encode(self):
+ eq = self.assertEqual
+
+ tests = {
+ b'': b'',
+ b'www.python.org': b'cXxL#aCvlSZ*DGca%T',
+ bytes(range(255)): b"""009C61O)~M2nh-c3=Iws5D^j+6crX17#SKH9337X"""
+ b"""AR!_nBqb&%C@Cr{EG;fCFflSSG&MFiI5|2yJUu=?KtV!7L`6nNNJ&ad"""
+ b"""OifNtP*GA-R8>}2SXo+ITwPvYU}0ioWMyV&XlZI|Y;A6DaB*^Tbai%j"""
+ b"""czJqze0_d@fPsR8goTEOh>41ejE#<ukdcy;l$Dm3n3<ZJoSmMZprN9p"""
+ b"""q@|{(sHv)}tgWuEu(7hUw6(UkxVgH!yuH4^z`?@9#Kp$P$jQpf%+1cv"""
+ b"""(9zP<)YaD4*xB0K+}+;a;Njxq<mKk)=;`X~?CtLF@bU8V^!4`l`1$(#"""
+ b"""{Qdp""",
+ b"""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"""
+ b"""0123456789!@#0^&*();:<>,. []{}""":
+ b"""VPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3r%YLqtVJM@UIZOH55pPf$@("""
+ b"""Q&d$}S6EqEFflSSG&MFiI5{CeBQRbjDkv#CIy^osE+AW7dwl""",
+ b'no padding..': b'Zf_uPVPs@!Zf7no',
+ b'zero compression\x00\x00\x00\x00': b'dS!BNAY*TBaB^jHb7^mG00000',
+ b'zero compression\x00\x00\x00': b'dS!BNAY*TBaB^jHb7^mG0000',
+ b"""Boundary:\x00\x00\x00\x00""": b"""LT`0$WMOi7IsgCw00""",
+ b'Space compr: ': b'Q*dEpWgug3ZE$irARr(h',
+ b'\xff': b'{{',
+ b'\xff'*2: b'|Nj',
+ b'\xff'*3: b'|Ns9',
+ b'\xff'*4: b'|NsC0',
+ }
+
+ for data, res in tests.items():
+ eq(base64.b85encode(data), res)
+
+ self.check_other_types(base64.b85encode, b"www.python.org",
+ b'cXxL#aCvlSZ*DGca%T')
+
+ def test_a85decode(self):
+ eq = self.assertEqual
+
+ tests = {
+ b'': b'',
+ b'GB\\6`E-ZP=Df.1GEb>': b'www.python.org',
+ b"""! ! * -'"\n\t\t9eu\r\n7# RL\vhG$k3[W&.oNg'GVB"(`=52*$$"""
+ b"""(B+<_pR,UFcb-n-Vr/1iJ-0JP==1c70M3&s#]4?Ykm5X@_(6q'R884cE"""
+ b"""H9MJ8X:f1+h<)lt#=BSg3>[:ZC?t!MSA7]@cBPD3sCi+'.E,fo>FEMbN"""
+ b"""G^4U^I!pHnJ:W<)KS>/9Ll%"IN/`jYOHG]iPa.Q$R$jD4S=Q7DTV8*TU"""
+ b"""nsrdW2ZetXKAY/Yd(L?['d?O\\@K2_]Y2%o^qmn*`5Ta:aN;TJbg"GZd"""
+ b"""*^:jeCE.%f\\,!5gtgiEi8N\\UjQ5OekiqBum-X60nF?)@o_%qPq"ad`"""
+ b"""r;HT""": bytes(range(255)),
+ b"""@:E_WAS,RgBkhF"D/O92EH6,BF`qtRH$VbC6UX@47n?3D92&&T:Jand;c"""
+ b"""Hat='/U/0JP==1c70M3&r-I,;<FN.OZ`-3]oSW/g+A(H[P""":
+ b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234'
+ b'56789!@#0^&*();:<>,. []{}',
+ b'DJpY:@:Wn_DJ(RS': b'no padding..',
+ b'H=_,8+Cf>,E,oN2F(oQ1z': b'zero compression\x00\x00\x00\x00',
+ b'H=_,8+Cf>,E,oN2F(oQ1!!!!': b'zero compression\x00\x00\x00',
+ b'6>q!aA79M(3WK-[!!': b"Boundary:\x00\x00\x00\x00",
+ b';fH/TAKYK$D/aMV+<VdL': b'Space compr: ',
+ b'rr': b'\xff',
+ b's8N': b'\xff'*2,
+ b's8W*': b'\xff'*3,
+ b's8W-!': b'\xff'*4,
+ }
+
+ for data, res in tests.items():
+ eq(base64.a85decode(data), res, data)
+ eq(base64.a85decode(data, adobe=False), res, data)
+ eq(base64.a85decode(data.decode("ascii"), adobe=False), res, data)
+ eq(base64.a85decode(b'<~' + data + b'~>', adobe=True), res, data)
+ eq(base64.a85decode('<~%s~>' % data.decode("ascii"), adobe=True),
+ res, data)
+
+ eq(base64.a85decode(b'yy', foldspaces=True, adobe=False), b' '*8)
+ eq(base64.a85decode(b'y+<Vd', foldspaces=True, adobe=False), b' '*7)
+ eq(base64.a85decode(b'y+<U', foldspaces=True, adobe=False), b' '*6)
+ eq(base64.a85decode(b'y+9', foldspaces=True, adobe=False), b' '*5)
+
+ self.check_other_types(base64.a85decode, b'GB\\6`E-ZP=Df.1GEb>',
+ b"www.python.org")
+
+ def test_b85decode(self):
+ eq = self.assertEqual
+
+ tests = {
+ b'': b'',
+ b'cXxL#aCvlSZ*DGca%T': b'www.python.org',
+ b"""009C61O)~M2nh-c3=Iws5D^j+6crX17#SKH9337X"""
+ b"""AR!_nBqb&%C@Cr{EG;fCFflSSG&MFiI5|2yJUu=?KtV!7L`6nNNJ&ad"""
+ b"""OifNtP*GA-R8>}2SXo+ITwPvYU}0ioWMyV&XlZI|Y;A6DaB*^Tbai%j"""
+ b"""czJqze0_d@fPsR8goTEOh>41ejE#<ukdcy;l$Dm3n3<ZJoSmMZprN9p"""
+ b"""q@|{(sHv)}tgWuEu(7hUw6(UkxVgH!yuH4^z`?@9#Kp$P$jQpf%+1cv"""
+ b"""(9zP<)YaD4*xB0K+}+;a;Njxq<mKk)=;`X~?CtLF@bU8V^!4`l`1$(#"""
+ b"""{Qdp""": bytes(range(255)),
+ b"""VPa!sWoBn+X=-b1ZEkOHadLBXb#`}nd3r%YLqtVJM@UIZOH55pPf$@("""
+ b"""Q&d$}S6EqEFflSSG&MFiI5{CeBQRbjDkv#CIy^osE+AW7dwl""":
+ b"""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"""
+ b"""0123456789!@#0^&*();:<>,. []{}""",
+ b'Zf_uPVPs@!Zf7no': b'no padding..',
+ b'dS!BNAY*TBaB^jHb7^mG00000': b'zero compression\x00\x00\x00\x00',
+ b'dS!BNAY*TBaB^jHb7^mG0000': b'zero compression\x00\x00\x00',
+ b"""LT`0$WMOi7IsgCw00""": b"""Boundary:\x00\x00\x00\x00""",
+ b'Q*dEpWgug3ZE$irARr(h': b'Space compr: ',
+ b'{{': b'\xff',
+ b'|Nj': b'\xff'*2,
+ b'|Ns9': b'\xff'*3,
+ b'|NsC0': b'\xff'*4,
+ }
+
+ for data, res in tests.items():
+ eq(base64.b85decode(data), res)
+ eq(base64.b85decode(data.decode("ascii")), res)
+
+ self.check_other_types(base64.b85decode, b'cXxL#aCvlSZ*DGca%T',
+ b"www.python.org")
+
+ def test_a85_padding(self):
+ eq = self.assertEqual
+
+ eq(base64.a85encode(b"x", pad=True), b'GQ7^D')
+ eq(base64.a85encode(b"xx", pad=True), b"G^'2g")
+ eq(base64.a85encode(b"xxx", pad=True), b'G^+H5')
+ eq(base64.a85encode(b"xxxx", pad=True), b'G^+IX')
+ eq(base64.a85encode(b"xxxxx", pad=True), b'G^+IXGQ7^D')
+
+ eq(base64.a85decode(b'GQ7^D'), b"x\x00\x00\x00")
+ eq(base64.a85decode(b"G^'2g"), b"xx\x00\x00")
+ eq(base64.a85decode(b'G^+H5'), b"xxx\x00")
+ eq(base64.a85decode(b'G^+IX'), b"xxxx")
+ eq(base64.a85decode(b'G^+IXGQ7^D'), b"xxxxx\x00\x00\x00")
+
+ def test_b85_padding(self):
+ eq = self.assertEqual
+
+ eq(base64.b85encode(b"x", pad=True), b'cmMzZ')
+ eq(base64.b85encode(b"xx", pad=True), b'cz6H+')
+ eq(base64.b85encode(b"xxx", pad=True), b'czAdK')
+ eq(base64.b85encode(b"xxxx", pad=True), b'czAet')
+ eq(base64.b85encode(b"xxxxx", pad=True), b'czAetcmMzZ')
+
+ eq(base64.b85decode(b'cmMzZ'), b"x\x00\x00\x00")
+ eq(base64.b85decode(b'cz6H+'), b"xx\x00\x00")
+ eq(base64.b85decode(b'czAdK'), b"xxx\x00")
+ eq(base64.b85decode(b'czAet'), b"xxxx")
+ eq(base64.b85decode(b'czAetcmMzZ'), b"xxxxx\x00\x00\x00")
+
+ def test_a85decode_errors(self):
+ illegal = (set(range(32)) | set(range(118, 256))) - set(b' \t\n\r\v')
+ for c in illegal:
+ with self.assertRaises(ValueError, msg=bytes([c])):
+ base64.a85decode(b'!!!!' + bytes([c]))
+ with self.assertRaises(ValueError, msg=bytes([c])):
+ base64.a85decode(b'!!!!' + bytes([c]), adobe=False)
+ with self.assertRaises(ValueError, msg=bytes([c])):
+ base64.a85decode(b'<~!!!!' + bytes([c]) + b'~>', adobe=True)
+
+ self.assertRaises(ValueError, base64.a85decode,
+ b"malformed", adobe=True)
+ self.assertRaises(ValueError, base64.a85decode,
+ b"<~still malformed", adobe=True)
+ self.assertRaises(ValueError, base64.a85decode,
+ b"also malformed~>", adobe=True)
+
+ # With adobe=False (the default), Adobe framing markers are disallowed
+ self.assertRaises(ValueError, base64.a85decode,
+ b"<~~>")
+ self.assertRaises(ValueError, base64.a85decode,
+ b"<~~>", adobe=False)
+ base64.a85decode(b"<~~>", adobe=True) # sanity check
+
+ self.assertRaises(ValueError, base64.a85decode,
+ b"abcx", adobe=False)
+ self.assertRaises(ValueError, base64.a85decode,
+ b"abcdey", adobe=False)
+ self.assertRaises(ValueError, base64.a85decode,
+ b"a b\nc", adobe=False, ignorechars=b"")
+
+ self.assertRaises(ValueError, base64.a85decode, b's', adobe=False)
+ self.assertRaises(ValueError, base64.a85decode, b's8', adobe=False)
+ self.assertRaises(ValueError, base64.a85decode, b's8W', adobe=False)
+ self.assertRaises(ValueError, base64.a85decode, b's8W-', adobe=False)
+ self.assertRaises(ValueError, base64.a85decode, b's8W-"', adobe=False)
+
+ def test_b85decode_errors(self):
+ illegal = list(range(33)) + \
+ list(b'"\',./:[\\]') + \
+ list(range(128, 256))
+ for c in illegal:
+ with self.assertRaises(ValueError, msg=bytes([c])):
+ base64.b85decode(b'0000' + bytes([c]))
+
+ self.assertRaises(ValueError, base64.b85decode, b'|')
+ self.assertRaises(ValueError, base64.b85decode, b'|N')
+ self.assertRaises(ValueError, base64.b85decode, b'|Ns')
+ self.assertRaises(ValueError, base64.b85decode, b'|NsC')
+ self.assertRaises(ValueError, base64.b85decode, b'|NsC1')
+
def test_decode_nonascii_str(self):
decode_funcs = (base64.b64decode,
base64.standard_b64decode,
base64.urlsafe_b64decode,
base64.b32decode,
- base64.b16decode)
+ base64.b16decode,
+ base64.b85decode,
+ base64.a85decode)
for f in decode_funcs:
self.assertRaises(ValueError, f, 'with non-ascii \xcb')