OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright 2016 The LUCI Authors. All rights reserved. | |
3 # Use of this source code is governed under the Apache License, Version 2.0 | |
4 # that can be found in the LICENSE file. | |
5 | |
6 import json | |
7 import os | |
8 import subprocess | |
9 import sys | |
10 import unittest | |
11 import copy | |
12 | |
13 from collections import OrderedDict | |
14 | |
15 import test_env | |
Michael Achenbach
2016/10/13 07:45:08
nit: order
iannucci
2016/10/13 22:03:20
nope, order is important. Can't import mock until
| |
16 import mock | |
17 | |
18 from expect_tests import CheckFrame | |
19 from recipe_engine import checker | |
20 | |
21 | |
22 class TestChecker(unittest.TestCase): | |
23 def sanitize(self, checkframe): | |
24 return checkframe._replace(line=0, fname='') | |
25 | |
26 def mk(self, fname, code, varmap): | |
27 return CheckFrame( | |
28 fname='', line=0, function=fname, code=code, varmap=varmap) | |
29 | |
30 def test_no_calls(self): | |
31 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
32 def body(_cfn): | |
Michael Achenbach
2016/10/13 07:45:08
nit: Maybe s/_cfn/_
iannucci
2016/10/13 22:03:20
Done.
| |
33 pass | |
34 body(c) | |
35 self.assertEqual(len(c.failed_checks), 0) | |
36 | |
37 def test_success_call(self): | |
38 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
39 def body(check): | |
40 check(True is True) | |
41 body(c) | |
42 self.assertEqual(len(c.failed_checks), 0) | |
43 | |
44 def test_simple_fail(self): | |
45 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
46 def body(check): | |
47 check(True is False) | |
48 body(c) | |
49 self.assertEqual(len(c.failed_checks), 1) | |
50 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
51 self.assertEqual( | |
52 self.sanitize(c.failed_checks[0].frames[0]), | |
53 self.mk('body', 'check((True is False))', {})) | |
54 | |
55 def test_simple_fail_multiline(self): | |
56 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
57 def body(check): | |
58 falsey = lambda: False | |
59 check( | |
60 True is | |
61 | |
62 falsey() | |
63 ) | |
64 body(c) | |
65 self.assertEqual(len(c.failed_checks), 1) | |
66 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
67 self.assertEqual( | |
68 self.sanitize(c.failed_checks[0].frames[0]), | |
69 self.mk('body', 'check((True is falsey()))', {})) | |
70 | |
71 def test_simple_fail_multiline_multistatement(self): | |
72 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
73 def body(check): | |
74 other = 'thing' | |
75 falsey = lambda: False | |
76 check( | |
77 True is | |
78 | |
79 falsey()); other # pylint: disable=pointless-statement | |
80 body(c) | |
81 self.assertEqual(len(c.failed_checks), 1) | |
82 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
83 self.assertEqual( | |
84 self.sanitize(c.failed_checks[0].frames[0]), | |
85 self.mk('body', 'check((True is falsey())); other', { | |
86 'other': "'thing'" })) | |
87 | |
88 def test_fail_nested_statement(self): | |
89 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
90 def body(check): | |
91 other = 'thing' | |
92 falsey = lambda: False | |
93 if True: | |
94 while True: | |
95 try: | |
96 check( | |
97 True is | |
98 | |
99 falsey()); other # pylint: disable=pointless-statement | |
100 break | |
101 except Exception: | |
102 pass | |
103 body(c) | |
104 self.assertEqual(len(c.failed_checks), 1) | |
105 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
106 self.assertEqual( | |
107 self.sanitize(c.failed_checks[0].frames[0]), | |
108 self.mk('body', 'check((True is falsey())); other', { | |
109 'other': "'thing'" })) | |
110 | |
111 def test_var_fail(self): | |
112 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
113 def body(check): | |
114 val = True | |
115 check(val is False) | |
116 body(c) | |
117 self.assertEqual(len(c.failed_checks), 1) | |
118 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
119 self.assertEqual( | |
120 self.sanitize(c.failed_checks[0].frames[0]), | |
121 self.mk('body', 'check((val is False))', {'val': 'True'})) | |
122 | |
123 def test_dict_membership(self): | |
124 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
125 def body(check): | |
126 targ = {'a': 'b', 'c': 'd'} | |
127 check('a' not in targ) | |
128 body(c) | |
129 self.assertEqual(len(c.failed_checks), 1) | |
130 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
131 self.assertEqual( | |
132 self.sanitize(c.failed_checks[0].frames[0]), | |
133 self.mk('body', "check(('a' not in targ))", | |
134 {'targ.keys()': "['a', 'c']"})) | |
135 | |
136 def test_dict_lookup(self): | |
137 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
138 def body(check): | |
139 targ = {'a': {'sub': 'b'}, 'c': 'd'} | |
140 check('cow' in targ['a']) | |
141 body(c) | |
142 self.assertEqual(len(c.failed_checks), 1) | |
143 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
144 self.assertEqual( | |
145 self.sanitize(c.failed_checks[0].frames[0]), | |
146 self.mk('body', "check(('cow' in targ['a']))", | |
147 {"targ['a'].keys()": "['sub']"})) | |
148 | |
149 def test_dict_lookup_nest(self): | |
150 c = checker.Checker('<filename>', 0, lambda: None, (), {}) | |
151 def body(check): | |
152 sub = 'sub' | |
153 targ = {'a': {'sub': 'whee'}, 'c': 'd'} | |
154 check('me' == targ['a'][sub]) | |
155 body(c) | |
156 self.assertEqual(len(c.failed_checks), 1) | |
157 self.assertEqual(len(c.failed_checks[0].frames), 1) | |
158 self.assertEqual( | |
159 self.sanitize(c.failed_checks[0].frames[0]), | |
160 self.mk('body', "check(('me' == targ['a'][sub]))", | |
161 {"targ['a'][sub]": "'whee'", 'sub': "'sub'"})) | |
162 | |
163 | |
164 class TestVerifySubset(unittest.TestCase): | |
165 @staticmethod | |
166 def mkData(*steps): | |
167 return OrderedDict([ | |
168 (s, { | |
169 'cmd': ['list', 'of', 'things'], | |
170 'env': { | |
171 'dict': 'of', | |
172 'many': 'strings,' | |
173 }, | |
174 'name': s, | |
175 'status_code': 1, | |
176 }) for s in steps | |
177 ]) | |
178 | |
179 def setUp(self): | |
180 self.v = checker.VerifySubset | |
181 self.d = self.mkData('a', 'b', 'c') | |
182 self.c = copy.deepcopy(self.d) | |
183 | |
184 def test_types(self): | |
185 self.assertIn( | |
186 "type mismatch: 'str' v 'OrderedDict'", | |
187 self.v('hi', self.d)) | |
188 | |
189 self.assertIn( | |
190 "type mismatch: 'list' v 'OrderedDict'", | |
191 self.v(['hi'], self.d)) | |
192 | |
193 def test_empty(self): | |
194 self.assertIsNone(self.v({}, self.d)) | |
195 self.assertIsNone(self.v(OrderedDict(), self.d)) | |
196 | |
197 def test_single_removal(self): | |
198 del self.c['c'] | |
199 self.assertIsNone(self.v(self.c, self.d)) | |
200 | |
201 def test_add(self): | |
202 self.c['d'] = self.c['a'] | |
203 self.assertIn( | |
204 "added key 'd'", | |
205 self.v(self.c, self.d)) | |
206 | |
207 def test_add_key(self): | |
208 self.c['c']['blort'] = 'cake' | |
209 self.assertIn( | |
210 "added key 'blort'", | |
211 self.v(self.c, self.d)) | |
212 | |
213 def test_key_alter(self): | |
214 self.c['c']['cmd'] = 'cake' | |
215 self.assertEqual( | |
216 "['c']['cmd']: type mismatch: 'str' v 'list'", | |
217 self.v(self.c, self.d)) | |
218 | |
219 def test_list_add(self): | |
220 self.c['c']['cmd'].append('something') | |
221 self.assertIn( | |
222 "['c']['cmd']: too long: 4 v 3", | |
223 self.v(self.c, self.d)) | |
224 | |
225 self.c['c']['cmd'].pop(0) | |
226 self.assertIn( | |
227 "['c']['cmd']: added 1 elements", | |
228 self.v(self.c, self.d)) | |
229 | |
230 def test_list_of_dict(self): | |
231 self.assertIsNone( | |
232 self.v( | |
233 [{'c': 'd', 'a': 'cat'}], | |
234 [{'a': 'b'}, {'c': 'd'}])) | |
235 | |
236 def test_ordereddict(self): | |
237 a = self.c['a'] | |
238 del self.c['a'] | |
239 self.c['a'] = a | |
240 self.assertIn( | |
241 "key 'a' is out of order", | |
242 self.v(self.c, self.d)) | |
243 | |
244 | |
245 if __name__ == '__main__': | |
246 sys.exit(unittest.main()) | |
OLD | NEW |