| OLD | NEW |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 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 os | 5 import os |
| 6 import re | 6 import re |
| 7 | 7 |
| 8 from google.appengine.ext import testbed | 8 from google.appengine.ext import testbed |
| 9 | 9 |
| 10 import webapp2 | 10 import webapp2 |
| 11 import webtest | 11 import webtest |
| 12 | 12 |
| 13 from common.waterfall import failure_type |
| 13 from handlers import build_failure | 14 from handlers import build_failure |
| 14 from handlers import handlers_util | 15 from handlers import handlers_util |
| 15 from handlers import result_status | 16 from handlers import result_status |
| 16 from model import analysis_approach_type | 17 from model import analysis_approach_type |
| 17 from model import analysis_status | 18 from model import analysis_status |
| 18 from model import suspected_cl_status | 19 from model import suspected_cl_status |
| 19 from model.base_build_model import BaseBuildModel | 20 from model.base_build_model import BaseBuildModel |
| 21 from model.suspected_cl_confidence import ConfidenceInformation |
| 22 from model.suspected_cl_confidence import SuspectedCLConfidence |
| 20 from model.wf_analysis import WfAnalysis | 23 from model.wf_analysis import WfAnalysis |
| 21 from model.wf_suspected_cl import WfSuspectedCL | 24 from model.wf_suspected_cl import WfSuspectedCL |
| 22 from model.wf_try_job import WfTryJob | 25 from model.wf_try_job import WfTryJob |
| 23 from waterfall import buildbot | 26 from waterfall import buildbot |
| 24 from waterfall.test import wf_testcase | 27 from waterfall.test import wf_testcase |
| 25 | 28 |
| 26 # Root directory appengine/findit. | 29 # Root directory appengine/findit. |
| 27 ROOT_DIR = os.path.join(os.path.dirname(__file__), | 30 ROOT_DIR = os.path.join(os.path.dirname(__file__), |
| 28 os.path.pardir, os.path.pardir) | 31 os.path.pardir, os.path.pardir) |
| 29 | 32 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 'revision': 'rev2', | 105 'revision': 'rev2', |
| 103 'commit_position': '2', | 106 'commit_position': '2', |
| 104 'review_url': 'url_2' | 107 'review_url': 'url_2' |
| 105 } | 108 } |
| 106 } | 109 } |
| 107 ] | 110 ] |
| 108 } | 111 } |
| 109 } | 112 } |
| 110 } | 113 } |
| 111 | 114 |
| 115 SAMPLE_HEURISTIC_1 = ConfidenceInformation( |
| 116 correct=100, total=100, confidence=1.0, score=5) |
| 117 |
| 118 SAMPLE_HEURISTIC_2 = ConfidenceInformation( |
| 119 correct=90, total=100, confidence=0.9, score=4) |
| 120 |
| 121 SAMPLE_TRY_JOB = ConfidenceInformation( |
| 122 correct=99, total=100, confidence=0.99, score=None) |
| 123 |
| 124 SAMPLE_HEURISTIC_TRY_JOB = ConfidenceInformation( |
| 125 correct=98, total=100, confidence=0.98, score=None) |
| 126 |
| 112 | 127 |
| 113 class BuildFailureTest(wf_testcase.WaterfallTestCase): | 128 class BuildFailureTest(wf_testcase.WaterfallTestCase): |
| 114 app_module = webapp2.WSGIApplication([ | 129 app_module = webapp2.WSGIApplication([ |
| 115 ('/build-failure', build_failure.BuildFailure), | 130 ('/build-failure', build_failure.BuildFailure), |
| 116 ], debug=True) | 131 ], debug=True) |
| 117 | 132 |
| 118 def setUp(self): | 133 def setUp(self): |
| 119 super(BuildFailureTest, self).setUp() | 134 super(BuildFailureTest, self).setUp() |
| 120 | 135 |
| 121 # Setup clean task queues. | 136 # Setup clean task queues. |
| 122 self.testbed.init_taskqueue_stub(root_path=ROOT_DIR) | 137 self.testbed.init_taskqueue_stub(root_path=ROOT_DIR) |
| 123 self.taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) | 138 self.taskqueue_stub = self.testbed.get_stub(testbed.TASKQUEUE_SERVICE_NAME) |
| 124 for queue in self.taskqueue_stub.GetQueues(): | 139 for queue in self.taskqueue_stub.GetQueues(): |
| 125 self.taskqueue_stub.FlushQueue(queue['name']) | 140 self.taskqueue_stub.FlushQueue(queue['name']) |
| 126 | 141 |
| 127 def MockedGetAllTryJobResults(master_name, builder_name, build_number, _): | 142 def MockedGetAllTryJobResults(master_name, builder_name, build_number, _): |
| 128 build_key = BaseBuildModel.CreateBuildId( | 143 build_key = BaseBuildModel.CreateBuildId( |
| 129 master_name, builder_name, build_number) | 144 master_name, builder_name, build_number) |
| 130 return SAMPLE_TRY_JOB_INFO.get(build_key, None) | 145 return SAMPLE_TRY_JOB_INFO.get(build_key, None) |
| 131 self.mock(handlers_util, 'GetAllTryJobResults', MockedGetAllTryJobResults) | 146 self.mock(handlers_util, 'GetAllTryJobResults', MockedGetAllTryJobResults) |
| 132 | 147 |
| 148 self.cl_confidences = SuspectedCLConfidence.Create() |
| 149 self.cl_confidences.compile_heuristic = [ |
| 150 SAMPLE_HEURISTIC_1, SAMPLE_HEURISTIC_2] |
| 151 self.cl_confidences.test_heuristic = [ |
| 152 SAMPLE_HEURISTIC_2, SAMPLE_HEURISTIC_1] |
| 153 self.cl_confidences.compile_try_job = SAMPLE_TRY_JOB |
| 154 self.cl_confidences.test_try_job = SAMPLE_TRY_JOB |
| 155 self.cl_confidences.compile_heuristic_try_job = SAMPLE_HEURISTIC_TRY_JOB |
| 156 self.cl_confidences.test_heuristic_try_job = SAMPLE_HEURISTIC_TRY_JOB |
| 157 self.cl_confidences.Save() |
| 158 |
| 133 def testGetTriageHistoryWhenUserIsNotAdmin(self): | 159 def testGetTriageHistoryWhenUserIsNotAdmin(self): |
| 134 analysis = WfAnalysis.Create('m', 'b', 1) | 160 analysis = WfAnalysis.Create('m', 'b', 1) |
| 135 analysis.status = analysis_status.COMPLETED | 161 analysis.status = analysis_status.COMPLETED |
| 136 analysis.triage_history = [ | 162 analysis.triage_history = [ |
| 137 { | 163 { |
| 138 'triage_timestamp': 1438380761, | 164 'triage_timestamp': 1438380761, |
| 139 'user_name': 'test', | 165 'user_name': 'test', |
| 140 'result_status': 'dummy status', | 166 'result_status': 'dummy status', |
| 141 'version': 'dummy version', | 167 'version': 'dummy version', |
| 142 } | 168 } |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 'revision': 'rev', | 821 'revision': 'rev', |
| 796 } | 822 } |
| 797 } | 823 } |
| 798 } | 824 } |
| 799 ] | 825 ] |
| 800 try_job.put() | 826 try_job.put() |
| 801 | 827 |
| 802 suspected_cl = WfSuspectedCL.Create('chromium', 'rev', 122) | 828 suspected_cl = WfSuspectedCL.Create('chromium', 'rev', 122) |
| 803 suspected_cl.builds = { | 829 suspected_cl.builds = { |
| 804 'm/b/123': { | 830 'm/b/123': { |
| 805 'failure_type': 'compile', | 831 'failure_type': failure_type.COMPILE, |
| 806 'failures': None, | 832 'failures': None, |
| 807 'status': suspected_cl_status.CORRECT, | 833 'status': suspected_cl_status.CORRECT, |
| 808 'approach': analysis_approach_type.HEURISTIC, | 834 'approaches': [analysis_approach_type.HEURISTIC, |
| 809 'top_score': 5, | 835 analysis_approach_type.TRY_JOB], |
| 810 'Confidence': 97.9 | 836 'top_score': 5 |
| 811 } | 837 } |
| 812 } | 838 } |
| 813 suspected_cl.put() | 839 suspected_cl.put() |
| 814 | 840 |
| 815 expected_try_job_result = { | 841 expected_try_job_result = { |
| 816 'status': 'completed', | 842 'status': 'completed', |
| 817 'url': 'build/url', | 843 'url': 'build/url', |
| 818 'completed': True, | 844 'completed': True, |
| 819 'culprit': { | 845 'culprit': { |
| 820 'revision': 'rev', | 846 'revision': 'rev', |
| 821 }, | 847 }, |
| 822 'failed': False, | 848 'failed': False, |
| 823 } | 849 } |
| 824 | 850 |
| 825 expected_suspected_cls = [ | 851 expected_suspected_cls = [ |
| 826 { | 852 { |
| 827 'repo_name': 'chromium', | 853 'repo_name': 'chromium', |
| 828 'revision': 'rev', | 854 'revision': 'rev', |
| 829 'commit_position': 122, | 855 'commit_position': 122, |
| 830 'url': None, | 856 'url': None, |
| 831 'status': suspected_cl_status.CORRECT | 857 'status': suspected_cl_status.CORRECT, |
| 858 'confidence': build_failure._PercentFormat( |
| 859 self.cl_confidences.compile_heuristic_try_job.confidence) |
| 832 } | 860 } |
| 833 ] | 861 ] |
| 834 | 862 |
| 835 build_url = buildbot.CreateBuildUrl('m', 'b', 123) | 863 build_url = buildbot.CreateBuildUrl('m', 'b', 123) |
| 836 response = self.test_app.get('/build-failure', | 864 response = self.test_app.get('/build-failure', |
| 837 params={'url': build_url, 'format': 'json'}) | 865 params={'url': build_url, 'format': 'json'}) |
| 838 | 866 |
| 839 self.assertEquals(200, response.status_int) | 867 self.assertEquals(200, response.status_int) |
| 840 self.assertEqual(expected_try_job_result, response.json_body['try_job']) | 868 self.assertEqual(expected_try_job_result, response.json_body['try_job']) |
| 841 self.assertEqual( | 869 self.assertEqual( |
| 842 expected_suspected_cls, response.json_body['suspected_cls']) | 870 expected_suspected_cls, response.json_body['suspected_cls']) |
| 843 | 871 |
| 844 def testGetAllSuspectedCLsAndCheckStatus(self): | 872 def testGetAllSuspectedCLsAndCheckStatus(self): |
| 845 master_name = 'm' | 873 master_name = 'm' |
| 846 builder_name = 'b' | 874 builder_name = 'b' |
| 847 build_number = 123 | 875 build_number = 123 |
| 848 analysis = WfAnalysis.Create(master_name, builder_name, build_number) | 876 analysis = WfAnalysis.Create(master_name, builder_name, build_number) |
| 849 analysis.suspected_cls = [ | 877 analysis.suspected_cls = [ |
| 850 { | 878 { |
| 851 'repo_name': 'chromium', | 879 'repo_name': 'chromium', |
| 852 'revision': 'rev', | 880 'revision': 'rev', |
| 853 'commit_position': 122, | 881 'commit_position': 122, |
| 854 'url': None | 882 'url': None |
| 855 } | 883 } |
| 856 ] | 884 ] |
| 857 analysis.put() | 885 analysis.put() |
| 858 suspected_cl = WfSuspectedCL.Create('chromium', 'rev', 122) | 886 suspected_cl = WfSuspectedCL.Create('chromium', 'rev', 122) |
| 859 suspected_cl.builds = { | 887 suspected_cl.builds = { |
| 860 'm/b/122': { | 888 'm/b/122': { |
| 861 'failure_type': 'compile', | 889 'failure_type': failure_type.COMPILE, |
| 862 'failures': None, | 890 'failures': None, |
| 863 'status': suspected_cl_status.CORRECT, | 891 'status': suspected_cl_status.CORRECT, |
| 864 'approach': analysis_approach_type.HEURISTIC, | 892 'approaches': [analysis_approach_type.TRY_JOB], |
| 865 'top_score': 5, | 893 'top_score': 5 |
| 866 'Confidence': 97.9 | |
| 867 } | 894 } |
| 868 } | 895 } |
| 869 suspected_cl.put() | 896 suspected_cl.put() |
| 870 | 897 |
| 871 expected_suspected_cls = [ | 898 expected_suspected_cls = [ |
| 872 { | 899 { |
| 873 'repo_name': 'chromium', | 900 'repo_name': 'chromium', |
| 874 'revision': 'rev', | 901 'revision': 'rev', |
| 875 'commit_position': 122, | 902 'commit_position': 122, |
| 876 'url': None, | 903 'url': None, |
| 877 'status': None | 904 'status': None, |
| 905 'confidence': None |
| 878 } | 906 } |
| 879 ] | 907 ] |
| 880 | 908 |
| 881 suspected_cls = build_failure._GetAllSuspectedCLsAndCheckStatus( | 909 suspected_cls = build_failure._GetAllSuspectedCLsAndCheckStatus( |
| 882 master_name, builder_name, build_number, analysis) | 910 master_name, builder_name, build_number, analysis) |
| 883 self.assertEqual( | 911 self.assertEqual( |
| 884 expected_suspected_cls, suspected_cls) | 912 expected_suspected_cls, suspected_cls) |
| 885 | 913 |
| 914 def testGetConfidenceScoreTestHeuristic(self): |
| 915 build = { |
| 916 'failure_type': failure_type.TEST, |
| 917 'failures': None, |
| 918 'status': suspected_cl_status.CORRECT, |
| 919 'approaches': [analysis_approach_type.HEURISTIC], |
| 920 'top_score': 5 |
| 921 } |
| 922 |
| 923 self.assertEqual( |
| 924 build_failure._PercentFormat( |
| 925 self.cl_confidences.test_heuristic[1].confidence), |
| 926 build_failure._GetConfidenceScore(self.cl_confidences, build)) |
| 927 |
| 928 def testGetConfidenceScoreCompileHeuristic(self): |
| 929 build = { |
| 930 'failure_type': failure_type.COMPILE, |
| 931 'failures': None, |
| 932 'status': suspected_cl_status.CORRECT, |
| 933 'approaches': [analysis_approach_type.HEURISTIC], |
| 934 'top_score': 4 |
| 935 } |
| 936 |
| 937 self.assertEqual( |
| 938 build_failure._PercentFormat( |
| 939 self.cl_confidences.compile_heuristic[1].confidence), |
| 940 build_failure._GetConfidenceScore(self.cl_confidences, build)) |
| 941 |
| 942 def testGetConfidenceScoreTestTryJob(self): |
| 943 build = { |
| 944 'failure_type': failure_type.TEST, |
| 945 'failures': None, |
| 946 'status': suspected_cl_status.CORRECT, |
| 947 'approaches': [analysis_approach_type.TRY_JOB], |
| 948 'top_score': 5 |
| 949 } |
| 950 |
| 951 self.assertEqual( |
| 952 build_failure._PercentFormat( |
| 953 self.cl_confidences.test_try_job.confidence), |
| 954 build_failure._GetConfidenceScore(self.cl_confidences, build)) |
| 955 |
| 956 def testGetConfidenceScoreCompileTryJob(self): |
| 957 build = { |
| 958 'failure_type': failure_type.COMPILE, |
| 959 'failures': None, |
| 960 'status': suspected_cl_status.CORRECT, |
| 961 'approaches': [analysis_approach_type.TRY_JOB], |
| 962 'top_score': 5 |
| 963 } |
| 964 |
| 965 self.assertEqual( |
| 966 build_failure._PercentFormat( |
| 967 self.cl_confidences.test_try_job.confidence), |
| 968 build_failure._GetConfidenceScore(self.cl_confidences, build)) |
| 969 |
| 970 def testGetConfidenceScoreTestHeuristicTryJob(self): |
| 971 build = { |
| 972 'failure_type': failure_type.TEST, |
| 973 'failures': None, |
| 974 'status': suspected_cl_status.CORRECT, |
| 975 'approaches': [analysis_approach_type.HEURISTIC, |
| 976 analysis_approach_type.TRY_JOB], |
| 977 'top_score': 5 |
| 978 } |
| 979 |
| 980 self.assertEqual( |
| 981 build_failure._PercentFormat( |
| 982 self.cl_confidences.test_heuristic_try_job.confidence), |
| 983 build_failure._GetConfidenceScore(self.cl_confidences, build)) |
| 984 |
| 985 def testGetConfidenceScoreNone(self): |
| 986 self.assertIsNone(build_failure._GetConfidenceScore(None, None)) |
| 987 |
| 988 def testGetConfidenceScoreUnexpected(self): |
| 989 build = { |
| 990 'failure_type': failure_type.COMPILE, |
| 991 'failures': None, |
| 992 'status': suspected_cl_status.CORRECT, |
| 993 'approaches': [analysis_approach_type.HEURISTIC], |
| 994 'top_score': 2 |
| 995 } |
| 996 |
| 997 self.assertIsNone(build_failure._GetConfidenceScore( |
| 998 self.cl_confidences, build)) |
| 999 |
| 1000 def testGetConfidenceScoreCompileNone(self): |
| 1001 build = { |
| 1002 'failure_type': failure_type.COMPILE, |
| 1003 'approaches': [] |
| 1004 } |
| 1005 self.assertIsNone(build_failure._GetConfidenceScore( |
| 1006 self.cl_confidences, build)) |
| 1007 |
| 1008 def testGetConfidenceScoreUnexpectedTest(self): |
| 1009 build = { |
| 1010 'failure_type': failure_type.TEST, |
| 1011 'failures': None, |
| 1012 'status': suspected_cl_status.CORRECT, |
| 1013 'approaches': [analysis_approach_type.HEURISTIC], |
| 1014 'top_score': 2 |
| 1015 } |
| 1016 |
| 1017 self.assertIsNone(build_failure._GetConfidenceScore( |
| 1018 self.cl_confidences, build)) |
| 1019 |
| 1020 def testGetConfidenceScoreTestNone(self): |
| 1021 build = { |
| 1022 'failure_type': failure_type.TEST, |
| 1023 'approaches': [] |
| 1024 } |
| 1025 self.assertIsNone(build_failure._GetConfidenceScore( |
| 1026 self.cl_confidences, build)) |
| 1027 |
| 1028 def testPercentFormatNone(self): |
| 1029 self.assertIsNone(build_failure._PercentFormat(None)) |
| OLD | NEW |