Skip to content

Commit cac967d

Browse files
gchwierkartben
authored andcommitted
twister: extend reason field in Twister reports
Extended the reason field in Twister report to include more detailed information for 'Build failure' and 'CMake build failure' Signed-off-by: Grzegorz Chwierut <[email protected]>
1 parent 0bb7849 commit cac967d

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

scripts/pylib/twister/twisterlib/reports.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,6 @@ def json_report(self, filename, version="NA", platform=None, filters=None):
372372
suite["available_rom"] = available_rom
373373
if instance.status in [TwisterStatus.ERROR, TwisterStatus.FAIL]:
374374
suite['status'] = instance.status
375-
suite["reason"] = instance.reason
376375
# FIXME
377376
if os.path.exists(pytest_log):
378377
suite["log"] = self.process_log(pytest_log)
@@ -382,6 +381,11 @@ def json_report(self, filename, version="NA", platform=None, filters=None):
382381
suite["log"] = self.process_log(device_log)
383382
else:
384383
suite["log"] = self.process_log(build_log)
384+
385+
suite["reason"] = self.get_detailed_reason(instance.reason, suite["log"])
386+
# update the reason to get more details also in other reports (e.g. junit)
387+
# where build log is not available
388+
instance.reason = suite["reason"]
385389
elif instance.status == TwisterStatus.FILTER:
386390
suite["status"] = TwisterStatus.FILTER
387391
suite["reason"] = instance.reason
@@ -798,3 +802,55 @@ def target_report(self, json_file, outdir, suffix):
798802
self.json_report(json_platform_file + "_footprint.json",
799803
version=self.env.version, platform=platform.name,
800804
filters=self.json_filters['footprint.json'])
805+
806+
def get_detailed_reason(self, reason: str, log: str) -> str:
807+
if reason == 'CMake build failure':
808+
if error_key := self._parse_cmake_build_failure(log):
809+
return f"{reason} - {error_key}"
810+
elif reason == 'Build failure': # noqa SIM102
811+
if error_key := self._parse_build_failure(log):
812+
return f"{reason} - {error_key}"
813+
return reason
814+
815+
@staticmethod
816+
def _parse_cmake_build_failure(log: str) -> str | None:
817+
last_warning = 'no warning found'
818+
lines = log.splitlines()
819+
for i, line in enumerate(lines):
820+
if "warning: " in line:
821+
last_warning = line
822+
elif "devicetree error: " in line:
823+
return "devicetree error"
824+
elif "fatal error: " in line:
825+
return line[line.index('fatal error: ') :].strip()
826+
elif "error: " in line: # error: Aborting due to Kconfig warnings
827+
if "undefined symbol" in last_warning:
828+
return last_warning[last_warning.index('undefined symbol') :].strip()
829+
return last_warning
830+
elif "CMake Error at" in line:
831+
for next_line in lines[i + 1 :]:
832+
if next_line.strip():
833+
return line + ' ' + next_line
834+
return line
835+
return None
836+
837+
@staticmethod
838+
def _parse_build_failure(log: str) -> str | None:
839+
last_warning = ''
840+
lines = log.splitlines()
841+
for i, line in enumerate(lines):
842+
if "undefined reference" in line:
843+
return line[line.index('undefined reference') :].strip()
844+
elif "error: ld returned" in line:
845+
if last_warning:
846+
return last_warning
847+
elif "overflowed by" in lines[i - 1]:
848+
return "ld.bfd: region overflowed"
849+
elif "ld.bfd: warning: " in lines[i - 1]:
850+
return "ld.bfd:" + lines[i - 1].split("ld.bfd:", 1)[-1]
851+
return line
852+
elif "error: " in line:
853+
return line[line.index('error: ') :].strip()
854+
elif ": in function " in line:
855+
last_warning = line[line.index('in function') :].strip()
856+
return None

0 commit comments

Comments
 (0)