1c3991f16SShawn McCarney /**
2c3991f16SShawn McCarney  * Copyright © 2020 IBM Corporation
3c3991f16SShawn McCarney  *
4c3991f16SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5c3991f16SShawn McCarney  * you may not use this file except in compliance with the License.
6c3991f16SShawn McCarney  * You may obtain a copy of the License at
7c3991f16SShawn McCarney  *
8c3991f16SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9c3991f16SShawn McCarney  *
10c3991f16SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11c3991f16SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12c3991f16SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c3991f16SShawn McCarney  * See the License for the specific language governing permissions and
14c3991f16SShawn McCarney  * limitations under the License.
15c3991f16SShawn McCarney  */
1617bac89eSShawn McCarney #include "action.hpp"
17c3991f16SShawn McCarney #include "chassis.hpp"
1817bac89eSShawn McCarney #include "configuration.hpp"
19db0b833cSShawn McCarney #include "device.hpp"
2017bac89eSShawn McCarney #include "i2c_interface.hpp"
21db0b833cSShawn McCarney #include "id_map.hpp"
2237af670eSShawn McCarney #include "log_phase_fault_action.hpp"
2317bac89eSShawn McCarney #include "mock_action.hpp"
2423b0d0d1SShawn McCarney #include "mock_error_logging.hpp"
252af5289dSShawn McCarney #include "mock_journal.hpp"
2617bac89eSShawn McCarney #include "mock_sensors.hpp"
2723243f84SBob King #include "mock_services.hpp"
288e2294dcSBob King #include "mocked_i2c_interface.hpp"
2937af670eSShawn McCarney #include "phase_fault.hpp"
3032252599SShawn McCarney #include "phase_fault_detection.hpp"
3117bac89eSShawn McCarney #include "presence_detection.hpp"
32db0b833cSShawn McCarney #include "rail.hpp"
33c3991f16SShawn McCarney #include "rule.hpp"
3417bac89eSShawn McCarney #include "sensor_monitoring.hpp"
352f9e14f6SShawn McCarney #include "sensors.hpp"
365cfe5103SBob King #include "services.hpp"
37c3991f16SShawn McCarney #include "system.hpp"
3823b0d0d1SShawn McCarney #include "test_sdbus_error.hpp"
39db0b833cSShawn McCarney #include "test_utils.hpp"
40c3991f16SShawn McCarney 
41c3991f16SShawn McCarney #include <memory>
42db0b833cSShawn McCarney #include <stdexcept>
432af5289dSShawn McCarney #include <string>
44c3991f16SShawn McCarney #include <utility>
45c3991f16SShawn McCarney #include <vector>
46c3991f16SShawn McCarney 
478e2294dcSBob King #include <gmock/gmock.h>
48c3991f16SShawn McCarney #include <gtest/gtest.h>
49c3991f16SShawn McCarney 
50c3991f16SShawn McCarney using namespace phosphor::power::regulators;
51db0b833cSShawn McCarney using namespace phosphor::power::regulators::test_utils;
52c3991f16SShawn McCarney 
538e2294dcSBob King using ::testing::A;
548e2294dcSBob King using ::testing::Return;
5523b0d0d1SShawn McCarney using ::testing::Throw;
568e2294dcSBob King using ::testing::TypedEq;
578e2294dcSBob King 
58cb3f6a63SShawn McCarney static const std::string chassisInvPath{
59cb3f6a63SShawn McCarney     "/xyz/openbmc_project/inventory/system/chassis"};
60cb3f6a63SShawn McCarney 
TEST(SystemTests,Constructor)61c3991f16SShawn McCarney TEST(SystemTests, Constructor)
62c3991f16SShawn McCarney {
63c3991f16SShawn McCarney     // Create Rules
64c3991f16SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
65db0b833cSShawn McCarney     rules.emplace_back(createRule("set_voltage_rule"));
66c3991f16SShawn McCarney 
67c3991f16SShawn McCarney     // Create Chassis
68c3991f16SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
69db0b833cSShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
70db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg1", {"rail1"}));
71cb3f6a63SShawn McCarney     chassis.emplace_back(
72cb3f6a63SShawn McCarney         std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)));
73c3991f16SShawn McCarney 
74c3991f16SShawn McCarney     // Create System
75c3991f16SShawn McCarney     System system{std::move(rules), std::move(chassis)};
76c3991f16SShawn McCarney     EXPECT_EQ(system.getChassis().size(), 1);
77c3991f16SShawn McCarney     EXPECT_EQ(system.getChassis()[0]->getNumber(), 1);
78db0b833cSShawn McCarney     EXPECT_NO_THROW(system.getIDMap().getRule("set_voltage_rule"));
79db0b833cSShawn McCarney     EXPECT_NO_THROW(system.getIDMap().getDevice("reg1"));
80db0b833cSShawn McCarney     EXPECT_NO_THROW(system.getIDMap().getRail("rail1"));
81db0b833cSShawn McCarney     EXPECT_THROW(system.getIDMap().getRail("rail2"), std::invalid_argument);
82c3991f16SShawn McCarney     EXPECT_EQ(system.getRules().size(), 1);
83c3991f16SShawn McCarney     EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule");
84c3991f16SShawn McCarney }
85c3991f16SShawn McCarney 
TEST(SystemTests,ClearCache)869bd94d36SShawn McCarney TEST(SystemTests, ClearCache)
879bd94d36SShawn McCarney {
889bd94d36SShawn McCarney     // Create PresenceDetection
899bd94d36SShawn McCarney     std::vector<std::unique_ptr<Action>> actions{};
90a3fecef3SShawn McCarney     auto presenceDetection =
919bd94d36SShawn McCarney         std::make_unique<PresenceDetection>(std::move(actions));
929bd94d36SShawn McCarney     PresenceDetection* presenceDetectionPtr = presenceDetection.get();
939bd94d36SShawn McCarney 
949bd94d36SShawn McCarney     // Create Device that contains PresenceDetection
95a3fecef3SShawn McCarney     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
96a3fecef3SShawn McCarney     auto device = std::make_unique<Device>(
979bd94d36SShawn McCarney         "reg1", true,
989bd94d36SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
999bd94d36SShawn McCarney         std::move(i2cInterface), std::move(presenceDetection));
1009bd94d36SShawn McCarney     Device* devicePtr = device.get();
1019bd94d36SShawn McCarney 
1029bd94d36SShawn McCarney     // Create Chassis that contains Device
1039bd94d36SShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
1049bd94d36SShawn McCarney     devices.emplace_back(std::move(device));
105*48781aefSPatrick Williams     auto chassis = std::make_unique<Chassis>(1, chassisInvPath,
106*48781aefSPatrick Williams                                              std::move(devices));
1079bd94d36SShawn McCarney     Chassis* chassisPtr = chassis.get();
1089bd94d36SShawn McCarney 
1099bd94d36SShawn McCarney     // Create System that contains Chassis
1109bd94d36SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
1119bd94d36SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassisVec{};
1129bd94d36SShawn McCarney     chassisVec.emplace_back(std::move(chassis));
1139bd94d36SShawn McCarney     System system{std::move(rules), std::move(chassisVec)};
1149bd94d36SShawn McCarney 
1159bd94d36SShawn McCarney     // Cache presence value in PresenceDetection
1169bd94d36SShawn McCarney     MockServices services{};
1179bd94d36SShawn McCarney     presenceDetectionPtr->execute(services, system, *chassisPtr, *devicePtr);
1189bd94d36SShawn McCarney     EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
1199bd94d36SShawn McCarney 
1209bd94d36SShawn McCarney     // Clear cached data in System
1219bd94d36SShawn McCarney     system.clearCache();
1229bd94d36SShawn McCarney 
1239bd94d36SShawn McCarney     // Verify presence value no longer cached in PresenceDetection
1249bd94d36SShawn McCarney     EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
1259bd94d36SShawn McCarney }
1269bd94d36SShawn McCarney 
TEST(SystemTests,ClearErrorHistory)12723b0d0d1SShawn McCarney TEST(SystemTests, ClearErrorHistory)
12823b0d0d1SShawn McCarney {
12923b0d0d1SShawn McCarney     // Create SensorMonitoring.  Will fail with a DBus exception.
130a3fecef3SShawn McCarney     auto action = std::make_unique<MockAction>();
13123b0d0d1SShawn McCarney     EXPECT_CALL(*action, execute)
13223b0d0d1SShawn McCarney         .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
13323b0d0d1SShawn McCarney     std::vector<std::unique_ptr<Action>> actions{};
13423b0d0d1SShawn McCarney     actions.emplace_back(std::move(action));
135a3fecef3SShawn McCarney     auto sensorMonitoring =
13623b0d0d1SShawn McCarney         std::make_unique<SensorMonitoring>(std::move(actions));
13723b0d0d1SShawn McCarney 
13823b0d0d1SShawn McCarney     // Create Rail
13923b0d0d1SShawn McCarney     std::unique_ptr<Configuration> configuration{};
140a3fecef3SShawn McCarney     auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
141a3fecef3SShawn McCarney                                        std::move(sensorMonitoring));
14223b0d0d1SShawn McCarney 
14323b0d0d1SShawn McCarney     // Create Device that contains Rail
144a3fecef3SShawn McCarney     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
14523b0d0d1SShawn McCarney     std::unique_ptr<PresenceDetection> presenceDetection{};
14623b0d0d1SShawn McCarney     std::unique_ptr<Configuration> deviceConfiguration{};
14732252599SShawn McCarney     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
14823b0d0d1SShawn McCarney     std::vector<std::unique_ptr<Rail>> rails{};
14923b0d0d1SShawn McCarney     rails.emplace_back(std::move(rail));
150a3fecef3SShawn McCarney     auto device = std::make_unique<Device>(
15123b0d0d1SShawn McCarney         "reg1", true,
15223b0d0d1SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
15323b0d0d1SShawn McCarney         std::move(i2cInterface), std::move(presenceDetection),
15432252599SShawn McCarney         std::move(deviceConfiguration), std::move(phaseFaultDetection),
15532252599SShawn McCarney         std::move(rails));
15623b0d0d1SShawn McCarney 
15723b0d0d1SShawn McCarney     // Create Chassis that contains Device
15823b0d0d1SShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
15923b0d0d1SShawn McCarney     devices.emplace_back(std::move(device));
160*48781aefSPatrick Williams     auto chassis = std::make_unique<Chassis>(1, chassisInvPath,
161*48781aefSPatrick Williams                                              std::move(devices));
16223b0d0d1SShawn McCarney 
16323b0d0d1SShawn McCarney     // Create System that contains Chassis
16423b0d0d1SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
16523b0d0d1SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassisVec{};
16623b0d0d1SShawn McCarney     chassisVec.emplace_back(std::move(chassis));
16723b0d0d1SShawn McCarney     System system{std::move(rules), std::move(chassisVec)};
16823b0d0d1SShawn McCarney 
169fa2734d6SShawn McCarney     // Create lambda that sets MockServices expectations.  The lambda allows
170fa2734d6SShawn McCarney     // us to set expectations multiple times without duplicate code.
171fa2734d6SShawn McCarney     auto setExpectations = [](MockServices& services) {
172fa2734d6SShawn McCarney         // Expect Sensors service to be called 10 times
17323b0d0d1SShawn McCarney         MockSensors& sensors = services.getMockSensors();
17423b0d0d1SShawn McCarney         EXPECT_CALL(sensors, startRail).Times(10);
17523b0d0d1SShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
17623b0d0d1SShawn McCarney         EXPECT_CALL(sensors, endRail).Times(10);
17723b0d0d1SShawn McCarney 
178fa2734d6SShawn McCarney         // Expect Journal service to be called 6 times to log error messages
17923b0d0d1SShawn McCarney         MockJournal& journal = services.getMockJournal();
18023b0d0d1SShawn McCarney         EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
18123b0d0d1SShawn McCarney             .Times(6);
18223b0d0d1SShawn McCarney         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
18323b0d0d1SShawn McCarney 
184fa2734d6SShawn McCarney         // Expect ErrorLogging service to be called once to log a DBus error
18523b0d0d1SShawn McCarney         MockErrorLogging& errorLogging = services.getMockErrorLogging();
186fa2734d6SShawn McCarney         EXPECT_CALL(errorLogging, logDBusError).Times(1);
187fa2734d6SShawn McCarney     };
18823b0d0d1SShawn McCarney 
189fa2734d6SShawn McCarney     // Monitor sensors 10 times.  Verify errors logged.
190fa2734d6SShawn McCarney     {
191fa2734d6SShawn McCarney         // Create mock services.  Set expectations via lambda.
192fa2734d6SShawn McCarney         MockServices services{};
193fa2734d6SShawn McCarney         setExpectations(services);
194fa2734d6SShawn McCarney 
195fa2734d6SShawn McCarney         for (int i = 1; i <= 10; ++i)
19623b0d0d1SShawn McCarney         {
19723b0d0d1SShawn McCarney             system.monitorSensors(services);
19823b0d0d1SShawn McCarney         }
199fa2734d6SShawn McCarney     }
20023b0d0d1SShawn McCarney 
20123b0d0d1SShawn McCarney     // Clear error history
20223b0d0d1SShawn McCarney     system.clearErrorHistory();
20323b0d0d1SShawn McCarney 
204fa2734d6SShawn McCarney     // Monitor sensors 10 more times.  Verify errors logged again.
205fa2734d6SShawn McCarney     {
206fa2734d6SShawn McCarney         // Create mock services.  Set expectations via lambda.
207fa2734d6SShawn McCarney         MockServices services{};
208fa2734d6SShawn McCarney         setExpectations(services);
209fa2734d6SShawn McCarney 
210fa2734d6SShawn McCarney         for (int i = 1; i <= 10; ++i)
21123b0d0d1SShawn McCarney         {
21223b0d0d1SShawn McCarney             system.monitorSensors(services);
21323b0d0d1SShawn McCarney         }
21423b0d0d1SShawn McCarney     }
215fa2734d6SShawn McCarney }
21623b0d0d1SShawn McCarney 
TEST(SystemTests,CloseDevices)2175b19ea51SShawn McCarney TEST(SystemTests, CloseDevices)
2185b19ea51SShawn McCarney {
2195b19ea51SShawn McCarney     // Specify an empty rules vector
2205b19ea51SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
2215b19ea51SShawn McCarney 
222d692d6dfSBob King     // Create mock services.  Expect logDebug() to be called.
223d692d6dfSBob King     MockServices services{};
224d692d6dfSBob King     MockJournal& journal = services.getMockJournal();
225d692d6dfSBob King     EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
226d692d6dfSBob King     EXPECT_CALL(journal, logDebug("Closing devices in chassis 3")).Times(1);
227d692d6dfSBob King     EXPECT_CALL(journal, logInfo(A<const std::string&>())).Times(0);
228d692d6dfSBob King     EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
229d692d6dfSBob King 
2305b19ea51SShawn McCarney     // Create Chassis
2315b19ea51SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
232cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(1, chassisInvPath + '1'));
233cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(3, chassisInvPath + '3'));
2345b19ea51SShawn McCarney 
2355b19ea51SShawn McCarney     // Create System
2365b19ea51SShawn McCarney     System system{std::move(rules), std::move(chassis)};
2375b19ea51SShawn McCarney 
2385b19ea51SShawn McCarney     // Call closeDevices()
239d692d6dfSBob King     system.closeDevices(services);
2405b19ea51SShawn McCarney }
2415b19ea51SShawn McCarney 
TEST(SystemTests,Configure)2422af5289dSShawn McCarney TEST(SystemTests, Configure)
2432af5289dSShawn McCarney {
2445cfe5103SBob King     // Create mock services.  Expect logInfo() to be called.
24523243f84SBob King     MockServices services{};
2465cfe5103SBob King     MockJournal& journal = services.getMockJournal();
2475cfe5103SBob King     EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
2485cfe5103SBob King     EXPECT_CALL(journal, logInfo("Configuring chassis 3")).Times(1);
2495cfe5103SBob King     EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
2505cfe5103SBob King     EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
25123243f84SBob King 
2522af5289dSShawn McCarney     // Specify an empty rules vector
2532af5289dSShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
2542af5289dSShawn McCarney 
2552af5289dSShawn McCarney     // Create Chassis
2562af5289dSShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
257cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(1, chassisInvPath + '1'));
258cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(3, chassisInvPath + '3'));
2592af5289dSShawn McCarney 
2602af5289dSShawn McCarney     // Create System
2612af5289dSShawn McCarney     System system{std::move(rules), std::move(chassis)};
2622af5289dSShawn McCarney 
2632af5289dSShawn McCarney     // Call configure()
26423243f84SBob King     system.configure(services);
2652af5289dSShawn McCarney }
2662af5289dSShawn McCarney 
TEST(SystemTests,DetectPhaseFaults)26737af670eSShawn McCarney TEST(SystemTests, DetectPhaseFaults)
26837af670eSShawn McCarney {
26937af670eSShawn McCarney     // Create mock services with the following expectations:
27037af670eSShawn McCarney     // - 2 error messages in journal for N phase fault detected in reg0
27137af670eSShawn McCarney     // - 2 error messages in journal for N phase fault detected in reg1
27237af670eSShawn McCarney     // - 1 N phase fault error logged for reg0
27337af670eSShawn McCarney     // - 1 N phase fault error logged for reg1
27437af670eSShawn McCarney     MockServices services{};
27537af670eSShawn McCarney     MockJournal& journal = services.getMockJournal();
27637af670eSShawn McCarney     EXPECT_CALL(journal,
27737af670eSShawn McCarney                 logError("n phase fault detected in regulator reg0: count=1"))
27837af670eSShawn McCarney         .Times(1);
27937af670eSShawn McCarney     EXPECT_CALL(journal,
28037af670eSShawn McCarney                 logError("n phase fault detected in regulator reg0: count=2"))
28137af670eSShawn McCarney         .Times(1);
28237af670eSShawn McCarney     EXPECT_CALL(journal,
28337af670eSShawn McCarney                 logError("n phase fault detected in regulator reg1: count=1"))
28437af670eSShawn McCarney         .Times(1);
28537af670eSShawn McCarney     EXPECT_CALL(journal,
28637af670eSShawn McCarney                 logError("n phase fault detected in regulator reg1: count=2"))
28737af670eSShawn McCarney         .Times(1);
28837af670eSShawn McCarney     MockErrorLogging& errorLogging = services.getMockErrorLogging();
28937af670eSShawn McCarney     EXPECT_CALL(errorLogging, logPhaseFault).Times(2);
29037af670eSShawn McCarney 
29137af670eSShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassisVec{};
29237af670eSShawn McCarney 
29337af670eSShawn McCarney     // Create Chassis 1 with regulator reg0
29437af670eSShawn McCarney     {
29537af670eSShawn McCarney         // Create PhaseFaultDetection
29637af670eSShawn McCarney         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
29737af670eSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
29837af670eSShawn McCarney         actions.push_back(std::move(action));
29937af670eSShawn McCarney         auto phaseFaultDetection =
30037af670eSShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
30137af670eSShawn McCarney 
30237af670eSShawn McCarney         // Create Device
30337af670eSShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
30437af670eSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
30537af670eSShawn McCarney         std::unique_ptr<Configuration> configuration{};
30637af670eSShawn McCarney         auto device = std::make_unique<Device>(
30737af670eSShawn McCarney             "reg0", true,
30837af670eSShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis1/motherboard/"
30937af670eSShawn McCarney             "reg0",
31037af670eSShawn McCarney             std::move(i2cInterface), std::move(presenceDetection),
31137af670eSShawn McCarney             std::move(configuration), std::move(phaseFaultDetection));
31237af670eSShawn McCarney 
31337af670eSShawn McCarney         // Create Chassis
31437af670eSShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
31537af670eSShawn McCarney         devices.emplace_back(std::move(device));
31637af670eSShawn McCarney         auto chassis = std::make_unique<Chassis>(1, chassisInvPath + '1',
31737af670eSShawn McCarney                                                  std::move(devices));
31837af670eSShawn McCarney         chassisVec.emplace_back(std::move(chassis));
31937af670eSShawn McCarney     }
32037af670eSShawn McCarney 
32137af670eSShawn McCarney     // Create Chassis 2 with regulator reg1
32237af670eSShawn McCarney     {
32337af670eSShawn McCarney         // Create PhaseFaultDetection
32437af670eSShawn McCarney         auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
32537af670eSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
32637af670eSShawn McCarney         actions.push_back(std::move(action));
32737af670eSShawn McCarney         auto phaseFaultDetection =
32837af670eSShawn McCarney             std::make_unique<PhaseFaultDetection>(std::move(actions));
32937af670eSShawn McCarney 
33037af670eSShawn McCarney         // Create Device
33137af670eSShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
33237af670eSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
33337af670eSShawn McCarney         std::unique_ptr<Configuration> configuration{};
33437af670eSShawn McCarney         auto device = std::make_unique<Device>(
33537af670eSShawn McCarney             "reg1", true,
33637af670eSShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis2/motherboard/"
33737af670eSShawn McCarney             "reg1",
33837af670eSShawn McCarney             std::move(i2cInterface), std::move(presenceDetection),
33937af670eSShawn McCarney             std::move(configuration), std::move(phaseFaultDetection));
34037af670eSShawn McCarney 
34137af670eSShawn McCarney         // Create Chassis
34237af670eSShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
34337af670eSShawn McCarney         devices.emplace_back(std::move(device));
34437af670eSShawn McCarney         auto chassis = std::make_unique<Chassis>(2, chassisInvPath + '2',
34537af670eSShawn McCarney                                                  std::move(devices));
34637af670eSShawn McCarney         chassisVec.emplace_back(std::move(chassis));
34737af670eSShawn McCarney     }
34837af670eSShawn McCarney 
34937af670eSShawn McCarney     // Create System that contains Chassis
35037af670eSShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
35137af670eSShawn McCarney     System system{std::move(rules), std::move(chassisVec)};
35237af670eSShawn McCarney 
35337af670eSShawn McCarney     // Call detectPhaseFaults() 5 times
35437af670eSShawn McCarney     for (int i = 1; i <= 5; ++i)
35537af670eSShawn McCarney     {
35637af670eSShawn McCarney         system.detectPhaseFaults(services);
35737af670eSShawn McCarney     }
35837af670eSShawn McCarney }
35937af670eSShawn McCarney 
TEST(SystemTests,GetChassis)360c3991f16SShawn McCarney TEST(SystemTests, GetChassis)
361c3991f16SShawn McCarney {
362c3991f16SShawn McCarney     // Specify an empty rules vector
363c3991f16SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
364c3991f16SShawn McCarney 
365c3991f16SShawn McCarney     // Create Chassis
366c3991f16SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
367cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(1, chassisInvPath + '1'));
368cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(3, chassisInvPath + '3'));
369c3991f16SShawn McCarney 
370c3991f16SShawn McCarney     // Create System
371c3991f16SShawn McCarney     System system{std::move(rules), std::move(chassis)};
372c3991f16SShawn McCarney     EXPECT_EQ(system.getChassis().size(), 2);
373c3991f16SShawn McCarney     EXPECT_EQ(system.getChassis()[0]->getNumber(), 1);
374c3991f16SShawn McCarney     EXPECT_EQ(system.getChassis()[1]->getNumber(), 3);
375c3991f16SShawn McCarney }
376c3991f16SShawn McCarney 
TEST(SystemTests,GetIDMap)377c3991f16SShawn McCarney TEST(SystemTests, GetIDMap)
378c3991f16SShawn McCarney {
379db0b833cSShawn McCarney     // Create Rules
380db0b833cSShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
381db0b833cSShawn McCarney     rules.emplace_back(createRule("set_voltage_rule"));
382db0b833cSShawn McCarney     rules.emplace_back(createRule("read_sensors_rule"));
383db0b833cSShawn McCarney 
384db0b833cSShawn McCarney     // Create Chassis
385db0b833cSShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
386db0b833cSShawn McCarney     {
387db0b833cSShawn McCarney         // Chassis 1
388db0b833cSShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
389db0b833cSShawn McCarney         devices.emplace_back(createDevice("reg1", {"rail1"}));
390db0b833cSShawn McCarney         devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
391cb3f6a63SShawn McCarney         chassis.emplace_back(std::make_unique<Chassis>(1, chassisInvPath + '1',
392cb3f6a63SShawn McCarney                                                        std::move(devices)));
393db0b833cSShawn McCarney     }
394db0b833cSShawn McCarney     {
395db0b833cSShawn McCarney         // Chassis 2
396db0b833cSShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
397db0b833cSShawn McCarney         devices.emplace_back(createDevice("reg3", {"rail3a", "rail3b"}));
398db0b833cSShawn McCarney         devices.emplace_back(createDevice("reg4"));
399cb3f6a63SShawn McCarney         chassis.emplace_back(std::make_unique<Chassis>(2, chassisInvPath + '2',
400cb3f6a63SShawn McCarney                                                        std::move(devices)));
401db0b833cSShawn McCarney     }
402db0b833cSShawn McCarney 
403db0b833cSShawn McCarney     // Create System
404db0b833cSShawn McCarney     System system{std::move(rules), std::move(chassis)};
405db0b833cSShawn McCarney     const IDMap& idMap = system.getIDMap();
406db0b833cSShawn McCarney 
407db0b833cSShawn McCarney     // Verify all Rules are in the IDMap
408db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRule("set_voltage_rule"));
409db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRule("read_sensors_rule"));
410db0b833cSShawn McCarney     EXPECT_THROW(idMap.getRule("set_voltage_rule2"), std::invalid_argument);
411db0b833cSShawn McCarney 
412db0b833cSShawn McCarney     // Verify all Devices are in the IDMap
413db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg1"));
414db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg2"));
415db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg3"));
416db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg4"));
417db0b833cSShawn McCarney     EXPECT_THROW(idMap.getDevice("reg5"), std::invalid_argument);
418db0b833cSShawn McCarney 
419db0b833cSShawn McCarney     // Verify all Rails are in the IDMap
420db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail1"));
421db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2a"));
422db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2b"));
423db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail3a"));
424db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail3b"));
425db0b833cSShawn McCarney     EXPECT_THROW(idMap.getRail("rail4"), std::invalid_argument);
426c3991f16SShawn McCarney }
427c3991f16SShawn McCarney 
TEST(SystemTests,GetRules)428c3991f16SShawn McCarney TEST(SystemTests, GetRules)
429c3991f16SShawn McCarney {
430c3991f16SShawn McCarney     // Create Rules
431c3991f16SShawn McCarney     std::vector<std::unique_ptr<Rule>> rules{};
432db0b833cSShawn McCarney     rules.emplace_back(createRule("set_voltage_rule"));
433db0b833cSShawn McCarney     rules.emplace_back(createRule("read_sensors_rule"));
434c3991f16SShawn McCarney 
435c3991f16SShawn McCarney     // Create Chassis
436c3991f16SShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassis{};
437cb3f6a63SShawn McCarney     chassis.emplace_back(std::make_unique<Chassis>(1, chassisInvPath));
438c3991f16SShawn McCarney 
439c3991f16SShawn McCarney     // Create System
440c3991f16SShawn McCarney     System system{std::move(rules), std::move(chassis)};
441c3991f16SShawn McCarney     EXPECT_EQ(system.getRules().size(), 2);
442c3991f16SShawn McCarney     EXPECT_EQ(system.getRules()[0]->getID(), "set_voltage_rule");
443c3991f16SShawn McCarney     EXPECT_EQ(system.getRules()[1]->getID(), "read_sensors_rule");
444c3991f16SShawn McCarney }
4458e2294dcSBob King 
TEST(SystemTests,MonitorSensors)4468e2294dcSBob King TEST(SystemTests, MonitorSensors)
4478e2294dcSBob King {
44817bac89eSShawn McCarney     // Create mock services.  Set Sensors service expectations.
4498a55292dSBob King     MockServices services{};
45017bac89eSShawn McCarney     MockSensors& sensors = services.getMockSensors();
45117bac89eSShawn McCarney     EXPECT_CALL(sensors, startRail("c1_vdd0",
45217bac89eSShawn McCarney                                    "/xyz/openbmc_project/inventory/system/"
45317bac89eSShawn McCarney                                    "chassis1/motherboard/vdd0_reg",
45417bac89eSShawn McCarney                                    chassisInvPath + '1'))
4558e2294dcSBob King         .Times(1);
45617bac89eSShawn McCarney     EXPECT_CALL(sensors, startRail("c2_vdd0",
45717bac89eSShawn McCarney                                    "/xyz/openbmc_project/inventory/system/"
45817bac89eSShawn McCarney                                    "chassis2/motherboard/vdd0_reg",
45917bac89eSShawn McCarney                                    chassisInvPath + '2'))
46017bac89eSShawn McCarney         .Times(1);
46117bac89eSShawn McCarney     EXPECT_CALL(sensors, setValue).Times(0);
46217bac89eSShawn McCarney     EXPECT_CALL(sensors, endRail(false)).Times(2);
4638e2294dcSBob King 
46417bac89eSShawn McCarney     std::vector<std::unique_ptr<Chassis>> chassisVec{};
46517bac89eSShawn McCarney 
46617bac89eSShawn McCarney     // Create Chassis 1
46717bac89eSShawn McCarney     {
46817bac89eSShawn McCarney         // Create SensorMonitoring for Rail
469a3fecef3SShawn McCarney         auto action = std::make_unique<MockAction>();
47017bac89eSShawn McCarney         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
4718e2294dcSBob King         std::vector<std::unique_ptr<Action>> actions{};
4728e2294dcSBob King         actions.emplace_back(std::move(action));
473a3fecef3SShawn McCarney         auto sensorMonitoring =
4748e2294dcSBob King             std::make_unique<SensorMonitoring>(std::move(actions));
4758e2294dcSBob King 
4768e2294dcSBob King         // Create Rail
4778e2294dcSBob King         std::unique_ptr<Configuration> configuration{};
478a3fecef3SShawn McCarney         auto rail = std::make_unique<Rail>("c1_vdd0", std::move(configuration),
479a3fecef3SShawn McCarney                                            std::move(sensorMonitoring));
4808e2294dcSBob King 
4818e2294dcSBob King         // Create Device
482a3fecef3SShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
4838e2294dcSBob King         std::unique_ptr<PresenceDetection> presenceDetection{};
4848e2294dcSBob King         std::unique_ptr<Configuration> deviceConfiguration{};
48532252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
48617bac89eSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
48717bac89eSShawn McCarney         rails.emplace_back(std::move(rail));
488a3fecef3SShawn McCarney         auto device = std::make_unique<Device>(
48917bac89eSShawn McCarney             "c1_vdd0_reg", true,
49017bac89eSShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis1/motherboard/"
49117bac89eSShawn McCarney             "vdd0_reg",
4928e2294dcSBob King             std::move(i2cInterface), std::move(presenceDetection),
49332252599SShawn McCarney             std::move(deviceConfiguration), std::move(phaseFaultDetection),
49432252599SShawn McCarney             std::move(rails));
4958e2294dcSBob King 
4968e2294dcSBob King         // Create Chassis
4978e2294dcSBob King         std::vector<std::unique_ptr<Device>> devices{};
4988e2294dcSBob King         devices.emplace_back(std::move(device));
499a3fecef3SShawn McCarney         auto chassis = std::make_unique<Chassis>(1, chassisInvPath + '1',
500a3fecef3SShawn McCarney                                                  std::move(devices));
50117bac89eSShawn McCarney         chassisVec.emplace_back(std::move(chassis));
50217bac89eSShawn McCarney     }
50317bac89eSShawn McCarney 
50417bac89eSShawn McCarney     // Create Chassis 2
50517bac89eSShawn McCarney     {
50617bac89eSShawn McCarney         // Create SensorMonitoring for Rail
507a3fecef3SShawn McCarney         auto action = std::make_unique<MockAction>();
50817bac89eSShawn McCarney         EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
50917bac89eSShawn McCarney         std::vector<std::unique_ptr<Action>> actions{};
51017bac89eSShawn McCarney         actions.emplace_back(std::move(action));
511a3fecef3SShawn McCarney         auto sensorMonitoring =
51217bac89eSShawn McCarney             std::make_unique<SensorMonitoring>(std::move(actions));
51317bac89eSShawn McCarney 
51417bac89eSShawn McCarney         // Create Rail
51517bac89eSShawn McCarney         std::unique_ptr<Configuration> configuration{};
516a3fecef3SShawn McCarney         auto rail = std::make_unique<Rail>("c2_vdd0", std::move(configuration),
517a3fecef3SShawn McCarney                                            std::move(sensorMonitoring));
51817bac89eSShawn McCarney 
51917bac89eSShawn McCarney         // Create Device
520a3fecef3SShawn McCarney         auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
52117bac89eSShawn McCarney         std::unique_ptr<PresenceDetection> presenceDetection{};
52217bac89eSShawn McCarney         std::unique_ptr<Configuration> deviceConfiguration{};
52332252599SShawn McCarney         std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
52417bac89eSShawn McCarney         std::vector<std::unique_ptr<Rail>> rails{};
52517bac89eSShawn McCarney         rails.emplace_back(std::move(rail));
526a3fecef3SShawn McCarney         auto device = std::make_unique<Device>(
52717bac89eSShawn McCarney             "c2_vdd0_reg", true,
52817bac89eSShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis2/motherboard/"
52917bac89eSShawn McCarney             "vdd0_reg",
53017bac89eSShawn McCarney             std::move(i2cInterface), std::move(presenceDetection),
53132252599SShawn McCarney             std::move(deviceConfiguration), std::move(phaseFaultDetection),
53232252599SShawn McCarney             std::move(rails));
53317bac89eSShawn McCarney 
53417bac89eSShawn McCarney         // Create Chassis
53517bac89eSShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
53617bac89eSShawn McCarney         devices.emplace_back(std::move(device));
537a3fecef3SShawn McCarney         auto chassis = std::make_unique<Chassis>(2, chassisInvPath + '2',
538a3fecef3SShawn McCarney                                                  std::move(devices));
53917bac89eSShawn McCarney         chassisVec.emplace_back(std::move(chassis));
54017bac89eSShawn McCarney     }
5418e2294dcSBob King 
5428e2294dcSBob King     // Create System that contains Chassis
5438e2294dcSBob King     std::vector<std::unique_ptr<Rule>> rules{};
5448e2294dcSBob King     System system{std::move(rules), std::move(chassisVec)};
5458e2294dcSBob King 
5468e2294dcSBob King     // Call monitorSensors()
5478a55292dSBob King     system.monitorSensors(services);
5488e2294dcSBob King }
549