blob: 717bb9d301ffbefac60ff212840f6c8d9e2faefa [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 McCarney9bd94d32021-01-25 19:40:42 -0600154TEST(DeviceTests, ClearCache)
155{
156 // Test where Device does not contain a PresenceDetection object
157 try
158 {
159 Device device{
160 "vdd_reg", false,
161 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
162 std::move(createI2CInterface())};
163 device.clearCache();
164 }
165 catch (...)
166 {
167 ADD_FAILURE() << "Should not have caught exception.";
168 }
169
170 // Test where Device contains a PresenceDetection object
171 {
172 // Create PresenceDetection
173 std::vector<std::unique_ptr<Action>> actions{};
174 std::unique_ptr<PresenceDetection> presenceDetection =
175 std::make_unique<PresenceDetection>(std::move(actions));
176 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
177
178 // Create Device
179 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
180 std::unique_ptr<Device> device = std::make_unique<Device>(
181 "reg1", true,
182 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
183 std::move(i2cInterface), std::move(presenceDetection));
184 Device* devicePtr = device.get();
185
186 // Create Chassis that contains Device
187 std::vector<std::unique_ptr<Device>> devices{};
188 devices.emplace_back(std::move(device));
189 std::unique_ptr<Chassis> chassis =
190 std::make_unique<Chassis>(1, std::move(devices));
191 Chassis* chassisPtr = chassis.get();
192
193 // Create System that contains Chassis
194 std::vector<std::unique_ptr<Rule>> rules{};
195 std::vector<std::unique_ptr<Chassis>> chassisVec{};
196 chassisVec.emplace_back(std::move(chassis));
197 System system{std::move(rules), std::move(chassisVec)};
198
199 // Cache presence value in PresenceDetection
200 MockServices services{};
201 presenceDetectionPtr->execute(services, system, *chassisPtr,
202 *devicePtr);
203 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
204
205 // Clear cached data in Device
206 devicePtr->clearCache();
207
208 // Verify presence value no longer cached in PresenceDetection
209 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
210 }
211}
212
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500213TEST(DeviceTests, Close)
214{
215 // Test where works: I2C interface is not open
216 {
217 // Create mock I2CInterface
218 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
219 std::make_unique<i2c::MockedI2CInterface>();
220 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
221 EXPECT_CALL(*i2cInterface, close).Times(0);
222
Bob Kingd692d6d2020-09-14 13:42:57 +0800223 // Create mock services. No logError should occur.
224 MockServices services{};
225 MockJournal& journal = services.getMockJournal();
226 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
227 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
228 .Times(0);
229
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500230 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800231 Device device{
232 "vdd_reg", true,
233 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
234 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500235
236 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800237 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500238 }
239
240 // Test where works: I2C interface is open
241 {
242 // Create mock I2CInterface
243 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
244 std::make_unique<i2c::MockedI2CInterface>();
245 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
246 EXPECT_CALL(*i2cInterface, close).Times(1);
247
Bob Kingd692d6d2020-09-14 13:42:57 +0800248 // Create mock services. No logError should occur.
249 MockServices services{};
250 MockJournal& journal = services.getMockJournal();
251 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
252 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
253 .Times(0);
254
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500255 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800256 Device device{
257 "vdd_reg", true,
258 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
259 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500260
261 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800262 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500263 }
264
265 // Test where fails: closing I2C interface fails
266 {
267 // Create mock I2CInterface
268 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
269 std::make_unique<i2c::MockedI2CInterface>();
270 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
271 EXPECT_CALL(*i2cInterface, close)
272 .Times(1)
273 .WillOnce(Throw(
274 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
275
Bob Kingd692d6d2020-09-14 13:42:57 +0800276 // Create mock services. Expect logError() to be called.
277 MockServices services{};
278 MockJournal& journal = services.getMockJournal();
279 std::vector<std::string> expectedErrMessagesException{
280 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
281 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
282 .Times(1);
283 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
284
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500285 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800286 Device device{
287 "vdd_reg", true,
288 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
289 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500290
291 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800292 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500293 }
294}
295
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500296TEST(DeviceTests, Configure)
297{
298 // Test where Configuration and Rails were not specified in constructor
299 {
Bob King5cfe5102020-07-30 16:26:18 +0800300 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800301 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800302 MockJournal& journal = services.getMockJournal();
303 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
304 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800305
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500306 // Create Device
307 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
308 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800309 "reg1", true,
310 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500311 std::move(i2cInterface));
312 Device* devicePtr = device.get();
313
314 // Create Chassis that contains Device
315 std::vector<std::unique_ptr<Device>> devices{};
316 devices.emplace_back(std::move(device));
317 std::unique_ptr<Chassis> chassis =
318 std::make_unique<Chassis>(1, std::move(devices));
319 Chassis* chassisPtr = chassis.get();
320
321 // Create System that contains Chassis
322 std::vector<std::unique_ptr<Rule>> rules{};
323 std::vector<std::unique_ptr<Chassis>> chassisVec{};
324 chassisVec.emplace_back(std::move(chassis));
325 System system{std::move(rules), std::move(chassisVec)};
326
Bob King5cfe5102020-07-30 16:26:18 +0800327 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800328 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500329 }
330
331 // Test where Configuration and Rails were specified in constructor
332 {
333 std::vector<std::unique_ptr<Rail>> rails{};
334
Bob King5cfe5102020-07-30 16:26:18 +0800335 // Create mock services. Expect logDebug() to be called.
336 // For the Device and both Rails, should execute the Configuration
337 // and log a debug message.
338 MockServices services{};
339 MockJournal& journal = services.getMockJournal();
340 EXPECT_CALL(journal, logDebug("Configuring reg1")).Times(1);
341 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
342 .Times(1);
343 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
344 .Times(1);
345 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
346
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500347 // Create Rail vdd0
348 {
349 // Create Configuration for Rail
350 std::optional<double> volts{1.3};
351 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
352 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
353 std::vector<std::unique_ptr<Action>> actions{};
354 actions.emplace_back(std::move(action));
355 std::unique_ptr<Configuration> configuration =
356 std::make_unique<Configuration>(volts, std::move(actions));
357
358 // Create Rail
359 std::unique_ptr<Rail> rail =
360 std::make_unique<Rail>("vdd0", std::move(configuration));
361 rails.emplace_back(std::move(rail));
362 }
363
364 // Create Rail vio0
365 {
366 // Create Configuration for Rail
367 std::optional<double> volts{3.2};
368 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
369 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
370 std::vector<std::unique_ptr<Action>> actions{};
371 actions.emplace_back(std::move(action));
372 std::unique_ptr<Configuration> configuration =
373 std::make_unique<Configuration>(volts, std::move(actions));
374
375 // Create Rail
376 std::unique_ptr<Rail> rail =
377 std::make_unique<Rail>("vio0", std::move(configuration));
378 rails.emplace_back(std::move(rail));
379 }
380
381 // Create Configuration for Device
382 std::optional<double> volts{};
383 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
384 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
385 std::vector<std::unique_ptr<Action>> actions{};
386 actions.emplace_back(std::move(action));
387 std::unique_ptr<Configuration> configuration =
388 std::make_unique<Configuration>(volts, std::move(actions));
389
390 // Create Device
391 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
392 std::unique_ptr<PresenceDetection> presenceDetection{};
393 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800394 "reg1", true,
395 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500396 std::move(i2cInterface), std::move(presenceDetection),
397 std::move(configuration), std::move(rails));
398 Device* devicePtr = device.get();
399
400 // Create Chassis that contains Device
401 std::vector<std::unique_ptr<Device>> devices{};
402 devices.emplace_back(std::move(device));
403 std::unique_ptr<Chassis> chassis =
404 std::make_unique<Chassis>(1, std::move(devices));
405 Chassis* chassisPtr = chassis.get();
406
407 // Create System that contains Chassis
408 std::vector<std::unique_ptr<Rule>> rules{};
409 std::vector<std::unique_ptr<Chassis>> chassisVec{};
410 chassisVec.emplace_back(std::move(chassis));
411 System system{std::move(rules), std::move(chassisVec)};
412
Bob King5cfe5102020-07-30 16:26:18 +0800413 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800414 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500415 }
416}
417
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500418TEST(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500419{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500420 // Test where Configuration was not specified in constructor
421 {
Bob Kinga76898f2020-10-13 15:08:33 +0800422 Device device{
423 "vdd_reg", true,
424 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
425 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500426 EXPECT_EQ(device.getConfiguration(), nullptr);
427 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600428
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500429 // Test where Configuration was specified in constructor
430 {
431 std::unique_ptr<PresenceDetection> presenceDetection{};
432
433 // Create Configuration
434 std::optional<double> volts{3.2};
435 std::vector<std::unique_ptr<Action>> actions{};
436 actions.push_back(std::make_unique<MockAction>());
437 actions.push_back(std::make_unique<MockAction>());
438 std::unique_ptr<Configuration> configuration =
439 std::make_unique<Configuration>(volts, std::move(actions));
440
441 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800442 Device device{
443 "vdd_reg",
444 true,
445 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
446 std::move(createI2CInterface()),
447 std::move(presenceDetection),
448 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500449 EXPECT_NE(device.getConfiguration(), nullptr);
450 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
451 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
452 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
453 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600454}
455
456TEST(DeviceTests, GetFRU)
457{
Bob Kinga76898f2020-10-13 15:08:33 +0800458 Device device{
459 "vdd_reg", true,
460 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
461 std::move(createI2CInterface())};
462 EXPECT_EQ(device.getFRU(),
463 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600464}
465
466TEST(DeviceTests, GetI2CInterface)
467{
468 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
469 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +0800470 Device device{
471 "vdd_reg", true,
472 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
473 std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600474 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500475}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500476
477TEST(DeviceTests, GetID)
478{
Bob Kinga76898f2020-10-13 15:08:33 +0800479 Device device{
480 "vdd_reg", false,
481 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
482 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500483 EXPECT_EQ(device.getID(), "vdd_reg");
484}
485
486TEST(DeviceTests, GetPresenceDetection)
487{
488 // Test where PresenceDetection was not specified in constructor
489 {
Bob Kinga76898f2020-10-13 15:08:33 +0800490 Device device{
491 "vdd_reg", true,
492 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
493 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500494 EXPECT_EQ(device.getPresenceDetection(), nullptr);
495 }
496
497 // Test where PresenceDetection was specified in constructor
498 {
499 // Create PresenceDetection
500 std::vector<std::unique_ptr<Action>> actions{};
501 actions.push_back(std::make_unique<MockAction>());
502 std::unique_ptr<PresenceDetection> presenceDetection =
503 std::make_unique<PresenceDetection>(std::move(actions));
504
505 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800506 Device device{
507 "vdd_reg", false,
508 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
509 std::move(createI2CInterface()), std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500510 EXPECT_NE(device.getPresenceDetection(), nullptr);
511 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
512 }
513}
514
515TEST(DeviceTests, GetRails)
516{
517 // Test where no rails were specified in constructor
518 {
Bob Kinga76898f2020-10-13 15:08:33 +0800519 Device device{
520 "vdd_reg", true,
521 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
522 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500523 EXPECT_EQ(device.getRails().size(), 0);
524 }
525
526 // Test where rails were specified in constructor
527 {
528 std::unique_ptr<PresenceDetection> presenceDetection{};
529 std::unique_ptr<Configuration> configuration{};
530
531 // Create vector of Rail objects
532 std::vector<std::unique_ptr<Rail>> rails{};
533 rails.push_back(std::make_unique<Rail>("vdd0"));
534 rails.push_back(std::make_unique<Rail>("vdd1"));
535
536 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800537 Device device{
538 "vdd_reg",
539 false,
540 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
541 std::move(createI2CInterface()),
542 std::move(presenceDetection),
543 std::move(configuration),
544 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500545 EXPECT_EQ(device.getRails().size(), 2);
546 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
547 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
548 }
549}
550
551TEST(DeviceTests, IsRegulator)
552{
Bob Kinga76898f2020-10-13 15:08:33 +0800553 Device device{
554 "vdd_reg", false,
555 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
556 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500557 EXPECT_EQ(device.isRegulator(), false);
558}
Bob King8e1cd0b2020-07-08 13:30:27 +0800559
560TEST(DeviceTests, MonitorSensors)
561{
562 // Test where Rails were not specified in constructor
563 {
Bob King8a552922020-08-05 17:02:31 +0800564 // Create mock services. No logging should occur.
565 MockServices services{};
566 MockJournal& journal = services.getMockJournal();
567 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
568 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
569
Bob King8e1cd0b2020-07-08 13:30:27 +0800570 // Create mock I2CInterface. A two-byte read should NOT occur.
571 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
572 std::make_unique<i2c::MockedI2CInterface>();
573 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
574
575 // Create Device
576 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800577 "reg1", true,
578 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800579 std::move(i2cInterface));
580 Device* devicePtr = device.get();
581
582 // Create Chassis that contains Device
583 std::vector<std::unique_ptr<Device>> devices{};
584 devices.emplace_back(std::move(device));
585 std::unique_ptr<Chassis> chassis =
586 std::make_unique<Chassis>(1, std::move(devices));
587 Chassis* chassisPtr = chassis.get();
588
589 // Create System that contains Chassis
590 std::vector<std::unique_ptr<Rule>> rules{};
591 std::vector<std::unique_ptr<Chassis>> chassisVec{};
592 chassisVec.emplace_back(std::move(chassis));
593 System system{std::move(rules), std::move(chassisVec)};
594
Bob King8a552922020-08-05 17:02:31 +0800595 // Call monitorSensors().
596 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800597 }
598
599 // Test where Rails were specified in constructor
600 {
Bob King8a552922020-08-05 17:02:31 +0800601 // Create mock services. No logging should occur.
602 MockServices services{};
603 MockJournal& journal = services.getMockJournal();
604 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
605 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
606
Bob King8e1cd0b2020-07-08 13:30:27 +0800607 std::vector<std::unique_ptr<Rail>> rails{};
608
609 // Create PMBusReadSensorAction
610 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
611 uint8_t command = 0x8C;
612 pmbus_utils::SensorDataFormat format{
613 pmbus_utils::SensorDataFormat::linear_11};
614 std::optional<int8_t> exponent{};
615 std::unique_ptr<PMBusReadSensorAction> action =
616 std::make_unique<PMBusReadSensorAction>(type, command, format,
617 exponent);
618
619 // Create mock I2CInterface. A two-byte read should occur.
620 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
621 std::make_unique<i2c::MockedI2CInterface>();
622 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
623 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
624 .Times(1);
625
626 // Create SensorMonitoring
627 std::vector<std::unique_ptr<Action>> actions{};
628 actions.emplace_back(std::move(action));
629 std::unique_ptr<SensorMonitoring> sensorMonitoring =
630 std::make_unique<SensorMonitoring>(std::move(actions));
631
632 // Create Rail
633 std::unique_ptr<Configuration> configuration{};
634 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
635 "vdd0", std::move(configuration), std::move(sensorMonitoring));
636 rails.emplace_back(std::move(rail));
637
638 // Create Device
639 std::unique_ptr<PresenceDetection> presenceDetection{};
640 std::unique_ptr<Configuration> deviceConfiguration{};
641 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800642 "reg1", true,
643 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800644 std::move(i2cInterface), std::move(presenceDetection),
645 std::move(deviceConfiguration), std::move(rails));
646 Device* devicePtr = device.get();
647
648 // Create Chassis that contains Device
649 std::vector<std::unique_ptr<Device>> devices{};
650 devices.emplace_back(std::move(device));
651 std::unique_ptr<Chassis> chassis =
652 std::make_unique<Chassis>(1, std::move(devices));
653 Chassis* chassisPtr = chassis.get();
654
655 // Create System that contains Chassis
656 std::vector<std::unique_ptr<Rule>> rules{};
657 std::vector<std::unique_ptr<Chassis>> chassisVec{};
658 chassisVec.emplace_back(std::move(chassis));
659 System system{std::move(rules), std::move(chassisVec)};
660
661 // Call monitorSensors().
Bob King8a552922020-08-05 17:02:31 +0800662 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800663 }
664}