Skip to content

Commit 756eeda

Browse files
[π˜€π—½π—Ώ] initial version
Created using spr 1.3.7
2 parents e85e035 + c78b010 commit 756eeda

File tree

2 files changed

+107
-9
lines changed

2 files changed

+107
-9
lines changed

β€Žpremerge/advisor/advisor_lib.pyβ€Ž

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import sqlite3
44
import logging
55
import re
6+
import json
7+
import os
68

79
import git_utils
810

@@ -121,9 +123,12 @@ def _try_explain_failing_at_head(
121123
) -> FailureExplanation | None:
122124
query = (
123125
"SELECT failure_message FROM failures "
124-
"WHERE source_type='postcommit' AND platform=?"
126+
"WHERE source_type='postcommit' AND platform=? AND test_file=?"
127+
)
128+
query_params = (
129+
platform,
130+
test_failure["name"],
125131
)
126-
query_params = (platform,)
127132
if base_commit_index:
128133
min_commit_index = (
129134
base_commit_index - EXPLAINED_HEAD_MAX_COMMIT_INDEX_DIFFERENCE
@@ -175,8 +180,11 @@ def _try_explain_flaky_failure(
175180
FailureExplanation object explaining the test failure.
176181
"""
177182
test_name_matches = db_connection.execute(
178-
"SELECT failure_message, commit_index FROM failures WHERE source_type='postcommit' AND platform=?",
179-
(platform,),
183+
"SELECT failure_message, commit_index FROM failures WHERE source_type='postcommit' AND platform=? AND test_file=?",
184+
(
185+
platform,
186+
test_failure["name"],
187+
),
180188
).fetchall()
181189
commit_indices = []
182190
for failure_message, commit_index in test_name_matches:
@@ -194,17 +202,50 @@ def _try_explain_flaky_failure(
194202
return None
195203

196204

205+
def _log_explanation_request(
206+
explanation_request: TestExplanationRequest,
207+
base_commit_index: int,
208+
db_connection: sqlite3.Connection,
209+
explanations: list[FailureExplanation],
210+
debug_folder: str,
211+
):
212+
explanation_log = {
213+
"request": explanation_request,
214+
"explanations": explanations,
215+
"base_commit_index": base_commit_index,
216+
"relevant_previous_failures": [],
217+
}
218+
for failure in explanation_request["failures"]:
219+
test_name_matches = db_connection.execute(
220+
"SELECT failure_message, commit_index, test_file "
221+
"FROM failures WHERE source_type='postcommit' AND platform=? AND test_file=?",
222+
(
223+
explanation_request["platform"],
224+
failure["name"],
225+
),
226+
).fetchall()
227+
explanation_log["relevant_previous_failures"].extend(test_name_matches)
228+
with open(
229+
os.path.join(
230+
debug_folder, str(base_commit_index) + "-" + str(int(time.time())) + ".txt"
231+
),
232+
"w",
233+
) as output_file:
234+
json.dump(explanation_log, output_file)
235+
236+
197237
def explain_failures(
198238
explanation_request: TestExplanationRequest,
199239
repository_path: str,
200240
db_connection: sqlite3.Connection,
241+
debug_folder: str | None = None,
201242
) -> list[FailureExplanation]:
202243
_canonicalize_failures(explanation_request["failures"])
203244
explanations = []
245+
commit_index = git_utils.get_commit_index(
246+
explanation_request["base_commit_sha"], repository_path, db_connection
247+
)
204248
for test_failure in explanation_request["failures"]:
205-
commit_index = git_utils.get_commit_index(
206-
explanation_request["base_commit_sha"], repository_path, db_connection
207-
)
208249
# We want to try and explain flaky failures first. Otherwise we might
209250
# explain a flaky failure as a failure at head if there is a recent
210251
# failure in the last couple of commits.
@@ -229,6 +270,10 @@ def explain_failures(
229270
explanations.append(
230271
{"name": test_failure["name"], "explained": False, "reason": None}
231272
)
273+
if debug_folder:
274+
_log_explanation_request(
275+
explanation_request, commit_index, db_connection, explanations, debug_folder
276+
)
232277
return explanations
233278

234279

β€Žpremerge/advisor/advisor_lib_test.pyβ€Ž

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import unittest
22
import tempfile
33
import sqlite3
4+
import json
45
import os
56

67
import advisor_lib
@@ -165,6 +166,7 @@ def _get_explained_failures(
165166
prev_failure_failure_name="a.ll",
166167
prev_failure_failure_message="failed in way 1",
167168
prev_failure_platform="linux-x86_64",
169+
debug_folder=None,
168170
) -> list[advisor_lib.FailureExplanation]:
169171
"""Constructs explanations.
170172
@@ -192,7 +194,7 @@ def _get_explained_failures(
192194
"platform": platform,
193195
}
194196
return advisor_lib.explain_failures(
195-
explanation_request, self.repository_path, self.db_connection
197+
explanation_request, self.repository_path, self.db_connection, debug_folder
196198
)
197199

198200
# Test that we can explain away a failure at head, assuming all of the
@@ -301,11 +303,53 @@ def test_no_explain_different_message(self):
301303
],
302304
)
303305

306+
def test_no_explain_different_test_file(self):
307+
self.assertListEqual(
308+
self._get_explained_failures(prev_failure_failure_name="b.ll"),
309+
[
310+
{
311+
"name": "a.ll",
312+
"explained": False,
313+
"reason": None,
314+
}
315+
],
316+
)
317+
318+
def test_explain_failures_debug_logging(self):
319+
with tempfile.TemporaryDirectory() as debug_folder:
320+
self._get_explained_failures(debug_folder=debug_folder)
321+
debug_outputs = os.listdir(debug_folder)
322+
self.assertEqual(len(debug_outputs), 1)
323+
with open(os.path.join(debug_folder, debug_outputs[0])) as debug_file:
324+
explanation_log = json.load(debug_file)
325+
self.assertDictEqual(
326+
explanation_log,
327+
{
328+
"request": {
329+
"failures": [
330+
{"name": "a.ll", "message": "failed in way 1"}
331+
],
332+
"base_commit_sha": "8d29a3bb6f3d92d65bf5811b53bf42bf63685359",
333+
"platform": "linux-x86_64",
334+
},
335+
"explanations": [
336+
{
337+
"name": "a.ll",
338+
"explained": True,
339+
"reason": "This test is already failing at the base commit.",
340+
}
341+
],
342+
"base_commit_index": 1,
343+
"relevant_previous_failures": [["failed in way 1", 1, "a.ll"]],
344+
},
345+
)
346+
304347
def _setup_flaky_test_info(
305348
self,
306349
source_type="postcommit",
307350
message="failed in way 1",
308351
second_failure_sha="6269677375726269677375726269677375726269",
352+
second_failure_test_file="a.ll",
309353
):
310354
failures_info = [
311355
{
@@ -322,7 +366,7 @@ def _setup_flaky_test_info(
322366
"base_commit_sha": second_failure_sha,
323367
"source_id": "100001",
324368
"failures": [
325-
{"name": "a.ll", "message": message},
369+
{"name": second_failure_test_file, "message": message},
326370
],
327371
"platform": "linux-x86_64",
328372
},
@@ -401,6 +445,15 @@ def test_no_explain_flaky_small_range(self):
401445
],
402446
)
403447

448+
def test_no_explain_flaky_different_files(self):
449+
self._setup_flaky_test_info(second_failure_test_file="b.ll")
450+
self.assertEqual(
451+
self._get_flaky_test_explanations(),
452+
[
453+
{"name": "a.ll", "explained": False, "reason": None},
454+
],
455+
)
456+
404457
def _setup_flaky_test_identification_info(self):
405458
failures = []
406459
# Setup a range of consistently failing tests that happen on sequential

0 commit comments

Comments
Β (0)