| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 def setUp(self): | 109 def setUp(self): |
| 112 super(LogLinearChangelistClassifierTest, self).setUp() | 110 super(LogLinearChangelistClassifierTest, self).setUp() |
| 113 weights = { | 111 weights = { |
| 114 'MinDistance': 1., | 112 'MinDistance': 1., |
| 115 'TopFrameIndex': 1., | 113 'TopFrameIndex': 1., |
| 116 } | 114 } |
| 117 | 115 |
| 118 self.changelist_classifier = LogLinearChangelistClassifier( | 116 self.changelist_classifier = LogLinearChangelistClassifier( |
| 119 GitilesRepository.Factory(self.GetMockHttpClient()), weights) | 117 GitilesRepository.Factory(self.GetMockHttpClient()), weights) |
| 120 | 118 |
| 121 def testAggregateChangedFilesAggregates(self): | |
| 122 """Test that ``AggregateChangedFiles`` does aggregate reasons per file. | |
| 123 | |
| 124 In the main/inner loop of ``AggregateChangedFiles``: if multiple | |
| 125 features all blame the same file change, we try to aggregate those | |
| 126 reasons so that we only report the file once (with all reasons). None | |
| 127 of the other tests here actually check the case where the same file | |
| 128 is blamed multiple times, so we check that here. | |
| 129 | |
| 130 In particular, we provide the same ``FeatureValue`` twice, and | |
| 131 hence the same ``ChangedFile`` twice; so we should get back a single | |
| 132 ``ChangedFile`` but with the ``reasons`` fields concatenated. | |
| 133 """ | |
| 134 file_reason = 'I blame you!' | |
| 135 file_blame = ChangedFile( | |
| 136 name = 'a.cc', | |
| 137 blame_url = None, | |
| 138 reasons = [file_reason] | |
| 139 ) | |
| 140 | |
| 141 feature_value = FeatureValue( | |
| 142 name = 'dummy feature', | |
| 143 value = 42, | |
| 144 reason = 'dummy reason', | |
| 145 changed_files = [file_blame] | |
| 146 ) | |
| 147 | |
| 148 expected_file_blame = file_blame._replace(reasons = [file_reason] * 2) | |
| 149 | |
| 150 self.assertListEqual( | |
| 151 [expected_file_blame], | |
| 152 self.changelist_classifier.AggregateChangedFiles( | |
| 153 [feature_value] * 2)) | |
| 154 | |
| 155 # TODO(http://crbug.com/659346): why do these mocks give coverage | 119 # TODO(http://crbug.com/659346): why do these mocks give coverage |
| 156 # failures? That's almost surely hiding a bug in the tests themselves. | 120 # failures? That's almost surely hiding a bug in the tests themselves. |
| 157 def testFindItForCrashNoRegressionRange(self): # pragma: no cover | 121 def testFindItForCrashNoRegressionRange(self): # pragma: no cover |
| 158 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) | 122 self.mock(ChromeDependencyFetcher, 'GetDependencyRollsDict', lambda *_: {}) |
| 159 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) | 123 self.mock(ChromeDependencyFetcher, 'GetDependency', lambda *_: {}) |
| 160 # N.B., for this one test we really do want regression_range=None. | 124 # N.B., for this one test we really do want regression_range=None. |
| 161 report = DUMMY_REPORT._replace(regression_range=None) | 125 report = DUMMY_REPORT._replace(regression_range=None) |
| 162 self.assertListEqual(self.changelist_classifier(report), []) | 126 self.assertListEqual(self.changelist_classifier(report), []) |
| 163 | 127 |
| 164 def testFindItForCrashNoMatchFound(self): | 128 def testFindItForCrashNoMatchFound(self): |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) | 317 'f.cc': AnalysisInfo(min_distance=20, min_distance_frame=frame3) |
| 354 } | 318 } |
| 355 | 319 |
| 356 return [suspect1, suspect2] | 320 return [suspect1, suspect2] |
| 357 | 321 |
| 358 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) | 322 self.mock(scorer_changelist_classifier, 'FindSuspects', _MockFindSuspects) |
| 359 | 323 |
| 360 suspects = self.changelist_classifier(DUMMY_REPORT) | 324 suspects = self.changelist_classifier(DUMMY_REPORT) |
| 361 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' | 325 self.assertFalse(suspects, 'Expected zero suspects, but found some:\n%s' |
| 362 % pprint.pformat([suspect.ToDict() for suspect in suspects])) | 326 % pprint.pformat([suspect.ToDict() for suspect in suspects])) |
| OLD | NEW |