13f1242f3SBrandon Wyman #include "../power_supply.hpp"
23f1242f3SBrandon Wyman #include "mock.hpp"
33f1242f3SBrandon Wyman 
43f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/Device/error.hpp>
53f1242f3SBrandon Wyman #include <xyz/openbmc_project/Common/error.hpp>
63f1242f3SBrandon Wyman 
73f1242f3SBrandon Wyman #include <gmock/gmock.h>
83f1242f3SBrandon Wyman #include <gtest/gtest.h>
93f1242f3SBrandon Wyman 
103f1242f3SBrandon Wyman using namespace phosphor::power::psu;
113f1242f3SBrandon Wyman using namespace phosphor::pmbus;
123f1242f3SBrandon Wyman 
133f1242f3SBrandon Wyman using ::testing::_;
143f1242f3SBrandon Wyman using ::testing::Assign;
153f1242f3SBrandon Wyman using ::testing::DoAll;
163f1242f3SBrandon Wyman using ::testing::Return;
173f1242f3SBrandon Wyman using ::testing::StrEq;
183f1242f3SBrandon Wyman 
193f1242f3SBrandon Wyman static auto PSUInventoryPath = "/xyz/bmc/inv/sys/chassis/board/powersupply0";
203f1242f3SBrandon Wyman 
213f1242f3SBrandon Wyman class PowerSupplyTests : public ::testing::Test
223f1242f3SBrandon Wyman {
233f1242f3SBrandon Wyman   public:
243f1242f3SBrandon Wyman     PowerSupplyTests() :
253f1242f3SBrandon Wyman         mockedUtil(reinterpret_cast<const MockedUtil&>(getUtils()))
263f1242f3SBrandon Wyman     {
273f1242f3SBrandon Wyman         ON_CALL(mockedUtil, getPresence(_, _)).WillByDefault(Return(false));
283f1242f3SBrandon Wyman     }
293f1242f3SBrandon Wyman 
303f1242f3SBrandon Wyman     ~PowerSupplyTests() override
313f1242f3SBrandon Wyman     {
323f1242f3SBrandon Wyman         freeUtils();
333f1242f3SBrandon Wyman     }
343f1242f3SBrandon Wyman 
353f1242f3SBrandon Wyman     const MockedUtil& mockedUtil;
363f1242f3SBrandon Wyman };
373f1242f3SBrandon Wyman 
383f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Constructor)
393f1242f3SBrandon Wyman {
403f1242f3SBrandon Wyman     /**
413f1242f3SBrandon Wyman      * @param[in] invpath - String for inventory path to use
423f1242f3SBrandon Wyman      * @param[in] i2cbus - The bus number this power supply is on
433f1242f3SBrandon Wyman      * @param[in] i2caddr - The 16-bit I2C address of the power supply
443f1242f3SBrandon Wyman      */
453f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
463f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
473f1242f3SBrandon Wyman     auto psu = std::make_unique<PowerSupply>(bus, PSUInventoryPath, 3, "0068");
483f1242f3SBrandon Wyman 
493f1242f3SBrandon Wyman     EXPECT_EQ(psu->isPresent(), false);
503f1242f3SBrandon Wyman     EXPECT_EQ(psu->isFaulted(), false);
513f1242f3SBrandon Wyman     EXPECT_EQ(psu->hasInputFault(), false);
523f1242f3SBrandon Wyman     EXPECT_EQ(psu->hasMFRFault(), false);
533f1242f3SBrandon Wyman     EXPECT_EQ(psu->hasVINUVFault(), false);
543f1242f3SBrandon Wyman }
553f1242f3SBrandon Wyman 
563f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, Analyze)
573f1242f3SBrandon Wyman {
583f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
593f1242f3SBrandon Wyman 
603f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
613f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 4, "0069"};
623f1242f3SBrandon Wyman     psu.analyze();
633f1242f3SBrandon Wyman     // By default, nothing should change.
643f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
653f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
663f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
673f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
683f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
693f1242f3SBrandon Wyman 
703f1242f3SBrandon Wyman     // In order to get the various faults tested, the power supply needs to be
713f1242f3SBrandon Wyman     // present in order to read from the PMBus device(s).
723f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
733f1242f3SBrandon Wyman         .Times(1)
743f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
753f1242f3SBrandon Wyman     PowerSupply psu2{bus, PSUInventoryPath, 5, "006a"};
763f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
773f1242f3SBrandon Wyman 
783f1242f3SBrandon Wyman     // STATUS_WORD 0x0000 is powered on, no faults.
793f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu2.getPMBus());
803f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
813f1242f3SBrandon Wyman     psu2.analyze();
823f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
833f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
843f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
853f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
863f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
873f1242f3SBrandon Wyman 
883f1242f3SBrandon Wyman     // STATUS_WORD input fault/warn
893f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
903f1242f3SBrandon Wyman         .Times(1)
913f1242f3SBrandon Wyman         .WillOnce(Return(status_word::INPUT_FAULT_WARN));
923f1242f3SBrandon Wyman     psu2.analyze();
933f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
943f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
953f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), true);
963f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
973f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
983f1242f3SBrandon Wyman 
993f1242f3SBrandon Wyman     // STATUS_WORD INPUT/UV fault.
1003f1242f3SBrandon Wyman     // First need it to return good status, then the fault
1013f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
1023f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
1033f1242f3SBrandon Wyman         .WillOnce(Return(status_word::VIN_UV_FAULT));
1043f1242f3SBrandon Wyman     psu2.analyze();
1053f1242f3SBrandon Wyman     psu2.analyze();
1063f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1073f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
1083f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
1093f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
1103f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), true);
1113f1242f3SBrandon Wyman 
1123f1242f3SBrandon Wyman     // STATUS_WORD MFR fault.
1133f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
1143f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
1153f1242f3SBrandon Wyman         .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
1163f1242f3SBrandon Wyman     psu2.analyze();
1173f1242f3SBrandon Wyman     psu2.analyze();
1183f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1193f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), true);
1203f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
1213f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), true);
1223f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
1233f1242f3SBrandon Wyman 
1243f1242f3SBrandon Wyman     // Ignore Temperature fault.
1253f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
1263f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
1273f1242f3SBrandon Wyman         .WillOnce(Return(status_word::TEMPERATURE_FAULT_WARN));
1283f1242f3SBrandon Wyman     psu2.analyze();
1293f1242f3SBrandon Wyman     psu2.analyze();
1303f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1313f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
1323f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
1333f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
1343f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
1353f1242f3SBrandon Wyman 
1363f1242f3SBrandon Wyman     // Ignore fan fault
1373f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
1383f1242f3SBrandon Wyman         .WillOnce(Return(0x0000))
1393f1242f3SBrandon Wyman         .WillOnce(Return(status_word::FAN_FAULT));
1403f1242f3SBrandon Wyman     psu2.analyze();
1413f1242f3SBrandon Wyman     psu2.analyze();
1423f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
1433f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isFaulted(), false);
1443f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasInputFault(), false);
1453f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasMFRFault(), false);
1463f1242f3SBrandon Wyman     EXPECT_EQ(psu2.hasVINUVFault(), false);
1473f1242f3SBrandon Wyman 
1483f1242f3SBrandon Wyman     // TODO: ReadFailure
1493f1242f3SBrandon Wyman }
1503f1242f3SBrandon Wyman 
1513f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, ClearFaults)
1523f1242f3SBrandon Wyman {
1533f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1543f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
1553f1242f3SBrandon Wyman         .Times(1)
1563f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
1573f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 13, "0068"};
1583f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
1593f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1603f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1613f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1623f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1633f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
1643f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0xFFFF));
1653f1242f3SBrandon Wyman     psu.analyze();
1663f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
1673f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
1683f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
1693f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
1703f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
171*3c208464SBrandon Wyman     EXPECT_CALL(mockPMBus, read("in1_input", _))
172*3c208464SBrandon Wyman         .Times(1)
173*3c208464SBrandon Wyman         .WillOnce(Return(209000));
1743f1242f3SBrandon Wyman     psu.clearFaults();
1753f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), true);
1763f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
1773f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
1783f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
1793f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
1803f1242f3SBrandon Wyman }
1813f1242f3SBrandon Wyman 
1823f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, UpdateInventory)
1833f1242f3SBrandon Wyman {
1843f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1853f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath)))
1863f1242f3SBrandon Wyman         .Times(1)
1873f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
1883f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
1893f1242f3SBrandon Wyman     psu.updateInventory();
1903f1242f3SBrandon Wyman     // TODO: Checks / Story #921
1913f1242f3SBrandon Wyman }
1923f1242f3SBrandon Wyman 
1933f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsPresent)
1943f1242f3SBrandon Wyman {
1953f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
1963f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, StrEq(PSUInventoryPath))).Times(1);
1973f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
1983f1242f3SBrandon Wyman     EXPECT_EQ(psu.isPresent(), false);
1993f1242f3SBrandon Wyman 
2003f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, _))
2013f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
2023f1242f3SBrandon Wyman     PowerSupply psu2{bus, PSUInventoryPath, 10, "006b"};
2033f1242f3SBrandon Wyman     EXPECT_EQ(psu2.isPresent(), true);
2043f1242f3SBrandon Wyman }
2053f1242f3SBrandon Wyman 
2063f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, IsFaulted)
2073f1242f3SBrandon Wyman {
2083f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2093f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, _))
2103f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
2113f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 11, "006f"};
2123f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), false);
2133f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2143f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0xFFFF));
2153f1242f3SBrandon Wyman     psu.analyze();
2163f1242f3SBrandon Wyman     EXPECT_EQ(psu.isFaulted(), true);
2173f1242f3SBrandon Wyman }
2183f1242f3SBrandon Wyman 
2193f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasInputFault)
2203f1242f3SBrandon Wyman {
2213f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2223f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, _))
2233f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
2243f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
2253f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2263f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
2273f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2283f1242f3SBrandon Wyman     psu.analyze();
2293f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
2303f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
2313f1242f3SBrandon Wyman         .Times(1)
2323f1242f3SBrandon Wyman         .WillOnce(Return(status_word::INPUT_FAULT_WARN));
2333f1242f3SBrandon Wyman     psu.analyze();
2343f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), true);
2353f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2363f1242f3SBrandon Wyman     psu.analyze();
2373f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasInputFault(), false);
2383f1242f3SBrandon Wyman }
2393f1242f3SBrandon Wyman 
2403f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasMFRFault)
2413f1242f3SBrandon Wyman {
2423f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2433f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, _))
2443f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
2453f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
2463f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2473f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
2483f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2493f1242f3SBrandon Wyman     psu.analyze();
2503f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
2513f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
2523f1242f3SBrandon Wyman         .Times(1)
2533f1242f3SBrandon Wyman         .WillOnce(Return(status_word::MFR_SPECIFIC_FAULT));
2543f1242f3SBrandon Wyman     psu.analyze();
2553f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), true);
2563f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2573f1242f3SBrandon Wyman     psu.analyze();
2583f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasMFRFault(), false);
2593f1242f3SBrandon Wyman }
2603f1242f3SBrandon Wyman 
2613f1242f3SBrandon Wyman TEST_F(PowerSupplyTests, HasVINUVFault)
2623f1242f3SBrandon Wyman {
2633f1242f3SBrandon Wyman     auto bus = sdbusplus::bus::new_default();
2643f1242f3SBrandon Wyman     EXPECT_CALL(mockedUtil, getPresence(_, _))
2653f1242f3SBrandon Wyman         .WillOnce(Return(true)); // present
2663f1242f3SBrandon Wyman     PowerSupply psu{bus, PSUInventoryPath, 3, "0068"};
2673f1242f3SBrandon Wyman     MockedPMBus& mockPMBus = static_cast<MockedPMBus&>(psu.getPMBus());
2683f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
2693f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2703f1242f3SBrandon Wyman     psu.analyze();
2713f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
2723f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _))
2733f1242f3SBrandon Wyman         .Times(1)
2743f1242f3SBrandon Wyman         .WillOnce(Return(status_word::VIN_UV_FAULT));
2753f1242f3SBrandon Wyman     psu.analyze();
2763f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), true);
2773f1242f3SBrandon Wyman     EXPECT_CALL(mockPMBus, read(_, _)).Times(1).WillOnce(Return(0x0000));
2783f1242f3SBrandon Wyman     psu.analyze();
2793f1242f3SBrandon Wyman     EXPECT_EQ(psu.hasVINUVFault(), false);
2803f1242f3SBrandon Wyman }
281