| OLD | NEW |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 copy | 5 import copy |
| 6 import logging | 6 import logging |
| 7 import math | 7 import math |
| 8 import pprint | 8 import pprint |
| 9 | 9 |
| 10 from common.dependency import Dependency | 10 from common.dependency import Dependency |
| 11 from common.dependency import DependencyRoll | 11 from common.dependency import DependencyRoll |
| 12 from common.chrome_dependency_fetcher import ChromeDependencyFetcher | 12 from common.chrome_dependency_fetcher import ChromeDependencyFetcher |
| 13 import crash.changelist_classifier as scorer_changelist_classifier | 13 import crash.changelist_classifier as scorer_changelist_classifier |
| 14 from crash.crash_report import CrashReport | 14 from crash.crash_report import CrashReport |
| 15 from crash.loglinear.changelist_classifier import LogLinearChangelistClassifier | 15 from crash.loglinear.changelist_classifier import LogLinearChangelistClassifier |
| 16 from crash.loglinear.changelist_features.min_distance import MinDistanceFeature |
| 17 from crash.loglinear.changelist_features.top_frame_index import ( |
| 18 TopFrameIndexFeature) |
| 19 from crash.loglinear.feature import WrapperMetaFeature |
| 20 from crash.loglinear.weight import Weight |
| 21 from crash.loglinear.weight import MetaWeight |
| 16 from crash.suspect import AnalysisInfo | 22 from crash.suspect import AnalysisInfo |
| 17 from crash.suspect import Suspect | 23 from crash.suspect import Suspect |
| 18 from crash.suspect import StackInfo | 24 from crash.suspect import StackInfo |
| 19 from crash.stacktrace import CallStack | 25 from crash.stacktrace import CallStack |
| 20 from crash.stacktrace import StackFrame | 26 from crash.stacktrace import StackFrame |
| 21 from crash.stacktrace import Stacktrace | 27 from crash.stacktrace import Stacktrace |
| 22 from crash.test.crash_test_suite import CrashTestSuite | 28 from crash.test.crash_test_suite import CrashTestSuite |
| 23 from crash.type_enums import CallStackFormatType | 29 from crash.type_enums import CallStackFormatType |
| 24 from crash.type_enums import LanguageType | 30 from crash.type_enums import LanguageType |
| 25 from libs.gitiles.change_log import ChangeLog | 31 from libs.gitiles.change_log import ChangeLog |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 CallStack(1, [], CallStackFormatType.DEFAULT, LanguageType.CPP)] | 119 CallStack(1, [], CallStackFormatType.DEFAULT, LanguageType.CPP)] |
| 114 DUMMY_REPORT = CrashReport( | 120 DUMMY_REPORT = CrashReport( |
| 115 None, None, None, Stacktrace(DUMMY_CALLSTACKS, DUMMY_CALLSTACKS[0]), | 121 None, None, None, Stacktrace(DUMMY_CALLSTACKS, DUMMY_CALLSTACKS[0]), |
| 116 (None, None)) | 122 (None, None)) |
| 117 | 123 |
| 118 | 124 |
| 119 class LogLinearChangelistClassifierTest(CrashTestSuite): | 125 class LogLinearChangelistClassifierTest(CrashTestSuite): |
| 120 | 126 |
| 121 def setUp(self): | 127 def setUp(self): |
| 122 super(LogLinearChangelistClassifierTest, self).setUp() | 128 super(LogLinearChangelistClassifierTest, self).setUp() |
| 123 weights = { | 129 meta_weight = MetaWeight({ |
| 124 'MinDistance': 1., | 130 'MinDistance': Weight(1.), |
| 125 'TopFrameIndex': 1., | 131 'TopFrameIndex': Weight(1.), |
| 126 } | 132 }) |
| 133 meta_feature = WrapperMetaFeature([MinDistanceFeature(), |
| 134 TopFrameIndexFeature()]) |
| 127 | 135 |
| 128 self.changelist_classifier = LogLinearChangelistClassifier( | 136 self.changelist_classifier = LogLinearChangelistClassifier( |
| 129 GitilesRepository.Factory(self.GetMockHttpClient()), weights) | 137 GitilesRepository.Factory(self.GetMockHttpClient()), |
| 138 meta_feature, meta_weight) |
| 130 | 139 |
| 131 # TODO(http://crbug.com/659346): why do these mocks give coverage | 140 # TODO(http://crbug.com/659346): why do these mocks give coverage |
| 132 # failures? That's almost surely hiding a bug in the tests themselves. | 141 # failures? That's almost surely hiding a bug in the tests themselves. |
| 133 def testFindItForCrashNoRegressionRange(self): # pragma: no cover | 142 def testFindItForCrashNoRegressionRange(self): # pragma: no cover |
| 134 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) | 143 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) |
| 135 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) | 144 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) |
| 136 # N.B., for this one test we really do want regression_range=None. | 145 # N.B., for this one test we really do want regression_range=None. |
| 137 report = DUMMY_REPORT._replace(regression_range=None) | 146 report = DUMMY_REPORT._replace(regression_range=None) |
| 138 self.assertListEqual(self.changelist_classifier(report), []) | 147 self.assertListEqual(self.changelist_classifier(report), []) |
| 139 | 148 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 | 207 |
| 199 expected_suspects = [ | 208 expected_suspects = [ |
| 200 { | 209 { |
| 201 'review_url': 'https://codereview.chromium.org/3281', | 210 'review_url': 'https://codereview.chromium.org/3281', |
| 202 'url': 'https://repo.test/+/3', | 211 'url': 'https://repo.test/+/3', |
| 203 'author': 'e@chromium.org', | 212 'author': 'e@chromium.org', |
| 204 'time': 'Thu Apr 1 21:24:43 2016', | 213 'time': 'Thu Apr 1 21:24:43 2016', |
| 205 'project_path': 'src/', | 214 'project_path': 'src/', |
| 206 'revision': '3', | 215 'revision': '3', |
| 207 'confidence': math.log(0.2857142857142857 * 0.6), | 216 'confidence': math.log(0.2857142857142857 * 0.6), |
| 208 'reasons': [ | 217 'reasons': ('MinDistance: -0.510826 -- Minimum distance is 20\n' |
| 209 ('MinDistance', math.log(0.6), 'Minimum distance is 20'), | 218 'TopFrameIndex: -1.252763 -- Top frame is #5'), |
| 210 ('TopFrameIndex', math.log(0.2857142857142857), | |
| 211 'Top frame is #5')], | |
| 212 'changed_files': [ | 219 'changed_files': [ |
| 213 { | 220 { |
| 214 'file': 'a.cc', | 221 'file': 'a.cc', |
| 215 'blame_url': None, | 222 'blame_url': None, |
| 216 'info': 'Minimum distance (LOC) 20, frame #5', | 223 'info': 'Minimum distance (LOC) 20, frame #5', |
| 217 }], | 224 }], |
| 218 }, { | 225 }, { |
| 219 'review_url': 'https://codereview.chromium.org/3281', | 226 'review_url': 'https://codereview.chromium.org/3281', |
| 220 'url': 'https://repo.test/+/1', | 227 'url': 'https://repo.test/+/1', |
| 221 'author': 'r@chromium.org', | 228 'author': 'r@chromium.org', |
| 222 'time': 'Thu Mar 31 21:24:43 2016', | 229 'time': 'Thu Mar 31 21:24:43 2016', |
| 223 'project_path': 'src/', | 230 'project_path': 'src/', |
| 224 'revision': '1', | 231 'revision': '1', |
| 225 'confidence': 0., | 232 'confidence': 0., |
| 226 'reasons': [ | 233 'reasons': ('MinDistance: 0.000000 -- Minimum distance is 0\n' |
| 227 ('MinDistance', 0., 'Minimum distance is 0'), | 234 'TopFrameIndex: 0.000000 -- Top frame is #0'), |
| 228 ('TopFrameIndex', 0., 'Top frame is #0')], | |
| 229 'changed_files': [ | 235 'changed_files': [ |
| 230 { | 236 { |
| 231 'file': 'a.cc', | 237 'file': 'a.cc', |
| 232 'blame_url': None, | 238 'blame_url': None, |
| 233 'info': 'Minimum distance (LOC) 0, frame #0', | 239 'info': 'Minimum distance (LOC) 0, frame #0', |
| 234 }], | 240 }], |
| 235 }, | 241 }, |
| 236 ] | 242 ] |
| 237 self.assertListEqual([suspect.ToDict() for suspect in suspects], | 243 self.assertListEqual([suspect.ToDict() for suspect in suspects], |
| 238 expected_suspects) | 244 expected_suspects) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 'author': 'r@chromium.org', | 286 'author': 'r@chromium.org', |
| 281 'changed_files': [ | 287 'changed_files': [ |
| 282 { | 288 { |
| 283 'blame_url': None, | 289 'blame_url': None, |
| 284 'file': 'a.cc', | 290 'file': 'a.cc', |
| 285 'info': 'Minimum distance (LOC) 1, frame #0' | 291 'info': 'Minimum distance (LOC) 1, frame #0' |
| 286 } | 292 } |
| 287 ], | 293 ], |
| 288 'confidence': math.log(0.98), | 294 'confidence': math.log(0.98), |
| 289 'project_path': 'src/', | 295 'project_path': 'src/', |
| 290 'reasons': [ | 296 'reasons': ('MinDistance: -0.020203 -- Minimum distance is 1\n' |
| 291 ('MinDistance', math.log(0.98), 'Minimum distance is 1'), | 297 'TopFrameIndex: 0.000000 -- Top frame is #0'), |
| 292 ('TopFrameIndex', 0., 'Top frame is #0'), | |
| 293 ], | |
| 294 'review_url': 'https://codereview.chromium.org/3281', | 298 'review_url': 'https://codereview.chromium.org/3281', |
| 295 'revision': '1', | 299 'revision': '1', |
| 296 'time': 'Thu Mar 31 21:24:43 2016', | 300 'time': 'Thu Mar 31 21:24:43 2016', |
| 297 'url': 'https://repo.test/+/1' | 301 'url': 'https://repo.test/+/1' |
| 298 }, | 302 }, |
| 299 ] | 303 ] |
| 300 self.assertListEqual([suspect.ToDict() for suspect in suspects], | 304 self.assertListEqual([suspect.ToDict() for suspect in suspects], |
| 301 expected_suspects) | 305 expected_suspects) |
| 302 | 306 |
| 303 def testFinditForCrashAllSuspectsWithZeroConfidences(self): | 307 def testFinditForCrashAllSuspectsWithZeroConfidences(self): |
| (...skipping 25 matching lines...) Expand all Loading... |
| 329 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) | 333 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) |
| 330 } | 334 } |
| 331 | 335 |
| 332 return [suspect1, suspect2] | 336 return [suspect1, suspect2] |
| 333 | 337 |
| 334 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) | 338 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) |
| 335 | 339 |
| 336 suspects = self.changelist_classifier(DUMMY_REPORT) | 340 suspects = self.changelist_classifier(DUMMY_REPORT) |
| 337 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' | 341 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' |
| 338 % pprint.pformat([suspect.ToDict() for suspect in suspects])) | 342 % pprint.pformat([suspect.ToDict() for suspect in suspects])) |
| OLD | NEW |