| 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.feature import ChangedFile | |
| 17 from crash.loglinear.feature import FeatureValue | |
| 18 from crash.suspect import AnalysisInfo | 16 from crash.suspect import AnalysisInfo |
| 19 from crash.suspect import Suspect | 17 from crash.suspect import Suspect |
| 20 from crash.suspect import StackInfo | 18 from crash.suspect import StackInfo |
| 21 from crash.stacktrace import CallStack | 19 from crash.stacktrace import CallStack |
| 22 from crash.stacktrace import StackFrame | 20 from crash.stacktrace import StackFrame |
| 23 from crash.stacktrace import Stacktrace | 21 from crash.stacktrace import Stacktrace |
| 24 from crash.test.crash_test_suite import CrashTestSuite | 22 from crash.test.crash_test_suite import CrashTestSuite |
| 25 from crash.type_enums import CallStackFormatType | 23 from crash.type_enums import CallStackFormatType |
| 26 from crash.type_enums import LanguageType | 24 from crash.type_enums import LanguageType |
| 27 from libs.gitiles.change_log import ChangeLog | 25 from libs.gitiles.change_log import ChangeLog |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 def setUp(self): | 121 def setUp(self): |
| 124 super(LogLinearChangelistClassifierTest, self).setUp() | 122 super(LogLinearChangelistClassifierTest, self).setUp() |
| 125 weights = { | 123 weights = { |
| 126 'MinDistance': 1., | 124 'MinDistance': 1., |
| 127 'TopFrameIndex': 1., | 125 'TopFrameIndex': 1., |
| 128 } | 126 } |
| 129 | 127 |
| 130 self.changelist_classifier = LogLinearChangelistClassifier( | 128 self.changelist_classifier = LogLinearChangelistClassifier( |
| 131 GitilesRepository.Factory(self.GetMockHttpClient()), weights) | 129 GitilesRepository.Factory(self.GetMockHttpClient()), weights) |
| 132 | 130 |
| 133 def testAggregateChangedFilesAggregates(self): | |
| 134 """Test that ``AggregateChangedFiles`` does aggregate reasons per file. | |
| 135 | |
| 136 In the main/inner loop of ``AggregateChangedFiles``: if multiple | |
| 137 features all blame the same file change, we try to aggregate those | |
| 138 reasons so that we only report the file once (with all reasons). None | |
| 139 of the other tests here actually check the case where the same file | |
| 140 is blamed multiple times, so we check that here. | |
| 141 | |
| 142 In particular, we provide the same ``FeatureValue`` twice, and | |
| 143 hence the same ``ChangedFile`` twice; so we should get back a single | |
| 144 ``ChangedFile`` but with the ``reasons`` fields concatenated. | |
| 145 """ | |
| 146 file_reason = 'I blame you!' | |
| 147 file_blame = ChangedFile( | |
| 148 name = 'a.cc', | |
| 149 blame_url = None, | |
| 150 reasons = [file_reason] | |
| 151 ) | |
| 152 | |
| 153 feature_value = FeatureValue( | |
| 154 name = 'dummy feature', | |
| 155 value = 42, | |
| 156 reason = 'dummy reason', | |
| 157 changed_files = [file_blame] | |
| 158 ) | |
| 159 | |
| 160 expected_file_blame = file_blame._replace(reasons = [file_reason] * 2) | |
| 161 | |
| 162 self.assertListEqual( | |
| 163 [expected_file_blame], | |
| 164 self.changelist_classifier.AggregateChangedFiles( | |
| 165 [feature_value] * 2)) | |
| 166 | |
| 167 # TODO(http://crbug.com/659346): why do these mocks give coverage | 131 # TODO(http://crbug.com/659346): why do these mocks give coverage |
| 168 # failures? That's almost surely hiding a bug in the tests themselves. | 132 # failures? That's almost surely hiding a bug in the tests themselves. |
| 169 def testFindItForCrashNoRegressionRange(self): # pragma: no cover | 133 def testFindItForCrashNoRegressionRange(self): # pragma: no cover |
| 170 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) | 134 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) |
| 171 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) | 135 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) |
| 172 # N.B., for this one test we really do want regression_range=None. | 136 # N.B., for this one test we really do want regression_range=None. |
| 173 report = DUMMY_REPORT._replace(regression_range=None) | 137 report = DUMMY_REPORT._replace(regression_range=None) |
| 174 self.assertListEqual(self.changelist_classifier(report), []) | 138 self.assertListEqual(self.changelist_classifier(report), []) |
| 175 | 139 |
| 176 def testFindItForCrashNoMatchFound(self): | 140 def testFindItForCrashNoMatchFound(self): |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) | 329 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) |
| 366 } | 330 } |
| 367 | 331 |
| 368 return [suspect1, suspect2] | 332 return [suspect1, suspect2] |
| 369 | 333 |
| 370 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) | 334 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) |
| 371 | 335 |
| 372 suspects = self.changelist_classifier(DUMMY_REPORT) | 336 suspects = self.changelist_classifier(DUMMY_REPORT) |
| 373 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' | 337 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' |
| 374 % pprint.pformat([suspect.ToDict() for suspect in suspects])) | 338 % pprint.pformat([suspect.ToDict() for suspect in suspects])) |
| OLD | NEW |