blob: ad2b9c29bd9e0d37e9aaabf34652a23c58bba844 [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 McCarney0b1a0e72020-03-11 18:01:44 -050022#include "mock_action.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050023#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080024#include "mock_services.hpp"
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050025#include "mocked_i2c_interface.hpp"
Bob King8e1cd0b2020-07-08 13:30:27 +080026#include "pmbus_read_sensor_action.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050027#include "presence_detection.hpp"
28#include "rail.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050029#include "rule.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050030#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050031#include "test_utils.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060032
33#include <memory>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050034#include <optional>
Shawn McCarney525e20c2020-04-14 11:05:39 -050035#include <string>
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060036#include <utility>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050037#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050038
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050039#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050040#include <gtest/gtest.h>
41
42using namespace phosphor::power::regulators;
Shawn McCarney8a3afd72020-03-12 14:28:44 -050043using namespace phosphor::power::regulators::test_utils;
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060044
Bob King8e1cd0b2020-07-08 13:30:27 +080045using ::testing::A;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050046using ::testing::Return;
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050047using ::testing::Throw;
Bob King8e1cd0b2020-07-08 13:30:27 +080048using ::testing::TypedEq;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050049
Shawn McCarneya2461b32019-10-24 18:53:01 -050050TEST(DeviceTests, Constructor)
51{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050052 // Test where only required parameters are specified
53 {
54 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
55 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +080056 Device device{
57 "vdd_reg", true,
58 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
59 std::move(i2cInterface)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050060 EXPECT_EQ(device.getID(), "vdd_reg");
61 EXPECT_EQ(device.isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +080062 EXPECT_EQ(
63 device.getFRU(),
64 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050065 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
66 EXPECT_EQ(device.getPresenceDetection(), nullptr);
67 EXPECT_EQ(device.getConfiguration(), nullptr);
68 EXPECT_EQ(device.getRails().size(), 0);
69 }
70
71 // Test where all parameters are specified
72 {
73 // Create I2CInterface
74 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
75 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
76
77 // Create PresenceDetection
78 std::vector<std::unique_ptr<Action>> actions{};
79 actions.push_back(std::make_unique<MockAction>());
80 std::unique_ptr<PresenceDetection> presenceDetection =
81 std::make_unique<PresenceDetection>(std::move(actions));
82
83 // Create Configuration
84 std::optional<double> volts{};
85 actions.clear();
86 actions.push_back(std::make_unique<MockAction>());
87 actions.push_back(std::make_unique<MockAction>());
88 std::unique_ptr<Configuration> configuration =
89 std::make_unique<Configuration>(volts, std::move(actions));
90
91 // Create vector of Rail objects
92 std::vector<std::unique_ptr<Rail>> rails{};
93 rails.push_back(std::make_unique<Rail>("vdd0"));
94 rails.push_back(std::make_unique<Rail>("vdd1"));
95
96 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +080097 Device device{
98 "vdd_reg",
99 false,
100 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
101 std::move(i2cInterface),
102 std::move(presenceDetection),
103 std::move(configuration),
104 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500105 EXPECT_EQ(device.getID(), "vdd_reg");
106 EXPECT_EQ(device.isRegulator(), false);
Bob Kinga76898f2020-10-13 15:08:33 +0800107 EXPECT_EQ(
108 device.getFRU(),
109 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1");
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500110 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
111 EXPECT_NE(device.getPresenceDetection(), nullptr);
112 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
113 EXPECT_NE(device.getConfiguration(), nullptr);
114 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
115 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
116 EXPECT_EQ(device.getRails().size(), 2);
117 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500118}
119
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500120TEST(DeviceTests, AddToIDMap)
121{
122 std::unique_ptr<PresenceDetection> presenceDetection{};
123 std::unique_ptr<Configuration> configuration{};
124
125 // Create vector of Rail objects
126 std::vector<std::unique_ptr<Rail>> rails{};
127 rails.push_back(std::make_unique<Rail>("vdd0"));
128 rails.push_back(std::make_unique<Rail>("vdd1"));
129
130 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800131 Device device{
132 "vdd_reg",
133 false,
134 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
135 std::move(createI2CInterface()),
136 std::move(presenceDetection),
137 std::move(configuration),
138 std::move(rails)};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500139
140 // Add Device and Rail objects to an IDMap
141 IDMap idMap{};
142 device.addToIDMap(idMap);
143
144 // Verify Device is in the IDMap
145 EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
146 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
147
148 // Verify all Rails are in the IDMap
149 EXPECT_NO_THROW(idMap.getRail("vdd0"));
150 EXPECT_NO_THROW(idMap.getRail("vdd1"));
151 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
152}
153
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500154TEST(DeviceTests, Close)
155{
156 // Test where works: I2C interface is not open
157 {
158 // Create mock I2CInterface
159 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
160 std::make_unique<i2c::MockedI2CInterface>();
161 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
162 EXPECT_CALL(*i2cInterface, close).Times(0);
163
Bob Kingd692d6d2020-09-14 13:42:57 +0800164 // Create mock services. No logError should occur.
165 MockServices services{};
166 MockJournal& journal = services.getMockJournal();
167 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
168 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
169 .Times(0);
170
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500171 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800172 Device device{
173 "vdd_reg", true,
174 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
175 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500176
177 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800178 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500179 }
180
181 // Test where works: I2C interface is open
182 {
183 // Create mock I2CInterface
184 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
185 std::make_unique<i2c::MockedI2CInterface>();
186 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
187 EXPECT_CALL(*i2cInterface, close).Times(1);
188
Bob Kingd692d6d2020-09-14 13:42:57 +0800189 // Create mock services. No logError should occur.
190 MockServices services{};
191 MockJournal& journal = services.getMockJournal();
192 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
193 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
194 .Times(0);
195
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500196 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800197 Device device{
198 "vdd_reg", true,
199 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
200 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500201
202 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800203 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500204 }
205
206 // Test where fails: closing I2C interface fails
207 {
208 // Create mock I2CInterface
209 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
210 std::make_unique<i2c::MockedI2CInterface>();
211 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
212 EXPECT_CALL(*i2cInterface, close)
213 .Times(1)
214 .WillOnce(Throw(
215 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
216
Bob Kingd692d6d2020-09-14 13:42:57 +0800217 // Create mock services. Expect logError() to be called.
218 MockServices services{};
219 MockJournal& journal = services.getMockJournal();
220 std::vector<std::string> expectedErrMessagesException{
221 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
222 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
223 .Times(1);
224 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
225
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500226 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800227 Device device{
228 "vdd_reg", true,
229 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
230 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500231
232 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800233 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500234 }
235}
236
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500237TEST(DeviceTests, Configure)
238{
239 // Test where Configuration and Rails were not specified in constructor
240 {
Bob King5cfe5102020-07-30 16:26:18 +0800241 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800242 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800243 MockJournal& journal = services.getMockJournal();
244 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
245 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800246
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500247 // Create Device
248 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
249 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800250 "reg1", true,
251 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500252 std::move(i2cInterface));
253 Device* devicePtr = device.get();
254
255 // Create Chassis that contains Device
256 std::vector<std::unique_ptr<Device>> devices{};
257 devices.emplace_back(std::move(device));
258 std::unique_ptr<Chassis> chassis =
259 std::make_unique<Chassis>(1, std::move(devices));
260 Chassis* chassisPtr = chassis.get();
261
262 // Create System that contains Chassis
263 std::vector<std::unique_ptr<Rule>> rules{};
264 std::vector<std::unique_ptr<Chassis>> chassisVec{};
265 chassisVec.emplace_back(std::move(chassis));
266 System system{std::move(rules), std::move(chassisVec)};
267
Bob King5cfe5102020-07-30 16:26:18 +0800268 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800269 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500270 }
271
272 // Test where Configuration and Rails were specified in constructor
273 {
274 std::vector<std::unique_ptr<Rail>> rails{};
275
Bob King5cfe5102020-07-30 16:26:18 +0800276 // Create mock services. Expect logDebug() to be called.
277 // For the Device and both Rails, should execute the Configuration
278 // and log a debug message.
279 MockServices services{};
280 MockJournal& journal = services.getMockJournal();
281 EXPECT_CALL(journal, logDebug("Configuring reg1")).Times(1);
282 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
283 .Times(1);
284 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
285 .Times(1);
286 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
287
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500288 // Create Rail vdd0
289 {
290 // Create Configuration for Rail
291 std::optional<double> volts{1.3};
292 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
293 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
294 std::vector<std::unique_ptr<Action>> actions{};
295 actions.emplace_back(std::move(action));
296 std::unique_ptr<Configuration> configuration =
297 std::make_unique<Configuration>(volts, std::move(actions));
298
299 // Create Rail
300 std::unique_ptr<Rail> rail =
301 std::make_unique<Rail>("vdd0", std::move(configuration));
302 rails.emplace_back(std::move(rail));
303 }
304
305 // Create Rail vio0
306 {
307 // Create Configuration for Rail
308 std::optional<double> volts{3.2};
309 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
310 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
311 std::vector<std::unique_ptr<Action>> actions{};
312 actions.emplace_back(std::move(action));
313 std::unique_ptr<Configuration> configuration =
314 std::make_unique<Configuration>(volts, std::move(actions));
315
316 // Create Rail
317 std::unique_ptr<Rail> rail =
318 std::make_unique<Rail>("vio0", std::move(configuration));
319 rails.emplace_back(std::move(rail));
320 }
321
322 // Create Configuration for Device
323 std::optional<double> volts{};
324 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
325 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
326 std::vector<std::unique_ptr<Action>> actions{};
327 actions.emplace_back(std::move(action));
328 std::unique_ptr<Configuration> configuration =
329 std::make_unique<Configuration>(volts, std::move(actions));
330
331 // Create Device
332 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
333 std::unique_ptr<PresenceDetection> presenceDetection{};
334 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800335 "reg1", true,
336 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500337 std::move(i2cInterface), std::move(presenceDetection),
338 std::move(configuration), std::move(rails));
339 Device* devicePtr = device.get();
340
341 // Create Chassis that contains Device
342 std::vector<std::unique_ptr<Device>> devices{};
343 devices.emplace_back(std::move(device));
344 std::unique_ptr<Chassis> chassis =
345 std::make_unique<Chassis>(1, std::move(devices));
346 Chassis* chassisPtr = chassis.get();
347
348 // Create System that contains Chassis
349 std::vector<std::unique_ptr<Rule>> rules{};
350 std::vector<std::unique_ptr<Chassis>> chassisVec{};
351 chassisVec.emplace_back(std::move(chassis));
352 System system{std::move(rules), std::move(chassisVec)};
353
Bob King5cfe5102020-07-30 16:26:18 +0800354 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800355 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500356 }
357}
358
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500359TEST(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500360{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500361 // Test where Configuration was not specified in constructor
362 {
Bob Kinga76898f2020-10-13 15:08:33 +0800363 Device device{
364 "vdd_reg", true,
365 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
366 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500367 EXPECT_EQ(device.getConfiguration(), nullptr);
368 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600369
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500370 // Test where Configuration was specified in constructor
371 {
372 std::unique_ptr<PresenceDetection> presenceDetection{};
373
374 // Create Configuration
375 std::optional<double> volts{3.2};
376 std::vector<std::unique_ptr<Action>> actions{};
377 actions.push_back(std::make_unique<MockAction>());
378 actions.push_back(std::make_unique<MockAction>());
379 std::unique_ptr<Configuration> configuration =
380 std::make_unique<Configuration>(volts, std::move(actions));
381
382 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800383 Device device{
384 "vdd_reg",
385 true,
386 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
387 std::move(createI2CInterface()),
388 std::move(presenceDetection),
389 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500390 EXPECT_NE(device.getConfiguration(), nullptr);
391 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
392 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
393 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
394 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600395}
396
397TEST(DeviceTests, GetFRU)
398{
Bob Kinga76898f2020-10-13 15:08:33 +0800399 Device device{
400 "vdd_reg", true,
401 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
402 std::move(createI2CInterface())};
403 EXPECT_EQ(device.getFRU(),
404 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600405}
406
407TEST(DeviceTests, GetI2CInterface)
408{
409 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
410 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +0800411 Device device{
412 "vdd_reg", true,
413 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
414 std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600415 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500416}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500417
418TEST(DeviceTests, GetID)
419{
Bob Kinga76898f2020-10-13 15:08:33 +0800420 Device device{
421 "vdd_reg", false,
422 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
423 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500424 EXPECT_EQ(device.getID(), "vdd_reg");
425}
426
427TEST(DeviceTests, GetPresenceDetection)
428{
429 // Test where PresenceDetection was not specified in constructor
430 {
Bob Kinga76898f2020-10-13 15:08:33 +0800431 Device device{
432 "vdd_reg", true,
433 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
434 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500435 EXPECT_EQ(device.getPresenceDetection(), nullptr);
436 }
437
438 // Test where PresenceDetection was specified in constructor
439 {
440 // Create PresenceDetection
441 std::vector<std::unique_ptr<Action>> actions{};
442 actions.push_back(std::make_unique<MockAction>());
443 std::unique_ptr<PresenceDetection> presenceDetection =
444 std::make_unique<PresenceDetection>(std::move(actions));
445
446 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800447 Device device{
448 "vdd_reg", false,
449 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
450 std::move(createI2CInterface()), std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500451 EXPECT_NE(device.getPresenceDetection(), nullptr);
452 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
453 }
454}
455
456TEST(DeviceTests, GetRails)
457{
458 // Test where no rails were specified in constructor
459 {
Bob Kinga76898f2020-10-13 15:08:33 +0800460 Device device{
461 "vdd_reg", true,
462 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
463 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500464 EXPECT_EQ(device.getRails().size(), 0);
465 }
466
467 // Test where rails were specified in constructor
468 {
469 std::unique_ptr<PresenceDetection> presenceDetection{};
470 std::unique_ptr<Configuration> configuration{};
471
472 // Create vector of Rail objects
473 std::vector<std::unique_ptr<Rail>> rails{};
474 rails.push_back(std::make_unique<Rail>("vdd0"));
475 rails.push_back(std::make_unique<Rail>("vdd1"));
476
477 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800478 Device device{
479 "vdd_reg",
480 false,
481 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
482 std::move(createI2CInterface()),
483 std::move(presenceDetection),
484 std::move(configuration),
485 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500486 EXPECT_EQ(device.getRails().size(), 2);
487 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
488 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
489 }
490}
491
492TEST(DeviceTests, IsRegulator)
493{
Bob Kinga76898f2020-10-13 15:08:33 +0800494 Device device{
495 "vdd_reg", false,
496 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
497 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500498 EXPECT_EQ(device.isRegulator(), false);
499}
Bob King8e1cd0b2020-07-08 13:30:27 +0800500
501TEST(DeviceTests, MonitorSensors)
502{
503 // Test where Rails were not specified in constructor
504 {
Bob King8a552922020-08-05 17:02:31 +0800505 // Create mock services. No logging should occur.
506 MockServices services{};
507 MockJournal& journal = services.getMockJournal();
508 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
509 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
510
Bob King8e1cd0b2020-07-08 13:30:27 +0800511 // Create mock I2CInterface. A two-byte read should NOT occur.
512 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
513 std::make_unique<i2c::MockedI2CInterface>();
514 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
515
516 // Create Device
517 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800518 "reg1", true,
519 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800520 std::move(i2cInterface));
521 Device* devicePtr = device.get();
522
523 // Create Chassis that contains Device
524 std::vector<std::unique_ptr<Device>> devices{};
525 devices.emplace_back(std::move(device));
526 std::unique_ptr<Chassis> chassis =
527 std::make_unique<Chassis>(1, std::move(devices));
528 Chassis* chassisPtr = chassis.get();
529
530 // Create System that contains Chassis
531 std::vector<std::unique_ptr<Rule>> rules{};
532 std::vector<std::unique_ptr<Chassis>> chassisVec{};
533 chassisVec.emplace_back(std::move(chassis));
534 System system{std::move(rules), std::move(chassisVec)};
535
Bob King8a552922020-08-05 17:02:31 +0800536 // Call monitorSensors().
537 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800538 }
539
540 // Test where Rails were specified in constructor
541 {
Bob King8a552922020-08-05 17:02:31 +0800542 // Create mock services. No logging should occur.
543 MockServices services{};
544 MockJournal& journal = services.getMockJournal();
545 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
546 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
547
Bob King8e1cd0b2020-07-08 13:30:27 +0800548 std::vector<std::unique_ptr<Rail>> rails{};
549
550 // Create PMBusReadSensorAction
551 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
552 uint8_t command = 0x8C;
553 pmbus_utils::SensorDataFormat format{
554 pmbus_utils::SensorDataFormat::linear_11};
555 std::optional<int8_t> exponent{};
556 std::unique_ptr<PMBusReadSensorAction> action =
557 std::make_unique<PMBusReadSensorAction>(type, command, format,
558 exponent);
559
560 // Create mock I2CInterface. A two-byte read should occur.
561 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
562 std::make_unique<i2c::MockedI2CInterface>();
563 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
564 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
565 .Times(1);
566
567 // Create SensorMonitoring
568 std::vector<std::unique_ptr<Action>> actions{};
569 actions.emplace_back(std::move(action));
570 std::unique_ptr<SensorMonitoring> sensorMonitoring =
571 std::make_unique<SensorMonitoring>(std::move(actions));
572
573 // Create Rail
574 std::unique_ptr<Configuration> configuration{};
575 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
576 "vdd0", std::move(configuration), std::move(sensorMonitoring));
577 rails.emplace_back(std::move(rail));
578
579 // Create Device
580 std::unique_ptr<PresenceDetection> presenceDetection{};
581 std::unique_ptr<Configuration> deviceConfiguration{};
582 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800583 "reg1", true,
584 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800585 std::move(i2cInterface), std::move(presenceDetection),
586 std::move(deviceConfiguration), std::move(rails));
587 Device* devicePtr = device.get();
588
589 // Create Chassis that contains Device
590 std::vector<std::unique_ptr<Device>> devices{};
591 devices.emplace_back(std::move(device));
592 std::unique_ptr<Chassis> chassis =
593 std::make_unique<Chassis>(1, std::move(devices));
594 Chassis* chassisPtr = chassis.get();
595
596 // Create System that contains Chassis
597 std::vector<std::unique_ptr<Rule>> rules{};
598 std::vector<std::unique_ptr<Chassis>> chassisVec{};
599 chassisVec.emplace_back(std::move(chassis));
600 System system{std::move(rules), std::move(chassisVec)};
601
602 // Call monitorSensors().
Bob King8a552922020-08-05 17:02:31 +0800603 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800604 }
605}