1"""
2Tests for uu module.
3Nick Mathewson
4"""
5
6import unittest
7from test import test_support as support
8
9import cStringIO
10import sys
11import uu
12
13plaintext = "The smooth-scaled python crept over the sleeping dog\n"
14
15encodedtext = """\
16M5&AE('-M;V]T:\"US8V%L960@<'ET:&]N(&-R97!T(&]V97(@=&AE('-L965P
17(:6YG(&1O9PH """
18
19encodedtextwrapped = "begin %03o %s\n" + encodedtext.replace("%", "%%") + "\n \nend\n"
20
21class UUTest(unittest.TestCase):
22
23    def test_encode(self):
24        inp = cStringIO.StringIO(plaintext)
25        out = cStringIO.StringIO()
26        uu.encode(inp, out, "t1")
27        self.assertEqual(out.getvalue(), encodedtextwrapped % (0666, "t1"))
28        inp = cStringIO.StringIO(plaintext)
29        out = cStringIO.StringIO()
30        uu.encode(inp, out, "t1", 0644)
31        self.assertEqual(out.getvalue(), encodedtextwrapped % (0644, "t1"))
32
33    def test_decode(self):
34        inp = cStringIO.StringIO(encodedtextwrapped % (0666, "t1"))
35        out = cStringIO.StringIO()
36        uu.decode(inp, out)
37        self.assertEqual(out.getvalue(), plaintext)
38        inp = cStringIO.StringIO(
39            "UUencoded files may contain many lines,\n" +
40            "even some that have 'begin' in them.\n" +
41            encodedtextwrapped % (0666, "t1")
42        )
43        out = cStringIO.StringIO()
44        uu.decode(inp, out)
45        self.assertEqual(out.getvalue(), plaintext)
46
47    def test_truncatedinput(self):
48        inp = cStringIO.StringIO("begin 644 t1\n" + encodedtext)
49        out = cStringIO.StringIO()
50        try:
51            uu.decode(inp, out)
52            self.fail("No exception raised")
53        except uu.Error, e:
54            self.assertEqual(str(e), "Truncated input file")
55
56    def test_missingbegin(self):
57        inp = cStringIO.StringIO("")
58        out = cStringIO.StringIO()
59        try:
60            uu.decode(inp, out)
61            self.fail("No exception raised")
62        except uu.Error, e:
63            self.assertEqual(str(e), "No valid begin line found in input file")
64
65    def test_garbage_padding(self):
66        # Issue #22406
67        encodedtext = (
68            "begin 644 file\n"
69            # length 1; bits 001100 111111 111111 111111
70            "\x21\x2C\x5F\x5F\x5F\n"
71            "\x20\n"
72            "end\n"
73        )
74        plaintext = "\x33"  # 00110011
75
76        inp = cStringIO.StringIO(encodedtext)
77        out = cStringIO.StringIO()
78        uu.decode(inp, out, quiet=True)
79        self.assertEqual(out.getvalue(), plaintext)
80
81        import codecs
82        decoded = codecs.decode(encodedtext, "uu_codec")
83        self.assertEqual(decoded, plaintext)
84
85class UUStdIOTest(unittest.TestCase):
86
87    def setUp(self):
88        self.stdin = sys.stdin
89        self.stdout = sys.stdout
90
91    def tearDown(self):
92        sys.stdin = self.stdin
93        sys.stdout = self.stdout
94
95    def test_encode(self):
96        sys.stdin = cStringIO.StringIO(plaintext)
97        sys.stdout = cStringIO.StringIO()
98        uu.encode("-", "-", "t1", 0666)
99        self.assertEqual(
100            sys.stdout.getvalue(),
101            encodedtextwrapped % (0666, "t1")
102        )
103
104    def test_decode(self):
105        sys.stdin = cStringIO.StringIO(encodedtextwrapped % (0666, "t1"))
106        sys.stdout = cStringIO.StringIO()
107        uu.decode("-", "-")
108        self.assertEqual(sys.stdout.getvalue(), plaintext)
109
110class UUFileTest(unittest.TestCase):
111
112    def setUp(self):
113        self.tmpin  = support.TESTFN + "i"
114        self.tmpout = support.TESTFN + "o"
115        self.addCleanup(support.unlink, self.tmpin)
116        self.addCleanup(support.unlink, self.tmpout)
117
118    def test_encode(self):
119        with open(self.tmpin, 'wb') as fin:
120            fin.write(plaintext)
121
122        with open(self.tmpin, 'rb') as fin:
123            with open(self.tmpout, 'w') as fout:
124                uu.encode(fin, fout, self.tmpin, mode=0o644)
125
126        with open(self.tmpout, 'r') as fout:
127            s = fout.read()
128        self.assertEqual(s, encodedtextwrapped % (0o644, self.tmpin))
129
130        # in_file and out_file as filenames
131        uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
132        with open(self.tmpout, 'r') as fout:
133            s = fout.read()
134        self.assertEqual(s, encodedtextwrapped % (0o644, self.tmpin))
135
136    def test_decode(self):
137        with open(self.tmpin, 'w') as f:
138            f.write(encodedtextwrapped % (0o644, self.tmpout))
139
140        with open(self.tmpin, 'r') as f:
141            uu.decode(f)
142
143        with open(self.tmpout, 'r') as f:
144            s = f.read()
145        self.assertEqual(s, plaintext)
146        # XXX is there an xp way to verify the mode?
147
148    def test_decode_filename(self):
149        with open(self.tmpin, 'w') as f:
150            f.write(encodedtextwrapped % (0o644, self.tmpout))
151
152        uu.decode(self.tmpin)
153
154        with open(self.tmpout, 'r') as f:
155            s = f.read()
156        self.assertEqual(s, plaintext)
157
158    def test_decodetwice(self):
159        # Verify that decode() will refuse to overwrite an existing file
160        with open(self.tmpin, 'wb') as f:
161            f.write(encodedtextwrapped % (0o644, self.tmpout))
162        with open(self.tmpin, 'r') as f:
163            uu.decode(f)
164
165        with open(self.tmpin, 'r') as f:
166            self.assertRaises(uu.Error, uu.decode, f)
167
168def test_main():
169    support.run_unittest(UUTest, UUStdIOTest, UUFileTest)
170
171if __name__=="__main__":
172    test_main()
173