#!/usr/bin/python3
# SPDX-License-Identifier: MIT

"""
This module contains unit tests for the failure functions in the amd-debug-tools package.
"""

from unittest.mock import patch, call

import logging
import unittest
import os

import amd_debug.failures


class TestFailures(unittest.TestCase):
    """Test failure functions"""

    @classmethod
    def setUpClass(cls):
        logging.basicConfig(filename="/dev/null", level=logging.DEBUG)

    @patch("builtins.print")
    def test_failures(self, mocked_print):
        """Test failure functions"""

        cls = amd_debug.failures.RtcAlarmWrong()
        self.assertEqual(
            cls.get_description(), "rtc_cmos is not configured to use ACPI alarm"
        )
        self.assertEqual(
            str(cls),
            "Some problems can occur during wakeup cycles if the HPET RTC "
            "emulation is used to wake systems. This can manifest in unexpected "
            "wakeups or high power consumption.For more information on this failure "
            "see:https://github.com/systemd/systemd/issues/24279",
        )
        cls = amd_debug.failures.MissingAmdgpu()
        self.assertEqual(cls.get_description(), "AMDGPU driver is missing")
        cls = amd_debug.failures.MissingAmdgpuFirmware(["foo", "bar"])
        self.assertEqual(cls.get_description(), "AMDGPU firmware is missing")
        cls = amd_debug.failures.AmdgpuPpFeatureMask()
        self.assertEqual(cls.get_description(), "AMDGPU ppfeaturemask changed")
        cls = amd_debug.failures.MissingAmdPmc()
        self.assertEqual(cls.get_description(), "AMD-PMC driver is missing")
        cls = amd_debug.failures.MissingThunderbolt()
        self.assertEqual(cls.get_description(), "thunderbolt driver is missing")
        cls = amd_debug.failures.MissingXhciHcd()
        self.assertEqual(cls.get_description(), "xhci_hcd driver is missing")
        cls = amd_debug.failures.MissingDriver("4")
        self.assertEqual(cls.get_description(), "4 driver is missing")
        cls = amd_debug.failures.AcpiBiosError("5")
        self.assertEqual(cls.get_description(), "ACPI BIOS Errors detected")
        cls = amd_debug.failures.UnsupportedModel()
        self.assertEqual(cls.get_description(), "Unsupported CPU model")
        cls = amd_debug.failures.UserNvmeConfiguration()
        self.assertEqual(cls.get_description(), "NVME ACPI support is disabled")
        cls = amd_debug.failures.AcpiNvmeStorageD3Enable("foo", 2)
        self.assertEqual(cls.get_description(), "foo missing ACPI attributes")
        cls = amd_debug.failures.DevSlpHostIssue()
        self.assertEqual(
            cls.get_description(), "AHCI controller doesn't support DevSlp"
        )
        cls = amd_debug.failures.DevSlpDiskIssue()
        self.assertEqual(cls.get_description(), "SATA disk doesn't support DevSlp")
        cls = amd_debug.failures.SleepModeWrong()
        self.assertEqual(
            cls.get_description(),
            "The system hasn't been configured for Modern Standby in BIOS setup",
        )
        cls = amd_debug.failures.DeepSleep()
        self.assertEqual(
            cls.get_description(),
            "The kernel command line is asserting the system to use deep sleep",
        )
        cls = amd_debug.failures.FadtWrong()
        self.assertEqual(
            cls.get_description(),
            "The kernel didn't emit a message that low power idle was supported",
        )
        cls = amd_debug.failures.Irq1Workaround()
        self.assertEqual(
            cls.get_description(),
            "The wakeup showed an IRQ1 wakeup source, which might be a platform firmware bug",
        )
        cls = amd_debug.failures.KernelRingBufferWrapped()
        self.assertEqual(cls.get_description(), "Kernel ringbuffer has wrapped")
        cls = amd_debug.failures.AmdHsmpBug()
        self.assertEqual(cls.get_description(), "amd-hsmp built in to kernel")
        cls = amd_debug.failures.WCN6855Bug()
        self.assertEqual(
            cls.get_description(),
            "The firmware loaded for the WCN6855 causes spurious wakeups",
        )
        cls = amd_debug.failures.I2CHidBug("touchpad", "block")
        self.assertEqual(
            cls.get_description(),
            "The touchpad device has been reported to cause high power consumption and spurious wakeups",
        )
        cls = amd_debug.failures.SpuriousWakeup(1, 0)
        self.assertEqual(
            cls.get_description(), "Userspace wasn't asleep at least 0:00:01"
        )
        cls = amd_debug.failures.LowHardwareSleepResidency(5, 30)
        self.assertEqual(
            cls.get_description(), "System had low hardware sleep residency"
        )
        cls = amd_debug.failures.MSRFailure()
        self.assertEqual(cls.get_description(), "PC6 or CC6 state disabled")
        cls = amd_debug.failures.TaintedKernel()
        self.assertEqual(cls.get_description(), "Kernel is tainted")
        cls = amd_debug.failures.DMArNotEnabled()
        self.assertEqual(cls.get_description(), "Pre-boot DMA protection disabled")
        cls = amd_debug.failures.MissingIommuACPI("foo")
        self.assertEqual(cls.get_description(), "Device foo missing from ACPI tables")
        cls = amd_debug.failures.MissingIommuPolicy("foo")
        self.assertEqual(
            cls.get_description(), "Device foo does not have IOMMU policy applied"
        )
        cls = amd_debug.failures.IommuPageFault("foo")
        self.assertEqual(cls.get_description(), "Page fault reported for foo")
        cls = amd_debug.failures.SMTNotEnabled()
        self.assertEqual(cls.get_description(), "SMT is not enabled")
        cls = amd_debug.failures.ASpmWrong()
        self.assertEqual(cls.get_description(), "ASPM is overridden")
        cls = amd_debug.failures.UnservicedGpio()
        self.assertEqual(cls.get_description(), "GPIO interrupt is not serviced")
        cls = amd_debug.failures.DmiNotSetup()
        self.assertEqual(cls.get_description(), "DMI data was not scanned")
        cls = amd_debug.failures.LimitedCores(10, 7)
        self.assertEqual(cls.get_description(), "CPU cores have been limited")
        cls = amd_debug.failures.RogAllyOldMcu(1, 2)
        self.assertEqual(cls.get_description(), "Rog Ally MCU firmware is too old")
        os.environ["TERM"] = "dumb"
        cls = amd_debug.failures.RogAllyMcuPowerSave()
        self.assertEqual(cls.get_description(), "Rog Ally MCU power save is disabled")
        failure = "The MCU powersave feature is disabled which will cause problems with the controller after suspend/resume."
        self.assertEqual(str(cls), failure)
        cls.get_failure()
        mocked_print.assert_has_calls(
            [
                call("🚦 Rog Ally MCU power save is disabled"),
                call(failure),
            ]
        )
