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"
2250e57c6bSShawn McCarney #include "log_phase_fault_action.hpp"
2317bac89eSShawn McCarney #include "mock_action.hpp"
249f3e54e6SShawn McCarney #include "mock_error_logging.hpp"
25525e20c9SShawn McCarney #include "mock_journal.hpp"
2617bac89eSShawn McCarney #include "mock_sensors.hpp"
2723243f84SBob King #include "mock_services.hpp"
28050531f5SShawn McCarney #include "mocked_i2c_interface.hpp"
2950e57c6bSShawn McCarney #include "phase_fault.hpp"
3032252599SShawn McCarney #include "phase_fault_detection.hpp"
31525e20c9SShawn McCarney #include "presence_detection.hpp"
32525e20c9SShawn McCarney #include "rail.hpp"
33525e20c9SShawn McCarney #include "rule.hpp"
3417bac89eSShawn McCarney #include "sensor_monitoring.hpp"
352f9e14f6SShawn McCarney #include "sensors.hpp"
36525e20c9SShawn McCarney #include "system.hpp"
379f3e54e6SShawn McCarney #include "test_sdbus_error.hpp"
388a3afd70SShawn McCarney #include "test_utils.hpp"
398a3afd70SShawn McCarney
408a3afd70SShawn McCarney #include <memory>
418a3afd70SShawn McCarney #include <stdexcept>
42525e20c9SShawn McCarney #include <string>
438a3afd70SShawn McCarney #include <utility>
448a3afd70SShawn McCarney #include <vector>
458a3afd70SShawn McCarney
46a2c81a61SBob King #include <gmock/gmock.h>
478a3afd70SShawn McCarney #include <gtest/gtest.h>
488a3afd70SShawn McCarney
498a3afd70SShawn McCarney using namespace phosphor::power::regulators;
508a3afd70SShawn McCarney using namespace phosphor::power::regulators::test_utils;
518a3afd70SShawn McCarney
52a2c81a61SBob King using ::testing::A;
53050531f5SShawn McCarney using ::testing::Return;
549f3e54e6SShawn McCarney using ::testing::Throw;
55a2c81a61SBob King using ::testing::TypedEq;
56050531f5SShawn McCarney
5783058606SShawn McCarney class ChassisTests : public ::testing::Test
5883058606SShawn McCarney {
5983058606SShawn McCarney public:
6083058606SShawn McCarney /**
6183058606SShawn McCarney * Constructor.
6283058606SShawn McCarney *
6383058606SShawn McCarney * Creates the System object needed for calling some Chassis methods.
6483058606SShawn McCarney */
ChassisTests()6583058606SShawn McCarney ChassisTests() : ::testing::Test{}
6683058606SShawn McCarney {
6783058606SShawn McCarney std::vector<std::unique_ptr<Rule>> rules{};
6883058606SShawn McCarney std::vector<std::unique_ptr<Chassis>> chassis{};
6983058606SShawn McCarney system = std::make_unique<System>(std::move(rules), std::move(chassis));
7083058606SShawn McCarney }
7183058606SShawn McCarney
7283058606SShawn McCarney protected:
7383058606SShawn McCarney const std::string defaultInventoryPath{
74cb3f6a63SShawn McCarney "/xyz/openbmc_project/inventory/system/chassis"};
75cb3f6a63SShawn McCarney
7683058606SShawn McCarney std::unique_ptr<System> system{};
7783058606SShawn McCarney };
7883058606SShawn McCarney
TEST_F(ChassisTests,Constructor)7983058606SShawn McCarney TEST_F(ChassisTests, Constructor)
808a3afd70SShawn McCarney {
818a3afd70SShawn McCarney // Test where works: Only required parameters are specified
828a3afd70SShawn McCarney {
83cb3f6a63SShawn McCarney Chassis chassis{2, defaultInventoryPath};
848a3afd70SShawn McCarney EXPECT_EQ(chassis.getNumber(), 2);
85cb3f6a63SShawn McCarney EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
868a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices().size(), 0);
878a3afd70SShawn McCarney }
888a3afd70SShawn McCarney
898a3afd70SShawn McCarney // Test where works: All parameters are specified
908a3afd70SShawn McCarney {
918a3afd70SShawn McCarney // Create vector of Device objects
928a3afd70SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
93db0b833cSShawn McCarney devices.emplace_back(createDevice("vdd_reg1"));
94db0b833cSShawn McCarney devices.emplace_back(createDevice("vdd_reg2"));
958a3afd70SShawn McCarney
968a3afd70SShawn McCarney // Create Chassis
97cb3f6a63SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
988a3afd70SShawn McCarney EXPECT_EQ(chassis.getNumber(), 1);
99cb3f6a63SShawn McCarney EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
1008a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices().size(), 2);
1018a3afd70SShawn McCarney }
1028a3afd70SShawn McCarney
1038a3afd70SShawn McCarney // Test where fails: Invalid chassis number < 1
1048a3afd70SShawn McCarney try
1058a3afd70SShawn McCarney {
106cb3f6a63SShawn McCarney Chassis chassis{0, defaultInventoryPath};
1078a3afd70SShawn McCarney ADD_FAILURE() << "Should not have reached this line.";
1088a3afd70SShawn McCarney }
1098a3afd70SShawn McCarney catch (const std::invalid_argument& e)
1108a3afd70SShawn McCarney {
1118a3afd70SShawn McCarney EXPECT_STREQ(e.what(), "Invalid chassis number: 0");
1128a3afd70SShawn McCarney }
1138a3afd70SShawn McCarney catch (...)
1148a3afd70SShawn McCarney {
1158a3afd70SShawn McCarney ADD_FAILURE() << "Should not have caught exception.";
1168a3afd70SShawn McCarney }
1178a3afd70SShawn McCarney }
1188a3afd70SShawn McCarney
TEST_F(ChassisTests,AddToIDMap)11983058606SShawn McCarney TEST_F(ChassisTests, AddToIDMap)
120db0b833cSShawn McCarney {
121db0b833cSShawn McCarney // Create vector of Device objects
122db0b833cSShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
123db0b833cSShawn McCarney devices.emplace_back(createDevice("reg1", {"rail1"}));
124db0b833cSShawn McCarney devices.emplace_back(createDevice("reg2", {"rail2a", "rail2b"}));
125db0b833cSShawn McCarney devices.emplace_back(createDevice("reg3"));
126db0b833cSShawn McCarney
127db0b833cSShawn McCarney // Create Chassis
128cb3f6a63SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
129db0b833cSShawn McCarney
130db0b833cSShawn McCarney // Add Device and Rail objects within the Chassis to an IDMap
131db0b833cSShawn McCarney IDMap idMap{};
132db0b833cSShawn McCarney chassis.addToIDMap(idMap);
133db0b833cSShawn McCarney
134db0b833cSShawn McCarney // Verify all Devices are in the IDMap
135db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg1"));
136db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg2"));
137db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getDevice("reg3"));
138db0b833cSShawn McCarney EXPECT_THROW(idMap.getDevice("reg4"), std::invalid_argument);
139db0b833cSShawn McCarney
140db0b833cSShawn McCarney // Verify all Rails are in the IDMap
141db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail1"));
142db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail2a"));
143db0b833cSShawn McCarney EXPECT_NO_THROW(idMap.getRail("rail2b"));
144db0b833cSShawn McCarney EXPECT_THROW(idMap.getRail("rail3"), std::invalid_argument);
145db0b833cSShawn McCarney }
146db0b833cSShawn McCarney
TEST_F(ChassisTests,ClearCache)14783058606SShawn McCarney TEST_F(ChassisTests, ClearCache)
1489bd94d36SShawn McCarney {
1499bd94d36SShawn McCarney // Create PresenceDetection
1509bd94d36SShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
15183058606SShawn McCarney auto presenceDetection =
1529bd94d36SShawn McCarney std::make_unique<PresenceDetection>(std::move(actions));
1539bd94d36SShawn McCarney PresenceDetection* presenceDetectionPtr = presenceDetection.get();
1549bd94d36SShawn McCarney
1559bd94d36SShawn McCarney // Create Device that contains PresenceDetection
15683058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
15783058606SShawn McCarney auto device = std::make_unique<Device>(
1589bd94d36SShawn McCarney "reg1", true,
1599bd94d36SShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
1609bd94d36SShawn McCarney std::move(i2cInterface), std::move(presenceDetection));
1619bd94d36SShawn McCarney Device* devicePtr = device.get();
1629bd94d36SShawn McCarney
1639bd94d36SShawn McCarney // Create Chassis that contains Device
1649bd94d36SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
1659bd94d36SShawn McCarney devices.emplace_back(std::move(device));
16683058606SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
1679bd94d36SShawn McCarney
1689bd94d36SShawn McCarney // Cache presence value in PresenceDetection
1699bd94d36SShawn McCarney MockServices services{};
17083058606SShawn McCarney presenceDetectionPtr->execute(services, *system, chassis, *devicePtr);
1719bd94d36SShawn McCarney EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
1729bd94d36SShawn McCarney
1739bd94d36SShawn McCarney // Clear cached data in Chassis
17483058606SShawn McCarney chassis.clearCache();
1759bd94d36SShawn McCarney
1769bd94d36SShawn McCarney // Verify presence value no longer cached in PresenceDetection
1779bd94d36SShawn McCarney EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
1789bd94d36SShawn McCarney }
1799bd94d36SShawn McCarney
TEST_F(ChassisTests,ClearErrorHistory)18083058606SShawn McCarney TEST_F(ChassisTests, ClearErrorHistory)
1819f3e54e6SShawn McCarney {
1829f3e54e6SShawn McCarney // Create SensorMonitoring. Will fail with a DBus exception.
18383058606SShawn McCarney auto action = std::make_unique<MockAction>();
1849f3e54e6SShawn McCarney EXPECT_CALL(*action, execute)
1859f3e54e6SShawn McCarney .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
1869f3e54e6SShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
1879f3e54e6SShawn McCarney actions.emplace_back(std::move(action));
18883058606SShawn McCarney auto sensorMonitoring =
1899f3e54e6SShawn McCarney std::make_unique<SensorMonitoring>(std::move(actions));
1909f3e54e6SShawn McCarney
1919f3e54e6SShawn McCarney // Create Rail
1929f3e54e6SShawn McCarney std::unique_ptr<Configuration> configuration{};
19383058606SShawn McCarney auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
19483058606SShawn McCarney std::move(sensorMonitoring));
1959f3e54e6SShawn McCarney
1969f3e54e6SShawn McCarney // Create Device that contains Rail
19783058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
1989f3e54e6SShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
1999f3e54e6SShawn McCarney std::unique_ptr<Configuration> deviceConfiguration{};
20032252599SShawn McCarney std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
2019f3e54e6SShawn McCarney std::vector<std::unique_ptr<Rail>> rails{};
2029f3e54e6SShawn McCarney rails.emplace_back(std::move(rail));
20383058606SShawn McCarney auto device = std::make_unique<Device>(
2049f3e54e6SShawn McCarney "reg1", true,
2059f3e54e6SShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
2069f3e54e6SShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
20732252599SShawn McCarney std::move(deviceConfiguration), std::move(phaseFaultDetection),
20832252599SShawn McCarney std::move(rails));
2099f3e54e6SShawn McCarney
2109f3e54e6SShawn McCarney // Create Chassis that contains Device
2119f3e54e6SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
2129f3e54e6SShawn McCarney devices.emplace_back(std::move(device));
21383058606SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
2149f3e54e6SShawn McCarney
215fa2734d6SShawn McCarney // Create lambda that sets MockServices expectations. The lambda allows
216fa2734d6SShawn McCarney // us to set expectations multiple times without duplicate code.
217fa2734d6SShawn McCarney auto setExpectations = [](MockServices& services) {
218fa2734d6SShawn McCarney // Expect Sensors service to be called 10 times
2199f3e54e6SShawn McCarney MockSensors& sensors = services.getMockSensors();
2209f3e54e6SShawn McCarney EXPECT_CALL(sensors, startRail).Times(10);
2219f3e54e6SShawn McCarney EXPECT_CALL(sensors, setValue).Times(0);
2229f3e54e6SShawn McCarney EXPECT_CALL(sensors, endRail).Times(10);
2239f3e54e6SShawn McCarney
224fa2734d6SShawn McCarney // Expect Journal service to be called 6 times to log error messages
2259f3e54e6SShawn McCarney MockJournal& journal = services.getMockJournal();
2269f3e54e6SShawn McCarney EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
2279f3e54e6SShawn McCarney .Times(6);
2289f3e54e6SShawn McCarney EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
2299f3e54e6SShawn McCarney
230fa2734d6SShawn McCarney // Expect ErrorLogging service to be called once to log a DBus error
2319f3e54e6SShawn McCarney MockErrorLogging& errorLogging = services.getMockErrorLogging();
232fa2734d6SShawn McCarney EXPECT_CALL(errorLogging, logDBusError).Times(1);
233fa2734d6SShawn McCarney };
2349f3e54e6SShawn McCarney
235fa2734d6SShawn McCarney // Monitor sensors 10 times. Verify errors logged.
236fa2734d6SShawn McCarney {
237fa2734d6SShawn McCarney // Create mock services. Set expectations via lambda.
238fa2734d6SShawn McCarney MockServices services{};
239fa2734d6SShawn McCarney setExpectations(services);
240fa2734d6SShawn McCarney
241fa2734d6SShawn McCarney for (int i = 1; i <= 10; ++i)
2429f3e54e6SShawn McCarney {
24383058606SShawn McCarney chassis.monitorSensors(services, *system);
2449f3e54e6SShawn McCarney }
245fa2734d6SShawn McCarney }
2469f3e54e6SShawn McCarney
2479f3e54e6SShawn McCarney // Clear error history
24883058606SShawn McCarney chassis.clearErrorHistory();
2499f3e54e6SShawn McCarney
250fa2734d6SShawn McCarney // Monitor sensors 10 more times. Verify errors logged again.
251fa2734d6SShawn McCarney {
252fa2734d6SShawn McCarney // Create mock services. Set expectations via lambda.
253fa2734d6SShawn McCarney MockServices services{};
254fa2734d6SShawn McCarney setExpectations(services);
255fa2734d6SShawn McCarney
256fa2734d6SShawn McCarney for (int i = 1; i <= 10; ++i)
2579f3e54e6SShawn McCarney {
25883058606SShawn McCarney chassis.monitorSensors(services, *system);
2599f3e54e6SShawn McCarney }
2609f3e54e6SShawn McCarney }
261fa2734d6SShawn McCarney }
2629f3e54e6SShawn McCarney
TEST_F(ChassisTests,CloseDevices)26383058606SShawn McCarney TEST_F(ChassisTests, CloseDevices)
264050531f5SShawn McCarney {
265050531f5SShawn McCarney // Test where no devices were specified in constructor
266050531f5SShawn McCarney {
267d692d6dfSBob King // Create mock services. Expect logDebug() to be called.
268d692d6dfSBob King MockServices services{};
269d692d6dfSBob King MockJournal& journal = services.getMockJournal();
270d692d6dfSBob King EXPECT_CALL(journal, logDebug("Closing devices in chassis 2")).Times(1);
271d692d6dfSBob King
272050531f5SShawn McCarney // Create Chassis
273cb3f6a63SShawn McCarney Chassis chassis{2, defaultInventoryPath};
274050531f5SShawn McCarney
275050531f5SShawn McCarney // Call closeDevices()
276d692d6dfSBob King chassis.closeDevices(services);
277050531f5SShawn McCarney }
278050531f5SShawn McCarney
279050531f5SShawn McCarney // Test where devices were specified in constructor
280050531f5SShawn McCarney {
281050531f5SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
282050531f5SShawn McCarney
283d692d6dfSBob King // Create mock services. Expect logDebug() to be called.
284d692d6dfSBob King MockServices services{};
285d692d6dfSBob King MockJournal& journal = services.getMockJournal();
286d692d6dfSBob King EXPECT_CALL(journal, logDebug("Closing devices in chassis 1")).Times(1);
287d692d6dfSBob King
288050531f5SShawn McCarney // Create Device vdd0_reg
289050531f5SShawn McCarney {
290050531f5SShawn McCarney // Create mock I2CInterface: isOpen() and close() should be called
29183058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
292050531f5SShawn McCarney EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
293050531f5SShawn McCarney EXPECT_CALL(*i2cInterface, close).Times(1);
294050531f5SShawn McCarney
295050531f5SShawn McCarney // Create Device
296*f5402197SPatrick Williams auto device = std::make_unique<Device>(
297*f5402197SPatrick Williams "vdd0_reg", true,
298a76898f1SBob King "/xyz/openbmc_project/inventory/"
299a76898f1SBob King "system/chassis/motherboard/vdd0_reg",
300050531f5SShawn McCarney std::move(i2cInterface));
301050531f5SShawn McCarney devices.emplace_back(std::move(device));
302050531f5SShawn McCarney }
303050531f5SShawn McCarney
304050531f5SShawn McCarney // Create Device vdd1_reg
305050531f5SShawn McCarney {
306050531f5SShawn McCarney // Create mock I2CInterface: isOpen() and close() should be called
30783058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
308050531f5SShawn McCarney EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
309050531f5SShawn McCarney EXPECT_CALL(*i2cInterface, close).Times(1);
310050531f5SShawn McCarney
311050531f5SShawn McCarney // Create Device
312*f5402197SPatrick Williams auto device = std::make_unique<Device>(
313*f5402197SPatrick Williams "vdd1_reg", true,
314a76898f1SBob King "/xyz/openbmc_project/inventory/"
315a76898f1SBob King "system/chassis/motherboard/vdd1_reg",
316050531f5SShawn McCarney std::move(i2cInterface));
317050531f5SShawn McCarney devices.emplace_back(std::move(device));
318050531f5SShawn McCarney }
319050531f5SShawn McCarney
320050531f5SShawn McCarney // Create Chassis
321cb3f6a63SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
322050531f5SShawn McCarney
323050531f5SShawn McCarney // Call closeDevices()
324d692d6dfSBob King chassis.closeDevices(services);
325050531f5SShawn McCarney }
326050531f5SShawn McCarney }
327050531f5SShawn McCarney
TEST_F(ChassisTests,Configure)32883058606SShawn McCarney TEST_F(ChassisTests, Configure)
329525e20c9SShawn McCarney {
330525e20c9SShawn McCarney // Test where no devices were specified in constructor
331525e20c9SShawn McCarney {
3325cfe5103SBob King // Create mock services. Expect logInfo() to be called.
33323243f84SBob King MockServices services{};
3345cfe5103SBob King MockJournal& journal = services.getMockJournal();
3355cfe5103SBob King EXPECT_CALL(journal, logInfo("Configuring chassis 1")).Times(1);
3365cfe5103SBob King EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
3375cfe5103SBob King EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
33823243f84SBob King
339525e20c9SShawn McCarney // Create Chassis
34083058606SShawn McCarney Chassis chassis{1, defaultInventoryPath};
341525e20c9SShawn McCarney
342525e20c9SShawn McCarney // Call configure()
34383058606SShawn McCarney chassis.configure(services, *system);
344525e20c9SShawn McCarney }
345525e20c9SShawn McCarney
346525e20c9SShawn McCarney // Test where devices were specified in constructor
347525e20c9SShawn McCarney {
348525e20c9SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
349525e20c9SShawn McCarney
3505cfe5103SBob King // Create mock services. Expect logInfo() and logDebug() to be called.
3515cfe5103SBob King MockServices services{};
3525cfe5103SBob King MockJournal& journal = services.getMockJournal();
3535cfe5103SBob King EXPECT_CALL(journal, logInfo("Configuring chassis 2")).Times(1);
3545cfe5103SBob King EXPECT_CALL(journal, logDebug("Configuring vdd0_reg: volts=1.300000"))
3555cfe5103SBob King .Times(1);
3565cfe5103SBob King EXPECT_CALL(journal, logDebug("Configuring vdd1_reg: volts=1.200000"))
3575cfe5103SBob King .Times(1);
3585cfe5103SBob King EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
3595cfe5103SBob King
360525e20c9SShawn McCarney // Create Device vdd0_reg
361525e20c9SShawn McCarney {
362525e20c9SShawn McCarney // Create Configuration
363525e20c9SShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
36483058606SShawn McCarney auto configuration =
365525e20c9SShawn McCarney std::make_unique<Configuration>(1.3, std::move(actions));
366525e20c9SShawn McCarney
367525e20c9SShawn McCarney // Create Device
36883058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
369525e20c9SShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
37083058606SShawn McCarney auto device = std::make_unique<Device>(
371a76898f1SBob King "vdd0_reg", true,
372a76898f1SBob King "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
373a76898f1SBob King "vdd0_reg",
374525e20c9SShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
375525e20c9SShawn McCarney std::move(configuration));
376525e20c9SShawn McCarney devices.emplace_back(std::move(device));
377525e20c9SShawn McCarney }
378525e20c9SShawn McCarney
379525e20c9SShawn McCarney // Create Device vdd1_reg
380525e20c9SShawn McCarney {
381525e20c9SShawn McCarney // Create Configuration
382525e20c9SShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
38383058606SShawn McCarney auto configuration =
384525e20c9SShawn McCarney std::make_unique<Configuration>(1.2, std::move(actions));
385525e20c9SShawn McCarney
386525e20c9SShawn McCarney // Create Device
38783058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
388525e20c9SShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
38983058606SShawn McCarney auto device = std::make_unique<Device>(
390a76898f1SBob King "vdd1_reg", true,
391a76898f1SBob King "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
392a76898f1SBob King "vdd1_reg",
393525e20c9SShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
394525e20c9SShawn McCarney std::move(configuration));
395525e20c9SShawn McCarney devices.emplace_back(std::move(device));
396525e20c9SShawn McCarney }
397525e20c9SShawn McCarney
398525e20c9SShawn McCarney // Create Chassis
39983058606SShawn McCarney Chassis chassis{2, defaultInventoryPath, std::move(devices)};
400525e20c9SShawn McCarney
401525e20c9SShawn McCarney // Call configure()
40283058606SShawn McCarney chassis.configure(services, *system);
403525e20c9SShawn McCarney }
404525e20c9SShawn McCarney }
405525e20c9SShawn McCarney
TEST_F(ChassisTests,DetectPhaseFaults)40650e57c6bSShawn McCarney TEST_F(ChassisTests, DetectPhaseFaults)
40750e57c6bSShawn McCarney {
40850e57c6bSShawn McCarney // Test where no devices were specified in constructor
40950e57c6bSShawn McCarney {
41050e57c6bSShawn McCarney // Create mock services. No errors should be logged.
41150e57c6bSShawn McCarney MockServices services{};
41250e57c6bSShawn McCarney MockJournal& journal = services.getMockJournal();
41350e57c6bSShawn McCarney EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
41450e57c6bSShawn McCarney MockErrorLogging& errorLogging = services.getMockErrorLogging();
41550e57c6bSShawn McCarney EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
41650e57c6bSShawn McCarney
41750e57c6bSShawn McCarney // Create Chassis
41850e57c6bSShawn McCarney Chassis chassis{1, defaultInventoryPath};
41950e57c6bSShawn McCarney
42050e57c6bSShawn McCarney // Call detectPhaseFaults() 5 times. Should do nothing.
42150e57c6bSShawn McCarney for (int i = 1; i <= 5; ++i)
42250e57c6bSShawn McCarney {
42350e57c6bSShawn McCarney chassis.detectPhaseFaults(services, *system);
42450e57c6bSShawn McCarney }
42550e57c6bSShawn McCarney }
42650e57c6bSShawn McCarney
42750e57c6bSShawn McCarney // Test where devices were specified in constructor
42850e57c6bSShawn McCarney {
42950e57c6bSShawn McCarney // Create mock services with the following expectations:
43050e57c6bSShawn McCarney // - 2 error messages in journal for N phase fault detected in reg0
43150e57c6bSShawn McCarney // - 2 error messages in journal for N phase fault detected in reg1
43250e57c6bSShawn McCarney // - 1 N phase fault error logged for reg0
43350e57c6bSShawn McCarney // - 1 N phase fault error logged for reg1
43450e57c6bSShawn McCarney MockServices services{};
43550e57c6bSShawn McCarney MockJournal& journal = services.getMockJournal();
43650e57c6bSShawn McCarney EXPECT_CALL(
43750e57c6bSShawn McCarney journal,
43850e57c6bSShawn McCarney logError("n phase fault detected in regulator reg0: count=1"))
43950e57c6bSShawn McCarney .Times(1);
44050e57c6bSShawn McCarney EXPECT_CALL(
44150e57c6bSShawn McCarney journal,
44250e57c6bSShawn McCarney logError("n phase fault detected in regulator reg0: count=2"))
44350e57c6bSShawn McCarney .Times(1);
44450e57c6bSShawn McCarney EXPECT_CALL(
44550e57c6bSShawn McCarney journal,
44650e57c6bSShawn McCarney logError("n phase fault detected in regulator reg1: count=1"))
44750e57c6bSShawn McCarney .Times(1);
44850e57c6bSShawn McCarney EXPECT_CALL(
44950e57c6bSShawn McCarney journal,
45050e57c6bSShawn McCarney logError("n phase fault detected in regulator reg1: count=2"))
45150e57c6bSShawn McCarney .Times(1);
45250e57c6bSShawn McCarney MockErrorLogging& errorLogging = services.getMockErrorLogging();
45350e57c6bSShawn McCarney EXPECT_CALL(errorLogging, logPhaseFault).Times(2);
45450e57c6bSShawn McCarney
45550e57c6bSShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
45650e57c6bSShawn McCarney
45750e57c6bSShawn McCarney // Create Device reg0
45850e57c6bSShawn McCarney {
45950e57c6bSShawn McCarney // Create PhaseFaultDetection
46050e57c6bSShawn McCarney auto action =
46150e57c6bSShawn McCarney std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
46250e57c6bSShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
46350e57c6bSShawn McCarney actions.push_back(std::move(action));
46450e57c6bSShawn McCarney auto phaseFaultDetection =
46550e57c6bSShawn McCarney std::make_unique<PhaseFaultDetection>(std::move(actions));
46650e57c6bSShawn McCarney
46750e57c6bSShawn McCarney // Create Device
46850e57c6bSShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
46950e57c6bSShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
47050e57c6bSShawn McCarney std::unique_ptr<Configuration> configuration{};
47150e57c6bSShawn McCarney auto device = std::make_unique<Device>(
47250e57c6bSShawn McCarney "reg0", true,
47350e57c6bSShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
47450e57c6bSShawn McCarney "reg0",
47550e57c6bSShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
47650e57c6bSShawn McCarney std::move(configuration), std::move(phaseFaultDetection));
47750e57c6bSShawn McCarney devices.emplace_back(std::move(device));
47850e57c6bSShawn McCarney }
47950e57c6bSShawn McCarney
48050e57c6bSShawn McCarney // Create Device reg1
48150e57c6bSShawn McCarney {
48250e57c6bSShawn McCarney // Create PhaseFaultDetection
48350e57c6bSShawn McCarney auto action =
48450e57c6bSShawn McCarney std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
48550e57c6bSShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
48650e57c6bSShawn McCarney actions.push_back(std::move(action));
48750e57c6bSShawn McCarney auto phaseFaultDetection =
48850e57c6bSShawn McCarney std::make_unique<PhaseFaultDetection>(std::move(actions));
48950e57c6bSShawn McCarney
49050e57c6bSShawn McCarney // Create Device
49150e57c6bSShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
49250e57c6bSShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
49350e57c6bSShawn McCarney std::unique_ptr<Configuration> configuration{};
49450e57c6bSShawn McCarney auto device = std::make_unique<Device>(
49550e57c6bSShawn McCarney "reg1", true,
49650e57c6bSShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
49750e57c6bSShawn McCarney "reg1",
49850e57c6bSShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
49950e57c6bSShawn McCarney std::move(configuration), std::move(phaseFaultDetection));
50050e57c6bSShawn McCarney devices.emplace_back(std::move(device));
50150e57c6bSShawn McCarney }
50250e57c6bSShawn McCarney
50350e57c6bSShawn McCarney // Create Chassis
50450e57c6bSShawn McCarney Chassis chassis{2, defaultInventoryPath, std::move(devices)};
50550e57c6bSShawn McCarney
50650e57c6bSShawn McCarney // Call detectPhaseFaults() 5 times
50750e57c6bSShawn McCarney for (int i = 1; i <= 5; ++i)
50850e57c6bSShawn McCarney {
50950e57c6bSShawn McCarney chassis.detectPhaseFaults(services, *system);
51050e57c6bSShawn McCarney }
51150e57c6bSShawn McCarney }
51250e57c6bSShawn McCarney }
51350e57c6bSShawn McCarney
TEST_F(ChassisTests,GetDevices)51483058606SShawn McCarney TEST_F(ChassisTests, GetDevices)
5158a3afd70SShawn McCarney {
5168a3afd70SShawn McCarney // Test where no devices were specified in constructor
5178a3afd70SShawn McCarney {
518cb3f6a63SShawn McCarney Chassis chassis{2, defaultInventoryPath};
5198a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices().size(), 0);
5208a3afd70SShawn McCarney }
5218a3afd70SShawn McCarney
5228a3afd70SShawn McCarney // Test where devices were specified in constructor
5238a3afd70SShawn McCarney {
5248a3afd70SShawn McCarney // Create vector of Device objects
5258a3afd70SShawn McCarney std::vector<std::unique_ptr<Device>> devices{};
526db0b833cSShawn McCarney devices.emplace_back(createDevice("vdd_reg1"));
527db0b833cSShawn McCarney devices.emplace_back(createDevice("vdd_reg2"));
5288a3afd70SShawn McCarney
5298a3afd70SShawn McCarney // Create Chassis
530cb3f6a63SShawn McCarney Chassis chassis{1, defaultInventoryPath, std::move(devices)};
5318a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices().size(), 2);
5328a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices()[0]->getID(), "vdd_reg1");
5338a3afd70SShawn McCarney EXPECT_EQ(chassis.getDevices()[1]->getID(), "vdd_reg2");
5348a3afd70SShawn McCarney }
5358a3afd70SShawn McCarney }
5368a3afd70SShawn McCarney
TEST_F(ChassisTests,GetInventoryPath)53783058606SShawn McCarney TEST_F(ChassisTests, GetInventoryPath)
538cb3f6a63SShawn McCarney {
539cb3f6a63SShawn McCarney Chassis chassis{3, defaultInventoryPath};
540cb3f6a63SShawn McCarney EXPECT_EQ(chassis.getInventoryPath(), defaultInventoryPath);
541cb3f6a63SShawn McCarney }
542cb3f6a63SShawn McCarney
TEST_F(ChassisTests,GetNumber)54383058606SShawn McCarney TEST_F(ChassisTests, GetNumber)
5448a3afd70SShawn McCarney {
545cb3f6a63SShawn McCarney Chassis chassis{3, defaultInventoryPath};
5468a3afd70SShawn McCarney EXPECT_EQ(chassis.getNumber(), 3);
5478a3afd70SShawn McCarney }
548a2c81a61SBob King
TEST_F(ChassisTests,MonitorSensors)54983058606SShawn McCarney TEST_F(ChassisTests, MonitorSensors)
550a2c81a61SBob King {
551a2c81a61SBob King // Test where no devices were specified in constructor
552a2c81a61SBob King {
55317bac89eSShawn McCarney // Create mock services. No Sensors methods should be called.
5548a55292dSBob King MockServices services{};
55517bac89eSShawn McCarney MockSensors& sensors = services.getMockSensors();
55617bac89eSShawn McCarney EXPECT_CALL(sensors, startRail).Times(0);
55717bac89eSShawn McCarney EXPECT_CALL(sensors, setValue).Times(0);
55817bac89eSShawn McCarney EXPECT_CALL(sensors, endRail).Times(0);
5598a55292dSBob King
560a2c81a61SBob King // Create Chassis
56183058606SShawn McCarney Chassis chassis{1, defaultInventoryPath};
562a2c81a61SBob King
563a2c81a61SBob King // Call monitorSensors(). Should do nothing.
56483058606SShawn McCarney chassis.monitorSensors(services, *system);
565a2c81a61SBob King }
566a2c81a61SBob King
567a2c81a61SBob King // Test where devices were specified in constructor
568a2c81a61SBob King {
56917bac89eSShawn McCarney // Create mock services. Set Sensors service expectations.
5708a55292dSBob King MockServices services{};
57117bac89eSShawn McCarney MockSensors& sensors = services.getMockSensors();
57217bac89eSShawn McCarney EXPECT_CALL(sensors, startRail("vdd0",
57317bac89eSShawn McCarney "/xyz/openbmc_project/inventory/system/"
57417bac89eSShawn McCarney "chassis/motherboard/vdd0_reg",
57517bac89eSShawn McCarney defaultInventoryPath))
57617bac89eSShawn McCarney .Times(1);
57717bac89eSShawn McCarney EXPECT_CALL(sensors, startRail("vdd1",
57817bac89eSShawn McCarney "/xyz/openbmc_project/inventory/system/"
57917bac89eSShawn McCarney "chassis/motherboard/vdd1_reg",
58017bac89eSShawn McCarney defaultInventoryPath))
58117bac89eSShawn McCarney .Times(1);
58217bac89eSShawn McCarney EXPECT_CALL(sensors, setValue).Times(0);
58317bac89eSShawn McCarney EXPECT_CALL(sensors, endRail(false)).Times(2);
5848a55292dSBob King
585a2c81a61SBob King std::vector<std::unique_ptr<Device>> devices{};
586a2c81a61SBob King
58717bac89eSShawn McCarney // Create Device vdd0_reg
58817bac89eSShawn McCarney {
58917bac89eSShawn McCarney // Create SensorMonitoring for Rail
59083058606SShawn McCarney auto action = std::make_unique<MockAction>();
59117bac89eSShawn McCarney EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
592a2c81a61SBob King std::vector<std::unique_ptr<Action>> actions{};
593a2c81a61SBob King actions.emplace_back(std::move(action));
59483058606SShawn McCarney auto sensorMonitoring =
595a2c81a61SBob King std::make_unique<SensorMonitoring>(std::move(actions));
596a2c81a61SBob King
597a2c81a61SBob King // Create Rail
598a2c81a61SBob King std::unique_ptr<Configuration> configuration{};
59983058606SShawn McCarney auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
60083058606SShawn McCarney std::move(sensorMonitoring));
601a2c81a61SBob King
602a2c81a61SBob King // Create Device
60383058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
604a2c81a61SBob King std::unique_ptr<PresenceDetection> presenceDetection{};
605a2c81a61SBob King std::unique_ptr<Configuration> deviceConfiguration{};
60632252599SShawn McCarney std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
60717bac89eSShawn McCarney std::vector<std::unique_ptr<Rail>> rails{};
60817bac89eSShawn McCarney rails.emplace_back(std::move(rail));
60983058606SShawn McCarney auto device = std::make_unique<Device>(
61017bac89eSShawn McCarney "vdd0_reg", true,
61117bac89eSShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
61217bac89eSShawn McCarney "vdd0_reg",
613a2c81a61SBob King std::move(i2cInterface), std::move(presenceDetection),
61432252599SShawn McCarney std::move(deviceConfiguration), std::move(phaseFaultDetection),
61532252599SShawn McCarney std::move(rails));
616a2c81a61SBob King devices.emplace_back(std::move(device));
61717bac89eSShawn McCarney }
61817bac89eSShawn McCarney
61917bac89eSShawn McCarney // Create Device vdd1_reg
62017bac89eSShawn McCarney {
62117bac89eSShawn McCarney // Create SensorMonitoring for Rail
62283058606SShawn McCarney auto action = std::make_unique<MockAction>();
62317bac89eSShawn McCarney EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
62417bac89eSShawn McCarney std::vector<std::unique_ptr<Action>> actions{};
62517bac89eSShawn McCarney actions.emplace_back(std::move(action));
62683058606SShawn McCarney auto sensorMonitoring =
62717bac89eSShawn McCarney std::make_unique<SensorMonitoring>(std::move(actions));
62817bac89eSShawn McCarney
62917bac89eSShawn McCarney // Create Rail
63017bac89eSShawn McCarney std::unique_ptr<Configuration> configuration{};
63183058606SShawn McCarney auto rail = std::make_unique<Rail>("vdd1", std::move(configuration),
63283058606SShawn McCarney std::move(sensorMonitoring));
63317bac89eSShawn McCarney
63417bac89eSShawn McCarney // Create Device
63583058606SShawn McCarney auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
63617bac89eSShawn McCarney std::unique_ptr<PresenceDetection> presenceDetection{};
63717bac89eSShawn McCarney std::unique_ptr<Configuration> deviceConfiguration{};
63832252599SShawn McCarney std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
63917bac89eSShawn McCarney std::vector<std::unique_ptr<Rail>> rails{};
64017bac89eSShawn McCarney rails.emplace_back(std::move(rail));
64183058606SShawn McCarney auto device = std::make_unique<Device>(
64217bac89eSShawn McCarney "vdd1_reg", true,
64317bac89eSShawn McCarney "/xyz/openbmc_project/inventory/system/chassis/motherboard/"
64417bac89eSShawn McCarney "vdd1_reg",
64517bac89eSShawn McCarney std::move(i2cInterface), std::move(presenceDetection),
64632252599SShawn McCarney std::move(deviceConfiguration), std::move(phaseFaultDetection),
64732252599SShawn McCarney std::move(rails));
64817bac89eSShawn McCarney devices.emplace_back(std::move(device));
64917bac89eSShawn McCarney }
65017bac89eSShawn McCarney
65117bac89eSShawn McCarney // Create Chassis that contains Devices
65283058606SShawn McCarney Chassis chassis{2, defaultInventoryPath, std::move(devices)};
653a2c81a61SBob King
654a2c81a61SBob King // Call monitorSensors()
65583058606SShawn McCarney chassis.monitorSensors(services, *system);
656a2c81a61SBob King }
657a2c81a61SBob King }
658