blob: 33bdab3f1af2e9ed15d44ffb3c2cffc0c7efe4f6 [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 McCarney81a2f902021-03-23 21:41:34 -050023#include "mock_error_logging.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050024#include "mock_journal.hpp"
Bob King23243f82020-07-29 10:38:57 +080025#include "mock_services.hpp"
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050026#include "mocked_i2c_interface.hpp"
Bob King8e1cd0b2020-07-08 13:30:27 +080027#include "pmbus_read_sensor_action.hpp"
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050028#include "presence_detection.hpp"
29#include "rail.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050030#include "rule.hpp"
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050031#include "system.hpp"
Shawn McCarney8a3afd72020-03-12 14:28:44 -050032#include "test_utils.hpp"
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060033
34#include <memory>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050035#include <optional>
Shawn McCarney525e20c2020-04-14 11:05:39 -050036#include <string>
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060037#include <utility>
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050038#include <vector>
Shawn McCarneya2461b32019-10-24 18:53:01 -050039
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050040#include <gmock/gmock.h>
Shawn McCarneya2461b32019-10-24 18:53:01 -050041#include <gtest/gtest.h>
42
43using namespace phosphor::power::regulators;
Shawn McCarney8a3afd72020-03-12 14:28:44 -050044using namespace phosphor::power::regulators::test_utils;
Shawn McCarneyafb7fc32019-12-11 19:42:03 -060045
Bob King8e1cd0b2020-07-08 13:30:27 +080046using ::testing::A;
Shawn McCarney81a2f902021-03-23 21:41:34 -050047using ::testing::Ref;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050048using ::testing::Return;
Shawn McCarneyb4d18a42020-06-02 10:27:05 -050049using ::testing::Throw;
Bob King8e1cd0b2020-07-08 13:30:27 +080050using ::testing::TypedEq;
Shawn McCarneyeb7bec42020-04-14 09:38:15 -050051
Shawn McCarneya2461b32019-10-24 18:53:01 -050052TEST(DeviceTests, Constructor)
53{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050054 // Test where only required parameters are specified
55 {
56 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
57 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +080058 Device device{
59 "vdd_reg", true,
60 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
61 std::move(i2cInterface)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050062 EXPECT_EQ(device.getID(), "vdd_reg");
63 EXPECT_EQ(device.isRegulator(), true);
Bob Kinga76898f2020-10-13 15:08:33 +080064 EXPECT_EQ(
65 device.getFRU(),
66 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarney0b1a0e72020-03-11 18:01:44 -050067 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
68 EXPECT_EQ(device.getPresenceDetection(), nullptr);
69 EXPECT_EQ(device.getConfiguration(), nullptr);
70 EXPECT_EQ(device.getRails().size(), 0);
71 }
72
73 // Test where all parameters are specified
74 {
75 // Create I2CInterface
76 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
77 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
78
79 // Create PresenceDetection
80 std::vector<std::unique_ptr<Action>> actions{};
81 actions.push_back(std::make_unique<MockAction>());
82 std::unique_ptr<PresenceDetection> presenceDetection =
83 std::make_unique<PresenceDetection>(std::move(actions));
84
85 // Create Configuration
86 std::optional<double> volts{};
87 actions.clear();
88 actions.push_back(std::make_unique<MockAction>());
89 actions.push_back(std::make_unique<MockAction>());
90 std::unique_ptr<Configuration> configuration =
91 std::make_unique<Configuration>(volts, std::move(actions));
92
93 // Create vector of Rail objects
94 std::vector<std::unique_ptr<Rail>> rails{};
95 rails.push_back(std::make_unique<Rail>("vdd0"));
96 rails.push_back(std::make_unique<Rail>("vdd1"));
97
98 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +080099 Device device{
100 "vdd_reg",
101 false,
102 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
103 std::move(i2cInterface),
104 std::move(presenceDetection),
105 std::move(configuration),
106 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500107 EXPECT_EQ(device.getID(), "vdd_reg");
108 EXPECT_EQ(device.isRegulator(), false);
Bob Kinga76898f2020-10-13 15:08:33 +0800109 EXPECT_EQ(
110 device.getFRU(),
111 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1");
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500112 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
113 EXPECT_NE(device.getPresenceDetection(), nullptr);
114 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
115 EXPECT_NE(device.getConfiguration(), nullptr);
116 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false);
117 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
118 EXPECT_EQ(device.getRails().size(), 2);
119 }
Shawn McCarneya2461b32019-10-24 18:53:01 -0500120}
121
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500122TEST(DeviceTests, AddToIDMap)
123{
124 std::unique_ptr<PresenceDetection> presenceDetection{};
125 std::unique_ptr<Configuration> configuration{};
126
127 // Create vector of Rail objects
128 std::vector<std::unique_ptr<Rail>> rails{};
129 rails.push_back(std::make_unique<Rail>("vdd0"));
130 rails.push_back(std::make_unique<Rail>("vdd1"));
131
132 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800133 Device device{
134 "vdd_reg",
135 false,
136 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
137 std::move(createI2CInterface()),
138 std::move(presenceDetection),
139 std::move(configuration),
140 std::move(rails)};
Shawn McCarneydb0b8332020-04-06 14:13:04 -0500141
142 // Add Device and Rail objects to an IDMap
143 IDMap idMap{};
144 device.addToIDMap(idMap);
145
146 // Verify Device is in the IDMap
147 EXPECT_NO_THROW(idMap.getDevice("vdd_reg"));
148 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument);
149
150 // Verify all Rails are in the IDMap
151 EXPECT_NO_THROW(idMap.getRail("vdd0"));
152 EXPECT_NO_THROW(idMap.getRail("vdd1"));
153 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument);
154}
155
Shawn McCarney9bd94d32021-01-25 19:40:42 -0600156TEST(DeviceTests, ClearCache)
157{
158 // Test where Device does not contain a PresenceDetection object
159 try
160 {
161 Device device{
162 "vdd_reg", false,
163 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
164 std::move(createI2CInterface())};
165 device.clearCache();
166 }
167 catch (...)
168 {
169 ADD_FAILURE() << "Should not have caught exception.";
170 }
171
172 // Test where Device contains a PresenceDetection object
173 {
174 // Create PresenceDetection
175 std::vector<std::unique_ptr<Action>> actions{};
176 std::unique_ptr<PresenceDetection> presenceDetection =
177 std::make_unique<PresenceDetection>(std::move(actions));
178 PresenceDetection* presenceDetectionPtr = presenceDetection.get();
179
180 // Create Device
181 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
182 std::unique_ptr<Device> device = std::make_unique<Device>(
183 "reg1", true,
184 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
185 std::move(i2cInterface), std::move(presenceDetection));
186 Device* devicePtr = device.get();
187
188 // Create Chassis that contains Device
189 std::vector<std::unique_ptr<Device>> devices{};
190 devices.emplace_back(std::move(device));
191 std::unique_ptr<Chassis> chassis =
192 std::make_unique<Chassis>(1, std::move(devices));
193 Chassis* chassisPtr = chassis.get();
194
195 // Create System that contains Chassis
196 std::vector<std::unique_ptr<Rule>> rules{};
197 std::vector<std::unique_ptr<Chassis>> chassisVec{};
198 chassisVec.emplace_back(std::move(chassis));
199 System system{std::move(rules), std::move(chassisVec)};
200
201 // Cache presence value in PresenceDetection
202 MockServices services{};
203 presenceDetectionPtr->execute(services, system, *chassisPtr,
204 *devicePtr);
205 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value());
206
207 // Clear cached data in Device
208 devicePtr->clearCache();
209
210 // Verify presence value no longer cached in PresenceDetection
211 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value());
212 }
213}
214
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500215TEST(DeviceTests, Close)
216{
217 // Test where works: I2C interface is not open
218 {
219 // Create mock I2CInterface
220 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
221 std::make_unique<i2c::MockedI2CInterface>();
222 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false));
223 EXPECT_CALL(*i2cInterface, close).Times(0);
224
Bob Kingd692d6d2020-09-14 13:42:57 +0800225 // Create mock services. No logError should occur.
226 MockServices services{};
227 MockJournal& journal = services.getMockJournal();
228 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
229 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
230 .Times(0);
231
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500232 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800233 Device device{
234 "vdd_reg", true,
235 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
236 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500237
238 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800239 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500240 }
241
242 // Test where works: I2C interface is open
243 {
244 // Create mock I2CInterface
245 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
246 std::make_unique<i2c::MockedI2CInterface>();
247 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
248 EXPECT_CALL(*i2cInterface, close).Times(1);
249
Bob Kingd692d6d2020-09-14 13:42:57 +0800250 // Create mock services. No logError should occur.
251 MockServices services{};
252 MockJournal& journal = services.getMockJournal();
253 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
254 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>()))
255 .Times(0);
256
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500257 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800258 Device device{
259 "vdd_reg", true,
260 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
261 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500262
263 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800264 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500265 }
266
267 // Test where fails: closing I2C interface fails
268 {
269 // Create mock I2CInterface
270 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
271 std::make_unique<i2c::MockedI2CInterface>();
272 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
273 EXPECT_CALL(*i2cInterface, close)
274 .Times(1)
275 .WillOnce(Throw(
276 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70}));
277
Shawn McCarney81a2f902021-03-23 21:41:34 -0500278 // Create mock services. Expect logError() and logI2CError() to be
279 // called.
Bob Kingd692d6d2020-09-14 13:42:57 +0800280 MockServices services{};
Shawn McCarney81a2f902021-03-23 21:41:34 -0500281 MockErrorLogging& errorLogging = services.getMockErrorLogging();
Bob Kingd692d6d2020-09-14 13:42:57 +0800282 MockJournal& journal = services.getMockJournal();
283 std::vector<std::string> expectedErrMessagesException{
284 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"};
285 EXPECT_CALL(journal, logError("Unable to close device vdd_reg"))
286 .Times(1);
287 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1);
Shawn McCarney81a2f902021-03-23 21:41:34 -0500288 EXPECT_CALL(errorLogging,
289 logI2CError(Entry::Level::Notice, Ref(journal),
290 "/dev/i2c-1", 0x70, 0))
291 .Times(1);
Bob Kingd692d6d2020-09-14 13:42:57 +0800292
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500293 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800294 Device device{
295 "vdd_reg", true,
296 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
297 std::move(i2cInterface)};
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500298
299 // Close Device
Bob Kingd692d6d2020-09-14 13:42:57 +0800300 device.close(services);
Shawn McCarneyb4d18a42020-06-02 10:27:05 -0500301 }
302}
303
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500304TEST(DeviceTests, Configure)
305{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600306 // Test where device is not present
307 {
308 // Create mock services. No logging should occur.
309 MockServices services{};
310 MockJournal& journal = services.getMockJournal();
311 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
312 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
313
314 // Create PresenceDetection. Indicates device is not present.
315 std::unique_ptr<MockAction> presAction = std::make_unique<MockAction>();
316 EXPECT_CALL(*presAction, execute).Times(1).WillOnce(Return(false));
317 std::vector<std::unique_ptr<Action>> presActions{};
318 presActions.emplace_back(std::move(presAction));
319 std::unique_ptr<PresenceDetection> presenceDetection =
320 std::make_unique<PresenceDetection>(std::move(presActions));
321
322 // Create Configuration. Action inside it should not be executed.
323 std::optional<double> volts{};
324 std::unique_ptr<MockAction> confAction = std::make_unique<MockAction>();
325 EXPECT_CALL(*confAction, execute).Times(0);
326 std::vector<std::unique_ptr<Action>> confActions{};
327 confActions.emplace_back(std::move(confAction));
328 std::unique_ptr<Configuration> configuration =
329 std::make_unique<Configuration>(volts, std::move(confActions));
330
331 // Create Device
332 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
333 std::unique_ptr<Device> device = std::make_unique<Device>(
334 "reg1", true,
335 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
336 std::move(i2cInterface), std::move(presenceDetection),
337 std::move(configuration));
338 Device* devicePtr = device.get();
339
340 // Create Chassis that contains Device
341 std::vector<std::unique_ptr<Device>> devices{};
342 devices.emplace_back(std::move(device));
343 std::unique_ptr<Chassis> chassis =
344 std::make_unique<Chassis>(1, std::move(devices));
345 Chassis* chassisPtr = chassis.get();
346
347 // Create System that contains Chassis
348 std::vector<std::unique_ptr<Rule>> rules{};
349 std::vector<std::unique_ptr<Chassis>> chassisVec{};
350 chassisVec.emplace_back(std::move(chassis));
351 System system{std::move(rules), std::move(chassisVec)};
352
353 // Call configure(). Should do nothing.
354 devicePtr->configure(services, system, *chassisPtr);
355 }
356
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500357 // Test where Configuration and Rails were not specified in constructor
358 {
Bob King5cfe5102020-07-30 16:26:18 +0800359 // Create mock services. No logging should occur.
Bob King23243f82020-07-29 10:38:57 +0800360 MockServices services{};
Bob King5cfe5102020-07-30 16:26:18 +0800361 MockJournal& journal = services.getMockJournal();
362 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
363 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
Bob King23243f82020-07-29 10:38:57 +0800364
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500365 // Create Device
366 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
367 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800368 "reg1", true,
369 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500370 std::move(i2cInterface));
371 Device* devicePtr = device.get();
372
373 // Create Chassis that contains Device
374 std::vector<std::unique_ptr<Device>> devices{};
375 devices.emplace_back(std::move(device));
376 std::unique_ptr<Chassis> chassis =
377 std::make_unique<Chassis>(1, std::move(devices));
378 Chassis* chassisPtr = chassis.get();
379
380 // Create System that contains Chassis
381 std::vector<std::unique_ptr<Rule>> rules{};
382 std::vector<std::unique_ptr<Chassis>> chassisVec{};
383 chassisVec.emplace_back(std::move(chassis));
384 System system{std::move(rules), std::move(chassisVec)};
385
Bob King5cfe5102020-07-30 16:26:18 +0800386 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800387 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500388 }
389
390 // Test where Configuration and Rails were specified in constructor
391 {
392 std::vector<std::unique_ptr<Rail>> rails{};
393
Bob King5cfe5102020-07-30 16:26:18 +0800394 // Create mock services. Expect logDebug() to be called.
395 // For the Device and both Rails, should execute the Configuration
396 // and log a debug message.
397 MockServices services{};
398 MockJournal& journal = services.getMockJournal();
399 EXPECT_CALL(journal, logDebug("Configuring reg1")).Times(1);
400 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000"))
401 .Times(1);
402 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000"))
403 .Times(1);
404 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
405
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500406 // Create Rail vdd0
407 {
408 // Create Configuration for Rail
409 std::optional<double> volts{1.3};
410 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
411 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
412 std::vector<std::unique_ptr<Action>> actions{};
413 actions.emplace_back(std::move(action));
414 std::unique_ptr<Configuration> configuration =
415 std::make_unique<Configuration>(volts, std::move(actions));
416
417 // Create Rail
418 std::unique_ptr<Rail> rail =
419 std::make_unique<Rail>("vdd0", std::move(configuration));
420 rails.emplace_back(std::move(rail));
421 }
422
423 // Create Rail vio0
424 {
425 // Create Configuration for Rail
426 std::optional<double> volts{3.2};
427 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
428 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
429 std::vector<std::unique_ptr<Action>> actions{};
430 actions.emplace_back(std::move(action));
431 std::unique_ptr<Configuration> configuration =
432 std::make_unique<Configuration>(volts, std::move(actions));
433
434 // Create Rail
435 std::unique_ptr<Rail> rail =
436 std::make_unique<Rail>("vio0", std::move(configuration));
437 rails.emplace_back(std::move(rail));
438 }
439
440 // Create Configuration for Device
441 std::optional<double> volts{};
442 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
443 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
444 std::vector<std::unique_ptr<Action>> actions{};
445 actions.emplace_back(std::move(action));
446 std::unique_ptr<Configuration> configuration =
447 std::make_unique<Configuration>(volts, std::move(actions));
448
449 // Create Device
450 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
451 std::unique_ptr<PresenceDetection> presenceDetection{};
452 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800453 "reg1", true,
454 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500455 std::move(i2cInterface), std::move(presenceDetection),
456 std::move(configuration), std::move(rails));
457 Device* devicePtr = device.get();
458
459 // Create Chassis that contains Device
460 std::vector<std::unique_ptr<Device>> devices{};
461 devices.emplace_back(std::move(device));
462 std::unique_ptr<Chassis> chassis =
463 std::make_unique<Chassis>(1, std::move(devices));
464 Chassis* chassisPtr = chassis.get();
465
466 // Create System that contains Chassis
467 std::vector<std::unique_ptr<Rule>> rules{};
468 std::vector<std::unique_ptr<Chassis>> chassisVec{};
469 chassisVec.emplace_back(std::move(chassis));
470 System system{std::move(rules), std::move(chassisVec)};
471
Bob King5cfe5102020-07-30 16:26:18 +0800472 // Call configure().
Bob King23243f82020-07-29 10:38:57 +0800473 devicePtr->configure(services, system, *chassisPtr);
Shawn McCarneyeb7bec42020-04-14 09:38:15 -0500474 }
475}
476
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500477TEST(DeviceTests, GetConfiguration)
Shawn McCarneya2461b32019-10-24 18:53:01 -0500478{
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500479 // Test where Configuration was not specified in constructor
480 {
Bob Kinga76898f2020-10-13 15:08:33 +0800481 Device device{
482 "vdd_reg", true,
483 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
484 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500485 EXPECT_EQ(device.getConfiguration(), nullptr);
486 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600487
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500488 // Test where Configuration was specified in constructor
489 {
490 std::unique_ptr<PresenceDetection> presenceDetection{};
491
492 // Create Configuration
493 std::optional<double> volts{3.2};
494 std::vector<std::unique_ptr<Action>> actions{};
495 actions.push_back(std::make_unique<MockAction>());
496 actions.push_back(std::make_unique<MockAction>());
497 std::unique_ptr<Configuration> configuration =
498 std::make_unique<Configuration>(volts, std::move(actions));
499
500 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800501 Device device{
502 "vdd_reg",
503 true,
504 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
505 std::move(createI2CInterface()),
506 std::move(presenceDetection),
507 std::move(configuration)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500508 EXPECT_NE(device.getConfiguration(), nullptr);
509 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true);
510 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2);
511 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2);
512 }
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600513}
514
515TEST(DeviceTests, GetFRU)
516{
Bob Kinga76898f2020-10-13 15:08:33 +0800517 Device device{
518 "vdd_reg", true,
519 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
520 std::move(createI2CInterface())};
521 EXPECT_EQ(device.getFRU(),
522 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2");
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600523}
524
525TEST(DeviceTests, GetI2CInterface)
526{
527 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
528 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get();
Bob Kinga76898f2020-10-13 15:08:33 +0800529 Device device{
530 "vdd_reg", true,
531 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
532 std::move(i2cInterface)};
Shawn McCarneyafb7fc32019-12-11 19:42:03 -0600533 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr);
Shawn McCarneya2461b32019-10-24 18:53:01 -0500534}
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500535
536TEST(DeviceTests, GetID)
537{
Bob Kinga76898f2020-10-13 15:08:33 +0800538 Device device{
539 "vdd_reg", false,
540 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
541 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500542 EXPECT_EQ(device.getID(), "vdd_reg");
543}
544
545TEST(DeviceTests, GetPresenceDetection)
546{
547 // Test where PresenceDetection was not specified in constructor
548 {
Bob Kinga76898f2020-10-13 15:08:33 +0800549 Device device{
550 "vdd_reg", true,
551 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
552 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500553 EXPECT_EQ(device.getPresenceDetection(), nullptr);
554 }
555
556 // Test where PresenceDetection was specified in constructor
557 {
558 // Create PresenceDetection
559 std::vector<std::unique_ptr<Action>> actions{};
560 actions.push_back(std::make_unique<MockAction>());
561 std::unique_ptr<PresenceDetection> presenceDetection =
562 std::make_unique<PresenceDetection>(std::move(actions));
563
564 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800565 Device device{
566 "vdd_reg", false,
567 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
568 std::move(createI2CInterface()), std::move(presenceDetection)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500569 EXPECT_NE(device.getPresenceDetection(), nullptr);
570 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1);
571 }
572}
573
574TEST(DeviceTests, GetRails)
575{
576 // Test where no rails were specified in constructor
577 {
Bob Kinga76898f2020-10-13 15:08:33 +0800578 Device device{
579 "vdd_reg", true,
580 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
581 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500582 EXPECT_EQ(device.getRails().size(), 0);
583 }
584
585 // Test where rails were specified in constructor
586 {
587 std::unique_ptr<PresenceDetection> presenceDetection{};
588 std::unique_ptr<Configuration> configuration{};
589
590 // Create vector of Rail objects
591 std::vector<std::unique_ptr<Rail>> rails{};
592 rails.push_back(std::make_unique<Rail>("vdd0"));
593 rails.push_back(std::make_unique<Rail>("vdd1"));
594
595 // Create Device
Bob Kinga76898f2020-10-13 15:08:33 +0800596 Device device{
597 "vdd_reg",
598 false,
599 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
600 std::move(createI2CInterface()),
601 std::move(presenceDetection),
602 std::move(configuration),
603 std::move(rails)};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500604 EXPECT_EQ(device.getRails().size(), 2);
605 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0");
606 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1");
607 }
608}
609
Shawn McCarney48033bf2021-01-27 17:56:49 -0600610TEST(DeviceTests, IsPresent)
611{
612 // Test where PresenceDetection not specified in constructor
613 {
614 // Create Device
615 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
616 std::unique_ptr<Device> device = std::make_unique<Device>(
617 "reg1", true,
618 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
619 std::move(i2cInterface));
620 Device* devicePtr = device.get();
621
622 // Create Chassis that contains Device
623 std::vector<std::unique_ptr<Device>> devices{};
624 devices.emplace_back(std::move(device));
625 std::unique_ptr<Chassis> chassis =
626 std::make_unique<Chassis>(1, std::move(devices));
627 Chassis* chassisPtr = chassis.get();
628
629 // Create System that contains Chassis
630 std::vector<std::unique_ptr<Rule>> rules{};
631 std::vector<std::unique_ptr<Chassis>> chassisVec{};
632 chassisVec.emplace_back(std::move(chassis));
633 System system{std::move(rules), std::move(chassisVec)};
634
635 // Create MockServices
636 MockServices services{};
637
638 // Since no PresenceDetection defined, isPresent() should return true
639 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
640 }
641
642 // Test where PresenceDetection was specified in constructor: Is present
643 {
644 // Create PresenceDetection. Indicates device is present.
645 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
646 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true));
647 std::vector<std::unique_ptr<Action>> actions{};
648 actions.emplace_back(std::move(action));
649 std::unique_ptr<PresenceDetection> presenceDetection =
650 std::make_unique<PresenceDetection>(std::move(actions));
651
652 // Create Device
653 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
654 std::unique_ptr<Device> device = std::make_unique<Device>(
655 "reg1", true,
656 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
657 std::move(i2cInterface), std::move(presenceDetection));
658 Device* devicePtr = device.get();
659
660 // Create Chassis that contains Device
661 std::vector<std::unique_ptr<Device>> devices{};
662 devices.emplace_back(std::move(device));
663 std::unique_ptr<Chassis> chassis =
664 std::make_unique<Chassis>(1, std::move(devices));
665 Chassis* chassisPtr = chassis.get();
666
667 // Create System that contains Chassis
668 std::vector<std::unique_ptr<Rule>> rules{};
669 std::vector<std::unique_ptr<Chassis>> chassisVec{};
670 chassisVec.emplace_back(std::move(chassis));
671 System system{std::move(rules), std::move(chassisVec)};
672
673 // Create MockServices
674 MockServices services{};
675
676 // PresenceDetection::execute() and isPresent() should return true
677 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr));
678 }
679
680 // Test where PresenceDetection was specified in constructor: Is not present
681 {
682 // Create PresenceDetection. Indicates device is not present.
683 std::unique_ptr<MockAction> action = std::make_unique<MockAction>();
684 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false));
685 std::vector<std::unique_ptr<Action>> actions{};
686 actions.emplace_back(std::move(action));
687 std::unique_ptr<PresenceDetection> presenceDetection =
688 std::make_unique<PresenceDetection>(std::move(actions));
689
690 // Create Device
691 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface();
692 std::unique_ptr<Device> device = std::make_unique<Device>(
693 "reg1", true,
694 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
695 std::move(i2cInterface), std::move(presenceDetection));
696 Device* devicePtr = device.get();
697
698 // Create Chassis that contains Device
699 std::vector<std::unique_ptr<Device>> devices{};
700 devices.emplace_back(std::move(device));
701 std::unique_ptr<Chassis> chassis =
702 std::make_unique<Chassis>(1, std::move(devices));
703 Chassis* chassisPtr = chassis.get();
704
705 // Create System that contains Chassis
706 std::vector<std::unique_ptr<Rule>> rules{};
707 std::vector<std::unique_ptr<Chassis>> chassisVec{};
708 chassisVec.emplace_back(std::move(chassis));
709 System system{std::move(rules), std::move(chassisVec)};
710
711 // Create MockServices
712 MockServices services{};
713
714 // PresenceDetection::execute() and isPresent() should return false
715 EXPECT_FALSE(devicePtr->isPresent(services, system, *chassisPtr));
716 }
717}
718
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500719TEST(DeviceTests, IsRegulator)
720{
Bob Kinga76898f2020-10-13 15:08:33 +0800721 Device device{
722 "vdd_reg", false,
723 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2",
724 std::move(createI2CInterface())};
Shawn McCarney0b1a0e72020-03-11 18:01:44 -0500725 EXPECT_EQ(device.isRegulator(), false);
726}
Bob King8e1cd0b2020-07-08 13:30:27 +0800727
728TEST(DeviceTests, MonitorSensors)
729{
Shawn McCarney48033bf2021-01-27 17:56:49 -0600730 // Test where device is not present
731 // TODO: Add this test when sensoring monitoring is fully implemented
732
Bob King8e1cd0b2020-07-08 13:30:27 +0800733 // Test where Rails were not specified in constructor
734 {
Bob King8a552922020-08-05 17:02:31 +0800735 // Create mock services. No logging should occur.
736 MockServices services{};
737 MockJournal& journal = services.getMockJournal();
738 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
739 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
740
Bob King8e1cd0b2020-07-08 13:30:27 +0800741 // Create mock I2CInterface. A two-byte read should NOT occur.
742 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
743 std::make_unique<i2c::MockedI2CInterface>();
744 EXPECT_CALL(*i2cInterface, read(A<uint8_t>(), A<uint16_t&>())).Times(0);
745
746 // Create Device
747 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800748 "reg1", true,
749 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800750 std::move(i2cInterface));
751 Device* devicePtr = device.get();
752
753 // Create Chassis that contains Device
754 std::vector<std::unique_ptr<Device>> devices{};
755 devices.emplace_back(std::move(device));
756 std::unique_ptr<Chassis> chassis =
757 std::make_unique<Chassis>(1, std::move(devices));
758 Chassis* chassisPtr = chassis.get();
759
760 // Create System that contains Chassis
761 std::vector<std::unique_ptr<Rule>> rules{};
762 std::vector<std::unique_ptr<Chassis>> chassisVec{};
763 chassisVec.emplace_back(std::move(chassis));
764 System system{std::move(rules), std::move(chassisVec)};
765
Bob King8a552922020-08-05 17:02:31 +0800766 // Call monitorSensors().
767 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800768 }
769
770 // Test where Rails were specified in constructor
771 {
Bob King8a552922020-08-05 17:02:31 +0800772 // Create mock services. No logging should occur.
773 MockServices services{};
774 MockJournal& journal = services.getMockJournal();
775 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0);
776 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0);
777
Bob King8e1cd0b2020-07-08 13:30:27 +0800778 std::vector<std::unique_ptr<Rail>> rails{};
779
780 // Create PMBusReadSensorAction
781 pmbus_utils::SensorValueType type{pmbus_utils::SensorValueType::iout};
782 uint8_t command = 0x8C;
783 pmbus_utils::SensorDataFormat format{
784 pmbus_utils::SensorDataFormat::linear_11};
785 std::optional<int8_t> exponent{};
786 std::unique_ptr<PMBusReadSensorAction> action =
787 std::make_unique<PMBusReadSensorAction>(type, command, format,
788 exponent);
789
790 // Create mock I2CInterface. A two-byte read should occur.
791 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface =
792 std::make_unique<i2c::MockedI2CInterface>();
793 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true));
794 EXPECT_CALL(*i2cInterface, read(TypedEq<uint8_t>(0x8C), A<uint16_t&>()))
795 .Times(1);
796
797 // Create SensorMonitoring
798 std::vector<std::unique_ptr<Action>> actions{};
799 actions.emplace_back(std::move(action));
800 std::unique_ptr<SensorMonitoring> sensorMonitoring =
801 std::make_unique<SensorMonitoring>(std::move(actions));
802
803 // Create Rail
804 std::unique_ptr<Configuration> configuration{};
805 std::unique_ptr<Rail> rail = std::make_unique<Rail>(
806 "vdd0", std::move(configuration), std::move(sensorMonitoring));
807 rails.emplace_back(std::move(rail));
808
809 // Create Device
810 std::unique_ptr<PresenceDetection> presenceDetection{};
811 std::unique_ptr<Configuration> deviceConfiguration{};
812 std::unique_ptr<Device> device = std::make_unique<Device>(
Bob Kinga76898f2020-10-13 15:08:33 +0800813 "reg1", true,
814 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1",
Bob King8e1cd0b2020-07-08 13:30:27 +0800815 std::move(i2cInterface), std::move(presenceDetection),
816 std::move(deviceConfiguration), std::move(rails));
817 Device* devicePtr = device.get();
818
819 // Create Chassis that contains Device
820 std::vector<std::unique_ptr<Device>> devices{};
821 devices.emplace_back(std::move(device));
822 std::unique_ptr<Chassis> chassis =
823 std::make_unique<Chassis>(1, std::move(devices));
824 Chassis* chassisPtr = chassis.get();
825
826 // Create System that contains Chassis
827 std::vector<std::unique_ptr<Rule>> rules{};
828 std::vector<std::unique_ptr<Chassis>> chassisVec{};
829 chassisVec.emplace_back(std::move(chassis));
830 System system{std::move(rules), std::move(chassisVec)};
831
832 // Call monitorSensors().
Bob King8a552922020-08-05 17:02:31 +0800833 devicePtr->monitorSensors(services, system, *chassisPtr);
Bob King8e1cd0b2020-07-08 13:30:27 +0800834 }
835}