blob: 479767be096648a69f00b467498984359a2ab970 [file] [log] [blame]
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -06001/**
2 * Copyright © 2024 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 */
16
Shawn McCarney24956592024-02-19 18:58:57 -060017#include "mock_device.hpp"
18#include "mock_services.hpp"
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060019#include "rail.hpp"
20
21#include <cstdint>
Shawn McCarney24956592024-02-19 18:58:57 -060022#include <map>
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060023#include <optional>
24#include <string>
Shawn McCarney24956592024-02-19 18:58:57 -060025#include <vector>
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060026
Shawn McCarney24956592024-02-19 18:58:57 -060027#include <gmock/gmock.h>
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060028#include <gtest/gtest.h>
29
30using namespace phosphor::power::sequencer;
31
Shawn McCarney24956592024-02-19 18:58:57 -060032using ::testing::Return;
33using ::testing::Throw;
34
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060035TEST(GPIOTests, Initialization)
36{
37 // Default initialization
38 {
39 GPIO gpio;
40 EXPECT_EQ(gpio.line, 0);
41 EXPECT_FALSE(gpio.activeLow);
42 }
43
44 // Explicit initialization
45 {
46 GPIO gpio{48, true};
47 EXPECT_EQ(gpio.line, 48);
48 EXPECT_TRUE(gpio.activeLow);
49 }
50}
51
52TEST(RailTests, Constructor)
53{
54 // Test where succeeds: No optional parameters have values
55 {
Shawn McCarney16e493a2024-01-29 14:20:32 -060056 std::string name{"12.0V"};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060057 std::optional<std::string> presence{};
58 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -060059 bool isPowerSupplyRail{true};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060060 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -060061 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060062 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -060063 Rail rail{name,
64 presence,
65 page,
66 isPowerSupplyRail,
67 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -060068 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060069 gpio};
70
Shawn McCarney16e493a2024-01-29 14:20:32 -060071 EXPECT_EQ(rail.getName(), "12.0V");
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060072 EXPECT_FALSE(rail.getPresence().has_value());
73 EXPECT_FALSE(rail.getPage().has_value());
Shawn McCarney16e493a2024-01-29 14:20:32 -060074 EXPECT_TRUE(rail.isPowerSupplyRail());
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060075 EXPECT_FALSE(rail.getCheckStatusVout());
Shawn McCarney9ec0d432024-02-09 18:26:00 -060076 EXPECT_FALSE(rail.getCompareVoltageToLimit());
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060077 EXPECT_FALSE(rail.getGPIO().has_value());
78 }
79
80 // Test where succeeds: All optional parameters have values
81 {
82 std::string name{"VCS_CPU1"};
83 std::optional<std::string> presence{
84 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1"};
85 std::optional<uint8_t> page{11};
Shawn McCarney16e493a2024-01-29 14:20:32 -060086 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060087 bool checkStatusVout{true};
Shawn McCarney9ec0d432024-02-09 18:26:00 -060088 bool compareVoltageToLimit{true};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060089 std::optional<GPIO> gpio{GPIO(60, true)};
Shawn McCarney16e493a2024-01-29 14:20:32 -060090 Rail rail{name,
91 presence,
92 page,
93 isPowerSupplyRail,
94 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -060095 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -060096 gpio};
97
98 EXPECT_EQ(rail.getName(), "VCS_CPU1");
99 EXPECT_TRUE(rail.getPresence().has_value());
100 EXPECT_EQ(
101 rail.getPresence().value(),
102 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1");
103 EXPECT_TRUE(rail.getPage().has_value());
104 EXPECT_EQ(rail.getPage().value(), 11);
Shawn McCarney16e493a2024-01-29 14:20:32 -0600105 EXPECT_FALSE(rail.isPowerSupplyRail());
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600106 EXPECT_TRUE(rail.getCheckStatusVout());
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600107 EXPECT_TRUE(rail.getCompareVoltageToLimit());
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600108 EXPECT_TRUE(rail.getGPIO().has_value());
109 EXPECT_EQ(rail.getGPIO().value().line, 60);
110 EXPECT_TRUE(rail.getGPIO().value().activeLow);
111 }
112
113 // Test where fails: checkStatusVout is true and page has no value
114 {
115 std::string name{"VDD1"};
116 std::optional<std::string> presence{};
117 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600118 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600119 bool checkStatusVout{true};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600120 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600121 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600122 EXPECT_THROW((Rail{name, presence, page, isPowerSupplyRail,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600123 checkStatusVout, compareVoltageToLimit, gpio}),
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600124 std::invalid_argument);
125 }
126
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600127 // Test where fails: compareVoltageToLimit is true and page has no value
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600128 {
129 std::string name{"VDD1"};
130 std::optional<std::string> presence{};
131 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600132 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600133 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600134 bool compareVoltageToLimit{true};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600135 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600136 EXPECT_THROW((Rail{name, presence, page, isPowerSupplyRail,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600137 checkStatusVout, compareVoltageToLimit, gpio}),
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600138 std::invalid_argument);
139 }
140}
141
142TEST(RailTests, GetName)
143{
144 std::string name{"VDD2"};
145 std::optional<std::string> presence{};
146 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600147 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600148 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600149 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600150 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600151 Rail rail{name,
152 presence,
153 page,
154 isPowerSupplyRail,
155 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600156 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600157 gpio};
158
159 EXPECT_EQ(rail.getName(), "VDD2");
160}
161
162TEST(RailTests, GetPresence)
163{
164 std::string name{"VDDR2"};
165 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600166 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600167 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600168 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600169 std::optional<GPIO> gpio{};
170
171 // Test where presence has no value
172 {
173 std::optional<std::string> presence{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600174 Rail rail{name,
175 presence,
176 page,
177 isPowerSupplyRail,
178 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600179 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600180 gpio};
181 EXPECT_FALSE(rail.getPresence().has_value());
182 }
183
184 // Test where presence has a value
185 {
186 std::optional<std::string> presence{
187 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2"};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600188 Rail rail{name,
189 presence,
190 page,
191 isPowerSupplyRail,
192 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600193 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600194 gpio};
195 EXPECT_TRUE(rail.getPresence().has_value());
196 EXPECT_EQ(
197 rail.getPresence().value(),
198 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2");
199 }
200}
201
202TEST(RailTests, GetPage)
203{
204 std::string name{"VDD2"};
205 std::optional<std::string> presence{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600206 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600207 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600208 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600209 std::optional<GPIO> gpio{};
210
211 // Test where page has no value
212 {
213 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600214 Rail rail{name,
215 presence,
216 page,
217 isPowerSupplyRail,
218 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600219 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600220 gpio};
221 EXPECT_FALSE(rail.getPage().has_value());
222 }
223
224 // Test where page has a value
225 {
226 std::optional<uint8_t> page{7};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600227 Rail rail{name,
228 presence,
229 page,
230 isPowerSupplyRail,
231 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600232 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600233 gpio};
234 EXPECT_TRUE(rail.getPage().has_value());
235 EXPECT_EQ(rail.getPage().value(), 7);
236 }
237}
238
Shawn McCarney16e493a2024-01-29 14:20:32 -0600239TEST(RailTests, IsPowerSupplyRail)
240{
241 std::string name{"12.0V"};
242 std::optional<std::string> presence{};
243 std::optional<uint8_t> page{};
244 bool isPowerSupplyRail{true};
245 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600246 bool compareVoltageToLimit{false};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600247 std::optional<GPIO> gpio{};
248 Rail rail{name,
249 presence,
250 page,
251 isPowerSupplyRail,
252 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600253 compareVoltageToLimit,
Shawn McCarney16e493a2024-01-29 14:20:32 -0600254 gpio};
255
256 EXPECT_TRUE(rail.isPowerSupplyRail());
257}
258
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600259TEST(RailTests, GetCheckStatusVout)
260{
261 std::string name{"VDD2"};
262 std::optional<std::string> presence{};
263 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600264 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600265 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600266 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600267 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600268 Rail rail{name,
269 presence,
270 page,
271 isPowerSupplyRail,
272 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600273 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600274 gpio};
275
276 EXPECT_FALSE(rail.getCheckStatusVout());
277}
278
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600279TEST(RailTests, GetCompareVoltageToLimit)
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600280{
281 std::string name{"VDD2"};
282 std::optional<std::string> presence{};
283 std::optional<uint8_t> page{13};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600284 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600285 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600286 bool compareVoltageToLimit{true};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600287 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600288 Rail rail{name,
289 presence,
290 page,
291 isPowerSupplyRail,
292 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600293 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600294 gpio};
295
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600296 EXPECT_TRUE(rail.getCompareVoltageToLimit());
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600297}
298
299TEST(RailTests, GetGPIO)
300{
301 std::string name{"VDD2"};
302 std::optional<std::string> presence{};
303 std::optional<uint8_t> page{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600304 bool isPowerSupplyRail{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600305 bool checkStatusVout{false};
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600306 bool compareVoltageToLimit{false};
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600307
308 // Test where gpio has no value
309 {
310 std::optional<GPIO> gpio{};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600311 Rail rail{name,
312 presence,
313 page,
314 isPowerSupplyRail,
315 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600316 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600317 gpio};
318 EXPECT_FALSE(rail.getGPIO().has_value());
319 }
320
321 // Test where gpio has a value
322 {
323 std::optional<GPIO> gpio{GPIO(12, false)};
Shawn McCarney16e493a2024-01-29 14:20:32 -0600324 Rail rail{name,
325 presence,
326 page,
327 isPowerSupplyRail,
328 checkStatusVout,
Shawn McCarney9ec0d432024-02-09 18:26:00 -0600329 compareVoltageToLimit,
Shawn McCarneyd6e9bfe2024-01-05 17:52:04 -0600330 gpio};
331 EXPECT_TRUE(rail.getGPIO().has_value());
332 EXPECT_EQ(rail.getGPIO().value().line, 12);
333 EXPECT_FALSE(rail.getGPIO().value().activeLow);
334 }
335}
Shawn McCarney24956592024-02-19 18:58:57 -0600336
337TEST(RailTests, IsPresent)
338{
339 std::string name{"VDD2"};
340 std::optional<uint8_t> page{};
341 bool isPowerSupplyRail{false};
342 bool checkStatusVout{false};
343 bool compareVoltageToLimit{false};
344 std::optional<GPIO> gpio{};
345
346 // Test where inventory path not specified; always returns true
347 {
348 std::optional<std::string> presence{};
349 Rail rail{name,
350 presence,
351 page,
352 isPowerSupplyRail,
353 checkStatusVout,
354 compareVoltageToLimit,
355 gpio};
356
357 MockServices services{};
358 EXPECT_CALL(services, isPresent).Times(0);
359
360 EXPECT_TRUE(rail.isPresent(services));
361 }
362
363 // Test where inventory path is not present
364 {
365 std::optional<std::string> presence{
366 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
367 Rail rail{name,
368 presence,
369 page,
370 isPowerSupplyRail,
371 checkStatusVout,
372 compareVoltageToLimit,
373 gpio};
374
375 MockServices services{};
376 EXPECT_CALL(services, isPresent(*presence))
377 .Times(1)
378 .WillOnce(Return(false));
379
380 EXPECT_FALSE(rail.isPresent(services));
381 }
382
383 // Test where inventory path is present
384 {
385 std::optional<std::string> presence{
386 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
387 Rail rail{name,
388 presence,
389 page,
390 isPowerSupplyRail,
391 checkStatusVout,
392 compareVoltageToLimit,
393 gpio};
394
395 MockServices services{};
396 EXPECT_CALL(services, isPresent(*presence))
397 .Times(1)
398 .WillOnce(Return(true));
399
400 EXPECT_TRUE(rail.isPresent(services));
401 }
402
403 // Test where exception occurs trying to get presence
404 {
405 std::optional<std::string> presence{
406 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
407 Rail rail{name,
408 presence,
409 page,
410 isPowerSupplyRail,
411 checkStatusVout,
412 compareVoltageToLimit,
413 gpio};
414
415 MockServices services{};
416 EXPECT_CALL(services, isPresent(*presence))
417 .Times(1)
418 .WillOnce(Throw(std::runtime_error{"Invalid object path"}));
419
420 try
421 {
422 rail.isPresent(services);
423 ADD_FAILURE() << "Should not have reached this line.";
424 }
425 catch (const std::exception& e)
426 {
427 EXPECT_STREQ(
428 e.what(),
429 "Unable to determine presence of rail VDD2 using "
430 "inventory path "
431 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2: "
432 "Invalid object path");
433 }
434 }
435}
436
437TEST(RailTests, GetStatusWord)
438{
439 std::string name{"VDD2"};
440 std::optional<std::string> presence{};
441 bool isPowerSupplyRail{false};
442 bool checkStatusVout{false};
443 bool compareVoltageToLimit{false};
444 std::optional<GPIO> gpio{};
445
446 // Test where page was not specified: Throws exception
447 {
448 std::optional<uint8_t> page{};
449 Rail rail{name,
450 presence,
451 page,
452 isPowerSupplyRail,
453 checkStatusVout,
454 compareVoltageToLimit,
455 gpio};
456
457 MockDevice device{};
458 EXPECT_CALL(device, getStatusWord).Times(0);
459
460 try
461 {
462 rail.getStatusWord(device);
463 ADD_FAILURE() << "Should not have reached this line.";
464 }
465 catch (const std::exception& e)
466 {
467 EXPECT_STREQ(e.what(),
468 "Unable to read STATUS_WORD value for rail VDD2: "
469 "No PAGE number defined for rail VDD2");
470 }
471 }
472
473 // Test where value read successfully
474 {
475 std::optional<uint8_t> page{2};
476 Rail rail{name,
477 presence,
478 page,
479 isPowerSupplyRail,
480 checkStatusVout,
481 compareVoltageToLimit,
482 gpio};
483
484 MockDevice device{};
485 EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
486
487 EXPECT_EQ(rail.getStatusWord(device), 0xbeef);
488 }
489
490 // Test where exception occurs trying to read value
491 {
492 std::optional<uint8_t> page{2};
493 Rail rail{name,
494 presence,
495 page,
496 isPowerSupplyRail,
497 checkStatusVout,
498 compareVoltageToLimit,
499 gpio};
500
501 MockDevice device{};
502 EXPECT_CALL(device, getStatusWord(2))
503 .Times(1)
504 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
505
506 try
507 {
508 rail.getStatusWord(device);
509 ADD_FAILURE() << "Should not have reached this line.";
510 }
511 catch (const std::exception& e)
512 {
513 EXPECT_STREQ(e.what(),
514 "Unable to read STATUS_WORD value for rail VDD2: "
515 "File does not exist");
516 }
517 }
518}
519
520TEST(RailTests, GetStatusVout)
521{
522 std::string name{"VDD2"};
523 std::optional<std::string> presence{};
524 bool isPowerSupplyRail{false};
525 bool checkStatusVout{false};
526 bool compareVoltageToLimit{false};
527 std::optional<GPIO> gpio{};
528
529 // Test where page was not specified: Throws exception
530 {
531 std::optional<uint8_t> page{};
532 Rail rail{name,
533 presence,
534 page,
535 isPowerSupplyRail,
536 checkStatusVout,
537 compareVoltageToLimit,
538 gpio};
539
540 MockDevice device{};
541 EXPECT_CALL(device, getStatusVout).Times(0);
542
543 try
544 {
545 rail.getStatusVout(device);
546 ADD_FAILURE() << "Should not have reached this line.";
547 }
548 catch (const std::exception& e)
549 {
550 EXPECT_STREQ(e.what(),
551 "Unable to read STATUS_VOUT value for rail VDD2: "
552 "No PAGE number defined for rail VDD2");
553 }
554 }
555
556 // Test where value read successfully
557 {
558 std::optional<uint8_t> page{2};
559 Rail rail{name,
560 presence,
561 page,
562 isPowerSupplyRail,
563 checkStatusVout,
564 compareVoltageToLimit,
565 gpio};
566
567 MockDevice device{};
568 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0xad));
569
570 EXPECT_EQ(rail.getStatusVout(device), 0xad);
571 }
572
573 // Test where exception occurs trying to read value
574 {
575 std::optional<uint8_t> page{2};
576 Rail rail{name,
577 presence,
578 page,
579 isPowerSupplyRail,
580 checkStatusVout,
581 compareVoltageToLimit,
582 gpio};
583
584 MockDevice device{};
585 EXPECT_CALL(device, getStatusVout(2))
586 .Times(1)
587 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
588
589 try
590 {
591 rail.getStatusVout(device);
592 ADD_FAILURE() << "Should not have reached this line.";
593 }
594 catch (const std::exception& e)
595 {
596 EXPECT_STREQ(e.what(),
597 "Unable to read STATUS_VOUT value for rail VDD2: "
598 "File does not exist");
599 }
600 }
601}
602
603TEST(RailTests, GetReadVout)
604{
605 std::string name{"VDD2"};
606 std::optional<std::string> presence{};
607 bool isPowerSupplyRail{false};
608 bool checkStatusVout{false};
609 bool compareVoltageToLimit{false};
610 std::optional<GPIO> gpio{};
611
612 // Test where page was not specified: Throws exception
613 {
614 std::optional<uint8_t> page{};
615 Rail rail{name,
616 presence,
617 page,
618 isPowerSupplyRail,
619 checkStatusVout,
620 compareVoltageToLimit,
621 gpio};
622
623 MockDevice device{};
624 EXPECT_CALL(device, getReadVout).Times(0);
625
626 try
627 {
628 rail.getReadVout(device);
629 ADD_FAILURE() << "Should not have reached this line.";
630 }
631 catch (const std::exception& e)
632 {
633 EXPECT_STREQ(e.what(),
634 "Unable to read READ_VOUT value for rail VDD2: "
635 "No PAGE number defined for rail VDD2");
636 }
637 }
638
639 // Test where value read successfully
640 {
641 std::optional<uint8_t> page{2};
642 Rail rail{name,
643 presence,
644 page,
645 isPowerSupplyRail,
646 checkStatusVout,
647 compareVoltageToLimit,
648 gpio};
649
650 MockDevice device{};
651 EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.23));
652
653 EXPECT_EQ(rail.getReadVout(device), 1.23);
654 }
655
656 // Test where exception occurs trying to read value
657 {
658 std::optional<uint8_t> page{2};
659 Rail rail{name,
660 presence,
661 page,
662 isPowerSupplyRail,
663 checkStatusVout,
664 compareVoltageToLimit,
665 gpio};
666
667 MockDevice device{};
668 EXPECT_CALL(device, getReadVout(2))
669 .Times(1)
670 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
671
672 try
673 {
674 rail.getReadVout(device);
675 ADD_FAILURE() << "Should not have reached this line.";
676 }
677 catch (const std::exception& e)
678 {
679 EXPECT_STREQ(e.what(),
680 "Unable to read READ_VOUT value for rail VDD2: "
681 "File does not exist");
682 }
683 }
684}
685
686TEST(RailTests, GetVoutUVFaultLimit)
687{
688 std::string name{"VDD2"};
689 std::optional<std::string> presence{};
690 bool isPowerSupplyRail{false};
691 bool checkStatusVout{false};
692 bool compareVoltageToLimit{false};
693 std::optional<GPIO> gpio{};
694
695 // Test where page was not specified: Throws exception
696 {
697 std::optional<uint8_t> page{};
698 Rail rail{name,
699 presence,
700 page,
701 isPowerSupplyRail,
702 checkStatusVout,
703 compareVoltageToLimit,
704 gpio};
705
706 MockDevice device{};
707 EXPECT_CALL(device, getVoutUVFaultLimit).Times(0);
708
709 try
710 {
711 rail.getVoutUVFaultLimit(device);
712 ADD_FAILURE() << "Should not have reached this line.";
713 }
714 catch (const std::exception& e)
715 {
716 EXPECT_STREQ(
717 e.what(),
718 "Unable to read VOUT_UV_FAULT_LIMIT value for rail VDD2: "
719 "No PAGE number defined for rail VDD2");
720 }
721 }
722
723 // Test where value read successfully
724 {
725 std::optional<uint8_t> page{2};
726 Rail rail{name,
727 presence,
728 page,
729 isPowerSupplyRail,
730 checkStatusVout,
731 compareVoltageToLimit,
732 gpio};
733
734 MockDevice device{};
735 EXPECT_CALL(device, getVoutUVFaultLimit(2))
736 .Times(1)
737 .WillOnce(Return(0.9));
738
739 EXPECT_EQ(rail.getVoutUVFaultLimit(device), 0.9);
740 }
741
742 // Test where exception occurs trying to read value
743 {
744 std::optional<uint8_t> page{2};
745 Rail rail{name,
746 presence,
747 page,
748 isPowerSupplyRail,
749 checkStatusVout,
750 compareVoltageToLimit,
751 gpio};
752
753 MockDevice device{};
754 EXPECT_CALL(device, getVoutUVFaultLimit(2))
755 .Times(1)
756 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
757
758 try
759 {
760 rail.getVoutUVFaultLimit(device);
761 ADD_FAILURE() << "Should not have reached this line.";
762 }
763 catch (const std::exception& e)
764 {
765 EXPECT_STREQ(
766 e.what(),
767 "Unable to read VOUT_UV_FAULT_LIMIT value for rail VDD2: "
768 "File does not exist");
769 }
770 }
771}
772
773TEST(RailTests, HasPgoodFault)
774{
775 std::string name{"VDD2"};
776 bool isPowerSupplyRail{false};
777
778 // Test where presence check defined: Rail is not present
779 {
780 std::optional<std::string> presence{
781 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
782 std::optional<uint8_t> page{3};
783 bool checkStatusVout{true};
784 bool compareVoltageToLimit{false};
785 std::optional<GPIO> gpio{};
786 Rail rail{name,
787 presence,
788 page,
789 isPowerSupplyRail,
790 checkStatusVout,
791 compareVoltageToLimit,
792 gpio};
793
794 MockDevice device{};
795
796 MockServices services{};
797 EXPECT_CALL(services, isPresent(*presence))
798 .Times(1)
799 .WillOnce(Return(false));
800 EXPECT_CALL(services, logInfoMsg("Rail VDD2 is not present")).Times(1);
801
802 std::vector<int> gpioValues{};
803 std::map<std::string, std::string> additionalData{};
804 EXPECT_FALSE(
805 rail.hasPgoodFault(device, services, gpioValues, additionalData));
806 EXPECT_EQ(additionalData.size(), 0);
807 }
808
809 // Test where presence check defined: Rail is present
810 {
811 std::optional<std::string> presence{
812 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
813 std::optional<uint8_t> page{};
814 bool checkStatusVout{false};
815 bool compareVoltageToLimit{false};
816 std::optional<GPIO> gpio{};
817 Rail rail{name,
818 presence,
819 page,
820 isPowerSupplyRail,
821 checkStatusVout,
822 compareVoltageToLimit,
823 gpio};
824
825 MockDevice device{};
826
827 MockServices services{};
828 EXPECT_CALL(services, isPresent(*presence))
829 .Times(1)
830 .WillOnce(Return(true));
831 EXPECT_CALL(services, logInfoMsg).Times(0);
832
833 std::vector<int> gpioValues{};
834 std::map<std::string, std::string> additionalData{};
835 EXPECT_FALSE(
836 rail.hasPgoodFault(device, services, gpioValues, additionalData));
837 EXPECT_EQ(additionalData.size(), 0);
838 }
839
840 // Test where no checks are specified
841 {
842 std::optional<std::string> presence{};
843 std::optional<uint8_t> page{};
844 bool checkStatusVout{false};
845 bool compareVoltageToLimit{false};
846 std::optional<GPIO> gpio{};
847 Rail rail{name,
848 presence,
849 page,
850 isPowerSupplyRail,
851 checkStatusVout,
852 compareVoltageToLimit,
853 gpio};
854
855 MockDevice device{};
856
857 MockServices services{};
858
859 std::vector<int> gpioValues{};
860 std::map<std::string, std::string> additionalData{};
861 EXPECT_FALSE(
862 rail.hasPgoodFault(device, services, gpioValues, additionalData));
863 EXPECT_EQ(additionalData.size(), 0);
864 }
865
866 // Test where 1 check defined: STATUS_VOUT: No fault detected
867 {
868 std::optional<std::string> presence{};
869 std::optional<uint8_t> page{2};
870 bool checkStatusVout{true};
871 bool compareVoltageToLimit{false};
872 std::optional<GPIO> gpio{};
873 Rail rail{name,
874 presence,
875 page,
876 isPowerSupplyRail,
877 checkStatusVout,
878 compareVoltageToLimit,
879 gpio};
880
881 MockDevice device{};
882 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
883
884 MockServices services{};
885
886 std::vector<int> gpioValues{};
887 std::map<std::string, std::string> additionalData{};
888 EXPECT_FALSE(
889 rail.hasPgoodFault(device, services, gpioValues, additionalData));
890 EXPECT_EQ(additionalData.size(), 0);
891 }
892
893 // Test where 1 check defined: STATUS_VOUT: No fault detected, but warning
894 // bits set
895 {
896 std::optional<std::string> presence{};
897 std::optional<uint8_t> page{2};
898 bool checkStatusVout{true};
899 bool compareVoltageToLimit{false};
900 std::optional<GPIO> gpio{};
901 Rail rail{name,
902 presence,
903 page,
904 isPowerSupplyRail,
905 checkStatusVout,
906 compareVoltageToLimit,
907 gpio};
908
909 MockDevice device{};
910 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x6a));
911
912 MockServices services{};
913 EXPECT_CALL(
914 services,
915 logInfoMsg("Rail VDD2 has warning bits set in STATUS_VOUT: 0x6a"))
916 .Times(1);
917
918 std::vector<int> gpioValues{};
919 std::map<std::string, std::string> additionalData{};
920 EXPECT_FALSE(
921 rail.hasPgoodFault(device, services, gpioValues, additionalData));
922 EXPECT_EQ(additionalData.size(), 0);
923 }
924
925 // Test where 1 check defined: STATUS_VOUT: Fault detected
926 // STATUS_WORD captured in additional data
927 {
928 std::optional<std::string> presence{};
929 std::optional<uint8_t> page{2};
930 bool checkStatusVout{true};
931 bool compareVoltageToLimit{false};
932 std::optional<GPIO> gpio{};
933 Rail rail{name,
934 presence,
935 page,
936 isPowerSupplyRail,
937 checkStatusVout,
938 compareVoltageToLimit,
939 gpio};
940
941 MockDevice device{};
942 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x10));
943 EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
944
945 MockServices services{};
946 EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
947 .Times(1);
948 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
949 .Times(1);
950 EXPECT_CALL(
951 services,
952 logErrorMsg("Rail VDD2 has fault bits set in STATUS_VOUT: 0x10"))
953 .Times(1);
954
955 std::vector<int> gpioValues{};
956 std::map<std::string, std::string> additionalData{};
957 EXPECT_TRUE(
958 rail.hasPgoodFault(device, services, gpioValues, additionalData));
959 EXPECT_EQ(additionalData.size(), 3);
960 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
961 EXPECT_EQ(additionalData["STATUS_VOUT"], "0x10");
962 EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
963 }
964
965 // Test where 1 check defined: STATUS_VOUT: Exception thrown
966 {
967 std::optional<std::string> presence{};
968 std::optional<uint8_t> page{2};
969 bool checkStatusVout{true};
970 bool compareVoltageToLimit{false};
971 std::optional<GPIO> gpio{};
972 Rail rail{name,
973 presence,
974 page,
975 isPowerSupplyRail,
976 checkStatusVout,
977 compareVoltageToLimit,
978 gpio};
979
980 MockDevice device{};
981 EXPECT_CALL(device, getStatusVout(2))
982 .Times(1)
983 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
984
985 MockServices services{};
986
987 std::vector<int> gpioValues{};
988 std::map<std::string, std::string> additionalData{};
989 try
990 {
991 rail.hasPgoodFault(device, services, gpioValues, additionalData);
992 ADD_FAILURE() << "Should not have reached this line.";
993 }
994 catch (const std::exception& e)
995 {
996 EXPECT_STREQ(e.what(),
997 "Unable to read STATUS_VOUT value for rail VDD2: "
998 "File does not exist");
999 }
1000 }
1001
1002 // Test where 1 check defined: GPIO: No fault detected
1003 // GPIO value is 1 and GPIO is active high
1004 {
1005 std::optional<std::string> presence{};
1006 std::optional<uint8_t> page{};
1007 bool checkStatusVout{false};
1008 bool compareVoltageToLimit{false};
1009 bool activeLow{false};
1010 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1011 Rail rail{name,
1012 presence,
1013 page,
1014 isPowerSupplyRail,
1015 checkStatusVout,
1016 compareVoltageToLimit,
1017 gpio};
1018
1019 MockDevice device{};
1020
1021 MockServices services{};
1022
1023 std::vector<int> gpioValues{1, 1, 1, 1, 1, 1};
1024 std::map<std::string, std::string> additionalData{};
1025 EXPECT_FALSE(
1026 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1027 EXPECT_EQ(additionalData.size(), 0);
1028 }
1029
1030 // Test where 1 check defined: GPIO: Fault detected
1031 // GPIO value is 0 and GPIO is active high
1032 // STATUS_WORD not captured since no PMBus page defined
1033 {
1034 std::optional<std::string> presence{};
1035 std::optional<uint8_t> page{};
1036 bool checkStatusVout{false};
1037 bool compareVoltageToLimit{false};
1038 bool activeLow{false};
1039 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1040 Rail rail{name,
1041 presence,
1042 page,
1043 isPowerSupplyRail,
1044 checkStatusVout,
1045 compareVoltageToLimit,
1046 gpio};
1047
1048 MockDevice device{};
1049
1050 MockServices services{};
1051 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1052 .Times(1);
1053 EXPECT_CALL(
1054 services,
1055 logErrorMsg(
1056 "Rail VDD2 pgood GPIO line offset 3 has inactive value 0"))
1057 .Times(1);
1058
1059 std::vector<int> gpioValues{1, 1, 1, 0, 1, 1};
1060 std::map<std::string, std::string> additionalData{};
1061 EXPECT_TRUE(
1062 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1063 EXPECT_EQ(additionalData.size(), 3);
1064 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1065 EXPECT_EQ(additionalData["GPIO_LINE"], "3");
1066 EXPECT_EQ(additionalData["GPIO_VALUE"], "0");
1067 }
1068
1069 // Test where 1 check defined: GPIO: Exception thrown: Invalid line offset
1070 {
1071 std::optional<std::string> presence{};
1072 std::optional<uint8_t> page{};
1073 bool checkStatusVout{false};
1074 bool compareVoltageToLimit{false};
1075 bool activeLow{false};
1076 std::optional<GPIO> gpio{GPIO(6, activeLow)};
1077 Rail rail{name,
1078 presence,
1079 page,
1080 isPowerSupplyRail,
1081 checkStatusVout,
1082 compareVoltageToLimit,
1083 gpio};
1084
1085 MockDevice device{};
1086
1087 MockServices services{};
1088
1089 std::vector<int> gpioValues{1, 1, 1, 1, 1, 1};
1090 std::map<std::string, std::string> additionalData{};
1091 try
1092 {
1093 rail.hasPgoodFault(device, services, gpioValues, additionalData);
1094 ADD_FAILURE() << "Should not have reached this line.";
1095 }
1096 catch (const std::exception& e)
1097 {
1098 EXPECT_STREQ(e.what(), "Invalid GPIO line offset 6 for rail VDD2: "
1099 "Device only has 6 GPIO values");
1100 }
1101 }
1102
1103 // Test where 1 check defined: READ_VOUT: No fault detected
1104 // Output voltage > UV limit
1105 {
1106 std::optional<std::string> presence{};
1107 std::optional<uint8_t> page{2};
1108 bool checkStatusVout{false};
1109 bool compareVoltageToLimit{true};
1110 std::optional<GPIO> gpio{};
1111 Rail rail{name,
1112 presence,
1113 page,
1114 isPowerSupplyRail,
1115 checkStatusVout,
1116 compareVoltageToLimit,
1117 gpio};
1118
1119 MockDevice device{};
1120 EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1121 EXPECT_CALL(device, getVoutUVFaultLimit(2))
1122 .Times(1)
1123 .WillOnce(Return(1.0));
1124
1125 MockServices services{};
1126
1127 std::vector<int> gpioValues{};
1128 std::map<std::string, std::string> additionalData{};
1129 EXPECT_FALSE(
1130 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1131 EXPECT_EQ(additionalData.size(), 0);
1132 }
1133
1134 // Test where 1 check defined: READ_VOUT: Fault detected
1135 // Output voltage < UV limit
1136 {
1137 std::optional<std::string> presence{};
1138 std::optional<uint8_t> page{2};
1139 bool checkStatusVout{false};
1140 bool compareVoltageToLimit{true};
1141 std::optional<GPIO> gpio{};
1142 Rail rail{name,
1143 presence,
1144 page,
1145 isPowerSupplyRail,
1146 checkStatusVout,
1147 compareVoltageToLimit,
1148 gpio};
1149
1150 MockDevice device{};
1151 EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1152 EXPECT_CALL(device, getVoutUVFaultLimit(2))
1153 .Times(1)
1154 .WillOnce(Return(1.2));
1155 EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1156
1157 MockServices services{};
1158 EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1159 .Times(1);
1160 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1161 .Times(1);
1162 EXPECT_CALL(
1163 services,
1164 logErrorMsg(
1165 "Rail VDD2 output voltage 1.1V is <= UV fault limit 1.2V"))
1166 .Times(1);
1167
1168 std::vector<int> gpioValues{};
1169 std::map<std::string, std::string> additionalData{};
1170 EXPECT_TRUE(
1171 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1172 EXPECT_EQ(additionalData.size(), 4);
1173 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1174 EXPECT_EQ(additionalData["READ_VOUT"], "1.1");
1175 EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.2");
1176 EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1177 }
1178
1179 // Test where 1 check defined: READ_VOUT: Exception thrown
1180 {
1181 std::optional<std::string> presence{};
1182 std::optional<uint8_t> page{2};
1183 bool checkStatusVout{false};
1184 bool compareVoltageToLimit{true};
1185 std::optional<GPIO> gpio{};
1186 Rail rail{name,
1187 presence,
1188 page,
1189 isPowerSupplyRail,
1190 checkStatusVout,
1191 compareVoltageToLimit,
1192 gpio};
1193
1194 MockDevice device{};
1195 EXPECT_CALL(device, getReadVout(2))
1196 .Times(1)
1197 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
1198
1199 MockServices services{};
1200
1201 std::vector<int> gpioValues{};
1202 std::map<std::string, std::string> additionalData{};
1203 try
1204 {
1205 rail.hasPgoodFault(device, services, gpioValues, additionalData);
1206 ADD_FAILURE() << "Should not have reached this line.";
1207 }
1208 catch (const std::exception& e)
1209 {
1210 EXPECT_STREQ(e.what(),
1211 "Unable to read READ_VOUT value for rail VDD2: "
1212 "File does not exist");
1213 }
1214 }
1215
1216 // Test where 3 checks defined: No fault detected
1217 // GPIO value is 0 and GPIO is active low
1218 {
1219 std::optional<std::string> presence{};
1220 std::optional<uint8_t> page{2};
1221 bool checkStatusVout{true};
1222 bool compareVoltageToLimit{true};
1223 bool activeLow{true};
1224 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1225 Rail rail{name,
1226 presence,
1227 page,
1228 isPowerSupplyRail,
1229 checkStatusVout,
1230 compareVoltageToLimit,
1231 gpio};
1232
1233 MockDevice device{};
1234 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1235 EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1236 EXPECT_CALL(device, getVoutUVFaultLimit(2))
1237 .Times(1)
1238 .WillOnce(Return(0.9));
1239
1240 MockServices services{};
1241
1242 std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1243 std::map<std::string, std::string> additionalData{};
1244 EXPECT_FALSE(
1245 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1246 EXPECT_EQ(additionalData.size(), 0);
1247 }
1248
1249 // Test where 3 checks defined: Fault detected via STATUS_VOUT
1250 {
1251 std::optional<std::string> presence{};
1252 std::optional<uint8_t> page{2};
1253 bool checkStatusVout{true};
1254 bool compareVoltageToLimit{true};
1255 bool activeLow{true};
1256 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1257 Rail rail{name,
1258 presence,
1259 page,
1260 isPowerSupplyRail,
1261 checkStatusVout,
1262 compareVoltageToLimit,
1263 gpio};
1264
1265 MockDevice device{};
1266 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x10));
1267 EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1268
1269 MockServices services{};
1270 EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1271 .Times(1);
1272 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1273 .Times(1);
1274 EXPECT_CALL(
1275 services,
1276 logErrorMsg("Rail VDD2 has fault bits set in STATUS_VOUT: 0x10"))
1277 .Times(1);
1278
1279 std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1280 std::map<std::string, std::string> additionalData{};
1281 EXPECT_TRUE(
1282 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1283 EXPECT_EQ(additionalData.size(), 3);
1284 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1285 EXPECT_EQ(additionalData["STATUS_VOUT"], "0x10");
1286 EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1287 }
1288
1289 // Test where 3 checks defined: Fault detected via GPIO
1290 // GPIO value is 1 and GPIO is active low
1291 {
1292 std::optional<std::string> presence{};
1293 std::optional<uint8_t> page{2};
1294 bool checkStatusVout{true};
1295 bool compareVoltageToLimit{true};
1296 bool activeLow{true};
1297 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1298 Rail rail{name,
1299 presence,
1300 page,
1301 isPowerSupplyRail,
1302 checkStatusVout,
1303 compareVoltageToLimit,
1304 gpio};
1305
1306 MockDevice device{};
1307 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1308 EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1309
1310 MockServices services{};
1311 EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1312 .Times(1);
1313 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1314 .Times(1);
1315 EXPECT_CALL(
1316 services,
1317 logErrorMsg(
1318 "Rail VDD2 pgood GPIO line offset 3 has inactive value 1"))
1319 .Times(1);
1320
1321 std::vector<int> gpioValues{0, 0, 0, 1, 0, 0};
1322 std::map<std::string, std::string> additionalData{};
1323 EXPECT_TRUE(
1324 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1325 EXPECT_EQ(additionalData.size(), 4);
1326 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1327 EXPECT_EQ(additionalData["GPIO_LINE"], "3");
1328 EXPECT_EQ(additionalData["GPIO_VALUE"], "1");
1329 EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1330 }
1331
1332 // Test where 3 checks defined: Fault detected via READ_VOUT
1333 // Output voltage == UV limit
1334 // STATUS_WORD not captured because reading it caused an exception
1335 {
1336 std::optional<std::string> presence{};
1337 std::optional<uint8_t> page{2};
1338 bool checkStatusVout{true};
1339 bool compareVoltageToLimit{true};
1340 bool activeLow{true};
1341 std::optional<GPIO> gpio{GPIO(3, activeLow)};
1342 Rail rail{name,
1343 presence,
1344 page,
1345 isPowerSupplyRail,
1346 checkStatusVout,
1347 compareVoltageToLimit,
1348 gpio};
1349
1350 MockDevice device{};
1351 EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1352 EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1353 EXPECT_CALL(device, getVoutUVFaultLimit(2))
1354 .Times(1)
1355 .WillOnce(Return(1.1));
1356 EXPECT_CALL(device, getStatusWord(2))
1357 .Times(1)
1358 .WillOnce(Throw(std::runtime_error{"File does not exist"}));
1359
1360 MockServices services{};
1361 EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1362 .Times(1);
1363 EXPECT_CALL(
1364 services,
1365 logErrorMsg(
1366 "Rail VDD2 output voltage 1.1V is <= UV fault limit 1.1V"))
1367 .Times(1);
1368
1369 std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1370 std::map<std::string, std::string> additionalData{};
1371 EXPECT_TRUE(
1372 rail.hasPgoodFault(device, services, gpioValues, additionalData));
1373 EXPECT_EQ(additionalData.size(), 3);
1374 EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1375 EXPECT_EQ(additionalData["READ_VOUT"], "1.1");
1376 EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.1");
1377 }
1378}