Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Lib / test / test_peepholer.py
blob4385a84c1fbf255f4c21d36f50e6acabf6c81f1d
1 import dis
2 import sys
3 from cStringIO import StringIO
4 import unittest
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
16 def dis_single(line):
17 return disassemble(compile(line, '', 'single'))
19 class TestTranforms(unittest.TestCase):
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)
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)',),
39 asm = dis_single(line)
40 self.assert_(elem in asm)
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)
53 def test_while_one(self):
54 # Skip over: LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP
55 def f():
56 while 1:
57 pass
58 return list
59 asm = disassemble(f)
60 for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'):
61 self.assert_(elem not in asm)
62 for elem in ('JUMP_ABSOLUTE',):
63 self.assert_(elem in asm)
65 def test_pack_unpack(self):
66 for line, elem in (
67 ('a, = a,', 'LOAD_CONST',),
68 ('a, b = a, b', 'ROT_TWO',),
69 ('a, b, c = a, b, c', 'ROT_THREE',),
71 asm = dis_single(line)
72 self.assert_(elem in asm)
73 self.assert_('BUILD_TUPLE' not in asm)
74 self.assert_('UNPACK_TUPLE' not in asm)
76 def test_folding_of_tuples_of_constants(self):
77 for line, elem in (
78 ('a = 1,2,3', '((1, 2, 3))'),
79 ('("a","b","c")', "(('a', 'b', 'c'))"),
80 ('a,b,c = 1,2,3', '((1, 2, 3))'),
81 ('(None, 1, None)', '((None, 1, None))'),
82 ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'),
84 asm = dis_single(line)
85 self.assert_(elem in asm)
86 self.assert_('BUILD_TUPLE' not in asm)
88 # Bug 1053819: Tuple of constants misidentified when presented with:
89 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . .
90 # The following would segfault upon compilation
91 def crater():
92 (~[
93 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
94 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
95 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
96 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
97 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
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,
105 def test_folding_of_binops_on_constants(self):
106 for line, elem in (
107 ('a = 2+3+4', '(9)'), # chained fold
108 ('"@"*4', "('@@@@')"), # check string ops
109 ('a="abc" + "def"', "('abcdef')"), # check string ops
110 ('a = 3**4', '(81)'), # binary power
111 ('a = 3*4', '(12)'), # binary multiply
112 ('a = 13//4', '(3)'), # binary floor divide
113 ('a = 14%4', '(2)'), # binary modulo
114 ('a = 2+3', '(5)'), # binary add
115 ('a = 13-4', '(9)'), # binary subtract
116 ('a = (12,13)[1]', '(13)'), # binary subscr
117 ('a = 13 << 2', '(52)'), # binary lshift
118 ('a = 13 >> 2', '(3)'), # binary rshift
119 ('a = 13 & 7', '(5)'), # binary and
120 ('a = 13 ^ 7', '(10)'), # binary xor
121 ('a = 13 | 7', '(15)'), # binary or
123 asm = dis_single(line)
124 self.assert_(elem in asm, asm)
125 self.assert_('BINARY_' not in asm)
127 # Verify that unfoldables are skipped
128 asm = dis_single('a=2+"b"')
129 self.assert_('(2)' in asm)
130 self.assert_("('b')" in asm)
132 # Verify that large sequences do not result from folding
133 asm = dis_single('a="x"*1000')
134 self.assert_('(1000)' in asm)
136 def test_folding_of_unaryops_on_constants(self):
137 for line, elem in (
138 ('`1`', "('1')"), # unary convert
139 ('-0.5', '(-0.5)'), # unary negative
140 ('~-2', '(1)'), # unary invert
142 asm = dis_single(line)
143 self.assert_(elem in asm, asm)
144 self.assert_('UNARY_' not in asm)
146 # Verify that unfoldables are skipped
147 for line, elem in (
148 ('-"abc"', "('abc')"), # unary negative
149 ('~"abc"', "('abc')"), # unary invert
151 asm = dis_single(line)
152 self.assert_(elem in asm, asm)
153 self.assert_('UNARY_' in asm)
155 def test_elim_extra_return(self):
156 # RETURN LOAD_CONST None RETURN --> RETURN
157 def f(x):
158 return x
159 asm = disassemble(f)
160 self.assert_('LOAD_CONST' not in asm)
161 self.assert_('(None)' not in asm)
162 self.assertEqual(asm.split().count('RETURN_VALUE'), 1)
166 def test_main(verbose=None):
167 import sys
168 from test import test_support
169 test_classes = (TestTranforms,)
170 test_support.run_unittest(*test_classes)
172 # verify reference counting
173 if verbose and hasattr(sys, "gettotalrefcount"):
174 import gc
175 counts = [None] * 5
176 for i in xrange(len(counts)):
177 test_support.run_unittest(*test_classes)
178 gc.collect()
179 counts[i] = sys.gettotalrefcount()
180 print counts
182 if __name__ == "__main__":
183 test_main(verbose=True)