blob: 50be8f312ad4b591254ea510b7e89be3b6bc7ec1 [file] [log] [blame]
#!/usr/bin/python3
# SPDX-License-Identifier: MIT
"""
This module contains unit tests for the kernel log functions in the amd-debug-tools package.
"""
from unittest.mock import patch, mock_open
import unittest
import logging
from amd_debug.kernel import sscanf_bios_args, get_kernel_command_line, DmesgLogger
class TestKernelLog(unittest.TestCase):
"""Test Common kernel scan functions"""
@classmethod
def setUpClass(cls):
logging.basicConfig(filename="/dev/null", level=logging.DEBUG)
def test_get_kernel_command_line(self):
"""Test get_kernel_command_line function"""
# Test case with a valid kernel command line that is fully filtered
kernel_cmdline = "quiet splash"
expected_output = ""
with patch(
"builtins.open", new_callable=mock_open, read_data=kernel_cmdline
) as _mock_file:
result = get_kernel_command_line()
self.assertEqual(result, expected_output)
# Test case with an empty kernel command line
kernel_cmdline = ""
expected_output = ""
with patch(
"builtins.open", new_callable=mock_open, read_data=kernel_cmdline
) as _mock_file:
result = get_kernel_command_line()
self.assertEqual(result, expected_output)
# Test case with a kernel command line containing special characters
kernel_cmdline = "quiet splash --debug=1"
expected_output = "--debug=1"
with patch(
"builtins.open", new_callable=mock_open, read_data=kernel_cmdline
) as _mock_file:
result = get_kernel_command_line()
self.assertEqual(result, expected_output)
# Test case with a kernel command line containing special characters
kernel_cmdline = "quiet splash initrd=foo modprobe.blacklist=foo"
expected_output = "modprobe.blacklist=foo"
with patch(
"builtins.open", new_callable=mock_open, read_data=kernel_cmdline
) as _mock_file:
result = get_kernel_command_line()
self.assertEqual(result, expected_output)
def test_sscanf_bios_args(self):
"""Test sscanf_bios_args function"""
# Test case with a valid line
line = 'ex_trace_args: "format_string", 0x1234, 0x5678'
expected_output = "format_string"
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
# Test case with an invalid line
line = 'invalid_line: "format_string", 0x1234, 0x5678'
result = sscanf_bios_args(line)
self.assertIsNone(result)
# Test case with a line containing "Unknown"
line = 'ex_trace_args: "format_string", Unknown, 0x5678'
expected_output = "format_string"
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
# make sure that lines with ex_trace_point are not parsed
line = 'ex_trace_point: "format_string", 0x1234, 0x5678'
result = sscanf_bios_args(line)
self.assertTrue(result)
# test a real post code line
line = 'ex_trace_args: " POST CODE: %X ACPI TIMER: %X TIME: %d.%d ms\\n", b0003f33, 83528798, 0, 77, 0, 0'
expected_output = "POST CODE: B0003F33 ACPI TIMER: 83528798 TIME: 0.77 ms"
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
# test a real _REG print
line = 'ex_trace_args: " OEM-ASL-PCIe Address (0x%X)._REG (%d %d) PCSA = %d\\n", ec303000, 2, 0, 0, 0, 0'
expected_output = "OEM-ASL-PCIe Address (0xEC303000)._REG (2 0) PCSA = 0"
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
# test case of too may arguments
line = 'ex_trace_args : " APGE = %d\\n", 1, 0, 0, 0, 0, 0'
expected_output = "APGE = 1"
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
# test case for Dispatch notify
line = "evmisc-0132 ev_queue_notify_reques: Dispatching Notify on [UBTC] (Device) Value 0x80 (Status Change) Node 00000000851b15c1"
expected_output = (
"Dispatching Notify on [UBTC] (Device) Value 0x80 (Status Change)"
)
result = sscanf_bios_args(line)
self.assertEqual(result, expected_output)
class TestDmesgLogger(unittest.TestCase):
"""Test Dmesg logger functions"""
@classmethod
def setUpClass(cls):
logging.basicConfig(filename="/dev/null", level=logging.DEBUG)
def test_dmesg_logger_initialization(self):
"""Test initialization of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg -h
mock_run.return_value.stdout = b"--since supported\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
self.assertTrue(logger.since_support)
self.assertEqual(logger.command, ["dmesg", "-t", "-k"])
def test_dmesg_logger_refresh_head(self):
"""Test _refresh_head method of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg
mock_run.return_value.stdout = b"line1\nline2\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
logger._refresh_head() # pylint: disable=protected-access
self.assertEqual(logger.buffer, "line1\nline2\n")
def test_dmesg_logger_seek_tail(self):
"""Test seek_tail method of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg
mock_run.return_value.stdout = b"line1\nline2\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
logger.seek_tail()
self.assertEqual(logger.buffer, "line1\nline2\n")
def test_dmesg_logger_process_callback(self):
"""Test process_callback method of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg
mock_run.return_value.stdout = b"line1\nline2\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
logger._refresh_head() # pylint: disable=protected-access
mock_callback = unittest.mock.Mock()
logger.process_callback(mock_callback)
mock_callback.assert_any_call("line1", None)
mock_callback.assert_any_call("line2", None)
def test_dmesg_logger_match_line(self):
"""Test match_line method of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg
mock_run.return_value.stdout = b"line1\nline2\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
logger._refresh_head() # pylint: disable=protected-access
result = logger.match_line(["line1"])
self.assertEqual(result, "line1")
result = logger.match_line(["nonexistent"])
self.assertEqual(result, "")
def test_dmesg_logger_match_pattern(self):
"""Test match_pattern method of DmesgLogger"""
with patch("subprocess.run") as mock_run:
# Mock the subprocess output for dmesg
mock_run.return_value.stdout = b"line1\nline2\n"
mock_run.return_value.returncode = 0
logger = DmesgLogger()
logger._refresh_head() # pylint: disable=protected-access
result = logger.match_pattern(r"line\d")
self.assertEqual(result, "line1")
result = logger.match_pattern(r"nonexistent")
self.assertEqual(result, "")