Home | History | Annotate | Download | only in test
      1 from test import test_support
      2 import unittest
      3 
      4 import sys, cStringIO, subprocess
      5 import quopri
      6 
      7 
      8 
      9 ENCSAMPLE = """\
     10 Here's a bunch of special=20
     11 
     12 =A1=A2=A3=A4=A5=A6=A7=A8=A9
     13 =AA=AB=AC=AD=AE=AF=B0=B1=B2=B3
     14 =B4=B5=B6=B7=B8=B9=BA=BB=BC=BD=BE
     15 =BF=C0=C1=C2=C3=C4=C5=C6
     16 =C7=C8=C9=CA=CB=CC=CD=CE=CF
     17 =D0=D1=D2=D3=D4=D5=D6=D7
     18 =D8=D9=DA=DB=DC=DD=DE=DF
     19 =E0=E1=E2=E3=E4=E5=E6=E7
     20 =E8=E9=EA=EB=EC=ED=EE=EF
     21 =F0=F1=F2=F3=F4=F5=F6=F7
     22 =F8=F9=FA=FB=FC=FD=FE=FF
     23 
     24 characters... have fun!
     25 """
     26 
     27 # First line ends with a space
     28 DECSAMPLE = "Here's a bunch of special \n" + \
     29 """\
     30 
     31 \xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9
     32 \xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3
     33 \xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe
     34 \xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6
     35 \xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf
     36 \xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7
     37 \xd8\xd9\xda\xdb\xdc\xdd\xde\xdf
     38 \xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7
     39 \xe8\xe9\xea\xeb\xec\xed\xee\xef
     40 \xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7
     41 \xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
     42 
     43 characters... have fun!
     44 """
     45 
     46 
     47 def withpythonimplementation(testfunc):
     48     def newtest(self):
     49         # Test default implementation
     50         testfunc(self)
     51         # Test Python implementation
     52         if quopri.b2a_qp is not None or quopri.a2b_qp is not None:
     53             oldencode = quopri.b2a_qp
     54             olddecode = quopri.a2b_qp
     55             try:
     56                 quopri.b2a_qp = None
     57                 quopri.a2b_qp = None
     58                 testfunc(self)
     59             finally:
     60                 quopri.b2a_qp = oldencode
     61                 quopri.a2b_qp = olddecode
     62     newtest.__name__ = testfunc.__name__
     63     return newtest
     64 
     65 class QuopriTestCase(unittest.TestCase):
     66     # Each entry is a tuple of (plaintext, encoded string).  These strings are
     67     # used in the "quotetabs=0" tests.
     68     STRINGS = (
     69         # Some normal strings
     70         ('hello', 'hello'),
     71         ('''hello
     72         there
     73         world''', '''hello
     74         there
     75         world'''),
     76         ('''hello
     77         there
     78         world
     79 ''', '''hello
     80         there
     81         world
     82 '''),
     83         ('\201\202\203', '=81=82=83'),
     84         # Add some trailing MUST QUOTE strings
     85         ('hello ', 'hello=20'),
     86         ('hello\t', 'hello=09'),
     87         # Some long lines.  First, a single line of 108 characters
     88         ('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\xd8\xd9\xda\xdb\xdc\xdd\xde\xdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
     89          '''xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=D8=D9=DA=DB=DC=DD=DE=DFx=
     90 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'''),
     91         # A line of exactly 76 characters, no soft line break should be needed
     92         ('yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
     93         'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'),
     94         # A line of 77 characters, forcing a soft line break at position 75,
     95         # and a second line of exactly 2 characters (because the soft line
     96         # break `=' sign counts against the line length limit).
     97         ('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
     98          '''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
     99 zz'''),
    100         # A line of 151 characters, forcing a soft line break at position 75,
    101         # with a second line of exactly 76 characters and no trailing =
    102         ('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
    103          '''zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz=
    104 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''),
    105         # A string containing a hard line break, but which the first line is
    106         # 151 characters and the second line is exactly 76 characters.  This
    107         # should leave us with three lines, the first which has a soft line
    108         # break, and which the second and third do not.
    109         ('''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
    110 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''',
    111          '''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy=
    112 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
    113 zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'''),
    114         # Now some really complex stuff ;)
    115         (DECSAMPLE, ENCSAMPLE),
    116         )
    117 
    118     # These are used in the "quotetabs=1" tests.
    119     ESTRINGS = (
    120         ('hello world', 'hello=20world'),
    121         ('hello\tworld', 'hello=09world'),
    122         )
    123 
    124     # These are used in the "header=1" tests.
    125     HSTRINGS = (
    126         ('hello world', 'hello_world'),
    127         ('hello_world', 'hello=5Fworld'),
    128         )
    129 
    130     @withpythonimplementation
    131     def test_encodestring(self):
    132         for p, e in self.STRINGS:
    133             self.assertTrue(quopri.encodestring(p) == e)
    134 
    135     @withpythonimplementation
    136     def test_decodestring(self):
    137         for p, e in self.STRINGS:
    138             self.assertTrue(quopri.decodestring(e) == p)
    139 
    140     @withpythonimplementation
    141     def test_idempotent_string(self):
    142         for p, e in self.STRINGS:
    143             self.assertTrue(quopri.decodestring(quopri.encodestring(e)) == e)
    144 
    145     @withpythonimplementation
    146     def test_encode(self):
    147         for p, e in self.STRINGS:
    148             infp = cStringIO.StringIO(p)
    149             outfp = cStringIO.StringIO()
    150             quopri.encode(infp, outfp, quotetabs=False)
    151             self.assertTrue(outfp.getvalue() == e)
    152 
    153     @withpythonimplementation
    154     def test_decode(self):
    155         for p, e in self.STRINGS:
    156             infp = cStringIO.StringIO(e)
    157             outfp = cStringIO.StringIO()
    158             quopri.decode(infp, outfp)
    159             self.assertTrue(outfp.getvalue() == p)
    160 
    161     @withpythonimplementation
    162     def test_embedded_ws(self):
    163         for p, e in self.ESTRINGS:
    164             self.assertTrue(quopri.encodestring(p, quotetabs=True) == e)
    165             self.assertTrue(quopri.decodestring(e) == p)
    166 
    167     @withpythonimplementation
    168     def test_encode_header(self):
    169         for p, e in self.HSTRINGS:
    170             self.assertTrue(quopri.encodestring(p, header=True) == e)
    171 
    172     @withpythonimplementation
    173     def test_decode_header(self):
    174         for p, e in self.HSTRINGS:
    175             self.assertTrue(quopri.decodestring(e, header=True) == p)
    176 
    177     def test_scriptencode(self):
    178         (p, e) = self.STRINGS[-1]
    179         process = subprocess.Popen([sys.executable, "-mquopri"],
    180                                    stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    181         self.addCleanup(process.stdout.close)
    182         cout, cerr = process.communicate(p)
    183         # On Windows, Python will output the result to stdout using
    184         # CRLF, as the mode of stdout is text mode. To compare this
    185         # with the expected result, we need to do a line-by-line comparison.
    186         self.assertEqual(cout.splitlines(), e.splitlines())
    187 
    188     def test_scriptdecode(self):
    189         (p, e) = self.STRINGS[-1]
    190         process = subprocess.Popen([sys.executable, "-mquopri", "-d"],
    191                                    stdin=subprocess.PIPE, stdout=subprocess.PIPE)
    192         self.addCleanup(process.stdout.close)
    193         cout, cerr = process.communicate(e)
    194         self.assertEqual(cout.splitlines(), p.splitlines())
    195 
    196 def test_main():
    197     test_support.run_unittest(QuopriTestCase)
    198 
    199 
    200 if __name__ == "__main__":
    201     test_main()
    202