| 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 from crash.stacktrace import StackFrame | 5 from crash.stacktrace import StackFrame |
| 6 from crash.stacktrace import CallStack | 6 from crash.stacktrace import CallStack |
| 7 from crash.project import Project |
| 7 from crash.project_classifier import ProjectClassifier | 8 from crash.project_classifier import ProjectClassifier |
| 8 from crash.suspect import Suspect | 9 from crash.suspect import Suspect |
| 9 from crash.test.predator_testcase import PredatorTestCase | 10 from crash.test.predator_testcase import PredatorTestCase |
| 10 from crash.type_enums import LanguageType | 11 from crash.type_enums import LanguageType |
| 12 from libs.gitiles.change_log import FileChangeInfo |
| 13 from libs.gitiles.diff import ChangeType |
| 11 from model.crash.crash_config import CrashConfig | 14 from model.crash.crash_config import CrashConfig |
| 12 | 15 |
| 13 | 16 |
| 14 class ProjectClassifierTest(PredatorTestCase): | 17 class ProjectClassifierTest(PredatorTestCase): |
| 18 """Tests ``ProjectClassifier`` class.""" |
| 15 | 19 |
| 16 def testGetProjectNameFromDepPath(self): | 20 def setUp(self): |
| 17 classifier = ProjectClassifier() | 21 super(ProjectClassifierTest, self).setUp() |
| 18 self.assertEqual(classifier._GetProjectFromDepPath('src/'), | 22 config = CrashConfig.Get().project_classifier |
| 19 'chromium') | 23 projects = [Project(name, path_regexs, function_regexs, host_directories) |
| 24 for name, path_regexs, function_regexs, host_directories |
| 25 in config['project_path_function_hosts']] |
| 26 self.classifier = ProjectClassifier( |
| 27 projects, config['top_n'], config['non_chromium_project_rank_priority']) |
| 20 | 28 |
| 21 self.assertEqual(classifier._GetProjectFromDepPath('src/abc'), | 29 def testClassifyCallStack(self): |
| 22 'chromium-abc') | 30 """Tests ``ClassifyCallStack`` method.""" |
| 31 callstack = CallStack( |
| 32 0, [StackFrame(0, 'src/', 'func', 'f.cc', 'src/f.cc', [2])]) |
| 33 self.assertEqual( |
| 34 self.classifier.ClassifyCallStack(callstack), 'chromium') |
| 23 | 35 |
| 24 self.assertEqual(classifier._GetProjectFromDepPath('unknown/unknown'), | 36 callstack = CallStack( |
| 25 'chromium-unknown_unknown') | 37 0, [StackFrame(0, '', 'android.a', 'comp1.cc', 'src/comp1.cc', [2])]) |
| 38 self.assertEqual( |
| 39 self.classifier.ClassifyCallStack(callstack), 'android_os') |
| 26 | 40 |
| 27 def testGetClassFromStackFrame(self): | 41 callstack = CallStack( |
| 28 classifier = ProjectClassifier() | 42 0, [StackFrame(0, '', 'func', 'comp2.cc', |
| 43 'googleplex-android/src/comp2.cc', [32])]) |
| 44 self.assertEqual( |
| 45 self.classifier.ClassifyCallStack(callstack), 'android_os') |
| 29 | 46 |
| 30 frame = StackFrame(0, 'src/', 'func', 'f.cc', 'src/f.cc', [2]) | 47 callstack = CallStack( |
| 48 0, [StackFrame(0, '', 'func', 'comp2.cc', 'unknown/comp2.cc', [32])]) |
| 49 self.assertIsNone(self.classifier.ClassifyCallStack(callstack)) |
| 50 |
| 51 callstack = CallStack( |
| 52 0, [StackFrame(0, '', 'android.a.b', 'f.java', 'unknown/f.java', [32])], |
| 53 language_type=LanguageType.JAVA) |
| 31 self.assertEqual( | 54 self.assertEqual( |
| 32 classifier.GetClassFromStackFrame(frame), 'chromium') | 55 self.classifier.ClassifyCallStack(callstack), 'android_os') |
| 33 | 56 |
| 34 frame = StackFrame(0, '', 'android.a', 'comp1.cc', 'src/comp1.cc', [2]) | 57 def testClassifyJavaCallstack(self): |
| 58 """Tests ``ClassifyCallStack`` classify java callstack.""" |
| 59 callstack = CallStack( |
| 60 0, [StackFrame(0, 'src/', 'org.chromium.ab', |
| 61 'f.java', 'unknown/f.java', [32])], |
| 62 language_type=LanguageType.JAVA) |
| 35 self.assertEqual( | 63 self.assertEqual( |
| 36 classifier.GetClassFromStackFrame(frame), 'android_os') | 64 self.classifier.ClassifyCallStack(callstack), 'chromium') |
| 37 | 65 |
| 38 frame = StackFrame(0, '', 'func', 'comp2.cc', | 66 def testClassifySuspect(self): |
| 39 'googleplex-android/src/comp2.cc', [32]) | 67 """Tests ``ClassifySuspect`` method.""" |
| 40 self.assertEqual( | 68 suspect = Suspect(self.GetDummyChangeLog(), 'src/') |
| 41 classifier.GetClassFromStackFrame(frame), 'android_os') | 69 self.assertEqual(self.classifier.ClassifySuspect(suspect), 'chromium') |
| 42 | 70 |
| 43 frame = StackFrame(0, '', 'func', 'comp2.cc', 'unknown/comp2.cc', [32]) | 71 def testClassifyEmptySuspect(self): |
| 44 self.assertEqual( | 72 """Tests ``ClassifySuspect`` returns None for empty suspect.""" |
| 45 classifier.GetClassFromStackFrame(frame), '') | 73 self.assertIsNone(self.classifier.ClassifySuspect(None)) |
| 46 | 74 |
| 47 def testGetClassFromSuspect(self): | 75 def testClassifySuspectNoTouchedFileMatch(self): |
| 48 classifier = ProjectClassifier() | 76 """Tests ``ClassifySuspect`` returns None if there is no file match.""" |
| 77 suspect = Suspect(self.GetDummyChangeLog(), 'dummy') |
| 78 suspect.touched_files = [FileChangeInfo(ChangeType.MODIFY, |
| 79 'a/b.h', 'a/b.h')] |
| 80 self.assertIsNone(self.classifier.ClassifySuspect(suspect)) |
| 49 | 81 |
| 50 suspect = Suspect(self.GetDummyChangeLog(), 'src/') | 82 def testClassifySuspects(self): |
| 51 suspect.file_to_stack_infos = {'a.cc': [( | 83 """Tests ``ClassifySuspects`` classify a list of ``Suspect``s.""" |
| 52 StackFrame(0, 'src/', 'func', 'a.cc', 'src/a.cc', [3]), 0 | 84 suspect1 = Suspect(self.GetDummyChangeLog(), 'src/') |
| 53 )]} | 85 suspect2 = Suspect(self.GetDummyChangeLog(), 'src/dep') |
| 54 self.assertEqual(classifier.GetClassFromSuspect(suspect), 'chromium') | 86 suspect3 = Suspect(self.GetDummyChangeLog(), 'src/dep') |
| 55 | 87 |
| 56 suspect.file_to_stack_infos = { | 88 self.assertEqual(self.classifier.ClassifySuspects( |
| 57 'comp1.cc': [ | 89 [suspect1, suspect2, suspect3]), 'chromium-dep') |
| 58 (StackFrame(0, 'src/', 'func', 'comp1.cc', 'src/comp1.cc', [2]), 0) | |
| 59 ] | |
| 60 } | |
| 61 self.assertEqual(classifier.GetClassFromSuspect(suspect), 'chromium') | |
| 62 | |
| 63 def testClassifyCrashStack(self): | |
| 64 classifier = ProjectClassifier() | |
| 65 | |
| 66 crash_stack = CallStack(0, frame_list=[ | |
| 67 StackFrame(0, 'src/', 'func', 'comp1.cc', 'src/comp1.cc', [2]), | |
| 68 StackFrame(1, 'src/', 'ff', 'comp1.cc', 'src/comp1.cc', [21]), | |
| 69 StackFrame(2, 'src/', 'func2', 'comp2.cc', 'src/comp2.cc', [8])]) | |
| 70 | |
| 71 self.assertEqual(classifier.Classify([], crash_stack), 'chromium') | |
| 72 | |
| 73 def testClassifyEmpty(self): | |
| 74 classifier = ProjectClassifier() | |
| 75 suspect = Suspect(self.GetDummyChangeLog(), '') | |
| 76 self.assertEqual(classifier.Classify([suspect], CallStack(0)), '') | |
| 77 | |
| 78 def testClassifyRankFunction(self): | |
| 79 classifier = ProjectClassifier() | |
| 80 | |
| 81 suspect1 = Suspect(self.GetDummyChangeLog(), 'src/') | |
| 82 suspect1.file_to_stack_infos = { | |
| 83 'comp1.cc': [ | |
| 84 (StackFrame(0, 'src/', 'func', 'comp1.cc', 'src/comp1.cc', [2]), 0) | |
| 85 ] | |
| 86 } | |
| 87 | |
| 88 self.assertEqual(classifier.Classify([suspect1], CallStack(0)), 'chromium') | |
| 89 | |
| 90 suspect2 = Suspect(self.GetDummyChangeLog(), '') | |
| 91 suspect2.file_to_stack_infos = { | |
| 92 'ad.cc': [ | |
| 93 (StackFrame(0, '', 'android.a', 'ad.cc', 'ad.cc', [2]), 0) | |
| 94 ] | |
| 95 } | |
| 96 | |
| 97 self.assertEqual(classifier.Classify([suspect2], CallStack(0)), | |
| 98 'android_os') | |
| 99 | |
| 100 self.assertEqual(classifier.Classify([suspect1, suspect2], CallStack(0)), | |
| 101 'chromium') | |
| 102 | |
| 103 def testClassifyForJavaRankFunction(self): | |
| 104 classifier = ProjectClassifier() | |
| 105 crash_stack = CallStack(0, | |
| 106 language_type=LanguageType.JAVA, | |
| 107 frame_list=[ | |
| 108 StackFrame(0, '', 'android.a.f', 'android/a/cc', | |
| 109 'android/a.java', [2]), | |
| 110 StackFrame(1, '', 'org.chromium.c', 'org/chromium/c.java', | |
| 111 'org/chromium/c.java', [8]) | |
| 112 ]) | |
| 113 | |
| 114 self.assertEqual(classifier.Classify([], crash_stack), | |
| 115 'chromium') | |
| 116 | |
| 117 # TODO(wrengr): what's the point of this? we're just testing that | |
| 118 # mocking does in fact mock. | |
| 119 def testClassifyReturnsNone(self): | |
| 120 self.mock(ProjectClassifier, 'Classify', lambda *_: None) | |
| 121 self.assertIsNone(ProjectClassifier().Classify([], CallStack(0))) | |
| 122 | |
| 123 def testProjectClassifierDoNotHaveConfig(self): | |
| 124 crash_config = CrashConfig.Get() | |
| 125 crash_config.project_classifier = {} | |
| 126 crash_config.put() | |
| 127 | |
| 128 crash_stack = CallStack(0, frame_list=[ | |
| 129 StackFrame(0, 'src/', 'func', 'comp1.cc', 'src/comp1.cc', [2]), | |
| 130 StackFrame(1, 'src/', 'ff', 'comp1.cc', 'src/comp1.cc', [21]), | |
| 131 StackFrame(2, 'src/', 'func2', 'comp2.cc', 'src/comp2.cc', [8])]) | |
| 132 | |
| 133 suspect1 = Suspect(self.GetDummyChangeLog(), 'src/') | |
| 134 suspect1.file_to_stack_infos = { | |
| 135 'comp1.cc': [ | |
| 136 (StackFrame(0, 'src/', 'func', 'comp1.cc', 'src/comp1.cc', [2]), 0) | |
| 137 ] | |
| 138 } | |
| 139 | |
| 140 self.assertIsNone(ProjectClassifier().Classify([suspect1], crash_stack)) | |
| 141 | |
| 142 def testSortHosts(self): | |
| 143 host_list = [ | |
| 144 'src/', | |
| 145 'src/chrome/browser/resources/', | |
| 146 'src/media/', | |
| 147 'src/sdch/', | |
| 148 'src/testing/', | |
| 149 'src/third_party/WebKit/', | |
| 150 'src/third_party/', | |
| 151 'src/tools/', | |
| 152 'src/chrome/test/data/layout_tests/' | |
| 153 ] | |
| 154 | |
| 155 crash_config = CrashConfig.Get() | |
| 156 crash_config.project_classifier['host_directories'] = host_list | |
| 157 | |
| 158 expected_sorted_host_list = [ | |
| 159 'src/chrome/test/data/layout_tests/', | |
| 160 'src/chrome/browser/resources/', | |
| 161 'src/third_party/WebKit/', | |
| 162 'src/media/', | |
| 163 'src/sdch/', | |
| 164 'src/testing/', | |
| 165 'src/third_party/', | |
| 166 'src/tools/', | |
| 167 'src/' | |
| 168 ] | |
| 169 | |
| 170 self.assertEqual( | |
| 171 ProjectClassifier().project_classifier_config['host_directories'], | |
| 172 expected_sorted_host_list) | |
| OLD | NEW |