18a3afd70SShawn McCarney /**
28a3afd70SShawn McCarney  * Copyright © 2020 IBM Corporation
38a3afd70SShawn McCarney  *
48a3afd70SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
58a3afd70SShawn McCarney  * you may not use this file except in compliance with the License.
68a3afd70SShawn McCarney  * You may obtain a copy of the License at
78a3afd70SShawn McCarney  *
88a3afd70SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
98a3afd70SShawn McCarney  *
108a3afd70SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
118a3afd70SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
128a3afd70SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138a3afd70SShawn McCarney  * See the License for the specific language governing permissions and
148a3afd70SShawn McCarney  * limitations under the License.
158a3afd70SShawn McCarney  */
16525e20c9SShawn McCarney #include "action.hpp"
178a3afd70SShawn McCarney #include "chassis.hpp"
18525e20c9SShawn McCarney #include "configuration.hpp"
198a3afd70SShawn McCarney #include "device.hpp"
208a3afd70SShawn McCarney #include "i2c_interface.hpp"
21db0b833cSShawn McCarney #include "id_map.hpp"
2217bac89eSShawn McCarney #include "mock_action.hpp"
239f3e54e6SShawn McCarney #include "mock_error_logging.hpp"
24525e20c9SShawn McCarney #include "mock_journal.hpp"
2517bac89eSShawn McCarney #include "mock_sensors.hpp"
2623243f84SBob King #include "mock_services.hpp"
27050531f5SShawn McCarney #include "mocked_i2c_interface.hpp"
2832252599SShawn McCarney #include "phase_fault_detection.hpp"
29525e20c9SShawn McCarney #include "presence_detection.hpp"
30525e20c9SShawn McCarney #include "rail.hpp"
31525e20c9SShawn McCarney #include "rule.hpp"
3217bac89eSShawn McCarney #include "sensor_monitoring.hpp"
332f9e14f6SShawn McCarney #include "sensors.hpp"
34525e20c9SShawn McCarney #include "system.hpp"
359f3e54e6SShawn McCarney #include "test_sdbus_error.hpp"
368a3afd70SShawn McCarney #include "test_utils.hpp"
378a3afd70SShawn McCarney 
388a3afd70SShawn McCarney #include <memory>
398a3afd70SShawn McCarney #include <stdexcept>
40525e20c9SShawn McCarney #include <string>
418a3afd70SShawn McCarney #include <utility>
428a3afd70SShawn McCarney #include <vector>
438a3afd70SShawn McCarney 
44a2c81a61SBob King #include <gmock/gmock.h>
458a3afd70SShawn McCarney #include <gtest/gtest.h>
468a3afd70SShawn McCarney 
478a3afd70SShawn McCarney using namespace phosphor::power::regulators;
488a3afd70SShawn McCarney using namespace phosphor::power::regulators::test_utils;
498a3afd70SShawn McCarney 
50a2c81a61SBob King using ::testing::A;
51050531f5SShawn McCarney using ::testing::Return;
529f3e54e6SShawn McCarney using ::testing::Throw;
53a2c81a61SBob King using ::testing::TypedEq;
54050531f5SShawn McCarney 
55*83058606SShawn McCarney class ChassisTests : public ::testing::Test
56*83058606SShawn McCarney {
57*83058606SShawn McCarney   public:
58*83058606SShawn McCarney     /**
59*83058606SShawn McCarney      * Constructor.
60*83058606SShawn McCarney      *
61*83058606SShawn McCarney      * Creates the System object needed for calling some Chassis methods.
62*83058606SShawn McCarney      */
63*83058606SShawn McCarney     ChassisTests() : ::testing::Test{}
64*83058606SShawn McCarney     {
65*83058606SShawn McCarney         std::vector<std::unique_ptr<Rule>> rules{};
66*83058606SShawn McCarney         std::vector<std::unique_ptr<Chassis>> chassis{};
67*83058606SShawn McCarney         system = std::make_unique<System>(std::move(rules), std::move(chassis));
68*83058606SShawn McCarney     }
69*83058606SShawn McCarney 
70*83058606SShawn McCarney   protected:
71*83058606SShawn McCarney     const std::string defaultInventoryPath{
72cb3f6a63SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis"};
73cb3f6a63SShawn McCarney 
74*83058606SShawn McCarney     std::unique_ptr<System> system{};
75*83058606SShawn McCarney };
76*83058606SShawn McCarney 
77*83058606SShawn McCarney TEST_F(ChassisTests, Constructor)
788a3afd70SShawn McCarney {
798a3afd70SShawn McCarney     // Test where works: Only required parameters are specified
808a3afd70SShawn McCarney     {
81cb3f6a63SShawn McCarney         Chassis chassis{2, defaultInventoryPath};
828a3afd70SShawn McCarney         EXPECT_EQ(chassis.getNumber(), 2);
83cb3f6a63SShawn McCarney         EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
848a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 0);
858a3afd70SShawn McCarney     }
868a3afd70SShawn McCarney 
878a3afd70SShawn McCarney     // Test where works: All parameters are specified
888a3afd70SShawn McCarney     {
898a3afd70SShawn McCarney         // Create vector of Device objects
908a3afd70SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
91db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg1"));
92db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg2"));
938a3afd70SShawn McCarney 
948a3afd70SShawn McCarney         // Create Chassis
95cb3f6a63SShawn McCarney         Chassis chassis{1, defaultInventoryPath, std::move(devices)};
968a3afd70SShawn McCarney         EXPECT_EQ(chassis.getNumber(), 1);
97cb3f6a63SShawn McCarney         EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
988a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 2);
998a3afd70SShawn McCarney     }
1008a3afd70SShawn McCarney 
1018a3afd70SShawn McCarney     // Test where fails: Invalid chassis number < 1
1028a3afd70SShawn McCarney     try
1038a3afd70SShawn McCarney     {
104cb3f6a63SShawn McCarney         Chassis chassis{0, defaultInventoryPath};
1058a3afd70SShawn McCarney         ADD_FAILURE() << "Should not have reached this line.";
1068a3afd70SShawn McCarney     }
1078a3afd70SShawn McCarney     catch (const std::invalid_argument& e)
1088a3afd70SShawn McCarney     {
1098a3afd70SShawn McCarney         EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
1108a3afd70SShawn McCarney     }
1118a3afd70SShawn McCarney     catch (...)
1128a3afd70SShawn McCarney     {
1138a3afd70SShawn McCarney         ADD_FAILURE() << "Should not have caught exception.";
1148a3afd70SShawn McCarney     }
1158a3afd70SShawn McCarney }
1168a3afd70SShawn McCarney 
117*83058606SShawn McCarney TEST_F(ChassisTests, AddToIDMap)
118db0b833cSShawn McCarney {
119db0b833cSShawn McCarney     // Create vector of Device objects
120db0b833cSShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
121db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg1", {"rail1"}));
122db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
123db0b833cSShawn McCarney     devices.emplace_back(createDevice("reg3"));
124db0b833cSShawn McCarney 
125db0b833cSShawn McCarney     // Create Chassis
126cb3f6a63SShawn McCarney     Chassis chassis{1, defaultInventoryPath, std::move(devices)};
127db0b833cSShawn McCarney 
128db0b833cSShawn McCarney     // Add Device and Rail objects within the Chassis to an IDMap
129db0b833cSShawn McCarney     IDMap idMap{};
130db0b833cSShawn McCarney     chassis.addToIDMap(idMap);
131db0b833cSShawn McCarney 
132db0b833cSShawn McCarney     // Verify all Devices are in the IDMap
133db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg1"));
134db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg2"));
135db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getDevice("reg3"));
136db0b833cSShawn McCarney     EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
137db0b833cSShawn McCarney 
138db0b833cSShawn McCarney     // Verify all Rails are in the IDMap
139db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail1"));
140db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2a"));
141db0b833cSShawn McCarney     EXPECT_NO_THROW(idMap.getRail("rail2b"));
142db0b833cSShawn McCarney     EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
143db0b833cSShawn McCarney }
144db0b833cSShawn McCarney 
145*83058606SShawn McCarney TEST_F(ChassisTests, ClearCache)
1469bd94d36SShawn McCarney {
1479bd94d36SShawn McCarney     // Create PresenceDetection
1489bd94d36SShawn McCarney     std::vector<std::unique_ptr<Action>> actions{};
149*83058606SShawn McCarney     auto presenceDetection =
1509bd94d36SShawn McCarney         std::make_unique<PresenceDetection>(std::move(actions));
1519bd94d36SShawn McCarney     PresenceDetection* presenceDetectionPtr = presenceDetection.get();
1529bd94d36SShawn McCarney 
1539bd94d36SShawn McCarney     // Create Device that contains PresenceDetection
154*83058606SShawn McCarney     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
155*83058606SShawn McCarney     auto device = std::make_unique<Device>(
1569bd94d36SShawn McCarney         "reg1", true,
1579bd94d36SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
1589bd94d36SShawn McCarney         std::move(i2cInterface), std::move(presenceDetection));
1599bd94d36SShawn McCarney     Device* devicePtr = device.get();
1609bd94d36SShawn McCarney 
1619bd94d36SShawn McCarney     // Create Chassis that contains Device
1629bd94d36SShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
1639bd94d36SShawn McCarney     devices.emplace_back(std::move(device));
164*83058606SShawn McCarney     Chassis chassis{1, defaultInventoryPath, std::move(devices)};
1659bd94d36SShawn McCarney 
1669bd94d36SShawn McCarney     // Cache presence value in PresenceDetection
1679bd94d36SShawn McCarney     MockServices services{};
168*83058606SShawn McCarney     presenceDetectionPtr->execute(services, *system, chassis, *devicePtr);
1699bd94d36SShawn McCarney     EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
1709bd94d36SShawn McCarney 
1719bd94d36SShawn McCarney     // Clear cached data in Chassis
172*83058606SShawn McCarney     chassis.clearCache();
1739bd94d36SShawn McCarney 
1749bd94d36SShawn McCarney     // Verify presence value no longer cached in PresenceDetection
1759bd94d36SShawn McCarney     EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
1769bd94d36SShawn McCarney }
1779bd94d36SShawn McCarney 
178*83058606SShawn McCarney TEST_F(ChassisTests, ClearErrorHistory)
1799f3e54e6SShawn McCarney {
1809f3e54e6SShawn McCarney     // Create SensorMonitoring.  Will fail with a DBus exception.
181*83058606SShawn McCarney     auto action = std::make_unique<MockAction>();
1829f3e54e6SShawn McCarney     EXPECT_CALL(*action, execute)
1839f3e54e6SShawn McCarney         .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
1849f3e54e6SShawn McCarney     std::vector<std::unique_ptr<Action>> actions{};
1859f3e54e6SShawn McCarney     actions.emplace_back(std::move(action));
186*83058606SShawn McCarney     auto sensorMonitoring =
1879f3e54e6SShawn McCarney         std::make_unique<SensorMonitoring>(std::move(actions));
1889f3e54e6SShawn McCarney 
1899f3e54e6SShawn McCarney     // Create Rail
1909f3e54e6SShawn McCarney     std::unique_ptr<Configuration> configuration{};
191*83058606SShawn McCarney     auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
192*83058606SShawn McCarney                                        std::move(sensorMonitoring));
1939f3e54e6SShawn McCarney 
1949f3e54e6SShawn McCarney     // Create Device that contains Rail
195*83058606SShawn McCarney     auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
1969f3e54e6SShawn McCarney     std::unique_ptr<PresenceDetection> presenceDetection{};
1979f3e54e6SShawn McCarney     std::unique_ptr<Configuration> deviceConfiguration{};
19832252599SShawn McCarney     std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
1999f3e54e6SShawn McCarney     std::vector<std::unique_ptr<Rail>> rails{};
2009f3e54e6SShawn McCarney     rails.emplace_back(std::move(rail));
201*83058606SShawn McCarney     auto device = std::make_unique<Device>(
2029f3e54e6SShawn McCarney         "reg1", true,
2039f3e54e6SShawn McCarney         "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
2049f3e54e6SShawn McCarney         std::move(i2cInterface), std::move(presenceDetection),
20532252599SShawn McCarney         std::move(deviceConfiguration), std::move(phaseFaultDetection),
20632252599SShawn McCarney         std::move(rails));
2079f3e54e6SShawn McCarney 
2089f3e54e6SShawn McCarney     // Create Chassis that contains Device
2099f3e54e6SShawn McCarney     std::vector<std::unique_ptr<Device>> devices{};
2109f3e54e6SShawn McCarney     devices.emplace_back(std::move(device));
211*83058606SShawn McCarney     Chassis chassis{1, defaultInventoryPath, std::move(devices)};
2129f3e54e6SShawn McCarney 
2139f3e54e6SShawn McCarney     // Create mock services
2149f3e54e6SShawn McCarney     MockServices services{};
2159f3e54e6SShawn McCarney 
2169f3e54e6SShawn McCarney     // Expect Sensors service to be called 5+5=10 times
2179f3e54e6SShawn McCarney     MockSensors& sensors = services.getMockSensors();
2189f3e54e6SShawn McCarney     EXPECT_CALL(sensors, startRail).Times(10);
2199f3e54e6SShawn McCarney     EXPECT_CALL(sensors, setValue).Times(0);
2209f3e54e6SShawn McCarney     EXPECT_CALL(sensors, endRail).Times(10);
2219f3e54e6SShawn McCarney 
2229f3e54e6SShawn McCarney     // Expect Journal service to be called 3+3=6 times to log error messages
2239f3e54e6SShawn McCarney     MockJournal& journal = services.getMockJournal();
2249f3e54e6SShawn McCarney     EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
2259f3e54e6SShawn McCarney         .Times(6);
2269f3e54e6SShawn McCarney     EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
2279f3e54e6SShawn McCarney 
2289f3e54e6SShawn McCarney     // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
2299f3e54e6SShawn McCarney     MockErrorLogging& errorLogging = services.getMockErrorLogging();
2309f3e54e6SShawn McCarney     EXPECT_CALL(errorLogging, logDBusError).Times(2);
2319f3e54e6SShawn McCarney 
2329f3e54e6SShawn McCarney     // Monitor sensors 5 times.  Should fail every time, write to journal 3
2339f3e54e6SShawn McCarney     // times, and log one error.
2349f3e54e6SShawn McCarney     for (int i = 1; i <= 5; ++i)
2359f3e54e6SShawn McCarney     {
236*83058606SShawn McCarney         chassis.monitorSensors(services, *system);
2379f3e54e6SShawn McCarney     }
2389f3e54e6SShawn McCarney 
2399f3e54e6SShawn McCarney     // Clear error history
240*83058606SShawn McCarney     chassis.clearErrorHistory();
2419f3e54e6SShawn McCarney 
2429f3e54e6SShawn McCarney     // Monitor sensors 5 times again.  Should fail every time, write to journal
2439f3e54e6SShawn McCarney     // 3 times, and log one error.
2449f3e54e6SShawn McCarney     for (int i = 1; i <= 5; ++i)
2459f3e54e6SShawn McCarney     {
246*83058606SShawn McCarney         chassis.monitorSensors(services, *system);
2479f3e54e6SShawn McCarney     }
2489f3e54e6SShawn McCarney }
2499f3e54e6SShawn McCarney 
250*83058606SShawn McCarney TEST_F(ChassisTests, CloseDevices)
251050531f5SShawn McCarney {
252050531f5SShawn McCarney     // Test where no devices were specified in constructor
253050531f5SShawn McCarney     {
254d692d6dfSBob King         // Create mock services.  Expect logDebug() to be called.
255d692d6dfSBob King         MockServices services{};
256d692d6dfSBob King         MockJournal& journal = services.getMockJournal();
257d692d6dfSBob King         EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
258d692d6dfSBob King 
259050531f5SShawn McCarney         // Create Chassis
260cb3f6a63SShawn McCarney         Chassis chassis{2, defaultInventoryPath};
261050531f5SShawn McCarney 
262050531f5SShawn McCarney         // Call closeDevices()
263d692d6dfSBob King         chassis.closeDevices(services);
264050531f5SShawn McCarney     }
265050531f5SShawn McCarney 
266050531f5SShawn McCarney     // Test where devices were specified in constructor
267050531f5SShawn McCarney     {
268050531f5SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
269050531f5SShawn McCarney 
270d692d6dfSBob King         // Create mock services.  Expect logDebug() to be called.
271d692d6dfSBob King         MockServices services{};
272d692d6dfSBob King         MockJournal& journal = services.getMockJournal();
273d692d6dfSBob King         EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
274d692d6dfSBob King 
275050531f5SShawn McCarney         // Create Device vdd0_reg
276050531f5SShawn McCarney         {
277050531f5SShawn McCarney             // Create mock I2CInterface: isOpen() and close() should be called
278*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
279050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
280050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, close).Times(1);
281050531f5SShawn McCarney 
282050531f5SShawn McCarney             // Create Device
283*83058606SShawn McCarney             auto device =
284a76898f1SBob King                 std::make_unique<Device>("vdd0_reg", true,
285a76898f1SBob King                                          "/xyz/openbmc_project/inventory/"
286a76898f1SBob King                                          "system/chassis/motherboard/vdd0_reg",
287050531f5SShawn McCarney                                          std::move(i2cInterface));
288050531f5SShawn McCarney             devices.emplace_back(std::move(device));
289050531f5SShawn McCarney         }
290050531f5SShawn McCarney 
291050531f5SShawn McCarney         // Create Device vdd1_reg
292050531f5SShawn McCarney         {
293050531f5SShawn McCarney             // Create mock I2CInterface: isOpen() and close() should be called
294*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
295050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
296050531f5SShawn McCarney             EXPECT_CALL(*i2cInterface, close).Times(1);
297050531f5SShawn McCarney 
298050531f5SShawn McCarney             // Create Device
299*83058606SShawn McCarney             auto device =
300a76898f1SBob King                 std::make_unique<Device>("vdd1_reg", true,
301a76898f1SBob King                                          "/xyz/openbmc_project/inventory/"
302a76898f1SBob King                                          "system/chassis/motherboard/vdd1_reg",
303050531f5SShawn McCarney                                          std::move(i2cInterface));
304050531f5SShawn McCarney             devices.emplace_back(std::move(device));
305050531f5SShawn McCarney         }
306050531f5SShawn McCarney 
307050531f5SShawn McCarney         // Create Chassis
308cb3f6a63SShawn McCarney         Chassis chassis{1, defaultInventoryPath, std::move(devices)};
309050531f5SShawn McCarney 
310050531f5SShawn McCarney         // Call closeDevices()
311d692d6dfSBob King         chassis.closeDevices(services);
312050531f5SShawn McCarney     }
313050531f5SShawn McCarney }
314050531f5SShawn McCarney 
315*83058606SShawn McCarney TEST_F(ChassisTests, Configure)
316525e20c9SShawn McCarney {
317525e20c9SShawn McCarney     // Test where no devices were specified in constructor
318525e20c9SShawn McCarney     {
3195cfe5103SBob King         // Create mock services.  Expect logInfo() to be called.
32023243f84SBob King         MockServices services{};
3215cfe5103SBob King         MockJournal& journal = services.getMockJournal();
3225cfe5103SBob King         EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
3235cfe5103SBob King         EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
3245cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
32523243f84SBob King 
326525e20c9SShawn McCarney         // Create Chassis
327*83058606SShawn McCarney         Chassis chassis{1, defaultInventoryPath};
328525e20c9SShawn McCarney 
329525e20c9SShawn McCarney         // Call configure()
330*83058606SShawn McCarney         chassis.configure(services, *system);
331525e20c9SShawn McCarney     }
332525e20c9SShawn McCarney 
333525e20c9SShawn McCarney     // Test where devices were specified in constructor
334525e20c9SShawn McCarney     {
335525e20c9SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
336525e20c9SShawn McCarney 
3375cfe5103SBob King         // Create mock services.  Expect logInfo() and logDebug() to be called.
3385cfe5103SBob King         MockServices services{};
3395cfe5103SBob King         MockJournal& journal = services.getMockJournal();
3405cfe5103SBob King         EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
3415cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
3425cfe5103SBob King             .Times(1);
3435cfe5103SBob King         EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
3445cfe5103SBob King             .Times(1);
3455cfe5103SBob King         EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
3465cfe5103SBob King 
347525e20c9SShawn McCarney         // Create Device vdd0_reg
348525e20c9SShawn McCarney         {
349525e20c9SShawn McCarney             // Create Configuration
350525e20c9SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
351*83058606SShawn McCarney             auto configuration =
352525e20c9SShawn McCarney                 std::make_unique<Configuration>(1.3, std::move(actions));
353525e20c9SShawn McCarney 
354525e20c9SShawn McCarney             // Create Device
355*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
356525e20c9SShawn McCarney             std::unique_ptr<PresenceDetection> presenceDetection{};
357*83058606SShawn McCarney             auto device = std::make_unique<Device>(
358a76898f1SBob King                 "vdd0_reg", true,
359a76898f1SBob King                 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
360a76898f1SBob King                 "vdd0_reg",
361525e20c9SShawn McCarney                 std::move(i2cInterface), std::move(presenceDetection),
362525e20c9SShawn McCarney                 std::move(configuration));
363525e20c9SShawn McCarney             devices.emplace_back(std::move(device));
364525e20c9SShawn McCarney         }
365525e20c9SShawn McCarney 
366525e20c9SShawn McCarney         // Create Device vdd1_reg
367525e20c9SShawn McCarney         {
368525e20c9SShawn McCarney             // Create Configuration
369525e20c9SShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
370*83058606SShawn McCarney             auto configuration =
371525e20c9SShawn McCarney                 std::make_unique<Configuration>(1.2, std::move(actions));
372525e20c9SShawn McCarney 
373525e20c9SShawn McCarney             // Create Device
374*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
375525e20c9SShawn McCarney             std::unique_ptr<PresenceDetection> presenceDetection{};
376*83058606SShawn McCarney             auto device = std::make_unique<Device>(
377a76898f1SBob King                 "vdd1_reg", true,
378a76898f1SBob King                 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
379a76898f1SBob King                 "vdd1_reg",
380525e20c9SShawn McCarney                 std::move(i2cInterface), std::move(presenceDetection),
381525e20c9SShawn McCarney                 std::move(configuration));
382525e20c9SShawn McCarney             devices.emplace_back(std::move(device));
383525e20c9SShawn McCarney         }
384525e20c9SShawn McCarney 
385525e20c9SShawn McCarney         // Create Chassis
386*83058606SShawn McCarney         Chassis chassis{2, defaultInventoryPath, std::move(devices)};
387525e20c9SShawn McCarney 
388525e20c9SShawn McCarney         // Call configure()
389*83058606SShawn McCarney         chassis.configure(services, *system);
390525e20c9SShawn McCarney     }
391525e20c9SShawn McCarney }
392525e20c9SShawn McCarney 
393*83058606SShawn McCarney TEST_F(ChassisTests, GetDevices)
3948a3afd70SShawn McCarney {
3958a3afd70SShawn McCarney     // Test where no devices were specified in constructor
3968a3afd70SShawn McCarney     {
397cb3f6a63SShawn McCarney         Chassis chassis{2, defaultInventoryPath};
3988a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 0);
3998a3afd70SShawn McCarney     }
4008a3afd70SShawn McCarney 
4018a3afd70SShawn McCarney     // Test where devices were specified in constructor
4028a3afd70SShawn McCarney     {
4038a3afd70SShawn McCarney         // Create vector of Device objects
4048a3afd70SShawn McCarney         std::vector<std::unique_ptr<Device>> devices{};
405db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg1"));
406db0b833cSShawn McCarney         devices.emplace_back(createDevice("vdd_reg2"));
4078a3afd70SShawn McCarney 
4088a3afd70SShawn McCarney         // Create Chassis
409cb3f6a63SShawn McCarney         Chassis chassis{1, defaultInventoryPath, std::move(devices)};
4108a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices().size(), 2);
4118a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
4128a3afd70SShawn McCarney         EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
4138a3afd70SShawn McCarney     }
4148a3afd70SShawn McCarney }
4158a3afd70SShawn McCarney 
416*83058606SShawn McCarney TEST_F(ChassisTests, GetInventoryPath)
417cb3f6a63SShawn McCarney {
418cb3f6a63SShawn McCarney     Chassis chassis{3, defaultInventoryPath};
419cb3f6a63SShawn McCarney     EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
420cb3f6a63SShawn McCarney }
421cb3f6a63SShawn McCarney 
422*83058606SShawn McCarney TEST_F(ChassisTests, GetNumber)
4238a3afd70SShawn McCarney {
424cb3f6a63SShawn McCarney     Chassis chassis{3, defaultInventoryPath};
4258a3afd70SShawn McCarney     EXPECT_EQ(chassis.getNumber(), 3);
4268a3afd70SShawn McCarney }
427a2c81a61SBob King 
428*83058606SShawn McCarney TEST_F(ChassisTests, MonitorSensors)
429a2c81a61SBob King {
430a2c81a61SBob King     // Test where no devices were specified in constructor
431a2c81a61SBob King     {
43217bac89eSShawn McCarney         // Create mock services.  No Sensors methods should be called.
4338a55292dSBob King         MockServices services{};
43417bac89eSShawn McCarney         MockSensors& sensors = services.getMockSensors();
43517bac89eSShawn McCarney         EXPECT_CALL(sensors, startRail).Times(0);
43617bac89eSShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
43717bac89eSShawn McCarney         EXPECT_CALL(sensors, endRail).Times(0);
4388a55292dSBob King 
439a2c81a61SBob King         // Create Chassis
440*83058606SShawn McCarney         Chassis chassis{1, defaultInventoryPath};
441a2c81a61SBob King 
442a2c81a61SBob King         // Call monitorSensors().  Should do nothing.
443*83058606SShawn McCarney         chassis.monitorSensors(services, *system);
444a2c81a61SBob King     }
445a2c81a61SBob King 
446a2c81a61SBob King     // Test where devices were specified in constructor
447a2c81a61SBob 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("vdd0",
45217bac89eSShawn McCarney                                        "/xyz/openbmc_project/inventory/system/"
45317bac89eSShawn McCarney                                        "chassis/motherboard/vdd0_reg",
45417bac89eSShawn McCarney                                        defaultInventoryPath))
45517bac89eSShawn McCarney             .Times(1);
45617bac89eSShawn McCarney         EXPECT_CALL(sensors, startRail("vdd1",
45717bac89eSShawn McCarney                                        "/xyz/openbmc_project/inventory/system/"
45817bac89eSShawn McCarney                                        "chassis/motherboard/vdd1_reg",
45917bac89eSShawn McCarney                                        defaultInventoryPath))
46017bac89eSShawn McCarney             .Times(1);
46117bac89eSShawn McCarney         EXPECT_CALL(sensors, setValue).Times(0);
46217bac89eSShawn McCarney         EXPECT_CALL(sensors, endRail(false)).Times(2);
4638a55292dSBob King 
464a2c81a61SBob King         std::vector<std::unique_ptr<Device>> devices{};
465a2c81a61SBob King 
46617bac89eSShawn McCarney         // Create Device vdd0_reg
46717bac89eSShawn McCarney         {
46817bac89eSShawn McCarney             // Create SensorMonitoring for Rail
469*83058606SShawn McCarney             auto action = std::make_unique<MockAction>();
47017bac89eSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
471a2c81a61SBob King             std::vector<std::unique_ptr<Action>> actions{};
472a2c81a61SBob King             actions.emplace_back(std::move(action));
473*83058606SShawn McCarney             auto sensorMonitoring =
474a2c81a61SBob King                 std::make_unique<SensorMonitoring>(std::move(actions));
475a2c81a61SBob King 
476a2c81a61SBob King             // Create Rail
477a2c81a61SBob King             std::unique_ptr<Configuration> configuration{};
478*83058606SShawn McCarney             auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
479*83058606SShawn McCarney                                                std::move(sensorMonitoring));
480a2c81a61SBob King 
481a2c81a61SBob King             // Create Device
482*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
483a2c81a61SBob King             std::unique_ptr<PresenceDetection> presenceDetection{};
484a2c81a61SBob 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));
488*83058606SShawn McCarney             auto device = std::make_unique<Device>(
48917bac89eSShawn McCarney                 "vdd0_reg", true,
49017bac89eSShawn McCarney                 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
49117bac89eSShawn McCarney                 "vdd0_reg",
492a2c81a61SBob King                 std::move(i2cInterface), std::move(presenceDetection),
49332252599SShawn McCarney                 std::move(deviceConfiguration), std::move(phaseFaultDetection),
49432252599SShawn McCarney                 std::move(rails));
495a2c81a61SBob King             devices.emplace_back(std::move(device));
49617bac89eSShawn McCarney         }
49717bac89eSShawn McCarney 
49817bac89eSShawn McCarney         // Create Device vdd1_reg
49917bac89eSShawn McCarney         {
50017bac89eSShawn McCarney             // Create SensorMonitoring for Rail
501*83058606SShawn McCarney             auto action = std::make_unique<MockAction>();
50217bac89eSShawn McCarney             EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
50317bac89eSShawn McCarney             std::vector<std::unique_ptr<Action>> actions{};
50417bac89eSShawn McCarney             actions.emplace_back(std::move(action));
505*83058606SShawn McCarney             auto sensorMonitoring =
50617bac89eSShawn McCarney                 std::make_unique<SensorMonitoring>(std::move(actions));
50717bac89eSShawn McCarney 
50817bac89eSShawn McCarney             // Create Rail
50917bac89eSShawn McCarney             std::unique_ptr<Configuration> configuration{};
510*83058606SShawn McCarney             auto rail = std::make_unique<Rail>("vdd1", std::move(configuration),
511*83058606SShawn McCarney                                                std::move(sensorMonitoring));
51217bac89eSShawn McCarney 
51317bac89eSShawn McCarney             // Create Device
514*83058606SShawn McCarney             auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
51517bac89eSShawn McCarney             std::unique_ptr<PresenceDetection> presenceDetection{};
51617bac89eSShawn McCarney             std::unique_ptr<Configuration> deviceConfiguration{};
51732252599SShawn McCarney             std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
51817bac89eSShawn McCarney             std::vector<std::unique_ptr<Rail>> rails{};
51917bac89eSShawn McCarney             rails.emplace_back(std::move(rail));
520*83058606SShawn McCarney             auto device = std::make_unique<Device>(
52117bac89eSShawn McCarney                 "vdd1_reg", true,
52217bac89eSShawn McCarney                 "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
52317bac89eSShawn McCarney                 "vdd1_reg",
52417bac89eSShawn McCarney                 std::move(i2cInterface), std::move(presenceDetection),
52532252599SShawn McCarney                 std::move(deviceConfiguration), std::move(phaseFaultDetection),
52632252599SShawn McCarney                 std::move(rails));
52717bac89eSShawn McCarney             devices.emplace_back(std::move(device));
52817bac89eSShawn McCarney         }
52917bac89eSShawn McCarney 
53017bac89eSShawn McCarney         // Create Chassis that contains Devices
531*83058606SShawn McCarney         Chassis chassis{2, defaultInventoryPath, std::move(devices)};
532a2c81a61SBob King 
533a2c81a61SBob King         // Call monitorSensors()
534*83058606SShawn McCarney         chassis.monitorSensors(services, *system);
535a2c81a61SBob King     }
536a2c81a61SBob King }
537