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 |