blob: 5a7e8533f286d767030225adaecdcebdf1423cfb [file] [log] [blame]
Shawn McCarneya2461b32019-10-24 18:53:01 -05001/**
2 * Copyright © 2019 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050016#include "action.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050017#include "chassis.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050018#include "configuration.hpp"
Shawn McCarneya2461b32019-10-24 18:53:01 -050019#include "device.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060020#include "i2c_interface.hpp"
Shawn McCarneydb0b8332020-04-06 14:13:04 -050021#include "id_map.hpp"
Shawn McCarney1fd0b142021-09-09 10:04:22 -050022#include "log_phase_fault_action.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050023#include "mock_action.hpp"
Shawn McCarney81a2f902021-03-23 21:41:34 -050024#include "mock_error_logging.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050025#include "mock_journal.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050026#include "mock_sensors.hpp"
Bob King23243f82020-07-29 10:38:57 +080027#include "mock_services.hpp"
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050028#include "mocked_i2c_interface.hpp"
Shawn McCarney1fd0b142021-09-09 10:04:22 -050029#include "phase_fault.hpp"
Shawn McCarney32252592021-09-08 15:29:36 -050030#include "phase_fault_detection.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050031#include "presence_detection.hpp"
32#include "rail.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050033#include "rule.hpp"
Shawn McCarney17bac892021-05-08 07:55:52 -050034#include "sensor_monitoring.hpp"
Shawn McCarney2f9e14f2021-04-29 02:45:18 -050035#include "sensors.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050036#include "system.hpp"
Shawn McCarney371e2442021-05-14 14:18:07 -050037#include "test_sdbus_error.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050038#include "test_utils.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060039
40#include <memory>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050041#include <optional>
Shawn McCarney525e20c2020-04-14 11:05:39 -050042#include <string>
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060043#include <utility>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050044#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050045
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050046#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050047#include <gtest/gtest.h>
48
49using namespace phosphor::power::regulators;
Shawn McCarney8a3afd72020-03-12 14:28:44 -050050using namespace phosphor::power::regulators::test_utils;
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060051
Bob King8e1cd0b2020-07-08 13:30:27 +080052using ::testing::A;
Shawn McCarney81a2f902021-03-23 21:41:34 -050053using ::testing::Ref;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050054using ::testing::Return;
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050055using ::testing::Throw;
Bob King8e1cd0b2020-07-08 13:30:27 +080056using ::testing::TypedEq;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050057
Shawn McCarney2874e902021-09-09 10:03:59 -050058class DeviceTests : public ::testing::Test
59{
60 public:
61 /**
62 * Constructor.
63 *
64 * Creates the Chassis and System objects needed for calling some Device
65 * methods.
66 */
67 DeviceTests() : ::testing::Test{}
68 {
69 // Create Chassis
70 auto chassis = std::make_unique<Chassis>(1, chassisInvPath);
71 this->chassis = chassis.get();
Shawn McCarneycb3f6a62021-04-30 10:54:30 -050072
Shawn McCarney2874e902021-09-09 10:03:59 -050073 // Create System
74 std::vector<std::unique_ptr<Rule>> rules{};
75 std::vector<std::unique_ptr<Chassis>> chassisVec{};
76 chassisVec.emplace_back(std::move(chassis));
77 this->system =
78 std::make_unique<System>(std::move(rules), std::move(chassisVec));
79 }
80
81 protected:
82 const std::string deviceInvPath{
83 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"};
84 const std::string chassisInvPath{
85 "/xyz/openbmc_project/inventory/system/chassis"};
86
87 // Note: This pointer does NOT need to be explicitly deleted. The Chassis
88 // object is owned by the System object and will be automatically deleted.
89 Chassis* chassis{nullptr};
90
91 std::unique_ptr<System> system{};
92};
93
94TEST_F(DeviceTests, Constructor)
Shawn McCarneya2461b32019-10-24 18:53:01 -050095{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050096 // Test where only required parameters are specified
97 {
98 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
99 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Shawn McCarney2874e902021-09-09 10:03:59 -0500100 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500101 EXPECT_EQ(device.getID(), "vdd_reg");
102 EXPECT_EQ(device.isRegulator(), true);
Shawn McCarney2874e902021-09-09 10:03:59 -0500103 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500104 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
105 EXPECT_EQ(device.getPresenceDetection(), nullptr);
106 EXPECT_EQ(device.getConfiguration(), nullptr);
Shawn McCarney32252592021-09-08 15:29:36 -0500107 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500108 EXPECT_EQ(device.getRails().size(), 0);
109 }
110
111 // Test where all parameters are specified
112 {
113 // Create I2CInterface
114 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
115 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
116
117 // Create PresenceDetection
118 std::vector<std::unique_ptr<Action>> actions{};
119 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500120 auto presenceDetection =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500121 std::make_unique<PresenceDetection>(std::move(actions));
122
123 // Create Configuration
124 std::optional<double> volts{};
125 actions.clear();
126 actions.push_back(std::make_unique<MockAction>());
127 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500128 auto configuration =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500129 std::make_unique<Configuration>(volts, std::move(actions));
130
Shawn McCarney32252592021-09-08 15:29:36 -0500131 // Create PhaseFaultDetection
132 actions.clear();
133 actions.push_back(std::make_unique<MockAction>());
134 actions.push_back(std::make_unique<MockAction>());
135 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500136 auto phaseFaultDetection =
Shawn McCarney32252592021-09-08 15:29:36 -0500137 std::make_unique<PhaseFaultDetection>(std::move(actions));
138
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500139 // Create vector of Rail objects
140 std::vector<std::unique_ptr<Rail>> rails{};
141 rails.push_back(std::make_unique<Rail>("vdd0"));
142 rails.push_back(std::make_unique<Rail>("vdd1"));
143
144 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500145 Device device{"vdd_reg",
146 false,
147 deviceInvPath,
148 std::move(i2cInterface),
149 std::move(presenceDetection),
150 std::move(configuration),
151 std::move(phaseFaultDetection),
152 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500153 EXPECT_EQ(device.getID(), "vdd_reg");
154 EXPECT_EQ(device.isRegulator(), false);
Shawn McCarney2874e902021-09-09 10:03:59 -0500155 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500156 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
157 EXPECT_NE(device.getPresenceDetection(), nullptr);
158 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
159 EXPECT_NE(device.getConfiguration(), nullptr);
160 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
161 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
Shawn McCarney32252592021-09-08 15:29:36 -0500162 EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
163 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 3);
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500164 EXPECT_EQ(device.getRails().size(), 2);
165 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500166}
167
Shawn McCarney2874e902021-09-09 10:03:59 -0500168TEST_F(DeviceTests, AddToIDMap)
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500169{
170 std::unique_ptr<PresenceDetection> presenceDetection{};
171 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500172 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500173
174 // Create vector of Rail objects
175 std::vector<std::unique_ptr<Rail>> rails{};
176 rails.push_back(std::make_unique<Rail>("vdd0"));
177 rails.push_back(std::make_unique<Rail>("vdd1"));
178
179 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500180 Device device{"vdd_reg",
181 false,
182 deviceInvPath,
183 std::move(createI2CInterface()),
184 std::move(presenceDetection),
185 std::move(configuration),
186 std::move(phaseFaultDetection),
187 std::move(rails)};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500188
189 // Add Device and Rail objects to an IDMap
190 IDMap idMap{};
191 device.addToIDMap(idMap);
192
193 // Verify Device is in the IDMap
194 EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
195 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
196
197 // Verify all Rails are in the IDMap
198 EXPECT_NO_THROW(idMap.getRail("vdd0"));
199 EXPECT_NO_THROW(idMap.getRail("vdd1"));
200 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
201}
202
Shawn McCarney2874e902021-09-09 10:03:59 -0500203TEST_F(DeviceTests, ClearCache)
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600204{
205 // Test where Device does not contain a PresenceDetection object
206 try
207 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500208 Device device{"vdd_reg", false, deviceInvPath,
209 std::move(createI2CInterface())};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600210 device.clearCache();
211 }
212 catch (...)
213 {
214 ADD_FAILURE() << "Should not have caught exception.";
215 }
216
217 // Test where Device contains a PresenceDetection object
218 {
219 // Create PresenceDetection
220 std::vector<std::unique_ptr<Action>> actions{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500221 auto presenceDetection =
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600222 std::make_unique<PresenceDetection>(std::move(actions));
223 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
224
225 // Create Device
226 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500227 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
228 std::move(presenceDetection)};
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600229
230 // Cache presence value in PresenceDetection
231 MockServices services{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500232 presenceDetectionPtr->execute(services, *system, *chassis, device);
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600233 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
234
235 // Clear cached data in Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500236 device.clearCache();
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600237
238 // Verify presence value no longer cached in PresenceDetection
239 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
240 }
241}
242
Shawn McCarney2874e902021-09-09 10:03:59 -0500243TEST_F(DeviceTests, ClearErrorHistory)
Shawn McCarney371e2442021-05-14 14:18:07 -0500244{
245 // Create SensorMonitoring. Will fail with a DBus exception.
Shawn McCarney2874e902021-09-09 10:03:59 -0500246 auto action = std::make_unique<MockAction>();
Shawn McCarney371e2442021-05-14 14:18:07 -0500247 EXPECT_CALL(*action, execute)
248 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"}));
249 std::vector<std::unique_ptr<Action>> actions{};
250 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500251 auto sensorMonitoring =
Shawn McCarney371e2442021-05-14 14:18:07 -0500252 std::make_unique<SensorMonitoring>(std::move(actions));
253
254 // Create Rail
255 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500256 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
257 std::move(sensorMonitoring));
Shawn McCarney371e2442021-05-14 14:18:07 -0500258
259 // Create Device that contains Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500260 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarney371e2442021-05-14 14:18:07 -0500261 std::unique_ptr<PresenceDetection> presenceDetection{};
262 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500263 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney371e2442021-05-14 14:18:07 -0500264 std::vector<std::unique_ptr<Rail>> rails{};
265 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500266 Device device{"reg2",
267 true,
268 deviceInvPath,
269 std::move(i2cInterface),
270 std::move(presenceDetection),
271 std::move(deviceConfiguration),
272 std::move(phaseFaultDetection),
273 std::move(rails)};
Shawn McCarney371e2442021-05-14 14:18:07 -0500274
275 // Create mock services
276 MockServices services{};
277
278 // Expect Sensors service to be called 5+5=10 times
279 MockSensors& sensors = services.getMockSensors();
280 EXPECT_CALL(sensors, startRail).Times(10);
281 EXPECT_CALL(sensors, setValue).Times(0);
282 EXPECT_CALL(sensors, endRail).Times(10);
283
284 // Expect Journal service to be called 3+3=6 times to log error messages
285 MockJournal& journal = services.getMockJournal();
286 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
287 .Times(6);
288 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6);
289
290 // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error
291 MockErrorLogging& errorLogging = services.getMockErrorLogging();
292 EXPECT_CALL(errorLogging, logDBusError).Times(2);
293
294 // Monitor sensors 5 times. Should fail every time, write to journal 3
295 // times, and log one error.
296 for (int i = 1; i <= 5; ++i)
297 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500298 device.monitorSensors(services, *system, *chassis);
Shawn McCarney371e2442021-05-14 14:18:07 -0500299 }
300
301 // Clear error history
Shawn McCarney2874e902021-09-09 10:03:59 -0500302 device.clearErrorHistory();
Shawn McCarney371e2442021-05-14 14:18:07 -0500303
304 // Monitor sensors 5 times again. Should fail every time, write to journal
305 // 3 times, and log one error.
306 for (int i = 1; i <= 5; ++i)
307 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500308 device.monitorSensors(services, *system, *chassis);
Shawn McCarney371e2442021-05-14 14:18:07 -0500309 }
310}
311
Shawn McCarney2874e902021-09-09 10:03:59 -0500312TEST_F(DeviceTests, Close)
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500313{
314 // Test where works: I2C interface is not open
315 {
316 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500317 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500318 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
319 EXPECT_CALL(*i2cInterface, close).Times(0);
320
Bob Kingd692d6d2020-09-14 13:42:57 +0800321 // Create mock services. No logError should occur.
322 MockServices services{};
323 MockJournal& journal = services.getMockJournal();
324 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
325 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
326 .Times(0);
327
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500328 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500329 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500330
331 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800332 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500333 }
334
335 // Test where works: I2C interface is open
336 {
337 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500338 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500339 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
340 EXPECT_CALL(*i2cInterface, close).Times(1);
341
Bob Kingd692d6d2020-09-14 13:42:57 +0800342 // Create mock services. No logError should occur.
343 MockServices services{};
344 MockJournal& journal = services.getMockJournal();
345 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
346 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
347 .Times(0);
348
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500349 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500350 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500351
352 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800353 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500354 }
355
356 // Test where fails: closing I2C interface fails
357 {
358 // Create mock I2CInterface
Shawn McCarney2874e902021-09-09 10:03:59 -0500359 auto i2cInterface = std::make_unique<i2c::MockedI2CInterface>();
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500360 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
361 EXPECT_CALL(*i2cInterface, close)
362 .Times(1)
363 .WillOnce(Throw(
364 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
365
Shawn McCarney81a2f902021-03-23 21:41:34 -0500366 // Create mock services. Expect logError() and logI2CError() to be
367 // called.
Bob Kingd692d6d2020-09-14 13:42:57 +0800368 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500369 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob Kingd692d6d2020-09-14 13:42:57 +0800370 MockJournal& journal = services.getMockJournal();
371 std::vector<std::string> expectedErrMessagesException{
372 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
373 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
374 .Times(1);
375 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500376 EXPECT_CALL(errorLogging,
377 logI2CError(Entry::Level::Notice, Ref(journal),
378 "/dev/i2c-1", 0x70, 0))
379 .Times(1);
Bob Kingd692d6d2020-09-14 13:42:57 +0800380
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500381 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500382 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500383
384 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800385 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500386 }
387}
388
Shawn McCarney2874e902021-09-09 10:03:59 -0500389TEST_F(DeviceTests, Configure)
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500390{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600391 // Test where device is not present
392 {
393 // Create mock services. No logging should occur.
394 MockServices services{};
395 MockJournal& journal = services.getMockJournal();
396 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
397 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
398
399 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500400 std::unique_ptr<PresenceDetection> presenceDetection{};
401 {
402 auto action = std::make_unique<MockAction>();
403 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
404 std::vector<std::unique_ptr<Action>> actions{};
405 actions.emplace_back(std::move(action));
406 presenceDetection =
407 std::make_unique<PresenceDetection>(std::move(actions));
408 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600409
410 // Create Configuration. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500411 std::unique_ptr<Configuration> configuration{};
412 {
413 std::optional<double> volts{};
414 auto action = std::make_unique<MockAction>();
415 EXPECT_CALL(*action, execute).Times(0);
416 std::vector<std::unique_ptr<Action>> actions{};
417 actions.emplace_back(std::move(action));
418 configuration =
419 std::make_unique<Configuration>(volts, std::move(actions));
420 }
Shawn McCarney48033bf2021-01-27 17:56:49 -0600421
422 // Create Device
423 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500424 Device device{"reg2",
425 true,
426 deviceInvPath,
427 std::move(i2cInterface),
428 std::move(presenceDetection),
429 std::move(configuration)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600430
431 // Call configure(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500432 device.configure(services, *system, *chassis);
Shawn McCarney48033bf2021-01-27 17:56:49 -0600433 }
434
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500435 // Test where Configuration and Rails were not specified in constructor
436 {
Bob King5cfe5102020-07-30 16:26:18 +0800437 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800438 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800439 MockJournal& journal = services.getMockJournal();
440 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
441 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800442
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500443 // Create Device
444 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500445 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500446
Bob King5cfe5102020-07-30 16:26:18 +0800447 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500448 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500449 }
450
451 // Test where Configuration and Rails were specified in constructor
452 {
453 std::vector<std::unique_ptr<Rail>> rails{};
454
Bob King5cfe5102020-07-30 16:26:18 +0800455 // Create mock services. Expect logDebug() to be called.
456 // For the Device and both Rails, should execute the Configuration
457 // and log a debug message.
458 MockServices services{};
459 MockJournal& journal = services.getMockJournal();
Shawn McCarney2874e902021-09-09 10:03:59 -0500460 EXPECT_CALL(journal, logDebug("Configuring reg2")).Times(1);
Bob King5cfe5102020-07-30 16:26:18 +0800461 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
462 .Times(1);
463 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
464 .Times(1);
465 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
466
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500467 // Create Rail vdd0
468 {
469 // Create Configuration for Rail
470 std::optional<double> volts{1.3};
Shawn McCarney2874e902021-09-09 10:03:59 -0500471 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500472 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
473 std::vector<std::unique_ptr<Action>> actions{};
474 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500475 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500476 std::make_unique<Configuration>(volts, std::move(actions));
477
478 // Create Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500479 auto rail =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500480 std::make_unique<Rail>("vdd0", std::move(configuration));
481 rails.emplace_back(std::move(rail));
482 }
483
484 // Create Rail vio0
485 {
486 // Create Configuration for Rail
487 std::optional<double> volts{3.2};
Shawn McCarney2874e902021-09-09 10:03:59 -0500488 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500489 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
490 std::vector<std::unique_ptr<Action>> actions{};
491 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500492 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500493 std::make_unique<Configuration>(volts, std::move(actions));
494
495 // Create Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500496 auto rail =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500497 std::make_unique<Rail>("vio0", std::move(configuration));
498 rails.emplace_back(std::move(rail));
499 }
500
501 // Create Configuration for Device
502 std::optional<double> volts{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500503 auto action = std::make_unique<MockAction>();
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500504 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
505 std::vector<std::unique_ptr<Action>> actions{};
506 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500507 auto configuration =
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500508 std::make_unique<Configuration>(volts, std::move(actions));
509
510 // Create Device
511 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
512 std::unique_ptr<PresenceDetection> presenceDetection{};
Shawn McCarney32252592021-09-08 15:29:36 -0500513 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500514 Device device{"reg2",
515 true,
516 deviceInvPath,
517 std::move(i2cInterface),
518 std::move(presenceDetection),
519 std::move(configuration),
520 std::move(phaseFaultDetection),
521 std::move(rails)};
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500522
Bob King5cfe5102020-07-30 16:26:18 +0800523 // Call configure().
Shawn McCarney2874e902021-09-09 10:03:59 -0500524 device.configure(services, *system, *chassis);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500525 }
526}
527
Shawn McCarney1fd0b142021-09-09 10:04:22 -0500528TEST_F(DeviceTests, DetectPhaseFaults)
529{
530 // Test where device is not present
531 {
532 // Create mock services. No errors should be logged.
533 MockServices services{};
534 MockJournal& journal = services.getMockJournal();
535 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
536 MockErrorLogging& errorLogging = services.getMockErrorLogging();
537 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
538
539 // Create PresenceDetection. Indicates device is not present.
540 std::unique_ptr<PresenceDetection> presenceDetection{};
541 {
542 auto action = std::make_unique<MockAction>();
543 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
544 std::vector<std::unique_ptr<Action>> actions{};
545 actions.emplace_back(std::move(action));
546 presenceDetection =
547 std::make_unique<PresenceDetection>(std::move(actions));
548 }
549
550 // Create PhaseFaultDetection. Action inside it should not be executed.
551 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
552 {
553 auto action = std::make_unique<MockAction>();
554 EXPECT_CALL(*action, execute).Times(0);
555 std::vector<std::unique_ptr<Action>> actions{};
556 actions.emplace_back(std::move(action));
557 phaseFaultDetection =
558 std::make_unique<PhaseFaultDetection>(std::move(actions));
559 }
560
561 // Create Device
562 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
563 std::unique_ptr<Configuration> configuration{};
564 Device device{"reg2",
565 true,
566 deviceInvPath,
567 std::move(i2cInterface),
568 std::move(presenceDetection),
569 std::move(configuration),
570 std::move(phaseFaultDetection)};
571
572 // Call detectPhaseFaults() 5 times. Should do nothing.
573 for (int i = 1; i <= 5; ++i)
574 {
575 device.detectPhaseFaults(services, *system, *chassis);
576 }
577 }
578
579 // Test where PhaseFaultDetection was not specified in constructor
580 {
581 // Create mock services. No errors should be logged.
582 MockServices services{};
583 MockJournal& journal = services.getMockJournal();
584 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
585 MockErrorLogging& errorLogging = services.getMockErrorLogging();
586 EXPECT_CALL(errorLogging, logPhaseFault).Times(0);
587
588 // Create Device
589 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
590 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
591
592 // Call detectPhaseFaults() 5 times. Should do nothing.
593 for (int i = 1; i <= 5; ++i)
594 {
595 device.detectPhaseFaults(services, *system, *chassis);
596 }
597 }
598
599 // Test where PhaseFaultDetection was specified in constructor
600 {
601 // Create mock services with the following expectations:
602 // - 2 error messages in journal for N phase fault detected
603 // - 1 N phase fault error logged
604 MockServices services{};
605 MockJournal& journal = services.getMockJournal();
606 EXPECT_CALL(
607 journal,
608 logError("n phase fault detected in regulator reg2: count=1"))
609 .Times(1);
610 EXPECT_CALL(
611 journal,
612 logError("n phase fault detected in regulator reg2: count=2"))
613 .Times(1);
614 MockErrorLogging& errorLogging = services.getMockErrorLogging();
615 EXPECT_CALL(errorLogging, logPhaseFault).Times(1);
616
617 // Create PhaseFaultDetection
618 auto action = std::make_unique<LogPhaseFaultAction>(PhaseFaultType::n);
619 std::vector<std::unique_ptr<Action>> actions{};
620 actions.push_back(std::move(action));
621 auto phaseFaultDetection =
622 std::make_unique<PhaseFaultDetection>(std::move(actions));
623
624 // Create Device
625 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
626 std::unique_ptr<PresenceDetection> presenceDetection{};
627 std::unique_ptr<Configuration> configuration{};
628 Device device{"reg2",
629 true,
630 deviceInvPath,
631 std::move(i2cInterface),
632 std::move(presenceDetection),
633 std::move(configuration),
634 std::move(phaseFaultDetection)};
635
636 // Call detectPhaseFaults() 5 times
637 for (int i = 1; i <= 5; ++i)
638 {
639 device.detectPhaseFaults(services, *system, *chassis);
640 }
641 }
642}
643
Shawn McCarney2874e902021-09-09 10:03:59 -0500644TEST_F(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500645{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500646 // Test where Configuration was not specified in constructor
647 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500648 Device device{"vdd_reg", true, deviceInvPath,
649 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500650 EXPECT_EQ(device.getConfiguration(), nullptr);
651 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600652
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500653 // Test where Configuration was specified in constructor
654 {
655 std::unique_ptr<PresenceDetection> presenceDetection{};
656
657 // Create Configuration
658 std::optional<double> volts{3.2};
659 std::vector<std::unique_ptr<Action>> actions{};
660 actions.push_back(std::make_unique<MockAction>());
661 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500662 auto configuration =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500663 std::make_unique<Configuration>(volts, std::move(actions));
664
665 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500666 Device device{"vdd_reg",
667 true,
668 deviceInvPath,
669 std::move(createI2CInterface()),
670 std::move(presenceDetection),
671 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500672 EXPECT_NE(device.getConfiguration(), nullptr);
673 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
674 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
675 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
676 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600677}
678
Shawn McCarney2874e902021-09-09 10:03:59 -0500679TEST_F(DeviceTests, GetFRU)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600680{
Shawn McCarney2874e902021-09-09 10:03:59 -0500681 Device device{"vdd_reg", true, deviceInvPath,
682 std::move(createI2CInterface())};
683 EXPECT_EQ(device.getFRU(), deviceInvPath);
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600684}
685
Shawn McCarney2874e902021-09-09 10:03:59 -0500686TEST_F(DeviceTests, GetI2CInterface)
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600687{
688 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
689 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Shawn McCarney2874e902021-09-09 10:03:59 -0500690 Device device{"vdd_reg", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600691 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500692}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500693
Shawn McCarney2874e902021-09-09 10:03:59 -0500694TEST_F(DeviceTests, GetID)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500695{
Shawn McCarney2874e902021-09-09 10:03:59 -0500696 Device device{"vdd_reg", false, deviceInvPath,
697 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500698 EXPECT_EQ(device.getID(), "vdd_reg");
699}
700
Shawn McCarney2874e902021-09-09 10:03:59 -0500701TEST_F(DeviceTests, GetPhaseFaultDetection)
Shawn McCarney32252592021-09-08 15:29:36 -0500702{
703 // Test where PhaseFaultDetection was not specified in constructor
704 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500705 Device device{"vdd_reg", true, deviceInvPath,
706 std::move(createI2CInterface())};
Shawn McCarney32252592021-09-08 15:29:36 -0500707 EXPECT_EQ(device.getPhaseFaultDetection(), nullptr);
708 }
709
710 // Test where PhaseFaultDetection was specified in constructor
711 {
712 // Create PhaseFaultDetection
713 std::vector<std::unique_ptr<Action>> actions{};
714 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500715 auto phaseFaultDetection =
Shawn McCarney32252592021-09-08 15:29:36 -0500716 std::make_unique<PhaseFaultDetection>(std::move(actions));
717
718 // Create Device
719 std::unique_ptr<PresenceDetection> presenceDetection{};
720 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500721 Device device{"vdd_reg",
722 false,
723 deviceInvPath,
724 std::move(createI2CInterface()),
725 std::move(presenceDetection),
726 std::move(configuration),
727 std::move(phaseFaultDetection)};
Shawn McCarney32252592021-09-08 15:29:36 -0500728 EXPECT_NE(device.getPhaseFaultDetection(), nullptr);
729 EXPECT_EQ(device.getPhaseFaultDetection()->getActions().size(), 1);
730 }
731}
732
Shawn McCarney2874e902021-09-09 10:03:59 -0500733TEST_F(DeviceTests, GetPresenceDetection)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500734{
735 // Test where PresenceDetection was not specified in constructor
736 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500737 Device device{"vdd_reg", true, deviceInvPath,
738 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500739 EXPECT_EQ(device.getPresenceDetection(), nullptr);
740 }
741
742 // Test where PresenceDetection was specified in constructor
743 {
744 // Create PresenceDetection
745 std::vector<std::unique_ptr<Action>> actions{};
746 actions.push_back(std::make_unique<MockAction>());
Shawn McCarney2874e902021-09-09 10:03:59 -0500747 auto presenceDetection =
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500748 std::make_unique<PresenceDetection>(std::move(actions));
749
750 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500751 Device device{"vdd_reg", false, deviceInvPath,
752 std::move(createI2CInterface()),
753 std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500754 EXPECT_NE(device.getPresenceDetection(), nullptr);
755 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
756 }
757}
758
Shawn McCarney2874e902021-09-09 10:03:59 -0500759TEST_F(DeviceTests, GetRails)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500760{
761 // Test where no rails were specified in constructor
762 {
Shawn McCarney2874e902021-09-09 10:03:59 -0500763 Device device{"vdd_reg", true, deviceInvPath,
764 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500765 EXPECT_EQ(device.getRails().size(), 0);
766 }
767
768 // Test where rails were specified in constructor
769 {
770 std::unique_ptr<PresenceDetection> presenceDetection{};
771 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500772 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500773
774 // Create vector of Rail objects
775 std::vector<std::unique_ptr<Rail>> rails{};
776 rails.push_back(std::make_unique<Rail>("vdd0"));
777 rails.push_back(std::make_unique<Rail>("vdd1"));
778
779 // Create Device
Shawn McCarney2874e902021-09-09 10:03:59 -0500780 Device device{"vdd_reg",
781 false,
782 deviceInvPath,
783 std::move(createI2CInterface()),
784 std::move(presenceDetection),
785 std::move(configuration),
786 std::move(phaseFaultDetection),
787 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500788 EXPECT_EQ(device.getRails().size(), 2);
789 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
790 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
791 }
792}
793
Shawn McCarney2874e902021-09-09 10:03:59 -0500794TEST_F(DeviceTests, IsPresent)
Shawn McCarney48033bf2021-01-27 17:56:49 -0600795{
796 // Test where PresenceDetection not specified in constructor
797 {
798 // Create Device
799 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500800 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600801
802 // Create MockServices
803 MockServices services{};
804
805 // Since no PresenceDetection defined, isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500806 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600807 }
808
809 // Test where PresenceDetection was specified in constructor: Is present
810 {
811 // Create PresenceDetection. Indicates device is present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500812 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600813 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
814 std::vector<std::unique_ptr<Action>> actions{};
815 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500816 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600817 std::make_unique<PresenceDetection>(std::move(actions));
818
819 // Create Device
820 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500821 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
822 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600823
824 // Create MockServices
825 MockServices services{};
826
827 // PresenceDetection::execute() and isPresent() should return true
Shawn McCarney2874e902021-09-09 10:03:59 -0500828 EXPECT_TRUE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600829 }
830
831 // Test where PresenceDetection was specified in constructor: Is not present
832 {
833 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500834 auto action = std::make_unique<MockAction>();
Shawn McCarney48033bf2021-01-27 17:56:49 -0600835 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
836 std::vector<std::unique_ptr<Action>> actions{};
837 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500838 auto presenceDetection =
Shawn McCarney48033bf2021-01-27 17:56:49 -0600839 std::make_unique<PresenceDetection>(std::move(actions));
840
841 // Create Device
842 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500843 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface),
844 std::move(presenceDetection)};
Shawn McCarney48033bf2021-01-27 17:56:49 -0600845
846 // Create MockServices
847 MockServices services{};
848
849 // PresenceDetection::execute() and isPresent() should return false
Shawn McCarney2874e902021-09-09 10:03:59 -0500850 EXPECT_FALSE(device.isPresent(services, *system, *chassis));
Shawn McCarney48033bf2021-01-27 17:56:49 -0600851 }
852}
853
Shawn McCarney2874e902021-09-09 10:03:59 -0500854TEST_F(DeviceTests, IsRegulator)
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500855{
Shawn McCarney2874e902021-09-09 10:03:59 -0500856 Device device{"vdd_reg", false, deviceInvPath,
857 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500858 EXPECT_EQ(device.isRegulator(), false);
859}
Bob King8e1cd0b2020-07-08 13:30:27 +0800860
Shawn McCarney2874e902021-09-09 10:03:59 -0500861TEST_F(DeviceTests, MonitorSensors)
Bob King8e1cd0b2020-07-08 13:30:27 +0800862{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600863 // Test where device is not present
Bob King8e1cd0b2020-07-08 13:30:27 +0800864 {
Shawn McCarney17bac892021-05-08 07:55:52 -0500865 // Create mock services. No Sensors methods should be called.
Bob King8a552922020-08-05 17:02:31 +0800866 MockServices services{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500867 MockSensors& sensors = services.getMockSensors();
868 EXPECT_CALL(sensors, startRail).Times(0);
869 EXPECT_CALL(sensors, setValue).Times(0);
870 EXPECT_CALL(sensors, endRail).Times(0);
Bob King8a552922020-08-05 17:02:31 +0800871
Shawn McCarney17bac892021-05-08 07:55:52 -0500872 // Create SensorMonitoring. Action inside it should not be executed.
Shawn McCarney2874e902021-09-09 10:03:59 -0500873 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
874 {
875 auto action = std::make_unique<MockAction>();
876 EXPECT_CALL(*action, execute).Times(0);
877 std::vector<std::unique_ptr<Action>> actions{};
878 actions.emplace_back(std::move(action));
879 sensorMonitoring =
880 std::make_unique<SensorMonitoring>(std::move(actions));
881 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800882
883 // Create Rail
884 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500885 auto rail = std::make_unique<Rail>("vddr1", std::move(configuration),
886 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500887
888 // Create PresenceDetection. Indicates device is not present.
Shawn McCarney2874e902021-09-09 10:03:59 -0500889 std::unique_ptr<PresenceDetection> presenceDetection{};
890 {
891 auto action = std::make_unique<MockAction>();
892 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
893 std::vector<std::unique_ptr<Action>> actions{};
894 actions.emplace_back(std::move(action));
895 presenceDetection =
896 std::make_unique<PresenceDetection>(std::move(actions));
897 }
Bob King8e1cd0b2020-07-08 13:30:27 +0800898
899 // Create Device
Shawn McCarney17bac892021-05-08 07:55:52 -0500900 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Bob King8e1cd0b2020-07-08 13:30:27 +0800901 std::unique_ptr<Configuration> deviceConfiguration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500902 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney17bac892021-05-08 07:55:52 -0500903 std::vector<std::unique_ptr<Rail>> rails{};
904 rails.emplace_back(std::move(rail));
Shawn McCarney2874e902021-09-09 10:03:59 -0500905 Device device{"reg2",
906 true,
907 deviceInvPath,
908 std::move(i2cInterface),
909 std::move(presenceDetection),
910 std::move(deviceConfiguration),
911 std::move(phaseFaultDetection),
912 std::move(rails)};
Bob King8e1cd0b2020-07-08 13:30:27 +0800913
Shawn McCarney17bac892021-05-08 07:55:52 -0500914 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500915 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500916 }
917
918 // Test where Rails were not specified in constructor
919 {
920 // Create mock services. No Sensors methods should be called.
921 MockServices services{};
922 MockSensors& sensors = services.getMockSensors();
923 EXPECT_CALL(sensors, startRail).Times(0);
924 EXPECT_CALL(sensors, setValue).Times(0);
925 EXPECT_CALL(sensors, endRail).Times(0);
926
927 // Create Device
928 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
Shawn McCarney2874e902021-09-09 10:03:59 -0500929 Device device{"reg2", true, deviceInvPath, std::move(i2cInterface)};
Shawn McCarney17bac892021-05-08 07:55:52 -0500930
931 // Call monitorSensors(). Should do nothing.
Shawn McCarney2874e902021-09-09 10:03:59 -0500932 device.monitorSensors(services, *system, *chassis);
Shawn McCarney17bac892021-05-08 07:55:52 -0500933 }
934
935 // Test where Rails were specified in constructor
936 {
937 // Create mock services. Set Sensors service expectations.
938 MockServices services{};
939 MockSensors& sensors = services.getMockSensors();
Shawn McCarney2874e902021-09-09 10:03:59 -0500940 EXPECT_CALL(sensors, startRail("vdd0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500941 .Times(1);
Shawn McCarney2874e902021-09-09 10:03:59 -0500942 EXPECT_CALL(sensors, startRail("vio0", deviceInvPath, chassisInvPath))
Shawn McCarney17bac892021-05-08 07:55:52 -0500943 .Times(1);
944 EXPECT_CALL(sensors, setValue).Times(0);
945 EXPECT_CALL(sensors, endRail(false)).Times(2);
946
947 std::vector<std::unique_ptr<Rail>> rails{};
948
949 // Create Rail vdd0
950 {
951 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500952 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500953 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
954 std::vector<std::unique_ptr<Action>> actions{};
955 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500956 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500957 std::make_unique<SensorMonitoring>(std::move(actions));
958
959 // Create Rail
960 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500961 auto rail = std::make_unique<Rail>("vdd0", std::move(configuration),
962 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500963 rails.emplace_back(std::move(rail));
964 }
965
966 // Create Rail vio0
967 {
968 // Create SensorMonitoring for Rail
Shawn McCarney2874e902021-09-09 10:03:59 -0500969 auto action = std::make_unique<MockAction>();
Shawn McCarney17bac892021-05-08 07:55:52 -0500970 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
971 std::vector<std::unique_ptr<Action>> actions{};
972 actions.emplace_back(std::move(action));
Shawn McCarney2874e902021-09-09 10:03:59 -0500973 auto sensorMonitoring =
Shawn McCarney17bac892021-05-08 07:55:52 -0500974 std::make_unique<SensorMonitoring>(std::move(actions));
975
976 // Create Rail
977 std::unique_ptr<Configuration> configuration{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500978 auto rail = std::make_unique<Rail>("vio0", std::move(configuration),
979 std::move(sensorMonitoring));
Shawn McCarney17bac892021-05-08 07:55:52 -0500980 rails.emplace_back(std::move(rail));
981 }
982
983 // Create Device that contains Rails
984 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
985 std::unique_ptr<PresenceDetection> presenceDetection{};
986 std::unique_ptr<Configuration> configuration{};
Shawn McCarney32252592021-09-08 15:29:36 -0500987 std::unique_ptr<PhaseFaultDetection> phaseFaultDetection{};
Shawn McCarney2874e902021-09-09 10:03:59 -0500988 Device device{"reg2",
989 true,
990 deviceInvPath,
991 std::move(i2cInterface),
992 std::move(presenceDetection),
993 std::move(configuration),
994 std::move(phaseFaultDetection),
995 std::move(rails)};
Shawn McCarney17bac892021-05-08 07:55:52 -0500996
997 // Call monitorSensors(). Should monitor sensors in both rails.
Shawn McCarney2874e902021-09-09 10:03:59 -0500998 device.monitorSensors(services, *system, *chassis);
Bob King8e1cd0b2020-07-08 13:30:27 +0800999 }
1000}