| OLD | NEW | 
|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright 2017 The LUCI Authors. All rights reserved. | 2 # Copyright 2017 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 shutil | 8 import shutil | 
| 9 import subprocess | 9 import subprocess | 
| 10 import sys | 10 import sys | 
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 550     self.assertEqual( | 550     self.assertEqual( | 
| 551         self.json_generator | 551         self.json_generator | 
| 552             .coverage_failure('recipe_modules/foo_module/api.py', [10]).get(), | 552             .coverage_failure('recipe_modules/foo_module/api.py', [10]).get(), | 
| 553         self.json_contents) | 553         self.json_contents) | 
| 554 | 554 | 
| 555   def test_train_basic(self): | 555   def test_train_basic(self): | 
| 556     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 556     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 557     rw.RunStepsLines = ['pass'] | 557     rw.RunStepsLines = ['pass'] | 
| 558     rw.add_expectation('basic') | 558     rw.add_expectation('basic') | 
| 559     rw.write() | 559     rw.write() | 
| 560     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 560     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 561     self.assertEqual(self.json_generator.get(), self.json_contents) | 561     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 562 | 562 | 
| 563   def test_train_missing(self): | 563   def test_train_missing(self): | 
| 564     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 564     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 565     rw.RunStepsLines = ['pass'] | 565     rw.RunStepsLines = ['pass'] | 
| 566     rw.write() | 566     rw.write() | 
| 567     self.assertFalse(os.path.exists(rw.expect_dir)) | 567     self.assertFalse(os.path.exists(rw.expect_dir)) | 
| 568     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 568     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 569     self.assertTrue(os.path.exists(rw.expect_dir)) | 569     self.assertTrue(os.path.exists(rw.expect_dir)) | 
| 570     expect_path = os.path.join(rw.expect_dir, 'basic.json') | 570     expect_path = os.path.join(rw.expect_dir, 'basic.json') | 
| 571     self.assertTrue(os.path.exists(expect_path)) | 571     self.assertTrue(os.path.exists(expect_path)) | 
| 572     with open(expect_path) as f: | 572     with open(expect_path) as f: | 
| 573       expect_contents = json.load(f) | 573       expect_contents = json.load(f) | 
| 574     self.assertEqual( | 574     self.assertEqual( | 
| 575         [{u'status_code': 0, u'recipe_result': None, u'name': u'$result'}], | 575         [{u'status_code': 0, u'recipe_result': None, u'name': u'$result'}], | 
| 576         expect_contents) | 576         expect_contents) | 
| 577     self.assertEqual(self.json_generator.get(), self.json_contents) | 577     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 578 | 578 | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 589     rw.DEPS = ['recipe_engine/step'] | 589     rw.DEPS = ['recipe_engine/step'] | 
| 590     rw.RunStepsLines = ['api.step("test", ["echo", "bar"])'] | 590     rw.RunStepsLines = ['api.step("test", ["echo", "bar"])'] | 
| 591     rw.write() | 591     rw.write() | 
| 592     with self.assertRaises(subprocess.CalledProcessError) as cm: | 592     with self.assertRaises(subprocess.CalledProcessError) as cm: | 
| 593       self._run_recipes('test', 'run', '--json', self.json_path) | 593       self._run_recipes('test', 'run', '--json', self.json_path) | 
| 594     self.assertIn('foo.basic failed', cm.exception.output) | 594     self.assertIn('foo.basic failed', cm.exception.output) | 
| 595     self.assertEqual(self.json_generator.diff_failure('foo.basic').get(), | 595     self.assertEqual(self.json_generator.diff_failure('foo.basic').get(), | 
| 596                      self.json_contents) | 596                      self.json_contents) | 
| 597 | 597 | 
| 598     # 3. Make sure training the recipe succeeds and produces correct results. | 598     # 3. Make sure training the recipe succeeds and produces correct results. | 
| 599     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 599     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 600     expect_path = os.path.join(rw.expect_dir, 'basic.json') | 600     expect_path = os.path.join(rw.expect_dir, 'basic.json') | 
| 601     with open(expect_path) as f: | 601     with open(expect_path) as f: | 
| 602       expect_contents = json.load(f) | 602       expect_contents = json.load(f) | 
| 603     self.assertEqual( | 603     self.assertEqual( | 
| 604         [{u'cmd': [u'echo', u'bar'], u'name': u'test'}, | 604         [{u'cmd': [u'echo', u'bar'], u'name': u'test'}, | 
| 605          {u'status_code': 0, u'recipe_result': None, u'name': u'$result'}], | 605          {u'status_code': 0, u'recipe_result': None, u'name': u'$result'}], | 
| 606         expect_contents) | 606         expect_contents) | 
| 607     self.assertEqual(self.json_generator.get(), self.json_contents) | 607     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 608 | 608 | 
| 609   def test_train_checks_coverage(self): | 609   def test_train_checks_coverage(self): | 
| 610     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 610     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 611     rw.RunStepsLines = ['if False:', '  pass'] | 611     rw.RunStepsLines = ['if False:', '  pass'] | 
| 612     rw.add_expectation('basic') | 612     rw.add_expectation('basic') | 
| 613     rw.write() | 613     rw.write() | 
| 614     with self.assertRaises(subprocess.CalledProcessError) as cm: | 614     with self.assertRaises(subprocess.CalledProcessError) as cm: | 
| 615       self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 615       self._run_recipes('test', 'train', '--json', self.json_path) | 
| 616     self.assertIn('FATAL: Insufficient coverage', cm.exception.output) | 616     self.assertIn('FATAL: Insufficient coverage', cm.exception.output) | 
| 617     self.assertNotIn('CHECK(FAIL)', cm.exception.output) | 617     self.assertNotIn('CHECK(FAIL)', cm.exception.output) | 
| 618     self.assertNotIn('foo.basic failed', cm.exception.output) | 618     self.assertNotIn('foo.basic failed', cm.exception.output) | 
| 619     self.assertEqual( | 619     self.assertEqual( | 
| 620         self.json_generator.coverage_failure('recipes/foo.py', [7]).get(), | 620         self.json_generator.coverage_failure('recipes/foo.py', [7]).get(), | 
| 621         self.json_contents) | 621         self.json_contents) | 
| 622 | 622 | 
| 623   def test_train_runs_checks(self): | 623   def test_train_runs_checks(self): | 
| 624     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 624     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 625     rw.RunStepsLines = ['pass'] | 625     rw.RunStepsLines = ['pass'] | 
| 626     rw.GenTestsLines = [ | 626     rw.GenTestsLines = [ | 
| 627         'yield api.test("basic") + \\', | 627         'yield api.test("basic") + \\', | 
| 628         '  api.post_process(post_process.MustRun, "bar")' | 628         '  api.post_process(post_process.MustRun, "bar")' | 
| 629     ] | 629     ] | 
| 630     rw.add_expectation('basic') | 630     rw.add_expectation('basic') | 
| 631     rw.write() | 631     rw.write() | 
| 632     with self.assertRaises(subprocess.CalledProcessError) as cm: | 632     with self.assertRaises(subprocess.CalledProcessError) as cm: | 
| 633       self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 633       self._run_recipes('test', 'train', '--json', self.json_path) | 
| 634     self.assertNotIn('FATAL: Insufficient coverage', cm.exception.output) | 634     self.assertNotIn('FATAL: Insufficient coverage', cm.exception.output) | 
| 635     self.assertIn('CHECK(FAIL)', cm.exception.output) | 635     self.assertIn('CHECK(FAIL)', cm.exception.output) | 
| 636     self.assertIn('foo.basic failed', cm.exception.output) | 636     self.assertIn('foo.basic failed', cm.exception.output) | 
| 637     self.assertEqual( | 637     self.assertEqual( | 
| 638         self.json_generator.check_failure( | 638         self.json_generator.check_failure( | 
| 639             'foo.basic', 'recipes/foo.py', 10, | 639             'foo.basic', 'recipes/foo.py', 10, | 
| 640             'MustRun', args=['\'bar\'']).get(), | 640             'MustRun', args=['\'bar\'']).get(), | 
| 641         self.json_contents) | 641         self.json_contents) | 
| 642 | 642 | 
| 643   def test_unused_expectation_file_test(self): | 643   def test_unused_expectation_file_test(self): | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 660         self.json_contents) | 660         self.json_contents) | 
| 661 | 661 | 
| 662   def test_unused_expectation_file_train(self): | 662   def test_unused_expectation_file_train(self): | 
| 663     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 663     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 664     rw.RunStepsLines = ['pass'] | 664     rw.RunStepsLines = ['pass'] | 
| 665     rw.add_expectation('basic') | 665     rw.add_expectation('basic') | 
| 666     rw.add_expectation('unused') | 666     rw.add_expectation('unused') | 
| 667     rw.write() | 667     rw.write() | 
| 668     expectation_file = os.path.join(rw.expect_dir, 'unused.json') | 668     expectation_file = os.path.join(rw.expect_dir, 'unused.json') | 
| 669     self.assertTrue(os.path.exists(expectation_file)) | 669     self.assertTrue(os.path.exists(expectation_file)) | 
| 670     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 670     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 671     self.assertFalse(os.path.exists(expectation_file)) | 671     self.assertFalse(os.path.exists(expectation_file)) | 
| 672     self.assertEqual(self.json_generator.get(), self.json_contents) | 672     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 673 | 673 | 
| 674   def test_unused_expectation_dir_test(self): | 674   def test_unused_expectation_dir_test(self): | 
| 675     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 675     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 676     rw.RunStepsLines = ['pass'] | 676     rw.RunStepsLines = ['pass'] | 
| 677     rw.add_expectation('basic') | 677     rw.add_expectation('basic') | 
| 678     rw.write() | 678     rw.write() | 
| 679     expectation_dir = os.path.join(rw.expect_dir, 'dir') | 679     expectation_dir = os.path.join(rw.expect_dir, 'dir') | 
| 680     os.makedirs(expectation_dir) | 680     os.makedirs(expectation_dir) | 
| 681     with self.assertRaises(subprocess.CalledProcessError) as cm: | 681     with self.assertRaises(subprocess.CalledProcessError) as cm: | 
| 682       self._run_recipes('test', 'run', '--json', self.json_path) | 682       self._run_recipes('test', 'run', '--json', self.json_path) | 
| 683     self.assertIn( | 683     self.assertIn( | 
| 684         'FATAL: unused expectations found:\n%s' % expectation_dir, | 684         'FATAL: unused expectations found:\n%s' % expectation_dir, | 
| 685         cm.exception.output) | 685         cm.exception.output) | 
| 686     self.assertTrue(os.path.exists(expectation_dir)) | 686     self.assertTrue(os.path.exists(expectation_dir)) | 
| 687     self.assertEqual( | 687     self.assertEqual( | 
| 688         self.json_generator | 688         self.json_generator | 
| 689             .unused_expectation('recipes/foo.expected/dir').get(), | 689             .unused_expectation('recipes/foo.expected/dir').get(), | 
| 690         self.json_contents) | 690         self.json_contents) | 
| 691 | 691 | 
| 692   def test_unused_expectation_dir_train(self): | 692   def test_unused_expectation_dir_train(self): | 
| 693     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 693     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 694     rw.RunStepsLines = ['pass'] | 694     rw.RunStepsLines = ['pass'] | 
| 695     rw.add_expectation('basic') | 695     rw.add_expectation('basic') | 
| 696     rw.write() | 696     rw.write() | 
| 697     expectation_dir = os.path.join(rw.expect_dir, 'dir') | 697     expectation_dir = os.path.join(rw.expect_dir, 'dir') | 
| 698     os.makedirs(expectation_dir) | 698     os.makedirs(expectation_dir) | 
| 699     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 699     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 700     self.assertFalse(os.path.exists(expectation_dir)) | 700     self.assertFalse(os.path.exists(expectation_dir)) | 
| 701     self.assertEqual(self.json_generator.get(), self.json_contents) | 701     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 702 | 702 | 
| 703   def test_drop_expectation_test(self): | 703   def test_drop_expectation_test(self): | 
| 704     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 704     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 705     rw.RunStepsLines = ['pass'] | 705     rw.RunStepsLines = ['pass'] | 
| 706     rw.GenTestsLines = [ | 706     rw.GenTestsLines = [ | 
| 707         'yield api.test("basic") + \\', | 707         'yield api.test("basic") + \\', | 
| 708         '  api.post_process(post_process.DropExpectation)' | 708         '  api.post_process(post_process.DropExpectation)' | 
| 709     ] | 709     ] | 
| 710     rw.write() | 710     rw.write() | 
| 711     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 711     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 
| 712     self.assertFalse(os.path.exists(expectation_file)) | 712     self.assertFalse(os.path.exists(expectation_file)) | 
| 713     self._run_recipes('test', 'run', '--json', self.json_path) | 713     self._run_recipes('test', 'run', '--json', self.json_path) | 
| 714     self.assertFalse(os.path.exists(expectation_file)) | 714     self.assertFalse(os.path.exists(expectation_file)) | 
| 715     self.assertEqual(self.json_generator.get(), self.json_contents) | 715     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 716 | 716 | 
| 717   def test_drop_expectation_train(self): | 717   def test_drop_expectation_train(self): | 
| 718     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 718     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 719     rw.RunStepsLines = ['pass'] | 719     rw.RunStepsLines = ['pass'] | 
| 720     rw.GenTestsLines = [ | 720     rw.GenTestsLines = [ | 
| 721         'yield api.test("basic") + \\', | 721         'yield api.test("basic") + \\', | 
| 722         '  api.post_process(post_process.DropExpectation)' | 722         '  api.post_process(post_process.DropExpectation)' | 
| 723     ] | 723     ] | 
| 724     rw.write() | 724     rw.write() | 
| 725     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 725     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 
| 726     self.assertFalse(os.path.exists(expectation_file)) | 726     self.assertFalse(os.path.exists(expectation_file)) | 
| 727     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 727     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 728     self.assertFalse(os.path.exists(expectation_file)) | 728     self.assertFalse(os.path.exists(expectation_file)) | 
| 729     self.assertEqual(self.json_generator.get(), self.json_contents) | 729     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 730 | 730 | 
| 731   def test_drop_expectation_test_unused(self): | 731   def test_drop_expectation_test_unused(self): | 
| 732     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 732     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 733     rw.RunStepsLines = ['pass'] | 733     rw.RunStepsLines = ['pass'] | 
| 734     rw.GenTestsLines = [ | 734     rw.GenTestsLines = [ | 
| 735         'yield api.test("basic") + \\', | 735         'yield api.test("basic") + \\', | 
| 736         '  api.post_process(post_process.DropExpectation)' | 736         '  api.post_process(post_process.DropExpectation)' | 
| 737     ] | 737     ] | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 756     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 756     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 757     rw.RunStepsLines = ['pass'] | 757     rw.RunStepsLines = ['pass'] | 
| 758     rw.GenTestsLines = [ | 758     rw.GenTestsLines = [ | 
| 759         'yield api.test("basic") + \\', | 759         'yield api.test("basic") + \\', | 
| 760         '  api.post_process(post_process.DropExpectation)' | 760         '  api.post_process(post_process.DropExpectation)' | 
| 761     ] | 761     ] | 
| 762     rw.add_expectation('basic') | 762     rw.add_expectation('basic') | 
| 763     rw.write() | 763     rw.write() | 
| 764     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 764     expectation_file = os.path.join(rw.expect_dir, 'basic.json') | 
| 765     self.assertTrue(os.path.exists(expectation_file)) | 765     self.assertTrue(os.path.exists(expectation_file)) | 
| 766     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 766     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 767     self.assertFalse(os.path.exists(expectation_file)) | 767     self.assertFalse(os.path.exists(expectation_file)) | 
| 768     self.assertFalse(os.path.exists(rw.expect_dir)) | 768     self.assertFalse(os.path.exists(rw.expect_dir)) | 
| 769     self.assertEqual(self.json_generator.get(), self.json_contents) | 769     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 770 | 770 | 
| 771   def test_unused_expectation_preserves_owners_test(self): | 771   def test_unused_expectation_preserves_owners_test(self): | 
| 772     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 772     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 773     rw.RunStepsLines = ['pass'] | 773     rw.RunStepsLines = ['pass'] | 
| 774     rw.add_expectation('basic') | 774     rw.add_expectation('basic') | 
| 775     rw.write() | 775     rw.write() | 
| 776     owners_file = os.path.join(rw.expect_dir, 'OWNERS') | 776     owners_file = os.path.join(rw.expect_dir, 'OWNERS') | 
| 777     with open(owners_file, 'w') as f: | 777     with open(owners_file, 'w') as f: | 
| 778       pass | 778       pass | 
| 779     self.assertTrue(os.path.exists(owners_file)) | 779     self.assertTrue(os.path.exists(owners_file)) | 
| 780     self._run_recipes('test', 'run', '--json', self.json_path) | 780     self._run_recipes('test', 'run', '--json', self.json_path) | 
| 781     self.assertTrue(os.path.exists(owners_file)) | 781     self.assertTrue(os.path.exists(owners_file)) | 
| 782     self.assertEqual(self.json_generator.get(), self.json_contents) | 782     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 783 | 783 | 
| 784   def test_unused_expectation_preserves_owners_train(self): | 784   def test_unused_expectation_preserves_owners_train(self): | 
| 785     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 785     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 786     rw.RunStepsLines = ['pass'] | 786     rw.RunStepsLines = ['pass'] | 
| 787     rw.add_expectation('basic') | 787     rw.add_expectation('basic') | 
| 788     rw.write() | 788     rw.write() | 
| 789     owners_file = os.path.join(rw.expect_dir, 'OWNERS') | 789     owners_file = os.path.join(rw.expect_dir, 'OWNERS') | 
| 790     with open(owners_file, 'w') as f: | 790     with open(owners_file, 'w') as f: | 
| 791       pass | 791       pass | 
| 792     self.assertTrue(os.path.exists(owners_file)) | 792     self.assertTrue(os.path.exists(owners_file)) | 
| 793     self._run_recipes('test', 'run', '--train', '--json', self.json_path) | 793     self._run_recipes('test', 'train', '--json', self.json_path) | 
| 794     self.assertTrue(os.path.exists(owners_file)) | 794     self.assertTrue(os.path.exists(owners_file)) | 
| 795     self.assertEqual(self.json_generator.get(), self.json_contents) | 795     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 796 | 796 | 
| 797   def test_test_slash_in_name(self): | 797   def test_test_slash_in_name(self): | 
| 798     test_name = 'bar/baz' | 798     test_name = 'bar/baz' | 
| 799     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 799     rw = RecipeWriter(os.path.join(self._root_dir, 'recipes'), 'foo') | 
| 800     rw.RunStepsLines = ['pass'] | 800     rw.RunStepsLines = ['pass'] | 
| 801     rw.GenTestsLines = ['yield api.test(%r)' % test_name] | 801     rw.GenTestsLines = ['yield api.test(%r)' % test_name] | 
| 802     rw.add_expectation(test_name) | 802     rw.add_expectation(test_name) | 
| 803     rw.write() | 803     rw.write() | 
| 804     self._run_recipes('test', 'run', '--json', self.json_path) | 804     self._run_recipes('test', 'run', '--json', self.json_path) | 
| 805     self.assertEqual(self.json_generator.get(), self.json_contents) | 805     self.assertEqual(self.json_generator.get(), self.json_contents) | 
| 806 | 806 | 
| 807 | 807 | 
| 808 if __name__ == '__main__': | 808 if __name__ == '__main__': | 
| 809   sys.exit(unittest.main()) | 809   sys.exit(unittest.main()) | 
| OLD | NEW | 
|---|