Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: appengine/findit/waterfall/test/build_failure_analysis_test.py

Issue 838003004: [Findit] Add three sub-pipelines to analyze build failure. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: . Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import unittest
6
7 from common.diff import ChangeType
8 from waterfall import build_failure_analysis
9 from waterfall.failure_signal import FailureSignal
10
11
12 class BuildFailureAnalysisTest(unittest.TestCase):
13
14 def testIsSameFile(self):
15 self.assertTrue(build_failure_analysis.IsSameFile('a/b/x.cc', 'x.cc'))
16 self.assertFalse(build_failure_analysis.IsSameFile('a/b/pre_x.cc.', 'x.cc'))
17 self.assertFalse(build_failure_analysis.IsSameFile('a/b/x.cc.', 'a/b/y.cc'))
18
19 def testJoinAsFilePath(self):
20 self.assertEqual('a/x.cc',
21 build_failure_analysis.JoinAsFilePath('a', 'x.cc'))
22 self.assertEqual('x.cc',
23 build_failure_analysis.JoinAsFilePath(None, 'x.cc'))
24
25 def testNormalizeObjectFile(self):
26 cases = {
27 'obj/a/T.x.o': 'a/x.o',
28 'obj/a/T.x.y.o': 'a/x.y.o',
29 'x.o': 'x.o'
30 }
31 for obj_file, expected_file in cases.iteritems():
32 self.assertEqual(
33 expected_file,
34 build_failure_analysis.NormalizeObjectFile(obj_file))
35
36 def testStripCommonPostfix(self):
37 cases = {
38 'a_file':
39 'a_file_%s.cc' % '_'.join(build_failure_analysis.COMMON_POSTFIXES),
40 'src/b_file': 'src/b_file_impl_mac.h',
41 'c_file': 'c_file_browsertest.cc'
42 }
43 for expected_file, file_path in cases.iteritems():
44 self.assertEqual(
45 expected_file,
46 build_failure_analysis.StripExtensionAndCommonPostfix(file_path))
47
48 def testIsCorrelated(self):
49 self.assertTrue(build_failure_analysis.IsCorrelated('a.h', 'a_test.py'))
50 self.assertTrue(build_failure_analysis.IsCorrelated('a.h', 'a_impl_test.o'))
51 self.assertTrue(build_failure_analysis.IsCorrelated('a/b/x.cc', 'a/b/y.cc'))
qyearsley 2015/01/15 21:15:03 Maybe add a negative case -- when is IsCorrelated
stgao 2015/01/16 20:21:39 Negative case added. If a CL changed file a.h, an
52
53 def testCheckFilesAgainstSuspectedCL(self):
54 failure_signal_json = {
55 'files': {
56 'src/a/b/f1.cc': [],
57 'b/c/f2.h': [10, 20],
58 'd/e/f3_test.cc': [],
59 'x/y/f4.py': [],
60 'f5_impl.cc': []
61 }
62 }
63 change_log_json = {
64 'touched_files': [
65 {
66 'change_type': ChangeType.ADD,
67 'old_path': '/dev/null',
68 'new_path': 'a/b/f1.cc'
69 },
70 {
71 'change_type': ChangeType.MODIFY,
72 'old_path': 'a/b/c/f2.h',
73 'new_path': 'a/b/c/f2.h'
74 },
75 {
76 'change_type': ChangeType.MODIFY,
77 'old_path': 'd/e/f3.h',
78 'new_path': 'd/e/f3.h'
79 },
80 {
81 'change_type': ChangeType.DELETE,
82 'old_path': 'x/y/f4.py',
83 'new_path': '/dev/null'
84 },
85 {
86 'change_type': ChangeType.DELETE,
87 'old_path': 'h/f5.h',
88 'new_path': '/dev/null'
89 },
90 {
91 'change_type': ChangeType.RENAME,
92 'old_path': 't/y/x.cc',
93 'new_path': 's/z/x.cc'
94 },
95 ]
96 }
97
98 justification = build_failure_analysis.CheckFiles(
99 FailureSignal.FromJson(failure_signal_json), change_log_json)
100 self.assertIsNotNone(justification)
101 self.assertEqual(2, justification['suspects'])
102 self.assertEqual(13, justification['scores'])
103
104 def testCheckFilesAgainstUnrelatedCL(self):
105 failure_signal_json = {
106 'files': {
107 'src/a/b/f.cc': [],
108 }
109 }
110 change_log_json = {
111 'touched_files': [
112 {
113 'change_type': ChangeType.ADD,
114 'old_path': '/dev/null',
115 'new_path': 'a/d/f1.cc'
116 },
117 ]
118 }
119
120 justification = build_failure_analysis.CheckFiles(
121 FailureSignal.FromJson(failure_signal_json), change_log_json)
122 self.assertIsNone(justification)
123
124 def testAnalyzeSuccesfulBuild(self):
125 failure_info = {
126 'failed': False,
127 }
128 result = build_failure_analysis.AnalyzeBuildFailure(
129 failure_info, None, None)
130 self.assertEqual(0, len(result))
131
132 def testAnalyzeBuildFailure(self):
133 failure_info = {
134 'failed': True,
135 'failed_steps': {
136 'a': {
137 'current_failure': 99,
138 'first_failure': 98,
139 },
140 'b': {
141 'current_failure': 99,
142 'first_failure': 98,
143 },
144 },
145 'builds': {
146 '99': {
147 'blame_list': ['r99_1', 'r99_2'],
148 },
149 '98': {
150 'blame_list': ['r98_1'],
151 },
152 }
153 }
154 change_logs = {
155 'r99_1': {
156 'touched_files': [
157 {
158 'change_type': ChangeType.ADD,
159 'old_path': '/dev/null',
160 'new_path': 'x/y/f99_1.cc'
161 },
162 ],
163 },
164 'r99_2': {
165 'touched_files': [
166 {
167 'change_type': ChangeType.MODIFY,
168 'old_path': 'a/b/f99_2.cc',
169 'new_path': 'a/b/f99_2.cc'
170 },
171 ],
172 },
173 'r98_1': {
174 'touched_files': [
175 {
176 'change_type': ChangeType.MODIFY,
177 'old_path': 'y/z/f98.cc',
178 'new_path': 'y/z/f98.cc'
179 },
180 ],
181 },
182 }
183 failure_signals_json = {
184 'a': {
185 'files': {
186 'src/a/b/f99_2.cc': [],
187 },
188 },
189 'b': {
190 'files': {
191 'f.cc': [],
192 },
193 },
194 }
195 expected_analysis_result = {
196 'a': {
197 'r99_2': {
198 'suspects': 0,
199 'scores': 1,
200 'hints': [
201 'modify a/b/f99_2.cc',
202 ]
203 },
204 },
205 }
206
207 analysis_result = build_failure_analysis.AnalyzeBuildFailure(
208 failure_info, change_logs, failure_signals_json)
209 self.assertEqual(expected_analysis_result, analysis_result)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698