Contact: fumanchu@aminus.org

Log in as guest/dejavu to create tickets

root/tags/1.4.0/test/test_codewalk.py

Revision 96 (checked in by fumanchu, 3 years ago)

Lots of changes to the test suite. Partially fixes #23.

  • Property svn:eol-style set to native
Line 
1 import datetime
2 try:
3     import fixedpoint
4 except ImportError:
5     fixedpoint = None
6 import sys
7 import unittest
8
9 from dejavu import codewalk
10 nums = codewalk.numeric_opcodes
11
12 amount = 5
13 a = [1,2,3,4,5]
14 f = [lambda x: x in a,
15      lambda x: x + datetime.date(2004, 1, 1),
16      lambda x, **kw: (x.Date == datetime.date(2004, 1, 1)
17                       and x.Qty < kw['Size']),
18      # Mix names from globals, locals, attrs
19      lambda x, amount: (4 != x.amount) or (amount * 3 > 20),
20      lambda x: 3 * 4 * 5 * x,
21      lambda x: a[2:4] == -x['offset'],
22      lambda x: amount == 5 or amount == x.Qty,
23      lambda x: not (x.a == 3 and (x.b > 1 or x.b < -10)),
24      # Unicode const
25      lambda x: x.Name == u'Dimsdale',
26      # getattr
27      lambda x: getattr(x, 'Name') == u'Dimsdale',
28      # multiple args
29      lambda x, y, z, **kw: x.Qty > 1 and y.Qty > 20 and z.Type == 'A',
30      ]
31
32 # Closure example = f[11]
33 def foo():
34     a = 5
35     def bar():
36         return a + 5
37     return bar
38 f.append(foo())
39
40 if fixedpoint:
41      f.append(lambda x: x.Amount > fixedpoint.FixedPoint(3, 2))
42
43 fcode = [func.func_code.co_code for func in f]
44
45
46 class VisitorTests(unittest.TestCase):
47    
48     def test_safe_tuple(self):
49         l = ['logic', 'icontains', 'getattr', 'x', 'field', 'criteria', u'GroupName']
50         self.assertEqual(codewalk.safe_tuple(l), ('logic', 'icontains', 'getattr',
51                                                   'x', 'field', 'criteria', 'GroupName'))
52    
53     def test_Localizer(self):
54         r = codewalk.Localizer(f[0]).bytecode()
55         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
56                                   'LOAD_CONST', 1, 0,
57                                   'COMPARE_OP', 6, 0,
58                                   'RETURN_VALUE']))
59         r = codewalk.Localizer(f[1]).bytecode()
60         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
61                                   'LOAD_CONST', 3, 0,
62                                   'LOAD_ATTR', 2, 0,
63                                   'LOAD_CONST', 1, 0,
64                                   'LOAD_CONST', 2, 0,
65                                   'LOAD_CONST', 2, 0,
66                                   'CALL_FUNCTION', 3, 0,
67                                   'BINARY_ADD',
68                                   'RETURN_VALUE']))
69         r = codewalk.Localizer(f[2]).bytecode()
70         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
71                                   'LOAD_ATTR', 1, 0,
72                                   'LOAD_CONST', 4, 0,
73                                   'LOAD_ATTR', 3, 0,
74                                   'LOAD_CONST', 1, 0,
75                                   'LOAD_CONST', 2, 0,
76                                   'LOAD_CONST', 2, 0,
77                                   'CALL_FUNCTION', 3, 0,
78                                   'COMPARE_OP', 2, 0,
79                                   'JUMP_IF_FALSE', 17, 0,
80                                   'POP_TOP',
81                                   'LOAD_FAST', 0, 0,
82                                   'LOAD_ATTR', 4, 0,
83                                   'LOAD_FAST', 1, 0,
84                                   'LOAD_CONST', 3, 0,
85                                   'BINARY_SUBSCR',
86                                   'COMPARE_OP', 0, 0,
87                                   'RETURN_VALUE']))
88        
89         r = codewalk.Localizer(f[3]).bytecode()
90         self.assertEqual(r, nums(['LOAD_CONST', 1, 0,
91                                   'LOAD_FAST', 0, 0,
92                                   'LOAD_ATTR', 1, 0,
93                                   'COMPARE_OP', 3, 0,
94                                   'JUMP_IF_TRUE', 14, 0,
95                                   'POP_TOP',
96                                   'LOAD_FAST', 1, 0,
97                                   'LOAD_CONST', 2, 0,
98                                   'BINARY_MULTIPLY',
99                                   'LOAD_CONST', 3, 0,
100                                   'COMPARE_OP', 4, 0,
101                                   'RETURN_VALUE']))
102    
103     def test_EarlyBinder(self):
104         r = codewalk.EarlyBinder(f[1]).bytecode()
105         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
106                                   'LOAD_CONST', 5, 0,
107                                   'BINARY_ADD',
108                                   'RETURN_VALUE']))
109         r = codewalk.EarlyBinder(f[2]).bytecode()
110         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
111                                   'LOAD_ATTR', 1, 0,
112                                   'LOAD_CONST', 6, 0,
113                                   'COMPARE_OP', 2, 0,
114                                   'JUMP_IF_FALSE', 17, 0,
115                                   'POP_TOP',
116                                   'LOAD_FAST', 0, 0,
117                                   'LOAD_ATTR', 4, 0,
118                                   'LOAD_FAST', 1, 0,
119                                   'LOAD_CONST', 3, 0,
120                                   'BINARY_SUBSCR',
121                                   'COMPARE_OP', 0, 0,
122                                   'RETURN_VALUE']))
123         r = codewalk.EarlyBinder(f[4]).bytecode()
124         self.assertEqual(r, nums(['LOAD_CONST', 5, 0,
125                                   'LOAD_FAST', 0, 0,
126                                   'BINARY_MULTIPLY',
127                                   'RETURN_VALUE']))
128         r = codewalk.EarlyBinder(f[5]).bytecode()
129         self.assertEqual(r, nums(['LOAD_CONST', 5, 0,
130                                   'LOAD_FAST', 0, 0,
131                                   'LOAD_CONST', 3, 0,
132                                   'BINARY_SUBSCR',
133                                   'UNARY_NEGATIVE',
134                                   'COMPARE_OP', 2, 0,
135                                   'RETURN_VALUE']))
136         r = codewalk.EarlyBinder(f[6]).bytecode()
137         self.assertEqual(r, nums(['LOAD_CONST', 2, 0,
138                                   'JUMP_IF_TRUE', 13, 0,
139                                   'POP_TOP',
140                                   'LOAD_CONST', 1, 0,
141                                   'LOAD_FAST', 0, 0,
142                                   'LOAD_ATTR', 2, 0,
143                                   'COMPARE_OP', 2, 0,
144                                   'RETURN_VALUE']))
145         r = codewalk.EarlyBinder(f[9]).bytecode()
146         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
147                                   # 2, since co_names was ('getattr', 'x').
148                                   'LOAD_ATTR', 2, 0,
149                                   'LOAD_CONST', 2, 0,
150                                   'COMPARE_OP', 2, 0,
151                                   'RETURN_VALUE']))
152         # Test a tainted (late-bound) function
153         e = lambda x: x.FirstDate >= datetime.date.today()
154         r = codewalk.EarlyBinder(e, bind_late=[datetime.date.today]).bytecode()
155         self.assertEqual(r, nums(['LOAD_FAST', 0, 0,
156                                   'LOAD_ATTR', 1, 0,
157                                   'LOAD_CONST', 3, 0,
158                                   'CALL_FUNCTION', 0, 0,
159                                   'COMPARE_OP', 5, 0,
160                                   'RETURN_VALUE']))
161        
162         # Closures (dereferencing of func_closure)
163         r = codewalk.EarlyBinder(f[11]).bytecode()
164         v = sys.version_info
165         if v[0] >= 2 and v[1] >= 4:
166             # This bytecode changed for Python 2.4
167             self.assertEqual(r, nums(['LOAD_CONST', 2, 0,
168                                       'RETURN_VALUE']))
169         else:
170             self.assertEqual(r, nums(['LOAD_CONST', 2, 0,
171                                       'RETURN_VALUE',
172                                       'LOAD_CONST', 0, 0,
173                                       'RETURN_VALUE']))
174    
175     def test_LambdaDecompiler(self):
176         s = ['lambda x: x in a',
177              'lambda x: x + datetime.date(2004, 1, 1)',
178              "lambda x, **kw: (x.Date == datetime.date(2004, 1, 1)) and (x.Qty < kw['Size'])",
179              "lambda x, amount: (4 != x.amount) or (amount * 3 > 20)",
180              "lambda x: 3 * 4 * 5 * x",
181              "lambda x: a[2:4] == -(x['offset'])",
182              "lambda x: (amount == 5) or (amount == x.Qty)",
183              "lambda x: not ((x.a == 3) and ((x.b > 1) or (x.b < -10)))",
184              "lambda x: x.Name == u'Dimsdale'",
185              "lambda x: getattr(x, 'Name') == u'Dimsdale'",
186              "lambda x, y, z, **kw: (x.Qty > 1) and ((y.Qty > 20) and (z.Type == 'A'))",
187              "",
188              ]
189         if fixedpoint:
190             s.append("lambda x: x.Amount > fixedpoint.FixedPoint(3, 2)")
191         for funcitem, stritem in zip(f, s):
192             if stritem: # Skip the closure one until I can write a lambda equivalent
193                 r = codewalk.LambdaDecompiler(funcitem).code()
194                 self.assertEqual(r, stritem)
195    
196     def test_BranchTracker(self):
197         r = codewalk.BranchTracker(f[6]).branches()
198         self.assertEqual(r, [9, 22])
199    
200     def test_KeywordInspector(self):
201         e = lambda x, **kw: x.Size > kw['Size']
202         self.assertEqual(codewalk.KeywordInspector(e).kwargs(), ["Size"])
203         e = lambda x: x.Size > kw['Size']
204         self.assertRaises(ValueError, codewalk.KeywordInspector, e)
205         e = lambda x, **kw: x.Date > x.newdate(kw['Year'], 1, 1)
206         self.assertEqual(codewalk.KeywordInspector(e).kwargs(), ["Year"])
207
208
209 if __name__ == "__main__":
210     unittest.main(__name__)
211
Note: See TracBrowser for help on using the browser.