Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(153432)

Delta Between Two Patch Sets: Lib/test/test_peepholer.py

Issue 16510: Using appropriate checks in tests
Left Patch Set: Created 7 years ago
Right Patch Set: Created 5 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/test_ossaudiodev.py ('k') | Lib/test/test_pep247.py » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 import dis 1 import dis
2 import re 2 import re
3 import sys 3 import sys
4 from io import StringIO 4 from io import StringIO
5 import unittest 5 import unittest
6 from math import copysign 6 from math import copysign
7 7
8 def disassemble(func): 8 from test.bytecode_helper import BytecodeTestCase
9 f = StringIO() 9
10 tmp = sys.stdout 10 class TestTranforms(BytecodeTestCase):
11 sys.stdout = f
12 try:
13 dis.dis(func)
14 finally:
15 sys.stdout = tmp
16 result = f.getvalue()
17 f.close()
18 return result
19
20 def dis_single(line):
21 return disassemble(compile(line, '', 'single'))
22
23
24 class TestTranforms(unittest.TestCase):
25 11
26 def test_unot(self): 12 def test_unot(self):
27 # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE' 13 # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE'
28 def unot(x): 14 def unot(x):
29 if not x == 2: 15 if not x == 2:
30 del x 16 del x
31 asm = disassemble(unot) 17 self.assertNotInBytecode(unot, 'UNARY_NOT')
32 for elem in ('UNARY_NOT', 'POP_JUMP_IF_FALSE'): 18 self.assertNotInBytecode(unot, 'POP_JUMP_IF_FALSE')
33 self.assertNotIn(elem, asm) 19 self.assertInBytecode(unot, 'POP_JUMP_IF_TRUE')
34 for elem in ('POP_JUMP_IF_TRUE',):
35 self.assertIn(elem, asm)
36 20
37 def test_elim_inversion_of_is_or_in(self): 21 def test_elim_inversion_of_is_or_in(self):
38 for line, elem in ( 22 for line, cmp_op in (
39 ('not a is b', '(is not)',), 23 ('not a is b', 'is not',),
40 ('not a in b', '(not in)',), 24 ('not a in b', 'not in',),
41 ('not a is not b', '(is)',), 25 ('not a is not b', 'is',),
42 ('not a not in b', '(in)',), 26 ('not a not in b', 'in',),
43 ): 27 ):
44 asm = dis_single(line) 28 code = compile(line, '', 'single')
45 self.assertIn(elem, asm) 29 self.assertInBytecode(code, 'COMPARE_OP', cmp_op)
46 30
47 def test_global_as_constant(self): 31 def test_global_as_constant(self):
48 # LOAD_GLOBAL None/True/False --> LOAD_CONST None/True/False 32 # LOAD_GLOBAL None/True/False --> LOAD_CONST None/True/False
49 def f(x): 33 def f(x):
50 None 34 None
51 None 35 None
52 return x 36 return x
53 def g(x): 37 def g(x):
54 True 38 True
55 return x 39 return x
56 def h(x): 40 def h(x):
57 False 41 False
58 return x 42 return x
59 for func, name in ((f, 'None'), (g, 'True'), (h, 'False')): 43 for func, elem in ((f, None), (g, True), (h, False)):
60 asm = disassemble(func) 44 self.assertNotInBytecode(func, 'LOAD_GLOBAL')
61 for elem in ('LOAD_GLOBAL',): 45 self.assertInBytecode(func, 'LOAD_CONST', elem)
62 self.assertNotIn(elem, asm)
63 for elem in ('LOAD_CONST', '('+name+')'):
64 self.assertIn(elem, asm)
65 def f(): 46 def f():
66 'Adding a docstring made this test fail in Py2.5.0' 47 'Adding a docstring made this test fail in Py2.5.0'
67 return None 48 return None
68 self.assertIn('LOAD_CONST', disassemble(f)) 49 self.assertNotInBytecode(f, 'LOAD_GLOBAL')
69 self.assertNotIn('LOAD_GLOBAL', disassemble(f)) 50 self.assertInBytecode(f, 'LOAD_CONST', None)
70 51
71 def test_while_one(self): 52 def test_while_one(self):
72 # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx 53 # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx
73 def f(): 54 def f():
74 while 1: 55 while 1:
75 pass 56 pass
76 return list 57 return list
77 asm = disassemble(f)
78 for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'): 58 for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'):
79 self.assertNotIn(elem, asm) 59 self.assertNotInBytecode(f, elem)
80 for elem in ('JUMP_ABSOLUTE',): 60 for elem in ('JUMP_ABSOLUTE',):
81 self.assertIn(elem, asm) 61 self.assertInBytecode(f, elem)
82 62
83 def test_pack_unpack(self): 63 def test_pack_unpack(self):
84 for line, elem in ( 64 for line, elem in (
85 ('a, = a,', 'LOAD_CONST',), 65 ('a, = a,', 'LOAD_CONST',),
86 ('a, b = a, b', 'ROT_TWO',), 66 ('a, b = a, b', 'ROT_TWO',),
87 ('a, b, c = a, b, c', 'ROT_THREE',), 67 ('a, b, c = a, b, c', 'ROT_THREE',),
88 ): 68 ):
89 asm = dis_single(line) 69 code = compile(line,'','single')
90 self.assertIn(elem, asm) 70 self.assertInBytecode(code, elem)
91 self.assertNotIn('BUILD_TUPLE', asm) 71 self.assertNotInBytecode(code, 'BUILD_TUPLE')
92 self.assertNotIn('UNPACK_TUPLE', asm) 72 self.assertNotInBytecode(code, 'UNPACK_TUPLE')
93 73
94 def test_folding_of_tuples_of_constants(self): 74 def test_folding_of_tuples_of_constants(self):
95 for line, elem in ( 75 for line, elem in (
96 ('a = 1,2,3', '((1, 2, 3))'), 76 ('a = 1,2,3', (1, 2, 3)),
97 ('("a","b","c")', "(('a', 'b', 'c'))"), 77 ('("a","b","c")', ('a', 'b', 'c')),
98 ('a,b,c = 1,2,3', '((1, 2, 3))'), 78 ('a,b,c = 1,2,3', (1, 2, 3)),
99 ('(None, 1, None)', '((None, 1, None))'), 79 ('(None, 1, None)', (None, 1, None)),
100 ('((1, 2), 3, 4)', '(((1, 2), 3, 4))'), 80 ('((1, 2), 3, 4)', ((1, 2), 3, 4)),
101 ): 81 ):
102 asm = dis_single(line) 82 code = compile(line,'','single')
103 self.assertIn(elem, asm) 83 self.assertInBytecode(code, 'LOAD_CONST', elem)
104 self.assertNotIn('BUILD_TUPLE', asm) 84 self.assertNotInBytecode(code, 'BUILD_TUPLE')
105 85
106 # Long tuples should be folded too. 86 # Long tuples should be folded too.
107 asm = dis_single(repr(tuple(range(10000)))) 87 code = compile(repr(tuple(range(10000))),'','single')
88 self.assertNotInBytecode(code, 'BUILD_TUPLE')
108 # One LOAD_CONST for the tuple, one for the None return value 89 # One LOAD_CONST for the tuple, one for the None return value
109 self.assertEqual(asm.count('LOAD_CONST'), 2) 90 load_consts = [instr for instr in dis.get_instructions(code)
110 self.assertNotIn('BUILD_TUPLE', asm) 91 if instr.opname == 'LOAD_CONST']
92 self.assertEqual(len(load_consts), 2)
111 93
112 # Bug 1053819: Tuple of constants misidentified when presented with: 94 # Bug 1053819: Tuple of constants misidentified when presented with:
113 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . . 95 # . . . opcode_with_arg 100 unary_opcode BUILD_TUPLE 1 . . .
114 # The following would segfault upon compilation 96 # The following would segfault upon compilation
115 def crater(): 97 def crater():
116 (~[ 98 (~[
117 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 99 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
118 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
119 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 101 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
120 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 102 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
121 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 103 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
122 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 104 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
123 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 105 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
124 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 106 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
125 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 107 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
126 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 108 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
127 ],) 109 ],)
128 110
129 def test_folding_of_lists_of_constants(self): 111 def test_folding_of_lists_of_constants(self):
130 for line, elem in ( 112 for line, elem in (
131 # in/not in constants with BUILD_LIST should be folded to a tuple: 113 # in/not in constants with BUILD_LIST should be folded to a tuple:
132 ('a in [1,2,3]', '(1, 2, 3)'), 114 ('a in [1,2,3]', (1, 2, 3)),
133 ('a not in ["a","b","c"]', "(('a', 'b', 'c'))"), 115 ('a not in ["a","b","c"]', ('a', 'b', 'c')),
134 ('a in [None, 1, None]', '((None, 1, None))'), 116 ('a in [None, 1, None]', (None, 1, None)),
135 ('a not in [(1, 2), 3, 4]', '(((1, 2), 3, 4))'), 117 ('a not in [(1, 2), 3, 4]', ((1, 2), 3, 4)),
136 ): 118 ):
137 asm = dis_single(line) 119 code = compile(line, '', 'single')
138 self.assertIn(elem, asm) 120 self.assertInBytecode(code, 'LOAD_CONST', elem)
139 self.assertNotIn('BUILD_LIST', asm) 121 self.assertNotInBytecode(code, 'BUILD_LIST')
140 122
141 def test_folding_of_sets_of_constants(self): 123 def test_folding_of_sets_of_constants(self):
142 for line, elem in ( 124 for line, elem in (
143 # in/not in constants with BUILD_SET should be folded to a frozenset : 125 # in/not in constants with BUILD_SET should be folded to a frozenset :
144 ('a in {1,2,3}', frozenset({1, 2, 3})), 126 ('a in {1,2,3}', frozenset({1, 2, 3})),
145 ('a not in {"a","b","c"}', frozenset({'a', 'c', 'b'})), 127 ('a not in {"a","b","c"}', frozenset({'a', 'c', 'b'})),
146 ('a in {None, 1, None}', frozenset({1, None})), 128 ('a in {None, 1, None}', frozenset({1, None})),
147 ('a not in {(1, 2), 3, 4}', frozenset({(1, 2), 3, 4})), 129 ('a not in {(1, 2), 3, 4}', frozenset({(1, 2), 3, 4})),
148 ('a in {1, 2, 3, 3, 2, 1}', frozenset({1, 2, 3})), 130 ('a in {1, 2, 3, 3, 2, 1}', frozenset({1, 2, 3})),
149 ): 131 ):
150 asm = dis_single(line) 132 code = compile(line, '', 'single')
151 self.assertNotIn('BUILD_SET', asm) 133 self.assertNotInBytecode(code, 'BUILD_SET')
152 134 self.assertInBytecode(code, 'LOAD_CONST', elem)
153 # Verify that the frozenset 'elem' is in the disassembly
154 # The ordering of the elements in repr( frozenset ) isn't
155 # guaranteed, so we jump through some hoops to ensure that we have
156 # the frozenset we expect:
157 self.assertIn('frozenset', asm)
158 # Extract the frozenset literal from the disassembly:
159 m = re.match(r'.*(frozenset\({.*}\)).*', asm, re.DOTALL)
160 self.assertTrue(m)
161 self.assertEqual(eval(m.group(1)), elem)
162 135
163 # Ensure that the resulting code actually works: 136 # Ensure that the resulting code actually works:
164 def f(a): 137 def f(a):
165 return a in {1, 2, 3} 138 return a in {1, 2, 3}
166 139
167 def g(a): 140 def g(a):
168 return a not in {1, 2, 3} 141 return a not in {1, 2, 3}
169 142
170 self.assertTrue(f(3)) 143 self.assertTrue(f(3))
171 self.assertFalse(f(4)) 144 self.assertFalse(f(4))
172 145
173 self.assertFalse(g(3)) 146 self.assertFalse(g(3))
174 self.assertTrue(g(4)) 147 self.assertTrue(g(4))
175 148
176 149
177 def test_folding_of_binops_on_constants(self): 150 def test_folding_of_binops_on_constants(self):
178 for line, elem in ( 151 for line, elem in (
179 ('a = 2+3+4', '(9)'), # chained fold 152 ('a = 2+3+4', 9), # chained fold
180 ('"@"*4', "('@@@@')"), # check string ops 153 ('"@"*4', '@@@@'), # check string ops
181 ('a="abc" + "def"', "('abcdef')"), # check string ops 154 ('a="abc" + "def"', 'abcdef'), # check string ops
182 ('a = 3**4', '(81)'), # binary power 155 ('a = 3**4', 81), # binary power
183 ('a = 3*4', '(12)'), # binary multiply 156 ('a = 3*4', 12), # binary multiply
184 ('a = 13//4', '(3)'), # binary floor divide 157 ('a = 13//4', 3), # binary floor divide
185 ('a = 14%4', '(2)'), # binary modulo 158 ('a = 14%4', 2), # binary modulo
186 ('a = 2+3', '(5)'), # binary add 159 ('a = 2+3', 5), # binary add
187 ('a = 13-4', '(9)'), # binary subtract 160 ('a = 13-4', 9), # binary subtract
188 ('a = (12,13)[1]', '(13)'), # binary subscr 161 ('a = (12,13)[1]', 13), # binary subscr
189 ('a = 13 << 2', '(52)'), # binary lshift 162 ('a = 13 << 2', 52), # binary lshift
190 ('a = 13 >> 2', '(3)'), # binary rshift 163 ('a = 13 >> 2', 3), # binary rshift
191 ('a = 13 & 7', '(5)'), # binary and 164 ('a = 13 & 7', 5), # binary and
192 ('a = 13 ^ 7', '(10)'), # binary xor 165 ('a = 13 ^ 7', 10), # binary xor
193 ('a = 13 | 7', '(15)'), # binary or 166 ('a = 13 | 7', 15), # binary or
194 ): 167 ):
195 asm = dis_single(line) 168 code = compile(line, '', 'single')
196 self.assertIn(elem, asm, asm) 169 self.assertInBytecode(code, 'LOAD_CONST', elem)
197 self.assertNotIn('BINARY_', asm) 170 for instr in dis.get_instructions(code):
171 self.assertFalse(instr.opname.startswith('BINARY_'))
198 172
199 # Verify that unfoldables are skipped 173 # Verify that unfoldables are skipped
200 asm = dis_single('a=2+"b"') 174 code = compile('a=2+"b"', '', 'single')
201 self.assertIn('(2)', asm) 175 self.assertInBytecode(code, 'LOAD_CONST', 2)
202 self.assertIn("('b')", asm) 176 self.assertInBytecode(code, 'LOAD_CONST', 'b')
203 177
204 # Verify that large sequences do not result from folding 178 # Verify that large sequences do not result from folding
205 asm = dis_single('a="x"*1000') 179 code = compile('a="x"*1000', '', 'single')
206 self.assertIn('(1000)', asm) 180 self.assertInBytecode(code, 'LOAD_CONST', 1000)
207 181
208 def test_binary_subscr_on_unicode(self): 182 def test_binary_subscr_on_unicode(self):
209 # valid code get optimized 183 # valid code get optimized
210 asm = dis_single('"foo"[0]') 184 code = compile('"foo"[0]', '', 'single')
211 self.assertIn("('f')", asm) 185 self.assertInBytecode(code, 'LOAD_CONST', 'f')
212 self.assertNotIn('BINARY_SUBSCR', asm) 186 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
213 asm = dis_single('"\u0061\uffff"[1]') 187 code = compile('"\u0061\uffff"[1]', '', 'single')
214 self.assertIn("('\\uffff')", asm) 188 self.assertInBytecode(code, 'LOAD_CONST', '\uffff')
215 self.assertNotIn('BINARY_SUBSCR', asm) 189 self.assertNotInBytecode(code,'BINARY_SUBSCR')
216 asm = dis_single('"\U00012345abcdef"[3]') 190
217 self.assertIn("('c')", asm) 191 # With PEP 393, non-BMP char get optimized
218 self.assertNotIn('BINARY_SUBSCR', asm) 192 code = compile('"\U00012345"[0]', '', 'single')
193 self.assertInBytecode(code, 'LOAD_CONST', '\U00012345')
194 self.assertNotInBytecode(code, 'BINARY_SUBSCR')
219 195
220 # invalid code doesn't get optimized 196 # invalid code doesn't get optimized
221 # out of range 197 # out of range
222 asm = dis_single('"fuu"[10]') 198 code = compile('"fuu"[10]', '', 'single')
223 self.assertIn('BINARY_SUBSCR', asm) 199 self.assertInBytecode(code, 'BINARY_SUBSCR')
224 200
225 def test_folding_of_unaryops_on_constants(self): 201 def test_folding_of_unaryops_on_constants(self):
226 for line, elem in ( 202 for line, elem in (
227 ('-0.5', '(-0.5)'), # unary negative 203 ('-0.5', -0.5), # unary negative
228 ('-0.0', '(-0.0)'), # -0.0 204 ('-0.0', -0.0), # -0.0
229 ('-(1.0-1.0)','(-0.0)'), # -0.0 after folding 205 ('-(1.0-1.0)', -0.0), # -0.0 after folding
230 ('-0', '(0)'), # -0 206 ('-0', 0), # -0
231 ('~-2', '(1)'), # unary invert 207 ('~-2', 1), # unary invert
232 ('+1', '(1)'), # unary positive 208 ('+1', 1), # unary positive
233 ): 209 ):
234 asm = dis_single(line) 210 code = compile(line, '', 'single')
235 self.assertIn(elem, asm, asm) 211 self.assertInBytecode(code, 'LOAD_CONST', elem)
236 self.assertNotIn('UNARY_', asm) 212 for instr in dis.get_instructions(code):
213 self.assertFalse(instr.opname.startswith('UNARY_'))
237 214
238 # Check that -0.0 works after marshaling 215 # Check that -0.0 works after marshaling
239 def negzero(): 216 def negzero():
240 return -(1.0-1.0) 217 return -(1.0-1.0)
241 218
242 self.assertNotIn('UNARY_', disassemble(negzero)) 219 for instr in dis.get_instructions(code):
243 self.assertLess(copysign(1.0, negzero()), 0) 220 self.assertFalse(instr.opname.startswith('UNARY_'))
244 221
245 # Verify that unfoldables are skipped 222 # Verify that unfoldables are skipped
246 for line, elem in ( 223 for line, elem, opname in (
247 ('-"abc"', "('abc')"), # unary negative 224 ('-"abc"', 'abc', 'UNARY_NEGATIVE'),
248 ('~"abc"', "('abc')"), # unary invert 225 ('~"abc"', 'abc', 'UNARY_INVERT'),
249 ): 226 ):
250 asm = dis_single(line) 227 code = compile(line, '', 'single')
251 self.assertIn(elem, asm, asm) 228 self.assertInBytecode(code, 'LOAD_CONST', elem)
252 self.assertIn('UNARY_', asm) 229 self.assertInBytecode(code, opname)
253 230
254 def test_elim_extra_return(self): 231 def test_elim_extra_return(self):
255 # RETURN LOAD_CONST None RETURN --> RETURN 232 # RETURN LOAD_CONST None RETURN --> RETURN
256 def f(x): 233 def f(x):
257 return x 234 return x
258 asm = disassemble(f) 235 self.assertNotInBytecode(f, 'LOAD_CONST', None)
259 self.assertNotIn('LOAD_CONST', asm) 236 returns = [instr for instr in dis.get_instructions(f)
260 self.assertNotIn('(None)', asm) 237 if instr.opname == 'RETURN_VALUE']
261 self.assertEqual(asm.split().count('RETURN_VALUE'), 1) 238 self.assertEqual(len(returns), 1)
262 239
263 def test_elim_jump_to_return(self): 240 def test_elim_jump_to_return(self):
264 # JUMP_FORWARD to RETURN --> RETURN 241 # JUMP_FORWARD to RETURN --> RETURN
265 def f(cond, true_value, false_value): 242 def f(cond, true_value, false_value):
266 return true_value if cond else false_value 243 return true_value if cond else false_value
267 asm = disassemble(f) 244 self.assertNotInBytecode(f, 'JUMP_FORWARD')
268 self.assertNotIn('JUMP_FORWARD', asm) 245 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
269 self.assertNotIn('JUMP_ABSOLUTE', asm) 246 returns = [instr for instr in dis.get_instructions(f)
270 self.assertEqual(asm.split().count('RETURN_VALUE'), 2) 247 if instr.opname == 'RETURN_VALUE']
248 self.assertEqual(len(returns), 2)
271 249
272 def test_elim_jump_after_return1(self): 250 def test_elim_jump_after_return1(self):
273 # Eliminate dead code: jumps immediately after returns can't be reached 251 # Eliminate dead code: jumps immediately after returns can't be reached
274 def f(cond1, cond2): 252 def f(cond1, cond2):
275 if cond1: return 1 253 if cond1: return 1
276 if cond2: return 2 254 if cond2: return 2
277 while 1: 255 while 1:
278 return 3 256 return 3
279 while 1: 257 while 1:
280 if cond1: return 4 258 if cond1: return 4
281 return 5 259 return 5
282 return 6 260 return 6
283 asm = disassemble(f) 261 self.assertNotInBytecode(f, 'JUMP_FORWARD')
284 self.assertNotIn('JUMP_FORWARD', asm) 262 self.assertNotInBytecode(f, 'JUMP_ABSOLUTE')
285 self.assertNotIn('JUMP_ABSOLUTE', asm) 263 returns = [instr for instr in dis.get_instructions(f)
286 self.assertEqual(asm.split().count('RETURN_VALUE'), 6) 264 if instr.opname == 'RETURN_VALUE']
265 self.assertEqual(len(returns), 6)
287 266
288 def test_elim_jump_after_return2(self): 267 def test_elim_jump_after_return2(self):
289 # Eliminate dead code: jumps immediately after returns can't be reached 268 # Eliminate dead code: jumps immediately after returns can't be reached
290 def f(cond1, cond2): 269 def f(cond1, cond2):
291 while 1: 270 while 1:
292 if cond1: return 4 271 if cond1: return 4
293 asm = disassemble(f) 272 self.assertNotInBytecode(f, 'JUMP_FORWARD')
294 self.assertNotIn('JUMP_FORWARD', asm)
295 # There should be one jump for the while loop. 273 # There should be one jump for the while loop.
296 self.assertEqual(asm.split().count('JUMP_ABSOLUTE'), 1) 274 returns = [instr for instr in dis.get_instructions(f)
297 self.assertEqual(asm.split().count('RETURN_VALUE'), 2) 275 if instr.opname == 'JUMP_ABSOLUTE']
276 self.assertEqual(len(returns), 1)
277 returns = [instr for instr in dis.get_instructions(f)
278 if instr.opname == 'RETURN_VALUE']
279 self.assertEqual(len(returns), 2)
298 280
299 def test_make_function_doesnt_bail(self): 281 def test_make_function_doesnt_bail(self):
300 def f(): 282 def f():
301 def g()->1+1: 283 def g()->1+1:
302 pass 284 pass
303 return g 285 return g
304 asm = disassemble(f) 286 self.assertNotInBytecode(f, 'BINARY_ADD')
305 self.assertNotIn('BINARY_ADD', asm)
306 287
307 def test_constant_folding(self): 288 def test_constant_folding(self):
308 # Issue #11244: aggressive constant folding. 289 # Issue #11244: aggressive constant folding.
309 exprs = [ 290 exprs = [
310 "3 * -5", 291 '3 * -5',
311 "-3 * 5", 292 '-3 * 5',
312 "2 * (3 * 4)", 293 '2 * (3 * 4)',
313 "(2 * 3) * 4", 294 '(2 * 3) * 4',
314 "(-1, 2, 3)", 295 '(-1, 2, 3)',
315 "(1, -2, 3)", 296 '(1, -2, 3)',
316 "(1, 2, -3)", 297 '(1, 2, -3)',
317 "(1, 2, -3) * 6", 298 '(1, 2, -3) * 6',
318 "lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}", 299 'lambda x: x in {(3 * -5) + (-1 - 6), (1, -2, 3) * 2, None}',
319 ] 300 ]
320 for e in exprs: 301 for e in exprs:
321 asm = dis_single(e) 302 code = compile(e, '', 'single')
322 self.assertNotIn('UNARY_', asm, e) 303 for instr in dis.get_instructions(code):
323 self.assertNotIn('BINARY_', asm, e) 304 self.assertFalse(instr.opname.startswith('UNARY_'))
324 self.assertNotIn('BUILD_', asm, e) 305 self.assertFalse(instr.opname.startswith('BINARY_'))
306 self.assertFalse(instr.opname.startswith('BUILD_'))
307
325 308
326 class TestBuglets(unittest.TestCase): 309 class TestBuglets(unittest.TestCase):
327 310
328 def test_bug_11510(self): 311 def test_bug_11510(self):
329 # folded constant set optimization was commingled with the tuple 312 # folded constant set optimization was commingled with the tuple
330 # unpacking optimization which would fail if the set had duplicate 313 # unpacking optimization which would fail if the set had duplicate
331 # elements so that the set length was unexpected 314 # elements so that the set length was unexpected
332 def f(): 315 def f():
333 x, y = {1, 1} 316 x, y = {1, 1}
334 return x, y 317 return x, y
335 with self.assertRaises(ValueError): 318 with self.assertRaises(ValueError):
336 f() 319 f()
337 320
338 321
339 def test_main(verbose=None): 322 def test_main(verbose=None):
340 import sys 323 import sys
341 from test import support 324 from test import support
342 test_classes = (TestTranforms, TestBuglets) 325 test_classes = (TestTranforms, TestBuglets)
343 support.run_unittest(*test_classes) 326 support.run_unittest(*test_classes)
344 327
345 # verify reference counting 328 # verify reference counting
346 if verbose and hasattr(sys, "gettotalrefcount"): 329 if verbose and hasattr(sys, 'gettotalrefcount'):
347 import gc 330 import gc
348 counts = [None] * 5 331 counts = [None] * 5
349 for i in range(len(counts)): 332 for i in range(len(counts)):
350 support.run_unittest(*test_classes) 333 support.run_unittest(*test_classes)
351 gc.collect() 334 gc.collect()
352 counts[i] = sys.gettotalrefcount() 335 counts[i] = sys.gettotalrefcount()
353 print(counts) 336 print(counts)
354 337
355 if __name__ == "__main__": 338 if __name__ == "__main__":
356 test_main(verbose=True) 339 test_main(verbose=True)
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+