(root)/
Python-3.12.0/
Lib/
test/
test_quopri.py
       1  import unittest
       2  
       3  import sys, io, subprocess
       4  import quopri
       5  
       6  from test import support
       7  
       8  
       9  ENCSAMPLE = b"""\
      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 = b"Here's a bunch of special \n" + \
      29  b"""\
      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 ESC[4;38;5;81mQuopriTestCase(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
      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          (b'hello', b'hello'),
      71          (b'''hello
      72          there
      73          world''', b'''hello
      74          there
      75          world'''),
      76          (b'''hello
      77          there
      78          world
      79  ''', b'''hello
      80          there
      81          world
      82  '''),
      83          (b'\201\202\203', b'=81=82=83'),
      84          # Add some trailing MUST QUOTE strings
      85          (b'hello ', b'hello=20'),
      86          (b'hello\t', b'hello=09'),
      87          # Some long lines.  First, a single line of 108 characters
      88          (b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\xd8\xd9\xda\xdb\xdc\xdd\xde\xdfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
      89           b'''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          (b'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
      93          b'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          (b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
      98           b'''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          (b'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz',
     103           b'''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          (b'''yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
     110  zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz''',
     111           b'''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          (b'hello world', b'hello=20world'),
     121          (b'hello\tworld', b'hello=09world'),
     122          )
     123  
     124      # These are used in the "header=1" tests.
     125      HSTRINGS = (
     126          (b'hello world', b'hello_world'),
     127          (b'hello_world', b'hello=5Fworld'),
     128          )
     129  
     130      @withpythonimplementation
     131      def test_encodestring(self):
     132          for p, e in self.STRINGS:
     133              self.assertEqual(quopri.encodestring(p), e)
     134  
     135      @withpythonimplementation
     136      def test_decodestring(self):
     137          for p, e in self.STRINGS:
     138              self.assertEqual(quopri.decodestring(e), p)
     139  
     140      @withpythonimplementation
     141      def test_decodestring_double_equals(self):
     142          # Issue 21511 - Ensure that byte string is compared to byte string
     143          # instead of int byte value
     144          decoded_value, encoded_value = (b"123=four", b"123==four")
     145          self.assertEqual(quopri.decodestring(encoded_value), decoded_value)
     146  
     147      @withpythonimplementation
     148      def test_idempotent_string(self):
     149          for p, e in self.STRINGS:
     150              self.assertEqual(quopri.decodestring(quopri.encodestring(e)), e)
     151  
     152      @withpythonimplementation
     153      def test_encode(self):
     154          for p, e in self.STRINGS:
     155              infp = io.BytesIO(p)
     156              outfp = io.BytesIO()
     157              quopri.encode(infp, outfp, quotetabs=False)
     158              self.assertEqual(outfp.getvalue(), e)
     159  
     160      @withpythonimplementation
     161      def test_decode(self):
     162          for p, e in self.STRINGS:
     163              infp = io.BytesIO(e)
     164              outfp = io.BytesIO()
     165              quopri.decode(infp, outfp)
     166              self.assertEqual(outfp.getvalue(), p)
     167  
     168      @withpythonimplementation
     169      def test_embedded_ws(self):
     170          for p, e in self.ESTRINGS:
     171              self.assertEqual(quopri.encodestring(p, quotetabs=True), e)
     172              self.assertEqual(quopri.decodestring(e), p)
     173  
     174      @withpythonimplementation
     175      def test_encode_header(self):
     176          for p, e in self.HSTRINGS:
     177              self.assertEqual(quopri.encodestring(p, header=True), e)
     178  
     179      @withpythonimplementation
     180      def test_decode_header(self):
     181          for p, e in self.HSTRINGS:
     182              self.assertEqual(quopri.decodestring(e, header=True), p)
     183  
     184      @support.requires_subprocess()
     185      def test_scriptencode(self):
     186          (p, e) = self.STRINGS[-1]
     187          process = subprocess.Popen([sys.executable, "-mquopri"],
     188                                     stdin=subprocess.PIPE, stdout=subprocess.PIPE)
     189          self.addCleanup(process.stdout.close)
     190          cout, cerr = process.communicate(p)
     191          # On Windows, Python will output the result to stdout using
     192          # CRLF, as the mode of stdout is text mode. To compare this
     193          # with the expected result, we need to do a line-by-line comparison.
     194          cout = cout.decode('latin-1').splitlines()
     195          e = e.decode('latin-1').splitlines()
     196          assert len(cout)==len(e)
     197          for i in range(len(cout)):
     198              self.assertEqual(cout[i], e[i])
     199          self.assertEqual(cout, e)
     200  
     201      @support.requires_subprocess()
     202      def test_scriptdecode(self):
     203          (p, e) = self.STRINGS[-1]
     204          process = subprocess.Popen([sys.executable, "-mquopri", "-d"],
     205                                     stdin=subprocess.PIPE, stdout=subprocess.PIPE)
     206          self.addCleanup(process.stdout.close)
     207          cout, cerr = process.communicate(e)
     208          cout = cout.decode('latin-1')
     209          p = p.decode('latin-1')
     210          self.assertEqual(cout.splitlines(), p.splitlines())
     211  
     212  if __name__ == "__main__":
     213      unittest.main()