| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import json | 5 import json |
| 6 import mock | 6 import mock |
| 7 import pickle | 7 import pickle |
| 8 import re | 8 import re |
| 9 | 9 |
| 10 from google.appengine.api import taskqueue | 10 from google.appengine.api import taskqueue |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 } | 546 } |
| 547 ] | 547 ] |
| 548 } | 548 } |
| 549 | 549 |
| 550 task = WfSwarmingTask.Create(master_name, builder_name, 3, 'b on platform') | 550 task = WfSwarmingTask.Create(master_name, builder_name, 3, 'b on platform') |
| 551 task.tests_statuses = { | 551 task.tests_statuses = { |
| 552 'Unittest3.Subtest1': { | 552 'Unittest3.Subtest1': { |
| 553 'total_run': 4, | 553 'total_run': 4, |
| 554 'SUCCESS': 2, | 554 'SUCCESS': 2, |
| 555 'FAILURE': 2 | 555 'FAILURE': 2 |
| 556 }, |
| 557 'Unittest3.Subtest2': { |
| 558 'total_run': 4, |
| 559 'SUCCESS': 2, |
| 560 'FAILURE': 2 |
| 556 } | 561 } |
| 557 } | 562 } |
| 558 task.put() | 563 task.put() |
| 559 | 564 |
| 560 analysis = WfAnalysis.Create(master_name, builder_name, build_number) | 565 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 561 analysis.status = analysis_status.COMPLETED | 566 analysis.status = analysis_status.COMPLETED |
| 562 analysis.failure_result_map = { | 567 analysis.failure_result_map = { |
| 563 'b on platform': { | 568 'b on platform': { |
| 564 'Unittest3.Subtest1': '/'.join([master_name, builder_name, '3']), | 569 'Unittest3.Subtest1': '/'.join([master_name, builder_name, '3']), |
| 570 'Unittest3.Subtest2': '/'.join([master_name, builder_name, '3']), |
| 565 }, | 571 }, |
| 566 } | 572 } |
| 567 analysis.result = { | 573 analysis.result = { |
| 568 'failures': [ | 574 'failures': [ |
| 569 { | 575 { |
| 570 'step_name': 'b on platform', | 576 'step_name': 'b on platform', |
| 571 'first_failure': 3, | 577 'first_failure': 3, |
| 572 'last_pass': 2, | 578 'last_pass': 2, |
| 573 'suspected_cls': [], | 579 'suspected_cls': [], |
| 574 'tests': [ | 580 'tests': [ |
| 575 { | 581 { |
| 576 'test_name': 'Unittest3.Subtest1', | 582 'test_name': 'Unittest3.Subtest1', |
| 577 'first_failure': 3, | 583 'first_failure': 3, |
| 578 'last_pass': 2, | 584 'last_pass': 2, |
| 579 'suspected_cls': [] | 585 'suspected_cls': [] |
| 586 }, |
| 587 { |
| 588 'test_name': 'Unittest3.Subtest2', |
| 589 'first_failure': 3, |
| 590 'last_pass': 2, |
| 591 'suspected_cls': [] |
| 580 } | 592 } |
| 581 ] | 593 ] |
| 582 } | 594 } |
| 583 ] | 595 ] |
| 584 } | 596 } |
| 585 analysis.put() | 597 analysis.put() |
| 586 | 598 |
| 587 expected_results = [ | 599 expected_results = [ |
| 588 { | 600 { |
| 589 'master_url': master_url, | 601 'master_url': master_url, |
| 590 'builder_name': builder_name, | 602 'builder_name': builder_name, |
| 591 'build_number': build_number, | 603 'build_number': build_number, |
| 592 'step_name': 'b on platform', | 604 'step_name': 'b on platform', |
| 593 'is_sub_test': True, | 605 'is_sub_test': True, |
| 594 'test_name': 'Unittest3.Subtest1', | 606 'test_name': 'Unittest3.Subtest1', |
| 595 'first_known_failed_build_number': 3, | 607 'first_known_failed_build_number': 3, |
| 596 'analysis_approach': 'HEURISTIC', | 608 'analysis_approach': 'HEURISTIC', |
| 597 'is_flaky_test': True, | 609 'is_flaky_test': True, |
| 598 'try_job_status': 'FINISHED' | 610 'try_job_status': 'FINISHED' |
| 611 }, |
| 612 { |
| 613 'master_url': master_url, |
| 614 'builder_name': builder_name, |
| 615 'build_number': build_number, |
| 616 'step_name': 'b on platform', |
| 617 'is_sub_test': True, |
| 618 'test_name': 'Unittest3.Subtest2', |
| 619 'first_known_failed_build_number': 3, |
| 620 'analysis_approach': 'HEURISTIC', |
| 621 'is_flaky_test': True, |
| 622 'try_job_status': 'FINISHED' |
| 599 } | 623 } |
| 600 ] | 624 ] |
| 601 | 625 |
| 602 self._MockMasterIsSupported(supported=True) | 626 self._MockMasterIsSupported(supported=True) |
| 603 | 627 |
| 604 response = self.call_api('AnalyzeBuildFailures', body=builds) | 628 response = self.call_api('AnalyzeBuildFailures', body=builds) |
| 605 self.assertEqual(200, response.status_int) | 629 self.assertEqual(200, response.status_int) |
| 606 self.assertEqual(expected_results, response.json_body.get('results')) | 630 self.assertEqual(expected_results, response.json_body.get('results')) |
| 607 | 631 |
| 608 @mock.patch.object(suspected_cl_util, 'GetSuspectedCLConfidenceScore') | 632 @mock.patch.object( |
| 633 suspected_cl_util, 'GetSuspectedCLConfidenceScoreAndApproach') |
| 609 def testTestLevelResultIsReturned(self, mock_fn): | 634 def testTestLevelResultIsReturned(self, mock_fn): |
| 610 master_name = 'm' | 635 master_name = 'm' |
| 611 builder_name = 'b' | 636 builder_name = 'b' |
| 612 build_number = 5 | 637 build_number = 5 |
| 613 | 638 |
| 614 master_url = 'https://build.chromium.org/p/%s' % master_name | 639 master_url = 'https://build.chromium.org/p/%s' % master_name |
| 615 builds = { | 640 builds = { |
| 616 'builds': [ | 641 'builds': [ |
| 617 { | 642 { |
| 618 'master_url': master_url, | 643 'master_url': master_url, |
| 619 'builder_name': builder_name, | 644 'builder_name': builder_name, |
| 620 'build_number': build_number | 645 'build_number': build_number |
| 621 } | 646 } |
| 622 ] | 647 ] |
| 623 } | 648 } |
| 624 | 649 |
| 625 task = WfSwarmingTask.Create(master_name, builder_name, 4, 'b on platform') | 650 task = WfSwarmingTask.Create(master_name, builder_name, 4, 'b on platform') |
| 626 task.parameters['ref_name'] = 'b' | 651 task.parameters['ref_name'] = 'b' |
| 652 task.status = analysis_status.COMPLETED |
| 627 task.put() | 653 task.put() |
| 628 | 654 |
| 629 try_job = WfTryJob.Create(master_name, builder_name, 4) | 655 try_job = WfTryJob.Create(master_name, builder_name, 4) |
| 630 try_job.status = analysis_status.COMPLETED | 656 try_job.status = analysis_status.COMPLETED |
| 631 try_job.test_results = [ | 657 try_job.test_results = [ |
| 632 { | 658 { |
| 633 'culprit': { | 659 'culprit': { |
| 634 'a': { | 660 'a': { |
| 635 'repo_name': 'chromium', | 661 'repo_name': 'chromium', |
| 636 'revision': 'r4_2', | 662 'revision': 'r4_2', |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 'suspected_cls': [] | 779 'suspected_cls': [] |
| 754 } | 780 } |
| 755 ] | 781 ] |
| 756 } | 782 } |
| 757 ] | 783 ] |
| 758 } | 784 } |
| 759 analysis.put() | 785 analysis.put() |
| 760 | 786 |
| 761 suspected_cl_42 = WfSuspectedCL.Create('chromium', 'r4_2', 42) | 787 suspected_cl_42 = WfSuspectedCL.Create('chromium', 'r4_2', 42) |
| 762 suspected_cl_42.builds = { | 788 suspected_cl_42.builds = { |
| 763 build_util.CreateBuildId(master_name, builder_name, 4): { | 789 build_util.CreateBuildId(master_name, builder_name, 5): { |
| 764 'approaches': [analysis_approach_type.TRY_JOB] | 790 'approaches': [analysis_approach_type.TRY_JOB] |
| 765 } | 791 } |
| 766 } | 792 } |
| 767 suspected_cl_42.put() | 793 suspected_cl_42.put() |
| 768 | 794 |
| 769 suspected_cl_21 = WfSuspectedCL.Create('chromium', 'r2_1', None) | 795 suspected_cl_21 = WfSuspectedCL.Create('chromium', 'r2_1', None) |
| 770 suspected_cl_21.builds = { | 796 suspected_cl_21.builds = { |
| 797 build_util.CreateBuildId(master_name, builder_name, 3): { |
| 798 'approaches': [analysis_approach_type.HEURISTIC], |
| 799 'top_score': 5 |
| 800 }, |
| 801 build_util.CreateBuildId(master_name, builder_name, 4): { |
| 802 'approaches': [analysis_approach_type.HEURISTIC], |
| 803 'top_score': 5 |
| 804 }, |
| 771 build_util.CreateBuildId(master_name, builder_name, build_number): { | 805 build_util.CreateBuildId(master_name, builder_name, build_number): { |
| 772 'approaches': [analysis_approach_type.HEURISTIC], | 806 'approaches': [analysis_approach_type.HEURISTIC], |
| 773 'top_score': 5 | 807 'top_score': 5 |
| 774 } | 808 } |
| 775 } | 809 } |
| 776 suspected_cl_21.put() | 810 suspected_cl_21.put() |
| 777 | 811 |
| 778 def confidence_side_effect(_, build_info): | 812 suspected_cl_410 = WfSuspectedCL.Create('chromium', 'r4_10', None) |
| 779 if build_info.get('top_score'): | 813 suspected_cl_410.builds = { |
| 780 return 90 | 814 build_util.CreateBuildId(master_name, builder_name, 4): { |
| 781 return 98 | 815 'approaches': [analysis_approach_type.HEURISTIC, |
| 816 analysis_approach_type.TRY_JOB], |
| 817 'top_score': 5 |
| 818 }, |
| 819 build_util.CreateBuildId(master_name, builder_name, build_number): { |
| 820 'approaches': [analysis_approach_type.HEURISTIC], |
| 821 'top_score': 5 |
| 822 } |
| 823 } |
| 824 suspected_cl_410.put() |
| 825 |
| 826 def confidence_side_effect(_, build_info, first_build_info): |
| 827 if (first_build_info and |
| 828 first_build_info.get('approaches') == [ |
| 829 analysis_approach_type.HEURISTIC, |
| 830 analysis_approach_type.TRY_JOB]): |
| 831 return 100, analysis_approach_type.TRY_JOB |
| 832 if build_info and build_info.get('top_score'): |
| 833 return 90, analysis_approach_type.HEURISTIC |
| 834 return 98, analysis_approach_type.TRY_JOB |
| 782 | 835 |
| 783 mock_fn.side_effect = confidence_side_effect | 836 mock_fn.side_effect = confidence_side_effect |
| 784 | 837 |
| 785 expected_results = [ | 838 expected_results = [ |
| 786 { | 839 { |
| 787 'master_url': master_url, | 840 'master_url': master_url, |
| 788 'builder_name': builder_name, | 841 'builder_name': builder_name, |
| 789 'build_number': build_number, | 842 'build_number': build_number, |
| 790 'step_name': 'a', | 843 'step_name': 'a', |
| 791 'is_sub_test': False, | 844 'is_sub_test': False, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 'build_number': build_number, | 902 'build_number': build_number, |
| 850 'step_name': 'b on platform', | 903 'step_name': 'b on platform', |
| 851 'is_sub_test': True, | 904 'is_sub_test': True, |
| 852 'test_name': 'Unittest3.Subtest1', | 905 'test_name': 'Unittest3.Subtest1', |
| 853 'first_known_failed_build_number': 4, | 906 'first_known_failed_build_number': 4, |
| 854 'suspected_cls': [ | 907 'suspected_cls': [ |
| 855 { | 908 { |
| 856 'repo_name': 'chromium', | 909 'repo_name': 'chromium', |
| 857 'revision': 'r4_10', | 910 'revision': 'r4_10', |
| 858 'commit_position': 410, | 911 'commit_position': 410, |
| 859 'analysis_approach': 'TRY_JOB' | 912 'analysis_approach': 'TRY_JOB', |
| 913 'confidence': 100 |
| 860 } | 914 } |
| 861 ], | 915 ], |
| 862 'analysis_approach': 'TRY_JOB', | 916 'analysis_approach': 'TRY_JOB', |
| 863 'is_flaky_test': False, | 917 'is_flaky_test': False, |
| 864 'try_job_status': 'FINISHED' | 918 'try_job_status': 'FINISHED' |
| 865 } | 919 } |
| 866 ] | 920 ] |
| 867 | 921 |
| 868 self._MockMasterIsSupported(supported=True) | 922 self._MockMasterIsSupported(supported=True) |
| 869 | 923 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 self.assertFalse(request.is_step) | 1041 self.assertFalse(request.is_step) |
| 988 self.assertEqual(123, request.bug_id) | 1042 self.assertEqual(123, request.bug_id) |
| 989 self.assertEqual(1, len(request.build_steps)) | 1043 self.assertEqual(1, len(request.build_steps)) |
| 990 self.assertEqual('m', request.build_steps[0].master_name) | 1044 self.assertEqual('m', request.build_steps[0].master_name) |
| 991 self.assertEqual('b', request.build_steps[0].builder_name) | 1045 self.assertEqual('b', request.build_steps[0].builder_name) |
| 992 self.assertEqual(456, request.build_steps[0].build_number) | 1046 self.assertEqual(456, request.build_steps[0].build_number) |
| 993 self.assertEqual('name (with patch) on Windows-7-SP1', | 1047 self.assertEqual('name (with patch) on Windows-7-SP1', |
| 994 request.build_steps[0].step_name) | 1048 request.build_steps[0].step_name) |
| 995 self.assertEqual('test@chromium.org', user_email) | 1049 self.assertEqual('test@chromium.org', user_email) |
| 996 self.assertTrue(is_admin) | 1050 self.assertTrue(is_admin) |
| 1051 |
| 1052 def testGetStatusAndCulpritFromTryJobSwarmingTaskIsRunning(self): |
| 1053 swarming_task = WfSwarmingTask.Create('m', 'b', 123, 'step') |
| 1054 swarming_task.put() |
| 1055 status, culprit = findit_api.FindItApi()._GetStatusAndCulpritFromTryJob( |
| 1056 None, swarming_task, None, 'step', None) |
| 1057 self.assertEqual(status, findit_api._TryJobStatus.RUNNING) |
| 1058 self.assertIsNone(culprit) |
| 1059 |
| 1060 |
| 1061 def testGetStatusAndCulpritFromTryJobTryJobFailed(self): |
| 1062 try_job = WfTryJob.Create('m', 'b', 123) |
| 1063 try_job.status = analysis_status.ERROR |
| 1064 try_job.put() |
| 1065 status, culprit = findit_api.FindItApi()._GetStatusAndCulpritFromTryJob( |
| 1066 try_job, None, None, None, None) |
| 1067 self.assertEqual(status, findit_api._TryJobStatus.FINISHED) |
| 1068 self.assertIsNone(culprit) |
| OLD | NEW |