blob: 594578fe0b126de7d2ebd8a5d796c0dea280e0e0 [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{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600298 // Test where device is not present
299 {
300 // Create mock services. No logging should occur.
301 MockServices services{};
302 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);
305
306 // Create PresenceDetection. Indicates device is not present.
307 std::unique_ptr<MockAction> presAction = std::make_unique<MockAction>();
308 EXPECT_CALL(*presAction, execute).Times(1).WillOnce(Return(false));
309 std::vector<std::unique_ptr<Action>> presActions{};
310 presActions.emplace_back(std::move(presAction));
311 std::unique_ptr<PresenceDetection> presenceDetection =
312 std::make_unique<PresenceDetection>(std::move(presActions));
313
314 // Create Configuration. Action inside it should not be executed.
315 std::optional<double> volts{};
316 std::unique_ptr<MockAction> confAction = std::make_unique<MockAction>();
317 EXPECT_CALL(*confAction, execute).Times(0);
318 std::vector<std::unique_ptr<Action>> confActions{};
319 confActions.emplace_back(std::move(confAction));
320 std::unique_ptr<Configuration> configuration =
321 std::make_unique<Configuration>(volts, std::move(confActions));
322
323 // Create Device
324 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
325 std::unique_ptr<Device> device = std::make_unique<Device>(
326 "reg1", true,
327 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
328 std::move(i2cInterface), std::move(presenceDetection),
329 std::move(configuration));
330 Device* devicePtr = device.get();
331
332 // Create Chassis that contains Device
333 std::vector<std::unique_ptr<Device>> devices{};
334 devices.emplace_back(std::move(device));
335 std::unique_ptr<Chassis> chassis =
336 std::make_unique<Chassis>(1, std::move(devices));
337 Chassis* chassisPtr = chassis.get();
338
339 // Create System that contains Chassis
340 std::vector<std::unique_ptr<Rule>> rules{};
341 std::vector<std::unique_ptr<Chassis>> chassisVec{};
342 chassisVec.emplace_back(std::move(chassis));
343 System system{std::move(rules), std::move(chassisVec)};
344
345 // Call configure(). Should do nothing.
346 devicePtr->configure(services, system, *chassisPtr);
347 }
348
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500349 // Test where Configuration and Rails were not specified in constructor
350 {
Bob King5cfe5102020-07-30 16:26:18 +0800351 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800352 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800353 MockJournal& journal = services.getMockJournal();
354 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
355 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800356
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500357 // Create Device
358 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
359 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800360 "reg1", true,
361 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500362 std::move(i2cInterface));
363 Device* devicePtr = device.get();
364
365 // Create Chassis that contains Device
366 std::vector<std::unique_ptr<Device>> devices{};
367 devices.emplace_back(std::move(device));
368 std::unique_ptr<Chassis> chassis =
369 std::make_unique<Chassis>(1, std::move(devices));
370 Chassis* chassisPtr = chassis.get();
371
372 // Create System that contains Chassis
373 std::vector<std::unique_ptr<Rule>> rules{};
374 std::vector<std::unique_ptr<Chassis>> chassisVec{};
375 chassisVec.emplace_back(std::move(chassis));
376 System system{std::move(rules), std::move(chassisVec)};
377
Bob King5cfe5102020-07-30 16:26:18 +0800378 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800379 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500380 }
381
382 // Test where Configuration and Rails were specified in constructor
383 {
384 std::vector<std::unique_ptr<Rail>> rails{};
385
Bob King5cfe5102020-07-30 16:26:18 +0800386 // Create mock services. Expect logDebug() to be called.
387 // For the Device and both Rails, should execute the Configuration
388 // and log a debug message.
389 MockServices services{};
390 MockJournal& journal = services.getMockJournal();
391 EXPECT_CALL(journal, logDebug("Configuring reg1")).Times(1);
392 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
393 .Times(1);
394 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
395 .Times(1);
396 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
397
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500398 // Create Rail vdd0
399 {
400 // Create Configuration for Rail
401 std::optional<double> volts{1.3};
402 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
403 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
404 std::vector<std::unique_ptr<Action>> actions{};
405 actions.emplace_back(std::move(action));
406 std::unique_ptr<Configuration> configuration =
407 std::make_unique<Configuration>(volts, std::move(actions));
408
409 // Create Rail
410 std::unique_ptr<Rail> rail =
411 std::make_unique<Rail>("vdd0", std::move(configuration));
412 rails.emplace_back(std::move(rail));
413 }
414
415 // Create Rail vio0
416 {
417 // Create Configuration for Rail
418 std::optional<double> volts{3.2};
419 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
420 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
421 std::vector<std::unique_ptr<Action>> actions{};
422 actions.emplace_back(std::move(action));
423 std::unique_ptr<Configuration> configuration =
424 std::make_unique<Configuration>(volts, std::move(actions));
425
426 // Create Rail
427 std::unique_ptr<Rail> rail =
428 std::make_unique<Rail>("vio0", std::move(configuration));
429 rails.emplace_back(std::move(rail));
430 }
431
432 // Create Configuration for Device
433 std::optional<double> volts{};
434 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
435 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
436 std::vector<std::unique_ptr<Action>> actions{};
437 actions.emplace_back(std::move(action));
438 std::unique_ptr<Configuration> configuration =
439 std::make_unique<Configuration>(volts, std::move(actions));
440
441 // Create Device
442 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
443 std::unique_ptr<PresenceDetection> presenceDetection{};
444 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800445 "reg1", true,
446 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500447 std::move(i2cInterface), std::move(presenceDetection),
448 std::move(configuration), std::move(rails));
449 Device* devicePtr = device.get();
450
451 // Create Chassis that contains Device
452 std::vector<std::unique_ptr<Device>> devices{};
453 devices.emplace_back(std::move(device));
454 std::unique_ptr<Chassis> chassis =
455 std::make_unique<Chassis>(1, std::move(devices));
456 Chassis* chassisPtr = chassis.get();
457
458 // Create System that contains Chassis
459 std::vector<std::unique_ptr<Rule>> rules{};
460 std::vector<std::unique_ptr<Chassis>> chassisVec{};
461 chassisVec.emplace_back(std::move(chassis));
462 System system{std::move(rules), std::move(chassisVec)};
463
Bob King5cfe5102020-07-30 16:26:18 +0800464 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800465 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500466 }
467}
468
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500469TEST(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500470{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500471 // Test where Configuration was not specified in constructor
472 {
Bob Kinga76898f2020-10-13 15:08:33 +0800473 Device device{
474 "vdd_reg", true,
475 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
476 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500477 EXPECT_EQ(device.getConfiguration(), nullptr);
478 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600479
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500480 // Test where Configuration was specified in constructor
481 {
482 std::unique_ptr<PresenceDetection> presenceDetection{};
483
484 // Create Configuration
485 std::optional<double> volts{3.2};
486 std::vector<std::unique_ptr<Action>> actions{};
487 actions.push_back(std::make_unique<MockAction>());
488 actions.push_back(std::make_unique<MockAction>());
489 std::unique_ptr<Configuration> configuration =
490 std::make_unique<Configuration>(volts, std::move(actions));
491
492 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800493 Device device{
494 "vdd_reg",
495 true,
496 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
497 std::move(createI2CInterface()),
498 std::move(presenceDetection),
499 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500500 EXPECT_NE(device.getConfiguration(), nullptr);
501 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
502 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
503 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
504 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600505}
506
507TEST(DeviceTests, GetFRU)
508{
Bob Kinga76898f2020-10-13 15:08:33 +0800509 Device device{
510 "vdd_reg", true,
511 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
512 std::move(createI2CInterface())};
513 EXPECT_EQ(device.getFRU(),
514 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600515}
516
517TEST(DeviceTests, GetI2CInterface)
518{
519 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
520 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +0800521 Device device{
522 "vdd_reg", true,
523 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
524 std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600525 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500526}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500527
528TEST(DeviceTests, GetID)
529{
Bob Kinga76898f2020-10-13 15:08:33 +0800530 Device device{
531 "vdd_reg", false,
532 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
533 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500534 EXPECT_EQ(device.getID(), "vdd_reg");
535}
536
537TEST(DeviceTests, GetPresenceDetection)
538{
539 // Test where PresenceDetection was not specified in constructor
540 {
Bob Kinga76898f2020-10-13 15:08:33 +0800541 Device device{
542 "vdd_reg", true,
543 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
544 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500545 EXPECT_EQ(device.getPresenceDetection(), nullptr);
546 }
547
548 // Test where PresenceDetection was specified in constructor
549 {
550 // Create PresenceDetection
551 std::vector<std::unique_ptr<Action>> actions{};
552 actions.push_back(std::make_unique<MockAction>());
553 std::unique_ptr<PresenceDetection> presenceDetection =
554 std::make_unique<PresenceDetection>(std::move(actions));
555
556 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800557 Device device{
558 "vdd_reg", false,
559 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
560 std::move(createI2CInterface()), std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500561 EXPECT_NE(device.getPresenceDetection(), nullptr);
562 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
563 }
564}
565
566TEST(DeviceTests, GetRails)
567{
568 // Test where no rails were specified in constructor
569 {
Bob Kinga76898f2020-10-13 15:08:33 +0800570 Device device{
571 "vdd_reg", true,
572 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
573 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500574 EXPECT_EQ(device.getRails().size(), 0);
575 }
576
577 // Test where rails were specified in constructor
578 {
579 std::unique_ptr<PresenceDetection> presenceDetection{};
580 std::unique_ptr<Configuration> configuration{};
581
582 // Create vector of Rail objects
583 std::vector<std::unique_ptr<Rail>> rails{};
584 rails.push_back(std::make_unique<Rail>("vdd0"));
585 rails.push_back(std::make_unique<Rail>("vdd1"));
586
587 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800588 Device device{
589 "vdd_reg",
590 false,
591 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
592 std::move(createI2CInterface()),
593 std::move(presenceDetection),
594 std::move(configuration),
595 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500596 EXPECT_EQ(device.getRails().size(), 2);
597 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
598 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
599 }
600}
601
Shawn McCarney48033bf2021-01-27 17:56:49 -0600602TEST(DeviceTests, IsPresent)
603{
604 // Test where PresenceDetection not specified in constructor
605 {
606 // Create Device
607 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
608 std::unique_ptr<Device> device = std::make_unique<Device>(
609 "reg1", true,
610 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
611 std::move(i2cInterface));
612 Device* devicePtr = device.get();
613
614 // Create Chassis that contains Device
615 std::vector<std::unique_ptr<Device>> devices{};
616 devices.emplace_back(std::move(device));
617 std::unique_ptr<Chassis> chassis =
618 std::make_unique<Chassis>(1, std::move(devices));
619 Chassis* chassisPtr = chassis.get();
620
621 // Create System that contains Chassis
622 std::vector<std::unique_ptr<Rule>> rules{};
623 std::vector<std::unique_ptr<Chassis>> chassisVec{};
624 chassisVec.emplace_back(std::move(chassis));
625 System system{std::move(rules), std::move(chassisVec)};
626
627 // Create MockServices
628 MockServices services{};
629
630 // Since no PresenceDetection defined, isPresent() should return true
631 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
632 }
633
634 // Test where PresenceDetection was specified in constructor: Is present
635 {
636 // Create PresenceDetection. Indicates device is present.
637 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
638 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
639 std::vector<std::unique_ptr<Action>> actions{};
640 actions.emplace_back(std::move(action));
641 std::unique_ptr<PresenceDetection> presenceDetection =
642 std::make_unique<PresenceDetection>(std::move(actions));
643
644 // Create Device
645 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
646 std::unique_ptr<Device> device = std::make_unique<Device>(
647 "reg1", true,
648 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
649 std::move(i2cInterface), std::move(presenceDetection));
650 Device* devicePtr = device.get();
651
652 // Create Chassis that contains Device
653 std::vector<std::unique_ptr<Device>> devices{};
654 devices.emplace_back(std::move(device));
655 std::unique_ptr<Chassis> chassis =
656 std::make_unique<Chassis>(1, std::move(devices));
657 Chassis* chassisPtr = chassis.get();
658
659 // Create System that contains Chassis
660 std::vector<std::unique_ptr<Rule>> rules{};
661 std::vector<std::unique_ptr<Chassis>> chassisVec{};
662 chassisVec.emplace_back(std::move(chassis));
663 System system{std::move(rules), std::move(chassisVec)};
664
665 // Create MockServices
666 MockServices services{};
667
668 // PresenceDetection::execute() and isPresent() should return true
669 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
670 }
671
672 // Test where PresenceDetection was specified in constructor: Is not present
673 {
674 // Create PresenceDetection. Indicates device is not present.
675 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
676 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
677 std::vector<std::unique_ptr<Action>> actions{};
678 actions.emplace_back(std::move(action));
679 std::unique_ptr<PresenceDetection> presenceDetection =
680 std::make_unique<PresenceDetection>(std::move(actions));
681
682 // Create Device
683 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
684 std::unique_ptr<Device> device = std::make_unique<Device>(
685 "reg1", true,
686 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
687 std::move(i2cInterface), std::move(presenceDetection));
688 Device* devicePtr = device.get();
689
690 // Create Chassis that contains Device
691 std::vector<std::unique_ptr<Device>> devices{};
692 devices.emplace_back(std::move(device));
693 std::unique_ptr<Chassis> chassis =
694 std::make_unique<Chassis>(1, std::move(devices));
695 Chassis* chassisPtr = chassis.get();
696
697 // Create System that contains Chassis
698 std::vector<std::unique_ptr<Rule>> rules{};
699 std::vector<std::unique_ptr<Chassis>> chassisVec{};
700 chassisVec.emplace_back(std::move(chassis));
701 System system{std::move(rules), std::move(chassisVec)};
702
703 // Create MockServices
704 MockServices services{};
705
706 // PresenceDetection::execute() and isPresent() should return false
707 EXPECT_FALSE(devicePtr->isPresent(services, system, *chassisPtr));
708 }
709}
710
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500711TEST(DeviceTests, IsRegulator)
712{
Bob Kinga76898f2020-10-13 15:08:33 +0800713 Device device{
714 "vdd_reg", false,
715 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
716 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500717 EXPECT_EQ(device.isRegulator(), false);
718}
Bob King8e1cd0b2020-07-08 13:30:27 +0800719
720TEST(DeviceTests, MonitorSensors)
721{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600722 // Test where device is not present
723 // TODO: Add this test when sensoring monitoring is fully implemented
724
Bob King8e1cd0b2020-07-08 13:30:27 +0800725 // Test where Rails were not specified in constructor
726 {
Bob King8a552922020-08-05 17:02:31 +0800727 // Create mock services. No logging should occur.
728 MockServices services{};
729 MockJournal& journal = services.getMockJournal();
730 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
731 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
732
Bob King8e1cd0b2020-07-08 13:30:27 +0800733 // Create mock I2CInterface. A two-byte read should NOT occur.
734 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
735 std::make_unique<i2c::MockedI2CInterface>();
736 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
737
738 // Create Device
739 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800740 "reg1", true,
741 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800742 std::move(i2cInterface));
743 Device* devicePtr = device.get();
744
745 // Create Chassis that contains Device
746 std::vector<std::unique_ptr<Device>> devices{};
747 devices.emplace_back(std::move(device));
748 std::unique_ptr<Chassis> chassis =
749 std::make_unique<Chassis>(1, std::move(devices));
750 Chassis* chassisPtr = chassis.get();
751
752 // Create System that contains Chassis
753 std::vector<std::unique_ptr<Rule>> rules{};
754 std::vector<std::unique_ptr<Chassis>> chassisVec{};
755 chassisVec.emplace_back(std::move(chassis));
756 System system{std::move(rules), std::move(chassisVec)};
757
Bob King8a552922020-08-05 17:02:31 +0800758 // Call monitorSensors().
759 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800760 }
761
762 // Test where Rails were specified in constructor
763 {
Bob King8a552922020-08-05 17:02:31 +0800764 // Create mock services. No logging should occur.
765 MockServices services{};
766 MockJournal& journal = services.getMockJournal();
767 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
768 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
769
Bob King8e1cd0b2020-07-08 13:30:27 +0800770 std::vector<std::unique_ptr<Rail>> rails{};
771
772 // Create PMBusReadSensorAction
773 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
774 uint8_t command = 0x8C;
775 pmbus_utils::SensorDataFormat format{
776 pmbus_utils::SensorDataFormat::linear_11};
777 std::optional<int8_t> exponent{};
778 std::unique_ptr<PMBusReadSensorAction> action =
779 std::make_unique<PMBusReadSensorAction>(type, command, format,
780 exponent);
781
782 // Create mock I2CInterface. A two-byte read should occur.
783 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
784 std::make_unique<i2c::MockedI2CInterface>();
785 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
786 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
787 .Times(1);
788
789 // Create SensorMonitoring
790 std::vector<std::unique_ptr<Action>> actions{};
791 actions.emplace_back(std::move(action));
792 std::unique_ptr<SensorMonitoring> sensorMonitoring =
793 std::make_unique<SensorMonitoring>(std::move(actions));
794
795 // Create Rail
796 std::unique_ptr<Configuration> configuration{};
797 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
798 "vdd0", std::move(configuration), std::move(sensorMonitoring));
799 rails.emplace_back(std::move(rail));
800
801 // Create Device
802 std::unique_ptr<PresenceDetection> presenceDetection{};
803 std::unique_ptr<Configuration> deviceConfiguration{};
804 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800805 "reg1", true,
806 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800807 std::move(i2cInterface), std::move(presenceDetection),
808 std::move(deviceConfiguration), std::move(rails));
809 Device* devicePtr = device.get();
810
811 // Create Chassis that contains Device
812 std::vector<std::unique_ptr<Device>> devices{};
813 devices.emplace_back(std::move(device));
814 std::unique_ptr<Chassis> chassis =
815 std::make_unique<Chassis>(1, std::move(devices));
816 Chassis* chassisPtr = chassis.get();
817
818 // Create System that contains Chassis
819 std::vector<std::unique_ptr<Rule>> rules{};
820 std::vector<std::unique_ptr<Chassis>> chassisVec{};
821 chassisVec.emplace_back(std::move(chassis));
822 System system{std::move(rules), std::move(chassisVec)};
823
824 // Call monitorSensors().
Bob King8a552922020-08-05 17:02:31 +0800825 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800826 }
827}