OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The LUCI Authors. All rights reserved. | 2 # Copyright 2016 The LUCI Authors. All rights reserved. |
3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
5 | 5 |
6 import json | 6 import json |
7 import os | 7 import os |
8 import subprocess | 8 import subprocess |
9 import sys | 9 import sys |
10 import unittest | 10 import unittest |
11 | 11 |
12 import repo_test_util | 12 import repo_test_util |
13 | 13 |
14 | 14 |
15 class TestAutoroll(repo_test_util.RepoTest): | 15 class TestAutoroll(repo_test_util.RepoTest): |
16 def run_roll(self, repo, *args): | 16 def run_roll(self, repo, *args): |
17 """Runs the autoroll command and returns JSON. | 17 """Runs the autoroll command and returns JSON. |
18 Does not commit the resulting roll. | 18 Does not commit the resulting roll. |
19 """ | 19 """ |
20 with repo_test_util.in_directory(repo['root']), \ | 20 with repo_test_util.in_directory(repo['root']), \ |
21 repo_test_util.temporary_file() as tempfile_path: | 21 repo_test_util.temporary_file() as tempfile_path: |
22 subprocess.check_output([ | 22 subprocess.check_output([ |
23 sys.executable, self._recipe_tool, | 23 sys.executable, self._recipe_tool, |
24 '--package', os.path.join( | 24 '--package', os.path.join( |
25 repo['root'], 'infra', 'config', 'recipes.cfg'), | 25 repo['root'], 'infra', 'config', 'recipes.cfg'), |
26 '--use-bootstrap', | 26 '--use-bootstrap', |
27 'autoroll', | 27 'autoroll', |
28 '--output-json', tempfile_path | 28 '--output-json', tempfile_path |
29 ] + list(args), stderr=subprocess.STDOUT) | 29 ] + list(args) , stderr=subprocess.STDOUT) |
30 with open(tempfile_path) as f: | 30 with open(tempfile_path) as f: |
31 return json.load(f) | 31 return json.load(f) |
32 | 32 |
33 def test_empty(self): | 33 def test_empty(self): |
34 """Tests the scenario where there are no roll candidates. | 34 """Tests the scenario where there are no roll candidates. |
35 """ | 35 """ |
36 repos = self.repo_setup({ | 36 repos = self.repo_setup({ |
37 'a': [], | 37 'a': [], |
38 }) | 38 }) |
39 | 39 |
40 roll_result = self.run_roll(repos['a']) | 40 roll_result = self.run_roll(repos['a']) |
41 self.assertFalse(roll_result['success']) | 41 self.assertFalse(roll_result['success']) |
42 self.assertEquals([], roll_result['roll_details']) | 42 self.assertEquals([], roll_result['roll_details']) |
43 self.assertEquals([], roll_result['rejected_candidates_details']) | 43 self.assertEquals([], roll_result['rejected_candidates_details']) |
44 | 44 |
| 45 def test_bogus_recipes_py(self): |
| 46 repos = self.repo_setup({ |
| 47 'a': [], |
| 48 'b': ['a'], |
| 49 }) |
| 50 self.get_package_spec(repos['b']) |
| 51 |
| 52 # Create a new commit in the A repo. |
| 53 self.commit_in_repo(repos['a'], message='c1') |
| 54 |
| 55 # goof up recipes.py in B repo. |
| 56 with open(os.path.join(repos['b']['root'], 'recipes.py'), 'wb') as f: |
| 57 print >> f, "Hey! This isn't even a python script." |
| 58 self.commit_in_repo(repos['b'], message='goof it up!') |
| 59 |
| 60 with self.assertRaises(subprocess.CalledProcessError) as ex: |
| 61 self.run_roll(repos['b']) |
| 62 self.assertIn('unable to find configuration section', ex.exception.output) |
| 63 |
| 64 |
45 def test_trivial(self): | 65 def test_trivial(self): |
46 """Tests the simplest trivial (i.e. no expectation changes) roll scenario. | 66 """Tests the simplest trivial (i.e. no expectation changes) roll scenario. |
47 """ | 67 """ |
48 repos = self.repo_setup({ | 68 repos = self.repo_setup({ |
49 'a': [], | 69 'a': [], |
50 'b': ['a'], | 70 'b': ['a'], |
51 }) | 71 }) |
52 b_package_spec = self.get_package_spec(repos['b']) | 72 b_package_spec = self.get_package_spec(repos['b']) |
53 | 73 |
54 # Create a new commit in the A repo. | 74 # Create a new commit in the A repo. |
(...skipping 28 matching lines...) Expand all Loading... |
83 def test_nontrivial(self): | 103 def test_nontrivial(self): |
84 """Tests the simplest nontrivial (i.e. expectation changes) roll scenario. | 104 """Tests the simplest nontrivial (i.e. expectation changes) roll scenario. |
85 """ | 105 """ |
86 repos = self.repo_setup({ | 106 repos = self.repo_setup({ |
87 'a': [], | 107 'a': [], |
88 'b': ['a'], | 108 'b': ['a'], |
89 }) | 109 }) |
90 b_package_spec = self.get_package_spec(repos['b']) | 110 b_package_spec = self.get_package_spec(repos['b']) |
91 | 111 |
92 # Set up a recipe in repo B depending on a module in repo A. | 112 # Set up a recipe in repo B depending on a module in repo A. |
93 a_c1 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) | 113 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) |
94 roll_result = self.run_roll(repos['b']) | 114 roll_result = self.run_roll(repos['b']) |
95 self.assertTrue(roll_result['success']) | 115 self.assertTrue(roll_result['success']) |
96 self.assertTrue(roll_result['trivial']) | 116 self.assertTrue(roll_result['trivial']) |
97 b_c1 = self.update_recipe( | 117 self.update_recipe( |
98 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) | 118 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) |
99 | 119 |
100 # Change API of the recipe module in a way that's compatible, | 120 # Change API of the recipe module in a way that's compatible, |
101 # but changes expectations. | 121 # but changes expectations. |
102 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) | 122 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) |
103 | 123 |
104 roll_result = self.run_roll(repos['b']) | 124 roll_result = self.run_roll(repos['b']) |
105 self.assertTrue(roll_result['success']) | 125 self.assertTrue(roll_result['success']) |
106 self.assertFalse(roll_result['trivial']) | 126 self.assertFalse(roll_result['trivial']) |
107 | 127 |
(...skipping 25 matching lines...) Expand all Loading... |
133 def test_failure(self): | 153 def test_failure(self): |
134 """Tests the simplest scenario where an automated roll is not possible | 154 """Tests the simplest scenario where an automated roll is not possible |
135 because of incompatible API changes. | 155 because of incompatible API changes. |
136 """ | 156 """ |
137 repos = self.repo_setup({ | 157 repos = self.repo_setup({ |
138 'a': [], | 158 'a': [], |
139 'b': ['a'], | 159 'b': ['a'], |
140 }) | 160 }) |
141 | 161 |
142 # Set up a recipe in repo B depending on a module in repo A. | 162 # Set up a recipe in repo B depending on a module in repo A. |
143 a_c1 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) | 163 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) |
144 roll_result = self.run_roll(repos['b']) | 164 roll_result = self.run_roll(repos['b']) |
145 self.assertTrue(roll_result['success']) | 165 self.assertTrue(roll_result['success']) |
146 self.assertTrue(roll_result['trivial']) | 166 self.assertTrue(roll_result['trivial']) |
147 b_c1 = self.update_recipe( | 167 self.update_recipe( |
148 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) | 168 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) |
149 | 169 |
150 # Change API of the recipe module in an incompatible way. | 170 # Change API of the recipe module in an incompatible way. |
151 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) | 171 self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) |
152 | 172 |
153 roll_result = self.run_roll(repos['b']) | 173 roll_result = self.run_roll(repos['b']) |
154 self.assertFalse(roll_result['success']) | 174 self.assertFalse(roll_result['success']) |
155 | 175 |
156 def test_jump_over_failure(self): | 176 def test_jump_over_failure(self): |
157 """Tests whether the roller considers pulling more commits to make | 177 """Tests whether the roller considers pulling more commits to make |
158 the roll succeed, when earlier ones have incompatible API changes | 178 the roll succeed, when earlier ones have incompatible API changes |
159 fixed later. | 179 fixed later. |
160 """ | 180 """ |
161 repos = self.repo_setup({ | 181 repos = self.repo_setup({ |
162 'a': [], | 182 'a': [], |
163 'b': ['a'], | 183 'b': ['a'], |
164 }) | 184 }) |
165 b_package_spec = self.get_package_spec(repos['b']) | 185 b_package_spec = self.get_package_spec(repos['b']) |
166 | 186 |
167 # Set up a recipe in repo B depending on a module in repo A. | 187 # Set up a recipe in repo B depending on a module in repo A. |
168 a_c1 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) | 188 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) |
169 roll_result = self.run_roll(repos['b']) | 189 roll_result = self.run_roll(repos['b']) |
170 self.assertTrue(roll_result['success']) | 190 self.assertTrue(roll_result['success']) |
171 self.assertTrue(roll_result['trivial']) | 191 self.assertTrue(roll_result['trivial']) |
172 b_c1 = self.update_recipe( | 192 self.update_recipe( |
173 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) | 193 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) |
174 | 194 |
175 # Change API of the recipe module in an incompatible way. | 195 # Change API of the recipe module in an incompatible way. |
176 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) | 196 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) |
177 | 197 |
178 # Restore compatibility, but change expectations. | 198 # Restore compatibility, but change expectations. |
179 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) | 199 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) |
180 | 200 |
181 roll_result = self.run_roll(repos['b']) | 201 roll_result = self.run_roll(repos['b']) |
182 self.assertTrue(roll_result['success']) | 202 self.assertTrue(roll_result['success']) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 """Test that with several nontrivial rolls possible, the minimal one | 237 """Test that with several nontrivial rolls possible, the minimal one |
218 is picked. | 238 is picked. |
219 """ | 239 """ |
220 repos = self.repo_setup({ | 240 repos = self.repo_setup({ |
221 'a': [], | 241 'a': [], |
222 'b': ['a'], | 242 'b': ['a'], |
223 }) | 243 }) |
224 b_package_spec = self.get_package_spec(repos['b']) | 244 b_package_spec = self.get_package_spec(repos['b']) |
225 | 245 |
226 # Set up a recipe in repo B depending on a module in repo A. | 246 # Set up a recipe in repo B depending on a module in repo A. |
227 a_c1 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) | 247 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) |
228 roll_result = self.run_roll(repos['b']) | 248 roll_result = self.run_roll(repos['b']) |
229 self.assertTrue(roll_result['success']) | 249 self.assertTrue(roll_result['success']) |
230 self.assertTrue(roll_result['trivial']) | 250 self.assertTrue(roll_result['trivial']) |
231 b_c1 = self.update_recipe( | 251 self.update_recipe( |
232 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) | 252 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) |
233 | 253 |
234 # Change API of the recipe module in an incompatible way. | 254 # Change API of the recipe module in an incompatible way. |
235 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) | 255 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) |
236 | 256 |
237 # Restore compatibility, but change expectations. | 257 # Restore compatibility, but change expectations. |
238 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) | 258 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) |
239 | 259 |
240 # Create another change that would result in a nontrivial roll, | 260 # Create another change that would result in a nontrivial roll, |
241 # which should not be picked - nontrivial rolls should be minimal. | 261 # which should not be picked - nontrivial rolls should be minimal. |
242 a_c4 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bam']}) | 262 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bam']}) |
243 | 263 |
244 roll_result = self.run_roll(repos['b']) | 264 roll_result = self.run_roll(repos['b']) |
245 self.assertTrue(roll_result['success']) | 265 self.assertTrue(roll_result['success']) |
246 self.assertFalse(roll_result['trivial']) | 266 self.assertFalse(roll_result['trivial']) |
247 | 267 |
248 expected_picked_roll = { | 268 expected_picked_roll = { |
249 'commit_infos': { | 269 'commit_infos': { |
250 'a': [ | 270 'a': [ |
251 { | 271 { |
252 'author': a_c2['author_email'], | 272 'author': a_c2['author_email'], |
(...skipping 28 matching lines...) Expand all Loading... |
281 This helps avoid noise with several rolls where one is sufficient, | 301 This helps avoid noise with several rolls where one is sufficient, |
282 with no expectation changes. | 302 with no expectation changes. |
283 """ | 303 """ |
284 repos = self.repo_setup({ | 304 repos = self.repo_setup({ |
285 'a': [], | 305 'a': [], |
286 'b': ['a'], | 306 'b': ['a'], |
287 }) | 307 }) |
288 b_package_spec = self.get_package_spec(repos['b']) | 308 b_package_spec = self.get_package_spec(repos['b']) |
289 | 309 |
290 # Set up a recipe in repo B depending on a module in repo A. | 310 # Set up a recipe in repo B depending on a module in repo A. |
291 a_c1 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) | 311 self.update_recipe_module(repos['a'], 'a_module', {'foo': ['bar']}) |
292 roll_result = self.run_roll(repos['b']) | 312 roll_result = self.run_roll(repos['b']) |
293 self.assertTrue(roll_result['success']) | 313 self.assertTrue(roll_result['success']) |
294 self.assertTrue(roll_result['trivial']) | 314 self.assertTrue(roll_result['trivial']) |
295 b_c1 = self.update_recipe( | 315 self.update_recipe( |
296 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) | 316 repos['b'], 'b_recipe', ['a/a_module'], [('a_module', 'foo')]) |
297 | 317 |
298 # Change API of the recipe module in an incompatible way. | 318 # Change API of the recipe module in an incompatible way. |
299 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) | 319 a_c2 = self.update_recipe_module(repos['a'], 'a_module', {'baz': ['baz']}) |
300 | 320 |
301 # Restore compatibility, but change expectations. | 321 # Restore compatibility, but change expectations. |
302 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) | 322 a_c3 = self.update_recipe_module(repos['a'], 'a_module', {'foo': ['baz']}) |
303 | 323 |
304 # Create another change that would result in a nontrivial roll, | 324 # Create another change that would result in a nontrivial roll, |
305 # which should not be picked - nontrivial rolls should be minimal. | 325 # which should not be picked - nontrivial rolls should be minimal. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 """ | 380 """ |
361 repos = self.repo_setup({ | 381 repos = self.repo_setup({ |
362 'a': [], | 382 'a': [], |
363 'b': ['a'], | 383 'b': ['a'], |
364 'c': ['b', 'a'], | 384 'c': ['b', 'a'], |
365 }) | 385 }) |
366 b_package_spec = self.get_package_spec(repos['b']) | 386 b_package_spec = self.get_package_spec(repos['b']) |
367 c_package_spec = self.get_package_spec(repos['c']) | 387 c_package_spec = self.get_package_spec(repos['c']) |
368 | 388 |
369 # Set up a recipe in repo C depending on a module in repo B. | 389 # Set up a recipe in repo C depending on a module in repo B. |
370 b_c1 = self.update_recipe_module(repos['b'], 'b_module', {'foo': ['bar']}) | 390 self.update_recipe_module(repos['b'], 'b_module', {'foo': ['bar']}) |
371 roll_result = self.run_roll(repos['c']) | 391 roll_result = self.run_roll(repos['c']) |
372 self.assertTrue(roll_result['success']) | 392 self.assertTrue(roll_result['success']) |
373 self.assertTrue(roll_result['trivial']) | 393 self.assertTrue(roll_result['trivial']) |
374 c_c1 = self.update_recipe( | 394 self.update_recipe( |
375 repos['c'], 'c_recipe', ['b/b_module'], [('b_module', 'foo')]) | 395 repos['c'], 'c_recipe', ['b/b_module'], [('b_module', 'foo')]) |
376 | 396 |
377 # Create a new commit in the A repo and roll it into B. | 397 # Create a new commit in the A repo and roll it into B. |
378 a_c1 = self.commit_in_repo(repos['a'], message='c1') | 398 a_c1 = self.commit_in_repo(repos['a'], message='c1') |
379 roll_result = self.run_roll(repos['b']) | 399 roll_result = self.run_roll(repos['b']) |
380 self.assertTrue(roll_result['success']) | 400 self.assertTrue(roll_result['success']) |
381 self.assertTrue(roll_result['trivial']) | 401 self.assertTrue(roll_result['trivial']) |
382 picked_roll = roll_result['picked_roll_details'] | 402 picked_roll = roll_result['picked_roll_details'] |
383 self.assertEqual( | 403 self.assertEqual( |
384 str(b_package_spec.dump()).replace( | 404 str(b_package_spec.dump()).replace( |
385 repos['a']['revision'], a_c1['revision']), | 405 repos['a']['revision'], a_c1['revision']), |
386 roll_result['picked_roll_details']['spec']) | 406 roll_result['picked_roll_details']['spec']) |
387 | 407 |
388 # Commit the roll. | 408 # Commit the roll. |
389 b_c2 = self.commit_in_repo(repos['b'], message='roll') | 409 b_c2 = self.commit_in_repo(repos['b'], message='roll') |
390 | 410 |
391 # Change API of the recipe module in an incompatible way. | 411 # Change API of the recipe module in an incompatible way. |
392 b_c3 = self.update_recipe_module(repos['b'], 'b_module', {'baz': ['baz']}) | 412 self.update_recipe_module(repos['b'], 'b_module', {'baz': ['baz']}) |
393 | 413 |
394 roll_result = self.run_roll(repos['c']) | 414 roll_result = self.run_roll(repos['c']) |
395 self.assertTrue(roll_result['success']) | 415 self.assertTrue(roll_result['success']) |
396 self.assertTrue(roll_result['trivial']) | 416 self.assertTrue(roll_result['trivial']) |
397 | 417 |
398 expected_picked_roll = { | 418 expected_picked_roll = { |
399 'commit_infos': { | 419 'commit_infos': { |
400 'a': [ | 420 'a': [ |
401 { | 421 { |
402 'author': a_c1['author_email'], | 422 'author': a_c1['author_email'], |
(...skipping 25 matching lines...) Expand all Loading... |
428 0, picked_roll['recipes_simulation_test']['rc']) | 448 0, picked_roll['recipes_simulation_test']['rc']) |
429 | 449 |
430 def test_no_backwards_roll(self): | 450 def test_no_backwards_roll(self): |
431 """Tests that we never roll backwards. | 451 """Tests that we never roll backwards. |
432 """ | 452 """ |
433 repos = self.repo_setup({ | 453 repos = self.repo_setup({ |
434 'a': [], | 454 'a': [], |
435 'b': ['a'], | 455 'b': ['a'], |
436 'c': ['b', 'a'], | 456 'c': ['b', 'a'], |
437 }) | 457 }) |
438 root_repo_spec = self.get_root_repo_spec(repos['c']) | 458 self.get_root_repo_spec(repos['c']) |
439 b_repo_spec = self.get_git_repo_spec(repos['b']) | 459 b_repo_spec = self.get_git_repo_spec(repos['b']) |
440 c_package_spec = self.get_package_spec(repos['c']) | 460 c_package_spec = self.get_package_spec(repos['c']) |
441 | 461 |
442 # Create a new commit in A repo and roll it to B. | 462 # Create a new commit in A repo and roll it to B. |
443 a_c1 = self.commit_in_repo(repos['a'], message='c1') | 463 a_c1 = self.commit_in_repo(repos['a'], message='c1') |
444 b_c1_rev = self.update_recipes_cfg( | 464 b_c1_rev = self.update_recipes_cfg( |
445 'b', self.updated_package_spec_pb(repos['b'], 'a', a_c1['revision'])) | 465 'b', self.updated_package_spec_pb(repos['b'], 'a', a_c1['revision'])) |
446 | 466 |
447 # Roll above commits to C. | 467 # Roll above commits to C. |
448 roll_result = self.run_roll(repos['c']) | 468 roll_result = self.run_roll(repos['c']) |
449 self.assertTrue(roll_result['success']) | 469 self.assertTrue(roll_result['success']) |
450 self.assertTrue(roll_result['trivial']) | 470 self.assertTrue(roll_result['trivial']) |
451 picked_roll = roll_result['picked_roll_details'] | 471 picked_roll = roll_result['picked_roll_details'] |
452 self.assertEqual( | 472 self.assertEqual( |
453 str(c_package_spec.dump()).replace( | 473 str(c_package_spec.dump()).replace( |
454 repos['a']['revision'], a_c1['revision']).replace( | 474 repos['a']['revision'], a_c1['revision']).replace( |
455 repos['b']['revision'], b_c1_rev), | 475 repos['b']['revision'], b_c1_rev), |
456 roll_result['picked_roll_details']['spec']) | 476 picked_roll['spec']) |
457 | 477 |
458 # Create a new commit in B that would result in backwards roll. | 478 # Create a new commit in B that would result in backwards roll. |
459 b_c2_rev = self.update_recipes_cfg( | 479 b_c2_rev = self.update_recipes_cfg( |
460 'b', self.updated_package_spec_pb( | 480 'b', self.updated_package_spec_pb( |
461 repos['b'], 'a', repos['a']['revision'])) | 481 repos['b'], 'a', repos['a']['revision'])) |
462 | 482 |
463 roll_result = self.run_roll(repos['c']) | 483 roll_result = self.run_roll(repos['c']) |
464 self.assertFalse(roll_result['success']) | 484 self.assertFalse(roll_result['success']) |
465 self.assertEqual([], roll_result['roll_details']) | 485 self.assertEqual([], roll_result['roll_details']) |
466 | 486 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 '--project=c', | 523 '--project=c', |
504 '--project=d', | 524 '--project=d', |
505 ) | 525 ) |
506 self.assertFalse(roll_result['success']) | 526 self.assertFalse(roll_result['success']) |
507 self.assertFalse(bool(roll_result['roll_details'])) | 527 self.assertFalse(bool(roll_result['roll_details'])) |
508 self.assertFalse(bool(roll_result['rejected_candidates_details'])) | 528 self.assertFalse(bool(roll_result['rejected_candidates_details'])) |
509 | 529 |
510 | 530 |
511 if __name__ == '__main__': | 531 if __name__ == '__main__': |
512 sys.exit(unittest.main()) | 532 sys.exit(unittest.main()) |
OLD | NEW |