Home | History | Annotate | Download | only in test
      1 """
      2 Tests for uu module.
      3 Nick Mathewson
      4 """
      5 
      6 import unittest
      7 from test import support
      8 
      9 import sys, os
     10 import uu
     11 import io
     12 
     13 plaintext = b"The smooth-scaled python crept over the sleeping dog\n"
     14 
     15 encodedtext = b"""\
     16 M5&AE('-M;V]T:\"US8V%L960@<'ET:&]N(&-R97!T(&]V97(@=&AE('-L965P
     17 (:6YG(&1O9PH """
     18 
     19 # Stolen from io.py
     20 class FakeIO(io.TextIOWrapper):
     21     """Text I/O implementation using an in-memory buffer.
     22 
     23     Can be a used as a drop-in replacement for sys.stdin and sys.stdout.
     24     """
     25 
     26     # XXX This is really slow, but fully functional
     27 
     28     def __init__(self, initial_value="", encoding="utf-8",
     29                  errors="strict", newline="\n"):
     30         super(FakeIO, self).__init__(io.BytesIO(),
     31                                      encoding=encoding,
     32                                      errors=errors,
     33                                      newline=newline)
     34         self._encoding = encoding
     35         self._errors = errors
     36         if initial_value:
     37             if not isinstance(initial_value, str):
     38                 initial_value = str(initial_value)
     39             self.write(initial_value)
     40             self.seek(0)
     41 
     42     def getvalue(self):
     43         self.flush()
     44         return self.buffer.getvalue().decode(self._encoding, self._errors)
     45 
     46 
     47 def encodedtextwrapped(mode, filename):
     48     return (bytes("begin %03o %s\n" % (mode, filename), "ascii") +
     49             encodedtext + b"\n \nend\n")
     50 
     51 class UUTest(unittest.TestCase):
     52 
     53     def test_encode(self):
     54         inp = io.BytesIO(plaintext)
     55         out = io.BytesIO()
     56         uu.encode(inp, out, "t1")
     57         self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1"))
     58         inp = io.BytesIO(plaintext)
     59         out = io.BytesIO()
     60         uu.encode(inp, out, "t1", 0o644)
     61         self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1"))
     62 
     63     def test_decode(self):
     64         inp = io.BytesIO(encodedtextwrapped(0o666, "t1"))
     65         out = io.BytesIO()
     66         uu.decode(inp, out)
     67         self.assertEqual(out.getvalue(), plaintext)
     68         inp = io.BytesIO(
     69             b"UUencoded files may contain many lines,\n" +
     70             b"even some that have 'begin' in them.\n" +
     71             encodedtextwrapped(0o666, "t1")
     72         )
     73         out = io.BytesIO()
     74         uu.decode(inp, out)
     75         self.assertEqual(out.getvalue(), plaintext)
     76 
     77     def test_truncatedinput(self):
     78         inp = io.BytesIO(b"begin 644 t1\n" + encodedtext)
     79         out = io.BytesIO()
     80         try:
     81             uu.decode(inp, out)
     82             self.fail("No exception raised")
     83         except uu.Error as e:
     84             self.assertEqual(str(e), "Truncated input file")
     85 
     86     def test_missingbegin(self):
     87         inp = io.BytesIO(b"")
     88         out = io.BytesIO()
     89         try:
     90             uu.decode(inp, out)
     91             self.fail("No exception raised")
     92         except uu.Error as e:
     93             self.assertEqual(str(e), "No valid begin line found in input file")
     94 
     95     def test_garbage_padding(self):
     96         # Issue #22406
     97         encodedtext = (
     98             b"begin 644 file\n"
     99             # length 1; bits 001100 111111 111111 111111
    100             b"\x21\x2C\x5F\x5F\x5F\n"
    101             b"\x20\n"
    102             b"end\n"
    103         )
    104         plaintext = b"\x33"  # 00110011
    105 
    106         with self.subTest("uu.decode()"):
    107             inp = io.BytesIO(encodedtext)
    108             out = io.BytesIO()
    109             uu.decode(inp, out, quiet=True)
    110             self.assertEqual(out.getvalue(), plaintext)
    111 
    112         with self.subTest("uu_codec"):
    113             import codecs
    114             decoded = codecs.decode(encodedtext, "uu_codec")
    115             self.assertEqual(decoded, plaintext)
    116 
    117 class UUStdIOTest(unittest.TestCase):
    118 
    119     def setUp(self):
    120         self.stdin = sys.stdin
    121         self.stdout = sys.stdout
    122 
    123     def tearDown(self):
    124         sys.stdin = self.stdin
    125         sys.stdout = self.stdout
    126 
    127     def test_encode(self):
    128         sys.stdin = FakeIO(plaintext.decode("ascii"))
    129         sys.stdout = FakeIO()
    130         uu.encode("-", "-", "t1", 0o666)
    131         self.assertEqual(sys.stdout.getvalue(),
    132                          encodedtextwrapped(0o666, "t1").decode("ascii"))
    133 
    134     def test_decode(self):
    135         sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1").decode("ascii"))
    136         sys.stdout = FakeIO()
    137         uu.decode("-", "-")
    138         stdout = sys.stdout
    139         sys.stdout = self.stdout
    140         sys.stdin = self.stdin
    141         self.assertEqual(stdout.getvalue(), plaintext.decode("ascii"))
    142 
    143 class UUFileTest(unittest.TestCase):
    144 
    145     def _kill(self, f):
    146         # close and remove file
    147         if f is None:
    148             return
    149         try:
    150             f.close()
    151         except (SystemExit, KeyboardInterrupt):
    152             raise
    153         except:
    154             pass
    155         try:
    156             os.unlink(f.name)
    157         except (SystemExit, KeyboardInterrupt):
    158             raise
    159         except:
    160             pass
    161 
    162     def setUp(self):
    163         self.tmpin  = support.TESTFN + "i"
    164         self.tmpout = support.TESTFN + "o"
    165 
    166     def tearDown(self):
    167         del self.tmpin
    168         del self.tmpout
    169 
    170     def test_encode(self):
    171         fin = fout = None
    172         try:
    173             support.unlink(self.tmpin)
    174             fin = open(self.tmpin, 'wb')
    175             fin.write(plaintext)
    176             fin.close()
    177 
    178             fin = open(self.tmpin, 'rb')
    179             fout = open(self.tmpout, 'wb')
    180             uu.encode(fin, fout, self.tmpin, mode=0o644)
    181             fin.close()
    182             fout.close()
    183 
    184             fout = open(self.tmpout, 'rb')
    185             s = fout.read()
    186             fout.close()
    187             self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
    188 
    189             # in_file and out_file as filenames
    190             uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
    191             fout = open(self.tmpout, 'rb')
    192             s = fout.read()
    193             fout.close()
    194             self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
    195 
    196         finally:
    197             self._kill(fin)
    198             self._kill(fout)
    199 
    200     def test_decode(self):
    201         f = None
    202         try:
    203             support.unlink(self.tmpin)
    204             f = open(self.tmpin, 'wb')
    205             f.write(encodedtextwrapped(0o644, self.tmpout))
    206             f.close()
    207 
    208             f = open(self.tmpin, 'rb')
    209             uu.decode(f)
    210             f.close()
    211 
    212             f = open(self.tmpout, 'rb')
    213             s = f.read()
    214             f.close()
    215             self.assertEqual(s, plaintext)
    216             # XXX is there an xp way to verify the mode?
    217         finally:
    218             self._kill(f)
    219 
    220     def test_decode_filename(self):
    221         f = None
    222         try:
    223             support.unlink(self.tmpin)
    224             f = open(self.tmpin, 'wb')
    225             f.write(encodedtextwrapped(0o644, self.tmpout))
    226             f.close()
    227 
    228             uu.decode(self.tmpin)
    229 
    230             f = open(self.tmpout, 'rb')
    231             s = f.read()
    232             f.close()
    233             self.assertEqual(s, plaintext)
    234         finally:
    235             self._kill(f)
    236 
    237     def test_decodetwice(self):
    238         # Verify that decode() will refuse to overwrite an existing file
    239         f = None
    240         try:
    241             f = io.BytesIO(encodedtextwrapped(0o644, self.tmpout))
    242 
    243             f = open(self.tmpin, 'rb')
    244             uu.decode(f)
    245             f.close()
    246 
    247             f = open(self.tmpin, 'rb')
    248             self.assertRaises(uu.Error, uu.decode, f)
    249             f.close()
    250         finally:
    251             self._kill(f)
    252 
    253 def test_main():
    254     support.run_unittest(UUTest,
    255                               UUStdIOTest,
    256                               UUFileTest,
    257                               )
    258 
    259 if __name__=="__main__":
    260     test_main()
    261