xref: /linux/tools/testing/selftests/devices/error_logs/test_device_error_logs.py (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0
3#
4# Copyright (c) 2024 Collabora Ltd
5#
6# This test checks for the presence of error (or more critical) log messages
7# coming from devices in the kernel log.
8#
9# One failed test case is reported for each device that has outputted error
10# logs. Devices with no errors do not produce a passing test case to avoid
11# polluting the results, therefore a successful run will list 0 tests run.
12#
13
14import glob
15import os
16import re
17import sys
18
19# Allow ksft module to be imported from different directory
20this_dir = os.path.dirname(os.path.realpath(__file__))
21sys.path.append(os.path.join(this_dir, "../../kselftest/"))
22
23import ksft
24
25kmsg = "/dev/kmsg"
26
27RE_log = re.compile(
28    r"(?P<prefix>[0-9]+),(?P<sequence>[0-9]+),(?P<timestamp>[0-9]+),(?P<flag>[^;]*)(,[^;]*)*;(?P<message>.*)"
29)
30RE_tag = re.compile(r" (?P<key>[^=]+)=(?P<value>.*)")
31
32PREFIX_ERROR = 3
33
34logs = []
35error_log_per_device = {}
36
37
38def parse_kmsg():
39    current_log = {}
40
41    with open(kmsg) as f:
42        os.set_blocking(f.fileno(), False)
43
44        for line in f:
45            tag_line = RE_tag.match(line)
46            log_line = RE_log.match(line)
47
48            if log_line:
49                if current_log:
50                    logs.append(current_log)  # Save last log
51
52                current_log = {
53                    "prefix": int(log_line.group("prefix")),
54                    "sequence": int(log_line.group("sequence")),
55                    "timestamp": int(log_line.group("timestamp")),
56                    "flag": log_line.group("flag"),
57                    "message": log_line.group("message"),
58                }
59            elif tag_line:
60                current_log[tag_line.group("key")] = tag_line.group("value")
61
62
63def generate_per_device_error_log():
64    for log in logs:
65        if log.get("DEVICE") and log["prefix"] <= PREFIX_ERROR:
66            if not error_log_per_device.get(log["DEVICE"]):
67                error_log_per_device[log["DEVICE"]] = []
68            error_log_per_device[log["DEVICE"]].append(log)
69
70
71parse_kmsg()
72
73generate_per_device_error_log()
74num_tests = len(error_log_per_device)
75
76ksft.print_header()
77ksft.set_plan(num_tests)
78
79for device in error_log_per_device:
80    for log in error_log_per_device[device]:
81        ksft.print_msg(log["message"])
82    ksft.test_result_fail(device)
83if num_tests == 0:
84    ksft.print_msg("No device error logs found")
85ksft.finished()
86