blob: c9f05e5b760d922cfaddf4a509d2fbc317b8b97f [file] [log] [blame]
Tim Peters48dacc62001-07-11 21:43:42 +00001"""
2Tests for uu module.
3Nick Mathewson
4"""
5
Walter Dörwald411e5a22003-05-06 08:57:41 +00006import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00007from test import support
Walter Dörwald411e5a22003-05-06 08:57:41 +00008
Timo Furrer17f05bb2019-01-17 15:15:53 +01009import os
10import stat
Serhiy Storchaka027f95c2018-06-03 17:22:42 +030011import sys
Tim Peters48dacc62001-07-11 21:43:42 +000012import uu
Guido van Rossum34d19282007-08-09 01:03:29 +000013import io
Tim Peters48dacc62001-07-11 21:43:42 +000014
Xiang Zhang13f1f422017-05-03 11:16:21 +080015plaintext = b"The symbols on top of your keyboard are !@#$%^&*()_+|~\n"
Walter Dörwald411e5a22003-05-06 08:57:41 +000016
Guido van Rossum34d19282007-08-09 01:03:29 +000017encodedtext = b"""\
Xiang Zhang13f1f422017-05-03 11:16:21 +080018M5&AE('-Y;6)O;',@;VX@=&]P(&]F('EO=7(@:V5Y8F]A<F0@87)E("% (R0E
19*7B8J*"E?*WQ^"@ """
Tim Peters48dacc62001-07-11 21:43:42 +000020
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000021# Stolen from io.py
22class FakeIO(io.TextIOWrapper):
23 """Text I/O implementation using an in-memory buffer.
24
25 Can be a used as a drop-in replacement for sys.stdin and sys.stdout.
26 """
27
28 # XXX This is really slow, but fully functional
29
30 def __init__(self, initial_value="", encoding="utf-8",
31 errors="strict", newline="\n"):
32 super(FakeIO, self).__init__(io.BytesIO(),
33 encoding=encoding,
34 errors=errors,
35 newline=newline)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000036 self._encoding = encoding
37 self._errors = errors
Alexandre Vassalotti794652d2008-06-11 22:58:36 +000038 if initial_value:
39 if not isinstance(initial_value, str):
40 initial_value = str(initial_value)
41 self.write(initial_value)
42 self.seek(0)
43
44 def getvalue(self):
45 self.flush()
46 return self.buffer.getvalue().decode(self._encoding, self._errors)
47
48
Xiang Zhang13f1f422017-05-03 11:16:21 +080049def encodedtextwrapped(mode, filename, backtick=False):
50 if backtick:
51 res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
52 encodedtext.replace(b' ', b'`') + b"\n`\nend\n")
53 else:
54 res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
55 encodedtext + b"\n \nend\n")
56 return res
Tim Peters48dacc62001-07-11 21:43:42 +000057
Walter Dörwald411e5a22003-05-06 08:57:41 +000058class UUTest(unittest.TestCase):
Tim Peters48dacc62001-07-11 21:43:42 +000059
Walter Dörwald411e5a22003-05-06 08:57:41 +000060 def test_encode(self):
Guido van Rossum34d19282007-08-09 01:03:29 +000061 inp = io.BytesIO(plaintext)
62 out = io.BytesIO()
Walter Dörwald411e5a22003-05-06 08:57:41 +000063 uu.encode(inp, out, "t1")
Guido van Rossum34d19282007-08-09 01:03:29 +000064 self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1"))
65 inp = io.BytesIO(plaintext)
66 out = io.BytesIO()
Guido van Rossumcd16bf62007-06-13 18:07:49 +000067 uu.encode(inp, out, "t1", 0o644)
Guido van Rossum34d19282007-08-09 01:03:29 +000068 self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1"))
Xiang Zhang13f1f422017-05-03 11:16:21 +080069 inp = io.BytesIO(plaintext)
70 out = io.BytesIO()
71 uu.encode(inp, out, "t1", backtick=True)
72 self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1", True))
73 with self.assertRaises(TypeError):
74 uu.encode(inp, out, "t1", 0o644, True)
Tim Peters48dacc62001-07-11 21:43:42 +000075
Walter Dörwald411e5a22003-05-06 08:57:41 +000076 def test_decode(self):
Xiang Zhang13f1f422017-05-03 11:16:21 +080077 for backtick in True, False:
78 inp = io.BytesIO(encodedtextwrapped(0o666, "t1", backtick=backtick))
79 out = io.BytesIO()
80 uu.decode(inp, out)
81 self.assertEqual(out.getvalue(), plaintext)
82 inp = io.BytesIO(
83 b"UUencoded files may contain many lines,\n" +
84 b"even some that have 'begin' in them.\n" +
85 encodedtextwrapped(0o666, "t1", backtick=backtick)
86 )
87 out = io.BytesIO()
88 uu.decode(inp, out)
89 self.assertEqual(out.getvalue(), plaintext)
Tim Peters48dacc62001-07-11 21:43:42 +000090
Walter Dörwald411e5a22003-05-06 08:57:41 +000091 def test_truncatedinput(self):
Guido van Rossum34d19282007-08-09 01:03:29 +000092 inp = io.BytesIO(b"begin 644 t1\n" + encodedtext)
93 out = io.BytesIO()
Walter Dörwald411e5a22003-05-06 08:57:41 +000094 try:
95 uu.decode(inp, out)
Andrew Svetlov737fb892012-12-18 21:14:22 +020096 self.fail("No exception raised")
Guido van Rossumb940e112007-01-10 16:19:56 +000097 except uu.Error as e:
Walter Dörwald411e5a22003-05-06 08:57:41 +000098 self.assertEqual(str(e), "Truncated input file")
Tim Peters48dacc62001-07-11 21:43:42 +000099
Walter Dörwald411e5a22003-05-06 08:57:41 +0000100 def test_missingbegin(self):
Guido van Rossum34d19282007-08-09 01:03:29 +0000101 inp = io.BytesIO(b"")
102 out = io.BytesIO()
Walter Dörwald411e5a22003-05-06 08:57:41 +0000103 try:
104 uu.decode(inp, out)
Andrew Svetlov737fb892012-12-18 21:14:22 +0200105 self.fail("No exception raised")
Guido van Rossumb940e112007-01-10 16:19:56 +0000106 except uu.Error as e:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000107 self.assertEqual(str(e), "No valid begin line found in input file")
Tim Peters48dacc62001-07-11 21:43:42 +0000108
Serhiy Storchaka519114d2014-11-07 14:04:37 +0200109 def test_garbage_padding(self):
110 # Issue #22406
Xiang Zhang13f1f422017-05-03 11:16:21 +0800111 encodedtext1 = (
Serhiy Storchaka519114d2014-11-07 14:04:37 +0200112 b"begin 644 file\n"
113 # length 1; bits 001100 111111 111111 111111
114 b"\x21\x2C\x5F\x5F\x5F\n"
115 b"\x20\n"
116 b"end\n"
117 )
Xiang Zhang13f1f422017-05-03 11:16:21 +0800118 encodedtext2 = (
119 b"begin 644 file\n"
120 # length 1; bits 001100 111111 111111 111111
121 b"\x21\x2C\x5F\x5F\x5F\n"
122 b"\x60\n"
123 b"end\n"
124 )
Serhiy Storchaka519114d2014-11-07 14:04:37 +0200125 plaintext = b"\x33" # 00110011
126
Xiang Zhang13f1f422017-05-03 11:16:21 +0800127 for encodedtext in encodedtext1, encodedtext2:
128 with self.subTest("uu.decode()"):
129 inp = io.BytesIO(encodedtext)
130 out = io.BytesIO()
131 uu.decode(inp, out, quiet=True)
132 self.assertEqual(out.getvalue(), plaintext)
Serhiy Storchaka519114d2014-11-07 14:04:37 +0200133
Xiang Zhang13f1f422017-05-03 11:16:21 +0800134 with self.subTest("uu_codec"):
135 import codecs
136 decoded = codecs.decode(encodedtext, "uu_codec")
137 self.assertEqual(decoded, plaintext)
Serhiy Storchaka519114d2014-11-07 14:04:37 +0200138
Walter Dörwald411e5a22003-05-06 08:57:41 +0000139class UUStdIOTest(unittest.TestCase):
Tim Peters48dacc62001-07-11 21:43:42 +0000140
Walter Dörwald411e5a22003-05-06 08:57:41 +0000141 def setUp(self):
142 self.stdin = sys.stdin
143 self.stdout = sys.stdout
Tim Peters48dacc62001-07-11 21:43:42 +0000144
Walter Dörwald411e5a22003-05-06 08:57:41 +0000145 def tearDown(self):
146 sys.stdin = self.stdin
147 sys.stdout = self.stdout
Barry Warsawd1795702001-08-17 20:00:11 +0000148
Walter Dörwald411e5a22003-05-06 08:57:41 +0000149 def test_encode(self):
Alexandre Vassalotti794652d2008-06-11 22:58:36 +0000150 sys.stdin = FakeIO(plaintext.decode("ascii"))
151 sys.stdout = FakeIO()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000152 uu.encode("-", "-", "t1", 0o666)
Guido van Rossum34d19282007-08-09 01:03:29 +0000153 self.assertEqual(sys.stdout.getvalue(),
154 encodedtextwrapped(0o666, "t1").decode("ascii"))
Walter Dörwald411e5a22003-05-06 08:57:41 +0000155
156 def test_decode(self):
Alexandre Vassalotti794652d2008-06-11 22:58:36 +0000157 sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1").decode("ascii"))
158 sys.stdout = FakeIO()
Walter Dörwald411e5a22003-05-06 08:57:41 +0000159 uu.decode("-", "-")
Guido van Rossum34d19282007-08-09 01:03:29 +0000160 stdout = sys.stdout
161 sys.stdout = self.stdout
162 sys.stdin = self.stdin
163 self.assertEqual(stdout.getvalue(), plaintext.decode("ascii"))
Walter Dörwald411e5a22003-05-06 08:57:41 +0000164
165class UUFileTest(unittest.TestCase):
166
Walter Dörwald411e5a22003-05-06 08:57:41 +0000167 def setUp(self):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000168 self.tmpin = support.TESTFN + "i"
169 self.tmpout = support.TESTFN + "o"
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300170 self.addCleanup(support.unlink, self.tmpin)
171 self.addCleanup(support.unlink, self.tmpout)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000172
173 def test_encode(self):
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300174 with open(self.tmpin, 'wb') as fin:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000175 fin.write(plaintext)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000176
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300177 with open(self.tmpin, 'rb') as fin:
178 with open(self.tmpout, 'wb') as fout:
179 uu.encode(fin, fout, self.tmpin, mode=0o644)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000180
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300181 with open(self.tmpout, 'rb') as fout:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000182 s = fout.read()
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300183 self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
Walter Dörwald705fd472005-11-21 18:55:56 +0000184
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300185 # in_file and out_file as filenames
186 uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
187 with open(self.tmpout, 'rb') as fout:
Walter Dörwald705fd472005-11-21 18:55:56 +0000188 s = fout.read()
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300189 self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
Walter Dörwald411e5a22003-05-06 08:57:41 +0000190
191 def test_decode(self):
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300192 with open(self.tmpin, 'wb') as f:
Guido van Rossum34d19282007-08-09 01:03:29 +0000193 f.write(encodedtextwrapped(0o644, self.tmpout))
Walter Dörwald411e5a22003-05-06 08:57:41 +0000194
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300195 with open(self.tmpin, 'rb') as f:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000196 uu.decode(f)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000197
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300198 with open(self.tmpout, 'rb') as f:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000199 s = f.read()
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300200 self.assertEqual(s, plaintext)
201 # XXX is there an xp way to verify the mode?
Walter Dörwald411e5a22003-05-06 08:57:41 +0000202
Antoine Pitrouf5698262010-10-31 16:04:14 +0000203 def test_decode_filename(self):
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300204 with open(self.tmpin, 'wb') as f:
Antoine Pitrouf5698262010-10-31 16:04:14 +0000205 f.write(encodedtextwrapped(0o644, self.tmpout))
Antoine Pitrouf5698262010-10-31 16:04:14 +0000206
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300207 uu.decode(self.tmpin)
Antoine Pitrouf5698262010-10-31 16:04:14 +0000208
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300209 with open(self.tmpout, 'rb') as f:
Antoine Pitrouf5698262010-10-31 16:04:14 +0000210 s = f.read()
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300211 self.assertEqual(s, plaintext)
Antoine Pitrouf5698262010-10-31 16:04:14 +0000212
Walter Dörwald411e5a22003-05-06 08:57:41 +0000213 def test_decodetwice(self):
214 # Verify that decode() will refuse to overwrite an existing file
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300215 with open(self.tmpin, 'wb') as f:
216 f.write(encodedtextwrapped(0o644, self.tmpout))
217 with open(self.tmpin, 'rb') as f:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000218 uu.decode(f)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000219
Serhiy Storchaka027f95c2018-06-03 17:22:42 +0300220 with open(self.tmpin, 'rb') as f:
Walter Dörwald411e5a22003-05-06 08:57:41 +0000221 self.assertRaises(uu.Error, uu.decode, f)
Walter Dörwald411e5a22003-05-06 08:57:41 +0000222
Timo Furrer17f05bb2019-01-17 15:15:53 +0100223 def test_decode_mode(self):
224 # Verify that decode() will set the given mode for the out_file
225 expected_mode = 0o444
226 with open(self.tmpin, 'wb') as f:
227 f.write(encodedtextwrapped(expected_mode, self.tmpout))
228
229 # make file writable again, so it can be removed (Windows only)
230 self.addCleanup(os.chmod, self.tmpout, expected_mode | stat.S_IWRITE)
231
232 with open(self.tmpin, 'rb') as f:
233 uu.decode(f)
234
235 self.assertEqual(
236 stat.S_IMODE(os.stat(self.tmpout).st_mode),
237 expected_mode
238 )
239
Walter Dörwald411e5a22003-05-06 08:57:41 +0000240
241if __name__=="__main__":
Xiang Zhang13f1f422017-05-03 11:16:21 +0800242 unittest.main()