python-2.5.2/win32/Lib/test/test_peepholer.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 import dis
       
     2 import sys
       
     3 from cStringIO import StringIO
       
     4 import unittest
       
     5 
       
     6 def disassemble(func):
       
     7     f = StringIO()
       
     8     tmp = sys.stdout
       
     9     sys.stdout = f
       
    10     dis.dis(func)
       
    11     sys.stdout = tmp
       
    12     result = f.getvalue()
       
    13     f.close()
       
    14     return result
       
    15 
       
    16 def dis_single(line):
       
    17     return disassemble(compile(line, '', 'single'))
       
    18 
       
    19 class TestTranforms(unittest.TestCase):
       
    20 
       
    21     def test_unot(self):
       
    22         # UNARY_NOT JUMP_IF_FALSE POP_TOP  -->  JUMP_IF_TRUE POP_TOP'
       
    23         def unot(x):
       
    24             if not x == 2:
       
    25                 del x
       
    26         asm = disassemble(unot)
       
    27         for elem in ('UNARY_NOT', 'JUMP_IF_FALSE'):
       
    28             self.assert_(elem not in asm)
       
    29         for elem in ('JUMP_IF_TRUE', 'POP_TOP'):
       
    30             self.assert_(elem in asm)
       
    31 
       
    32     def test_elim_inversion_of_is_or_in(self):
       
    33         for line, elem in (
       
    34             ('not a is b', '(is not)',),
       
    35             ('not a in b', '(not in)',),
       
    36             ('not a is not b', '(is)',),
       
    37             ('not a not in b', '(in)',),
       
    38             ):
       
    39             asm = dis_single(line)
       
    40             self.assert_(elem in asm)
       
    41 
       
    42     def test_none_as_constant(self):
       
    43         # LOAD_GLOBAL None  -->  LOAD_CONST None
       
    44         def f(x):
       
    45             None
       
    46             return x
       
    47         asm = disassemble(f)
       
    48         for elem in ('LOAD_GLOBAL',):
       
    49             self.assert_(elem not in asm)
       
    50         for elem in ('LOAD_CONST', '(None)'):
       
    51             self.assert_(elem in asm)
       
    52         def f():
       
    53             'Adding a docstring made this test fail in Py2.5.0'
       
    54             return None
       
    55         self.assert_('LOAD_CONST' in disassemble(f))
       
    56         self.assert_('LOAD_GLOBAL' not in disassemble(f))
       
    57 
       
    58     def test_while_one(self):
       
    59         # Skip over:  LOAD_CONST trueconst  JUMP_IF_FALSE xx  POP_TOP
       
    60         def f():
       
    61             while 1:
       
    62                 pass
       
    63             return list
       
    64         asm = disassemble(f)
       
    65         for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'):
       
    66             self.assert_(elem not in asm)
       
    67         for elem in ('JUMP_ABSOLUTE',):
       
    68             self.assert_(elem in asm)
       
    69 
       
    70     def test_pack_unpack(self):
       
    71         for line, elem in (
       
    72             ('a, = a,', 'LOAD_CONST',),
       
    73             ('a, b = a, b', 'ROT_TWO',),
       
    74             ('a, b, c = a, b, c', 'ROT_THREE',),
       
    75             ):
       
    76             asm = dis_single(line)
       
    77             self.assert_(elem in asm)
       
    78             self.assert_('BUILD_TUPLE' not in asm)
       
    79             self.assert_('UNPACK_TUPLE' not in asm)
       
    80 
       
    81     def test_folding_of_tuples_of_constants(self):
       
    82         for line, elem in (
       
    83             ('a = 1,2,3', '((1, 2, 3))'),
       
    84             ('("a","b","c")', "(('a', 'b', 'c'))"),
       
    85             ('a,b,c = 1,2,3', '((1, 2, 3))'),
       
    86             ('(None, 1, None)', '((None, 1, None))'),
       
    87             ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'),
       
    88             ):
       
    89             asm = dis_single(line)
       
    90             self.assert_(elem in asm)
       
    91             self.assert_('BUILD_TUPLE' not in asm)
       
    92 
       
    93         # Bug 1053819:  Tuple of constants misidentified when presented with:
       
    94         # . . . opcode_with_arg 100   unary_opcode   BUILD_TUPLE 1  . . .
       
    95         # The following would segfault upon compilation
       
    96         def crater():
       
    97             (~[
       
    98                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
    99                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   100                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   101                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   102                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   103                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   104                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   105                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   106                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   107                 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
       
   108             ],)
       
   109 
       
   110     def test_folding_of_binops_on_constants(self):
       
   111         for line, elem in (
       
   112             ('a = 2+3+4', '(9)'),                   # chained fold
       
   113             ('"@"*4', "('@@@@')"),                  # check string ops
       
   114             ('a="abc" + "def"', "('abcdef')"),      # check string ops
       
   115             ('a = 3**4', '(81)'),                   # binary power
       
   116             ('a = 3*4', '(12)'),                    # binary multiply
       
   117             ('a = 13//4', '(3)'),                   # binary floor divide
       
   118             ('a = 14%4', '(2)'),                    # binary modulo
       
   119             ('a = 2+3', '(5)'),                     # binary add
       
   120             ('a = 13-4', '(9)'),                    # binary subtract
       
   121             ('a = (12,13)[1]', '(13)'),             # binary subscr
       
   122             ('a = 13 << 2', '(52)'),                # binary lshift
       
   123             ('a = 13 >> 2', '(3)'),                 # binary rshift
       
   124             ('a = 13 & 7', '(5)'),                  # binary and
       
   125             ('a = 13 ^ 7', '(10)'),                 # binary xor
       
   126             ('a = 13 | 7', '(15)'),                 # binary or
       
   127             ):
       
   128             asm = dis_single(line)
       
   129             self.assert_(elem in asm, asm)
       
   130             self.assert_('BINARY_' not in asm)
       
   131 
       
   132         # Verify that unfoldables are skipped
       
   133         asm = dis_single('a=2+"b"')
       
   134         self.assert_('(2)' in asm)
       
   135         self.assert_("('b')" in asm)
       
   136 
       
   137         # Verify that large sequences do not result from folding
       
   138         asm = dis_single('a="x"*1000')
       
   139         self.assert_('(1000)' in asm)
       
   140 
       
   141     def test_folding_of_unaryops_on_constants(self):
       
   142         for line, elem in (
       
   143             ('`1`', "('1')"),                       # unary convert
       
   144             ('-0.5', '(-0.5)'),                     # unary negative
       
   145             ('~-2', '(1)'),                         # unary invert
       
   146         ):
       
   147             asm = dis_single(line)
       
   148             self.assert_(elem in asm, asm)
       
   149             self.assert_('UNARY_' not in asm)
       
   150 
       
   151         # Verify that unfoldables are skipped
       
   152         for line, elem in (
       
   153             ('-"abc"', "('abc')"),                  # unary negative
       
   154             ('~"abc"', "('abc')"),                  # unary invert
       
   155         ):
       
   156             asm = dis_single(line)
       
   157             self.assert_(elem in asm, asm)
       
   158             self.assert_('UNARY_' in asm)
       
   159 
       
   160     def test_elim_extra_return(self):
       
   161         # RETURN LOAD_CONST None RETURN  -->  RETURN
       
   162         def f(x):
       
   163             return x
       
   164         asm = disassemble(f)
       
   165         self.assert_('LOAD_CONST' not in asm)
       
   166         self.assert_('(None)' not in asm)
       
   167         self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
       
   168 
       
   169 
       
   170 
       
   171 def test_main(verbose=None):
       
   172     import sys
       
   173     from test import test_support
       
   174     test_classes = (TestTranforms,)
       
   175     test_support.run_unittest(*test_classes)
       
   176 
       
   177     # verify reference counting
       
   178     if verbose and hasattr(sys, "gettotalrefcount"):
       
   179         import gc
       
   180         counts = [None] * 5
       
   181         for i in xrange(len(counts)):
       
   182             test_support.run_unittest(*test_classes)
       
   183             gc.collect()
       
   184             counts[i] = sys.gettotalrefcount()
       
   185         print counts
       
   186 
       
   187 if __name__ == "__main__":
       
   188     test_main(verbose=True)