1+ # This tests some of the common built-in functions and methods.
2+ # We need a decent model of data flow through these in order to
3+ # analyse most programs.
4+ #
5+ # All functions starting with "test_" should run and execute `print("OK")` exactly once.
6+ # This can be checked by running validTest.py.
7+
8+ import sys
9+ import os
10+
11+ sys .path .append (os .path .dirname (os .path .dirname ((__file__ ))))
12+ from testlib import expects
13+
14+ # These are defined so that we can evaluate the test code.
15+ NONSOURCE = "not a source"
16+ SOURCE = "source"
17+
18+ def is_source (x ):
19+ return x == "source" or x == b"source" or x == 42 or x == 42.0 or x == 42j
20+
21+ def SINK (x ):
22+ if is_source (x ):
23+ print ("OK" )
24+ else :
25+ print ("Unexpected flow" , x )
26+
27+ def SINK_F (x ):
28+ if is_source (x ):
29+ print ("Unexpected flow" , x )
30+ else :
31+ print ("OK" )
32+
33+
34+ # Actual tests
35+
36+ ## Container constructors
37+
38+ ### List
39+
40+ @expects (2 )
41+ def test_list_from_list ():
42+ l1 = [SOURCE , NONSOURCE ]
43+ l2 = list (l1 )
44+ SINK (l2 [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l2[0]"
45+ SINK_F (l2 [1 ]) # expecting FP due to imprecise flow
46+
47+ # -- skip list_from_string
48+
49+ @expects (2 )
50+ def test_list_from_tuple ():
51+ t = (SOURCE , NONSOURCE )
52+ l = list (t )
53+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
54+ SINK_F (l [1 ]) # expecting FP due to imprecise flow
55+
56+ def test_list_from_set ():
57+ s = {SOURCE }
58+ l = list (s )
59+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
60+
61+ @expects (2 )
62+ def test_list_from_dict ():
63+ d = {SOURCE : 'v' , NONSOURCE : 'v2' }
64+ l = list (d )
65+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
66+ SINK_F (l [1 ]) # expecting FP due to imprecise flow
67+
68+ ### Tuple
69+
70+ @expects (2 )
71+ def test_tuple_from_list ():
72+ l = [SOURCE , NONSOURCE ]
73+ t = tuple (l )
74+ SINK (t [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
75+ SINK_F (t [1 ])
76+
77+ @expects (2 )
78+ def test_tuple_from_tuple ():
79+ t0 = (SOURCE , NONSOURCE )
80+ t = tuple (t0 )
81+ SINK (t [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
82+ SINK_F (t [1 ])
83+
84+ def test_tuple_from_set ():
85+ s = {SOURCE }
86+ t = tuple (s )
87+ SINK (t [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
88+
89+ @expects (2 )
90+ def test_tuple_from_dict ():
91+ d = {SOURCE : "v1" , NONSOURCE : "v2" }
92+ t = tuple (d )
93+ SINK (t [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> t[0]"
94+ SINK_F (t [1 ])
95+
96+
97+ ### Set
98+
99+ def test_set_from_list ():
100+ l = [SOURCE ]
101+ s = set (l )
102+ v = s .pop ()
103+ SINK (v ) #$ MISSING: flow="SOURCE, l:-3 -> v"
104+
105+ def test_set_from_tuple ():
106+ t = (SOURCE ,)
107+ s = set (t )
108+ v = s .pop ()
109+ SINK (v ) #$ MISSING: flow="SOURCE, l:-3 -> v"
110+
111+ def test_set_from_set ():
112+ s0 = {SOURCE }
113+ s = set (s0 )
114+ v = s .pop ()
115+ SINK (v ) #$ MISSING: flow="SOURCE, l:-3 -> v"
116+
117+ def test_set_from_dict ():
118+ d = {SOURCE : "val" }
119+ s = set (d )
120+ v = s .pop ()
121+ SINK (v ) #$ MISSING: flow="SOURCE, l:-3 -> v"
122+
123+
124+ ### Dict
125+
126+ @expects (2 )
127+ def test_dict_from_keyword ():
128+ d = dict (k = SOURCE , k1 = NONSOURCE )
129+ SINK (d ["k" ]) #$ MISSING: flow="SOURCE, l:-1 -> d[k]"
130+ SINK_F (d ["k1" ])
131+
132+ @expects (2 )
133+ def test_dict_from_list ():
134+ d = dict ([("k" , SOURCE ), ("k1" , NONSOURCE )])
135+ SINK (d ["k" ]) #$ MISSING: flow="SOURCE, l:-1 -> d[k]"
136+ SINK_F (d ["k1" ])
137+
138+ @expects (2 )
139+ def test_dict_from_dict ():
140+ d1 = {'k' : SOURCE , 'k1' : NONSOURCE }
141+ d2 = dict (d1 )
142+ SINK (d2 ["k" ]) #$ MISSING: flow="SOURCE, l:-2 -> d[k]"
143+ SINK_F (d2 ["k1" ])
144+
145+ ## Container methods
146+
147+ ### List
148+
149+ def test_list_pop ():
150+ l = [SOURCE ]
151+ v = l .pop ()
152+ SINK (v ) #$ flow="SOURCE, l:-2 -> v"
153+
154+ def test_list_pop_index ():
155+ l = [SOURCE ]
156+ v = l .pop (0 )
157+ SINK (v ) #$ MISSING: flow="SOURCE, l:-2 -> v"
158+
159+ def test_list_pop_index_imprecise ():
160+ l = [SOURCE , NONSOURCE ]
161+ v = l .pop (1 )
162+ SINK_F (v )
163+
164+ @expects (2 )
165+ def test_list_copy ():
166+ l0 = [SOURCE , NONSOURCE ]
167+ l = l0 .copy ()
168+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
169+ SINK_F (l [1 ])
170+
171+ def test_list_append ():
172+ l = [NONSOURCE ]
173+ l .append (SOURCE )
174+ SINK (l [1 ]) #$ MISSING: flow="SOURCE, l:-1 -> l[1]"
175+
176+ ### Set
177+
178+ def test_set_pop ():
179+ s = {SOURCE }
180+ v = s .pop ()
181+ SINK (v ) #$ flow="SOURCE, l:-2 -> v"
182+
183+ def test_set_copy ():
184+ s0 = {SOURCE }
185+ s = s0 .copy ()
186+ SINK (s .pop ()) #$ MISSING: flow="SOURCE, l:-2 -> s.pop()"
187+
188+ def test_set_add ():
189+ s = set ([])
190+ s .add (SOURCE )
191+ SINK (s .pop ()) #$ MISSING: flow="SOURCE, l:-2 -> s.pop()"
192+
193+ ### Dict
194+
195+ def test_dict_keys ():
196+ d = {SOURCE : "value" }
197+ keys = d .keys ()
198+ key_list = list (keys )
199+ SINK (key_list [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> key_list[0]"
200+
201+ def test_dict_values ():
202+ d = {'k' : SOURCE }
203+ vals = d .values ()
204+ val_list = list (vals )
205+ SINK (val_list [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> val_list[0]"
206+
207+ @expects (4 )
208+ def test_dict_items ():
209+ d = {'k' : SOURCE , SOURCE : "value" }
210+ items = d .items ()
211+ item_list = list (items )
212+ SINK_F (item_list [0 ][0 ]) # expecting FP due to imprecise flow
213+ SINK (item_list [0 ][1 ]) #$ MISSING: flow="SOURCE, l:-4 -> item_list[0][1]"
214+ SINK (item_list [1 ][0 ]) #$ MISSING: flow="SOURCE, l:-5 -> item_list[1][0]"
215+ SINK_F (item_list [1 ][1 ]) # expecting FP due to imprecise flow
216+
217+ @expects (2 )
218+ def test_dict_pop ():
219+ d = {'k' : SOURCE }
220+ v = d .pop ("k" )
221+ SINK (v ) #$ flow="SOURCE, l:-2 -> v"
222+ v1 = d .pop ("k" , SOURCE )
223+ SINK (v1 ) #$ flow="SOURCE, l:-4 -> v1"
224+
225+ @expects (2 )
226+ def test_dict_get ():
227+ d = {'k' : SOURCE }
228+ v = d .get ("k" )
229+ SINK (v ) #$ flow="SOURCE, l:-2 -> v"
230+ v1 = d .get ("k" , SOURCE )
231+ SINK (v1 ) #$ flow="SOURCE, l:-4 -> v1"
232+
233+ @expects (2 )
234+ def test_dict_popitem ():
235+ d = {'k' : SOURCE }
236+ t = d .popitem () # could be any pair (before 3.7), but we only have one
237+ SINK_F (t [0 ])
238+ SINK (t [1 ]) #$ MISSING: flow="SOURCE, l:-3 -> t[1]"
239+
240+ @expects (2 )
241+ def test_dict_copy ():
242+ d = {'k' : SOURCE , 'k1' : NONSOURCE }
243+ d1 = d .copy ()
244+ SINK (d1 ["k" ]) #$ MISSING: flow="SOURCE, l:-2 -> d[k]"
245+ SINK_F (d1 ["k1" ])
246+
247+
248+ ## Functions on containers
249+
250+ ### sorted
251+
252+ def test_sorted_list ():
253+ l0 = [SOURCE ]
254+ l = sorted (l0 )
255+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
256+
257+ def test_sorted_tuple ():
258+ t = (SOURCE ,)
259+ l = sorted (t )
260+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
261+
262+ def test_sorted_set ():
263+ s = {SOURCE }
264+ l = sorted (s )
265+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
266+
267+ def test_sorted_dict ():
268+ d = {SOURCE : "val" }
269+ l = sorted (d )
270+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-2 -> l[0]"
271+
272+ ### reversed
273+
274+ @expects (2 )
275+ def test_reversed_list ():
276+ l0 = [SOURCE , NONSOURCE ]
277+ r = reversed (l0 )
278+ l = list (r )
279+ SINK_F (l [0 ])
280+ SINK (l [1 ]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]"
281+
282+ @expects (2 )
283+ def test_reversed_tuple ():
284+ t = (SOURCE , NONSOURCE )
285+ r = reversed (t )
286+ l = list (r )
287+ SINK_F (l [0 ])
288+ SINK (l [1 ]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]"
289+
290+ @expects (2 )
291+ def test_reversed_dict ():
292+ d = {SOURCE : "v1" , NONSOURCE : "v2" }
293+ r = reversed (d )
294+ l = list (r )
295+ SINK_F (l [0 ])
296+ SINK (l [1 ]) #$ MISSING: flow="SOURCE, l:-4 -> l[1]"
297+
298+ ### iter
299+
300+ def test_iter_list ():
301+ l0 = [SOURCE ]
302+ i = iter (l0 )
303+ l = list (i )
304+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> l[0]"
305+
306+ def test_iter_tuple ():
307+ t = (SOURCE ,)
308+ i = iter (t )
309+ l = list (i )
310+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> l[0]"
311+
312+ def test_iter_set ():
313+ t = {SOURCE }
314+ i = iter (t )
315+ l = list (i )
316+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> l[0]"
317+
318+ def test_iter_dict ():
319+ d = {SOURCE : "val" }
320+ i = iter (d )
321+ l = list (i )
322+ SINK (l [0 ]) #$ MISSING: flow="SOURCE, l:-3 -> l[0]"
323+
324+ ### next
325+
326+ def test_next_list ():
327+ l = [SOURCE ]
328+ i = iter (l )
329+ n = next (i )
330+ SINK (n ) #$ MISSING: flow="SOURCE, l:-3 -> n"
331+
332+ def test_next_tuple ():
333+ t = (SOURCE ,)
334+ i = iter (t )
335+ n = next (i )
336+ SINK (n ) #$ MISSING: flow="SOURCE, l:-3 -> n"
337+
338+ def test_next_set ():
339+ s = {SOURCE }
340+ i = iter (s )
341+ n = next (i )
342+ SINK (n ) #$ MISSING: flow="SOURCE, l:-3 -> n"
343+
344+ def test_next_dict ():
345+ d = {SOURCE : "val" }
346+ i = iter (d )
347+ n = next (i )
348+ SINK (n ) #$ MISSING: flow="SOURCE, l:-3 -> n"
0 commit comments