1d6e9bfe2SShawn McCarney /**
2d6e9bfe2SShawn McCarney  * Copyright © 2024 IBM Corporation
3d6e9bfe2SShawn McCarney  *
4d6e9bfe2SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5d6e9bfe2SShawn McCarney  * you may not use this file except in compliance with the License.
6d6e9bfe2SShawn McCarney  * You may obtain a copy of the License at
7d6e9bfe2SShawn McCarney  *
8d6e9bfe2SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9d6e9bfe2SShawn McCarney  *
10d6e9bfe2SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11d6e9bfe2SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12d6e9bfe2SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d6e9bfe2SShawn McCarney  * See the License for the specific language governing permissions and
14d6e9bfe2SShawn McCarney  * limitations under the License.
15d6e9bfe2SShawn McCarney  */
16d6e9bfe2SShawn McCarney 
17*24956598SShawn McCarney #include "mock_device.hpp"
18*24956598SShawn McCarney #include "mock_services.hpp"
19d6e9bfe2SShawn McCarney #include "rail.hpp"
20d6e9bfe2SShawn McCarney 
21d6e9bfe2SShawn McCarney #include <cstdint>
22*24956598SShawn McCarney #include <map>
23d6e9bfe2SShawn McCarney #include <optional>
24d6e9bfe2SShawn McCarney #include <string>
25*24956598SShawn McCarney #include <vector>
26d6e9bfe2SShawn McCarney 
27*24956598SShawn McCarney #include <gmock/gmock.h>
28d6e9bfe2SShawn McCarney #include <gtest/gtest.h>
29d6e9bfe2SShawn McCarney 
30d6e9bfe2SShawn McCarney using namespace phosphor::power::sequencer;
31d6e9bfe2SShawn McCarney 
32*24956598SShawn McCarney using ::testing::Return;
33*24956598SShawn McCarney using ::testing::Throw;
34*24956598SShawn McCarney 
35d6e9bfe2SShawn McCarney TEST(GPIOTests, Initialization)
36d6e9bfe2SShawn McCarney {
37d6e9bfe2SShawn McCarney     // Default initialization
38d6e9bfe2SShawn McCarney     {
39d6e9bfe2SShawn McCarney         GPIO gpio;
40d6e9bfe2SShawn McCarney         EXPECT_EQ(gpio.line, 0);
41d6e9bfe2SShawn McCarney         EXPECT_FALSE(gpio.activeLow);
42d6e9bfe2SShawn McCarney     }
43d6e9bfe2SShawn McCarney 
44d6e9bfe2SShawn McCarney     // Explicit initialization
45d6e9bfe2SShawn McCarney     {
46d6e9bfe2SShawn McCarney         GPIO gpio{48, true};
47d6e9bfe2SShawn McCarney         EXPECT_EQ(gpio.line, 48);
48d6e9bfe2SShawn McCarney         EXPECT_TRUE(gpio.activeLow);
49d6e9bfe2SShawn McCarney     }
50d6e9bfe2SShawn McCarney }
51d6e9bfe2SShawn McCarney 
52d6e9bfe2SShawn McCarney TEST(RailTests, Constructor)
53d6e9bfe2SShawn McCarney {
54d6e9bfe2SShawn McCarney     // Test where succeeds: No optional parameters have values
55d6e9bfe2SShawn McCarney     {
5616e493afSShawn McCarney         std::string name{"12.0V"};
57d6e9bfe2SShawn McCarney         std::optional<std::string> presence{};
58d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{};
5916e493afSShawn McCarney         bool isPowerSupplyRail{true};
60d6e9bfe2SShawn McCarney         bool checkStatusVout{false};
619ec0d43dSShawn McCarney         bool compareVoltageToLimit{false};
62d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{};
6316e493afSShawn McCarney         Rail rail{name,
6416e493afSShawn McCarney                   presence,
6516e493afSShawn McCarney                   page,
6616e493afSShawn McCarney                   isPowerSupplyRail,
6716e493afSShawn McCarney                   checkStatusVout,
689ec0d43dSShawn McCarney                   compareVoltageToLimit,
69d6e9bfe2SShawn McCarney                   gpio};
70d6e9bfe2SShawn McCarney 
7116e493afSShawn McCarney         EXPECT_EQ(rail.getName(), "12.0V");
72d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getPresence().has_value());
73d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getPage().has_value());
7416e493afSShawn McCarney         EXPECT_TRUE(rail.isPowerSupplyRail());
75d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getCheckStatusVout());
769ec0d43dSShawn McCarney         EXPECT_FALSE(rail.getCompareVoltageToLimit());
77d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getGPIO().has_value());
78d6e9bfe2SShawn McCarney     }
79d6e9bfe2SShawn McCarney 
80d6e9bfe2SShawn McCarney     // Test where succeeds: All optional parameters have values
81d6e9bfe2SShawn McCarney     {
82d6e9bfe2SShawn McCarney         std::string name{"VCS_CPU1"};
83d6e9bfe2SShawn McCarney         std::optional<std::string> presence{
84d6e9bfe2SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1"};
85d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{11};
8616e493afSShawn McCarney         bool isPowerSupplyRail{false};
87d6e9bfe2SShawn McCarney         bool checkStatusVout{true};
889ec0d43dSShawn McCarney         bool compareVoltageToLimit{true};
89d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{GPIO(60, true)};
9016e493afSShawn McCarney         Rail rail{name,
9116e493afSShawn McCarney                   presence,
9216e493afSShawn McCarney                   page,
9316e493afSShawn McCarney                   isPowerSupplyRail,
9416e493afSShawn McCarney                   checkStatusVout,
959ec0d43dSShawn McCarney                   compareVoltageToLimit,
96d6e9bfe2SShawn McCarney                   gpio};
97d6e9bfe2SShawn McCarney 
98d6e9bfe2SShawn McCarney         EXPECT_EQ(rail.getName(), "VCS_CPU1");
99d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getPresence().has_value());
100d6e9bfe2SShawn McCarney         EXPECT_EQ(
101d6e9bfe2SShawn McCarney             rail.getPresence().value(),
102d6e9bfe2SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu1");
103d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getPage().has_value());
104d6e9bfe2SShawn McCarney         EXPECT_EQ(rail.getPage().value(), 11);
10516e493afSShawn McCarney         EXPECT_FALSE(rail.isPowerSupplyRail());
106d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getCheckStatusVout());
1079ec0d43dSShawn McCarney         EXPECT_TRUE(rail.getCompareVoltageToLimit());
108d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getGPIO().has_value());
109d6e9bfe2SShawn McCarney         EXPECT_EQ(rail.getGPIO().value().line, 60);
110d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getGPIO().value().activeLow);
111d6e9bfe2SShawn McCarney     }
112d6e9bfe2SShawn McCarney 
113d6e9bfe2SShawn McCarney     // Test where fails: checkStatusVout is true and page has no value
114d6e9bfe2SShawn McCarney     {
115d6e9bfe2SShawn McCarney         std::string name{"VDD1"};
116d6e9bfe2SShawn McCarney         std::optional<std::string> presence{};
117d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{};
11816e493afSShawn McCarney         bool isPowerSupplyRail{false};
119d6e9bfe2SShawn McCarney         bool checkStatusVout{true};
1209ec0d43dSShawn McCarney         bool compareVoltageToLimit{false};
121d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{};
12216e493afSShawn McCarney         EXPECT_THROW((Rail{name, presence, page, isPowerSupplyRail,
1239ec0d43dSShawn McCarney                            checkStatusVout, compareVoltageToLimit, gpio}),
124d6e9bfe2SShawn McCarney                      std::invalid_argument);
125d6e9bfe2SShawn McCarney     }
126d6e9bfe2SShawn McCarney 
1279ec0d43dSShawn McCarney     // Test where fails: compareVoltageToLimit is true and page has no value
128d6e9bfe2SShawn McCarney     {
129d6e9bfe2SShawn McCarney         std::string name{"VDD1"};
130d6e9bfe2SShawn McCarney         std::optional<std::string> presence{};
131d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{};
13216e493afSShawn McCarney         bool isPowerSupplyRail{false};
133d6e9bfe2SShawn McCarney         bool checkStatusVout{false};
1349ec0d43dSShawn McCarney         bool compareVoltageToLimit{true};
135d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{};
13616e493afSShawn McCarney         EXPECT_THROW((Rail{name, presence, page, isPowerSupplyRail,
1379ec0d43dSShawn McCarney                            checkStatusVout, compareVoltageToLimit, gpio}),
138d6e9bfe2SShawn McCarney                      std::invalid_argument);
139d6e9bfe2SShawn McCarney     }
140d6e9bfe2SShawn McCarney }
141d6e9bfe2SShawn McCarney 
142d6e9bfe2SShawn McCarney TEST(RailTests, GetName)
143d6e9bfe2SShawn McCarney {
144d6e9bfe2SShawn McCarney     std::string name{"VDD2"};
145d6e9bfe2SShawn McCarney     std::optional<std::string> presence{};
146d6e9bfe2SShawn McCarney     std::optional<uint8_t> page{};
14716e493afSShawn McCarney     bool isPowerSupplyRail{false};
148d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
1499ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
150d6e9bfe2SShawn McCarney     std::optional<GPIO> gpio{};
15116e493afSShawn McCarney     Rail rail{name,
15216e493afSShawn McCarney               presence,
15316e493afSShawn McCarney               page,
15416e493afSShawn McCarney               isPowerSupplyRail,
15516e493afSShawn McCarney               checkStatusVout,
1569ec0d43dSShawn McCarney               compareVoltageToLimit,
157d6e9bfe2SShawn McCarney               gpio};
158d6e9bfe2SShawn McCarney 
159d6e9bfe2SShawn McCarney     EXPECT_EQ(rail.getName(), "VDD2");
160d6e9bfe2SShawn McCarney }
161d6e9bfe2SShawn McCarney 
162d6e9bfe2SShawn McCarney TEST(RailTests, GetPresence)
163d6e9bfe2SShawn McCarney {
164d6e9bfe2SShawn McCarney     std::string name{"VDDR2"};
165d6e9bfe2SShawn McCarney     std::optional<uint8_t> page{};
16616e493afSShawn McCarney     bool isPowerSupplyRail{false};
167d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
1689ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
169d6e9bfe2SShawn McCarney     std::optional<GPIO> gpio{};
170d6e9bfe2SShawn McCarney 
171d6e9bfe2SShawn McCarney     // Test where presence has no value
172d6e9bfe2SShawn McCarney     {
173d6e9bfe2SShawn McCarney         std::optional<std::string> presence{};
17416e493afSShawn McCarney         Rail rail{name,
17516e493afSShawn McCarney                   presence,
17616e493afSShawn McCarney                   page,
17716e493afSShawn McCarney                   isPowerSupplyRail,
17816e493afSShawn McCarney                   checkStatusVout,
1799ec0d43dSShawn McCarney                   compareVoltageToLimit,
180d6e9bfe2SShawn McCarney                   gpio};
181d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getPresence().has_value());
182d6e9bfe2SShawn McCarney     }
183d6e9bfe2SShawn McCarney 
184d6e9bfe2SShawn McCarney     // Test where presence has a value
185d6e9bfe2SShawn McCarney     {
186d6e9bfe2SShawn McCarney         std::optional<std::string> presence{
187d6e9bfe2SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2"};
18816e493afSShawn McCarney         Rail rail{name,
18916e493afSShawn McCarney                   presence,
19016e493afSShawn McCarney                   page,
19116e493afSShawn McCarney                   isPowerSupplyRail,
19216e493afSShawn McCarney                   checkStatusVout,
1939ec0d43dSShawn McCarney                   compareVoltageToLimit,
194d6e9bfe2SShawn McCarney                   gpio};
195d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getPresence().has_value());
196d6e9bfe2SShawn McCarney         EXPECT_EQ(
197d6e9bfe2SShawn McCarney             rail.getPresence().value(),
198d6e9bfe2SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm2");
199d6e9bfe2SShawn McCarney     }
200d6e9bfe2SShawn McCarney }
201d6e9bfe2SShawn McCarney 
202d6e9bfe2SShawn McCarney TEST(RailTests, GetPage)
203d6e9bfe2SShawn McCarney {
204d6e9bfe2SShawn McCarney     std::string name{"VDD2"};
205d6e9bfe2SShawn McCarney     std::optional<std::string> presence{};
20616e493afSShawn McCarney     bool isPowerSupplyRail{false};
207d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
2089ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
209d6e9bfe2SShawn McCarney     std::optional<GPIO> gpio{};
210d6e9bfe2SShawn McCarney 
211d6e9bfe2SShawn McCarney     // Test where page has no value
212d6e9bfe2SShawn McCarney     {
213d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{};
21416e493afSShawn McCarney         Rail rail{name,
21516e493afSShawn McCarney                   presence,
21616e493afSShawn McCarney                   page,
21716e493afSShawn McCarney                   isPowerSupplyRail,
21816e493afSShawn McCarney                   checkStatusVout,
2199ec0d43dSShawn McCarney                   compareVoltageToLimit,
220d6e9bfe2SShawn McCarney                   gpio};
221d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getPage().has_value());
222d6e9bfe2SShawn McCarney     }
223d6e9bfe2SShawn McCarney 
224d6e9bfe2SShawn McCarney     // Test where page has a value
225d6e9bfe2SShawn McCarney     {
226d6e9bfe2SShawn McCarney         std::optional<uint8_t> page{7};
22716e493afSShawn McCarney         Rail rail{name,
22816e493afSShawn McCarney                   presence,
22916e493afSShawn McCarney                   page,
23016e493afSShawn McCarney                   isPowerSupplyRail,
23116e493afSShawn McCarney                   checkStatusVout,
2329ec0d43dSShawn McCarney                   compareVoltageToLimit,
233d6e9bfe2SShawn McCarney                   gpio};
234d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getPage().has_value());
235d6e9bfe2SShawn McCarney         EXPECT_EQ(rail.getPage().value(), 7);
236d6e9bfe2SShawn McCarney     }
237d6e9bfe2SShawn McCarney }
238d6e9bfe2SShawn McCarney 
23916e493afSShawn McCarney TEST(RailTests, IsPowerSupplyRail)
24016e493afSShawn McCarney {
24116e493afSShawn McCarney     std::string name{"12.0V"};
24216e493afSShawn McCarney     std::optional<std::string> presence{};
24316e493afSShawn McCarney     std::optional<uint8_t> page{};
24416e493afSShawn McCarney     bool isPowerSupplyRail{true};
24516e493afSShawn McCarney     bool checkStatusVout{false};
2469ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
24716e493afSShawn McCarney     std::optional<GPIO> gpio{};
24816e493afSShawn McCarney     Rail rail{name,
24916e493afSShawn McCarney               presence,
25016e493afSShawn McCarney               page,
25116e493afSShawn McCarney               isPowerSupplyRail,
25216e493afSShawn McCarney               checkStatusVout,
2539ec0d43dSShawn McCarney               compareVoltageToLimit,
25416e493afSShawn McCarney               gpio};
25516e493afSShawn McCarney 
25616e493afSShawn McCarney     EXPECT_TRUE(rail.isPowerSupplyRail());
25716e493afSShawn McCarney }
25816e493afSShawn McCarney 
259d6e9bfe2SShawn McCarney TEST(RailTests, GetCheckStatusVout)
260d6e9bfe2SShawn McCarney {
261d6e9bfe2SShawn McCarney     std::string name{"VDD2"};
262d6e9bfe2SShawn McCarney     std::optional<std::string> presence{};
263d6e9bfe2SShawn McCarney     std::optional<uint8_t> page{};
26416e493afSShawn McCarney     bool isPowerSupplyRail{false};
265d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
2669ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
267d6e9bfe2SShawn McCarney     std::optional<GPIO> gpio{};
26816e493afSShawn McCarney     Rail rail{name,
26916e493afSShawn McCarney               presence,
27016e493afSShawn McCarney               page,
27116e493afSShawn McCarney               isPowerSupplyRail,
27216e493afSShawn McCarney               checkStatusVout,
2739ec0d43dSShawn McCarney               compareVoltageToLimit,
274d6e9bfe2SShawn McCarney               gpio};
275d6e9bfe2SShawn McCarney 
276d6e9bfe2SShawn McCarney     EXPECT_FALSE(rail.getCheckStatusVout());
277d6e9bfe2SShawn McCarney }
278d6e9bfe2SShawn McCarney 
2799ec0d43dSShawn McCarney TEST(RailTests, GetCompareVoltageToLimit)
280d6e9bfe2SShawn McCarney {
281d6e9bfe2SShawn McCarney     std::string name{"VDD2"};
282d6e9bfe2SShawn McCarney     std::optional<std::string> presence{};
283d6e9bfe2SShawn McCarney     std::optional<uint8_t> page{13};
28416e493afSShawn McCarney     bool isPowerSupplyRail{false};
285d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
2869ec0d43dSShawn McCarney     bool compareVoltageToLimit{true};
287d6e9bfe2SShawn McCarney     std::optional<GPIO> gpio{};
28816e493afSShawn McCarney     Rail rail{name,
28916e493afSShawn McCarney               presence,
29016e493afSShawn McCarney               page,
29116e493afSShawn McCarney               isPowerSupplyRail,
29216e493afSShawn McCarney               checkStatusVout,
2939ec0d43dSShawn McCarney               compareVoltageToLimit,
294d6e9bfe2SShawn McCarney               gpio};
295d6e9bfe2SShawn McCarney 
2969ec0d43dSShawn McCarney     EXPECT_TRUE(rail.getCompareVoltageToLimit());
297d6e9bfe2SShawn McCarney }
298d6e9bfe2SShawn McCarney 
299d6e9bfe2SShawn McCarney TEST(RailTests, GetGPIO)
300d6e9bfe2SShawn McCarney {
301d6e9bfe2SShawn McCarney     std::string name{"VDD2"};
302d6e9bfe2SShawn McCarney     std::optional<std::string> presence{};
303d6e9bfe2SShawn McCarney     std::optional<uint8_t> page{};
30416e493afSShawn McCarney     bool isPowerSupplyRail{false};
305d6e9bfe2SShawn McCarney     bool checkStatusVout{false};
3069ec0d43dSShawn McCarney     bool compareVoltageToLimit{false};
307d6e9bfe2SShawn McCarney 
308d6e9bfe2SShawn McCarney     // Test where gpio has no value
309d6e9bfe2SShawn McCarney     {
310d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{};
31116e493afSShawn McCarney         Rail rail{name,
31216e493afSShawn McCarney                   presence,
31316e493afSShawn McCarney                   page,
31416e493afSShawn McCarney                   isPowerSupplyRail,
31516e493afSShawn McCarney                   checkStatusVout,
3169ec0d43dSShawn McCarney                   compareVoltageToLimit,
317d6e9bfe2SShawn McCarney                   gpio};
318d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getGPIO().has_value());
319d6e9bfe2SShawn McCarney     }
320d6e9bfe2SShawn McCarney 
321d6e9bfe2SShawn McCarney     // Test where gpio has a value
322d6e9bfe2SShawn McCarney     {
323d6e9bfe2SShawn McCarney         std::optional<GPIO> gpio{GPIO(12, false)};
32416e493afSShawn McCarney         Rail rail{name,
32516e493afSShawn McCarney                   presence,
32616e493afSShawn McCarney                   page,
32716e493afSShawn McCarney                   isPowerSupplyRail,
32816e493afSShawn McCarney                   checkStatusVout,
3299ec0d43dSShawn McCarney                   compareVoltageToLimit,
330d6e9bfe2SShawn McCarney                   gpio};
331d6e9bfe2SShawn McCarney         EXPECT_TRUE(rail.getGPIO().has_value());
332d6e9bfe2SShawn McCarney         EXPECT_EQ(rail.getGPIO().value().line, 12);
333d6e9bfe2SShawn McCarney         EXPECT_FALSE(rail.getGPIO().value().activeLow);
334d6e9bfe2SShawn McCarney     }
335d6e9bfe2SShawn McCarney }
336*24956598SShawn McCarney 
337*24956598SShawn McCarney TEST(RailTests, IsPresent)
338*24956598SShawn McCarney {
339*24956598SShawn McCarney     std::string name{"VDD2"};
340*24956598SShawn McCarney     std::optional<uint8_t> page{};
341*24956598SShawn McCarney     bool isPowerSupplyRail{false};
342*24956598SShawn McCarney     bool checkStatusVout{false};
343*24956598SShawn McCarney     bool compareVoltageToLimit{false};
344*24956598SShawn McCarney     std::optional<GPIO> gpio{};
345*24956598SShawn McCarney 
346*24956598SShawn McCarney     // Test where inventory path not specified; always returns true
347*24956598SShawn McCarney     {
348*24956598SShawn McCarney         std::optional<std::string> presence{};
349*24956598SShawn McCarney         Rail rail{name,
350*24956598SShawn McCarney                   presence,
351*24956598SShawn McCarney                   page,
352*24956598SShawn McCarney                   isPowerSupplyRail,
353*24956598SShawn McCarney                   checkStatusVout,
354*24956598SShawn McCarney                   compareVoltageToLimit,
355*24956598SShawn McCarney                   gpio};
356*24956598SShawn McCarney 
357*24956598SShawn McCarney         MockServices services{};
358*24956598SShawn McCarney         EXPECT_CALL(services, isPresent).Times(0);
359*24956598SShawn McCarney 
360*24956598SShawn McCarney         EXPECT_TRUE(rail.isPresent(services));
361*24956598SShawn McCarney     }
362*24956598SShawn McCarney 
363*24956598SShawn McCarney     // Test where inventory path is not present
364*24956598SShawn McCarney     {
365*24956598SShawn McCarney         std::optional<std::string> presence{
366*24956598SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
367*24956598SShawn McCarney         Rail rail{name,
368*24956598SShawn McCarney                   presence,
369*24956598SShawn McCarney                   page,
370*24956598SShawn McCarney                   isPowerSupplyRail,
371*24956598SShawn McCarney                   checkStatusVout,
372*24956598SShawn McCarney                   compareVoltageToLimit,
373*24956598SShawn McCarney                   gpio};
374*24956598SShawn McCarney 
375*24956598SShawn McCarney         MockServices services{};
376*24956598SShawn McCarney         EXPECT_CALL(services, isPresent(*presence))
377*24956598SShawn McCarney             .Times(1)
378*24956598SShawn McCarney             .WillOnce(Return(false));
379*24956598SShawn McCarney 
380*24956598SShawn McCarney         EXPECT_FALSE(rail.isPresent(services));
381*24956598SShawn McCarney     }
382*24956598SShawn McCarney 
383*24956598SShawn McCarney     // Test where inventory path is present
384*24956598SShawn McCarney     {
385*24956598SShawn McCarney         std::optional<std::string> presence{
386*24956598SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
387*24956598SShawn McCarney         Rail rail{name,
388*24956598SShawn McCarney                   presence,
389*24956598SShawn McCarney                   page,
390*24956598SShawn McCarney                   isPowerSupplyRail,
391*24956598SShawn McCarney                   checkStatusVout,
392*24956598SShawn McCarney                   compareVoltageToLimit,
393*24956598SShawn McCarney                   gpio};
394*24956598SShawn McCarney 
395*24956598SShawn McCarney         MockServices services{};
396*24956598SShawn McCarney         EXPECT_CALL(services, isPresent(*presence))
397*24956598SShawn McCarney             .Times(1)
398*24956598SShawn McCarney             .WillOnce(Return(true));
399*24956598SShawn McCarney 
400*24956598SShawn McCarney         EXPECT_TRUE(rail.isPresent(services));
401*24956598SShawn McCarney     }
402*24956598SShawn McCarney 
403*24956598SShawn McCarney     // Test where exception occurs trying to get presence
404*24956598SShawn McCarney     {
405*24956598SShawn McCarney         std::optional<std::string> presence{
406*24956598SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
407*24956598SShawn McCarney         Rail rail{name,
408*24956598SShawn McCarney                   presence,
409*24956598SShawn McCarney                   page,
410*24956598SShawn McCarney                   isPowerSupplyRail,
411*24956598SShawn McCarney                   checkStatusVout,
412*24956598SShawn McCarney                   compareVoltageToLimit,
413*24956598SShawn McCarney                   gpio};
414*24956598SShawn McCarney 
415*24956598SShawn McCarney         MockServices services{};
416*24956598SShawn McCarney         EXPECT_CALL(services, isPresent(*presence))
417*24956598SShawn McCarney             .Times(1)
418*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"Invalid object path"}));
419*24956598SShawn McCarney 
420*24956598SShawn McCarney         try
421*24956598SShawn McCarney         {
422*24956598SShawn McCarney             rail.isPresent(services);
423*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
424*24956598SShawn McCarney         }
425*24956598SShawn McCarney         catch (const std::exception& e)
426*24956598SShawn McCarney         {
427*24956598SShawn McCarney             EXPECT_STREQ(
428*24956598SShawn McCarney                 e.what(),
429*24956598SShawn McCarney                 "Unable to determine presence of rail VDD2 using "
430*24956598SShawn McCarney                 "inventory path "
431*24956598SShawn McCarney                 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2: "
432*24956598SShawn McCarney                 "Invalid object path");
433*24956598SShawn McCarney         }
434*24956598SShawn McCarney     }
435*24956598SShawn McCarney }
436*24956598SShawn McCarney 
437*24956598SShawn McCarney TEST(RailTests, GetStatusWord)
438*24956598SShawn McCarney {
439*24956598SShawn McCarney     std::string name{"VDD2"};
440*24956598SShawn McCarney     std::optional<std::string> presence{};
441*24956598SShawn McCarney     bool isPowerSupplyRail{false};
442*24956598SShawn McCarney     bool checkStatusVout{false};
443*24956598SShawn McCarney     bool compareVoltageToLimit{false};
444*24956598SShawn McCarney     std::optional<GPIO> gpio{};
445*24956598SShawn McCarney 
446*24956598SShawn McCarney     // Test where page was not specified: Throws exception
447*24956598SShawn McCarney     {
448*24956598SShawn McCarney         std::optional<uint8_t> page{};
449*24956598SShawn McCarney         Rail rail{name,
450*24956598SShawn McCarney                   presence,
451*24956598SShawn McCarney                   page,
452*24956598SShawn McCarney                   isPowerSupplyRail,
453*24956598SShawn McCarney                   checkStatusVout,
454*24956598SShawn McCarney                   compareVoltageToLimit,
455*24956598SShawn McCarney                   gpio};
456*24956598SShawn McCarney 
457*24956598SShawn McCarney         MockDevice device{};
458*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord).Times(0);
459*24956598SShawn McCarney 
460*24956598SShawn McCarney         try
461*24956598SShawn McCarney         {
462*24956598SShawn McCarney             rail.getStatusWord(device);
463*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
464*24956598SShawn McCarney         }
465*24956598SShawn McCarney         catch (const std::exception& e)
466*24956598SShawn McCarney         {
467*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
468*24956598SShawn McCarney                          "Unable to read STATUS_WORD value for rail VDD2: "
469*24956598SShawn McCarney                          "No PAGE number defined for rail VDD2");
470*24956598SShawn McCarney         }
471*24956598SShawn McCarney     }
472*24956598SShawn McCarney 
473*24956598SShawn McCarney     // Test where value read successfully
474*24956598SShawn McCarney     {
475*24956598SShawn McCarney         std::optional<uint8_t> page{2};
476*24956598SShawn McCarney         Rail rail{name,
477*24956598SShawn McCarney                   presence,
478*24956598SShawn McCarney                   page,
479*24956598SShawn McCarney                   isPowerSupplyRail,
480*24956598SShawn McCarney                   checkStatusVout,
481*24956598SShawn McCarney                   compareVoltageToLimit,
482*24956598SShawn McCarney                   gpio};
483*24956598SShawn McCarney 
484*24956598SShawn McCarney         MockDevice device{};
485*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
486*24956598SShawn McCarney 
487*24956598SShawn McCarney         EXPECT_EQ(rail.getStatusWord(device), 0xbeef);
488*24956598SShawn McCarney     }
489*24956598SShawn McCarney 
490*24956598SShawn McCarney     // Test where exception occurs trying to read value
491*24956598SShawn McCarney     {
492*24956598SShawn McCarney         std::optional<uint8_t> page{2};
493*24956598SShawn McCarney         Rail rail{name,
494*24956598SShawn McCarney                   presence,
495*24956598SShawn McCarney                   page,
496*24956598SShawn McCarney                   isPowerSupplyRail,
497*24956598SShawn McCarney                   checkStatusVout,
498*24956598SShawn McCarney                   compareVoltageToLimit,
499*24956598SShawn McCarney                   gpio};
500*24956598SShawn McCarney 
501*24956598SShawn McCarney         MockDevice device{};
502*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2))
503*24956598SShawn McCarney             .Times(1)
504*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
505*24956598SShawn McCarney 
506*24956598SShawn McCarney         try
507*24956598SShawn McCarney         {
508*24956598SShawn McCarney             rail.getStatusWord(device);
509*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
510*24956598SShawn McCarney         }
511*24956598SShawn McCarney         catch (const std::exception& e)
512*24956598SShawn McCarney         {
513*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
514*24956598SShawn McCarney                          "Unable to read STATUS_WORD value for rail VDD2: "
515*24956598SShawn McCarney                          "File does not exist");
516*24956598SShawn McCarney         }
517*24956598SShawn McCarney     }
518*24956598SShawn McCarney }
519*24956598SShawn McCarney 
520*24956598SShawn McCarney TEST(RailTests, GetStatusVout)
521*24956598SShawn McCarney {
522*24956598SShawn McCarney     std::string name{"VDD2"};
523*24956598SShawn McCarney     std::optional<std::string> presence{};
524*24956598SShawn McCarney     bool isPowerSupplyRail{false};
525*24956598SShawn McCarney     bool checkStatusVout{false};
526*24956598SShawn McCarney     bool compareVoltageToLimit{false};
527*24956598SShawn McCarney     std::optional<GPIO> gpio{};
528*24956598SShawn McCarney 
529*24956598SShawn McCarney     // Test where page was not specified: Throws exception
530*24956598SShawn McCarney     {
531*24956598SShawn McCarney         std::optional<uint8_t> page{};
532*24956598SShawn McCarney         Rail rail{name,
533*24956598SShawn McCarney                   presence,
534*24956598SShawn McCarney                   page,
535*24956598SShawn McCarney                   isPowerSupplyRail,
536*24956598SShawn McCarney                   checkStatusVout,
537*24956598SShawn McCarney                   compareVoltageToLimit,
538*24956598SShawn McCarney                   gpio};
539*24956598SShawn McCarney 
540*24956598SShawn McCarney         MockDevice device{};
541*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout).Times(0);
542*24956598SShawn McCarney 
543*24956598SShawn McCarney         try
544*24956598SShawn McCarney         {
545*24956598SShawn McCarney             rail.getStatusVout(device);
546*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
547*24956598SShawn McCarney         }
548*24956598SShawn McCarney         catch (const std::exception& e)
549*24956598SShawn McCarney         {
550*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
551*24956598SShawn McCarney                          "Unable to read STATUS_VOUT value for rail VDD2: "
552*24956598SShawn McCarney                          "No PAGE number defined for rail VDD2");
553*24956598SShawn McCarney         }
554*24956598SShawn McCarney     }
555*24956598SShawn McCarney 
556*24956598SShawn McCarney     // Test where value read successfully
557*24956598SShawn McCarney     {
558*24956598SShawn McCarney         std::optional<uint8_t> page{2};
559*24956598SShawn McCarney         Rail rail{name,
560*24956598SShawn McCarney                   presence,
561*24956598SShawn McCarney                   page,
562*24956598SShawn McCarney                   isPowerSupplyRail,
563*24956598SShawn McCarney                   checkStatusVout,
564*24956598SShawn McCarney                   compareVoltageToLimit,
565*24956598SShawn McCarney                   gpio};
566*24956598SShawn McCarney 
567*24956598SShawn McCarney         MockDevice device{};
568*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0xad));
569*24956598SShawn McCarney 
570*24956598SShawn McCarney         EXPECT_EQ(rail.getStatusVout(device), 0xad);
571*24956598SShawn McCarney     }
572*24956598SShawn McCarney 
573*24956598SShawn McCarney     // Test where exception occurs trying to read value
574*24956598SShawn McCarney     {
575*24956598SShawn McCarney         std::optional<uint8_t> page{2};
576*24956598SShawn McCarney         Rail rail{name,
577*24956598SShawn McCarney                   presence,
578*24956598SShawn McCarney                   page,
579*24956598SShawn McCarney                   isPowerSupplyRail,
580*24956598SShawn McCarney                   checkStatusVout,
581*24956598SShawn McCarney                   compareVoltageToLimit,
582*24956598SShawn McCarney                   gpio};
583*24956598SShawn McCarney 
584*24956598SShawn McCarney         MockDevice device{};
585*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2))
586*24956598SShawn McCarney             .Times(1)
587*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
588*24956598SShawn McCarney 
589*24956598SShawn McCarney         try
590*24956598SShawn McCarney         {
591*24956598SShawn McCarney             rail.getStatusVout(device);
592*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
593*24956598SShawn McCarney         }
594*24956598SShawn McCarney         catch (const std::exception& e)
595*24956598SShawn McCarney         {
596*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
597*24956598SShawn McCarney                          "Unable to read STATUS_VOUT value for rail VDD2: "
598*24956598SShawn McCarney                          "File does not exist");
599*24956598SShawn McCarney         }
600*24956598SShawn McCarney     }
601*24956598SShawn McCarney }
602*24956598SShawn McCarney 
603*24956598SShawn McCarney TEST(RailTests, GetReadVout)
604*24956598SShawn McCarney {
605*24956598SShawn McCarney     std::string name{"VDD2"};
606*24956598SShawn McCarney     std::optional<std::string> presence{};
607*24956598SShawn McCarney     bool isPowerSupplyRail{false};
608*24956598SShawn McCarney     bool checkStatusVout{false};
609*24956598SShawn McCarney     bool compareVoltageToLimit{false};
610*24956598SShawn McCarney     std::optional<GPIO> gpio{};
611*24956598SShawn McCarney 
612*24956598SShawn McCarney     // Test where page was not specified: Throws exception
613*24956598SShawn McCarney     {
614*24956598SShawn McCarney         std::optional<uint8_t> page{};
615*24956598SShawn McCarney         Rail rail{name,
616*24956598SShawn McCarney                   presence,
617*24956598SShawn McCarney                   page,
618*24956598SShawn McCarney                   isPowerSupplyRail,
619*24956598SShawn McCarney                   checkStatusVout,
620*24956598SShawn McCarney                   compareVoltageToLimit,
621*24956598SShawn McCarney                   gpio};
622*24956598SShawn McCarney 
623*24956598SShawn McCarney         MockDevice device{};
624*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout).Times(0);
625*24956598SShawn McCarney 
626*24956598SShawn McCarney         try
627*24956598SShawn McCarney         {
628*24956598SShawn McCarney             rail.getReadVout(device);
629*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
630*24956598SShawn McCarney         }
631*24956598SShawn McCarney         catch (const std::exception& e)
632*24956598SShawn McCarney         {
633*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
634*24956598SShawn McCarney                          "Unable to read READ_VOUT value for rail VDD2: "
635*24956598SShawn McCarney                          "No PAGE number defined for rail VDD2");
636*24956598SShawn McCarney         }
637*24956598SShawn McCarney     }
638*24956598SShawn McCarney 
639*24956598SShawn McCarney     // Test where value read successfully
640*24956598SShawn McCarney     {
641*24956598SShawn McCarney         std::optional<uint8_t> page{2};
642*24956598SShawn McCarney         Rail rail{name,
643*24956598SShawn McCarney                   presence,
644*24956598SShawn McCarney                   page,
645*24956598SShawn McCarney                   isPowerSupplyRail,
646*24956598SShawn McCarney                   checkStatusVout,
647*24956598SShawn McCarney                   compareVoltageToLimit,
648*24956598SShawn McCarney                   gpio};
649*24956598SShawn McCarney 
650*24956598SShawn McCarney         MockDevice device{};
651*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.23));
652*24956598SShawn McCarney 
653*24956598SShawn McCarney         EXPECT_EQ(rail.getReadVout(device), 1.23);
654*24956598SShawn McCarney     }
655*24956598SShawn McCarney 
656*24956598SShawn McCarney     // Test where exception occurs trying to read value
657*24956598SShawn McCarney     {
658*24956598SShawn McCarney         std::optional<uint8_t> page{2};
659*24956598SShawn McCarney         Rail rail{name,
660*24956598SShawn McCarney                   presence,
661*24956598SShawn McCarney                   page,
662*24956598SShawn McCarney                   isPowerSupplyRail,
663*24956598SShawn McCarney                   checkStatusVout,
664*24956598SShawn McCarney                   compareVoltageToLimit,
665*24956598SShawn McCarney                   gpio};
666*24956598SShawn McCarney 
667*24956598SShawn McCarney         MockDevice device{};
668*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2))
669*24956598SShawn McCarney             .Times(1)
670*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
671*24956598SShawn McCarney 
672*24956598SShawn McCarney         try
673*24956598SShawn McCarney         {
674*24956598SShawn McCarney             rail.getReadVout(device);
675*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
676*24956598SShawn McCarney         }
677*24956598SShawn McCarney         catch (const std::exception& e)
678*24956598SShawn McCarney         {
679*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
680*24956598SShawn McCarney                          "Unable to read READ_VOUT value for rail VDD2: "
681*24956598SShawn McCarney                          "File does not exist");
682*24956598SShawn McCarney         }
683*24956598SShawn McCarney     }
684*24956598SShawn McCarney }
685*24956598SShawn McCarney 
686*24956598SShawn McCarney TEST(RailTests, GetVoutUVFaultLimit)
687*24956598SShawn McCarney {
688*24956598SShawn McCarney     std::string name{"VDD2"};
689*24956598SShawn McCarney     std::optional<std::string> presence{};
690*24956598SShawn McCarney     bool isPowerSupplyRail{false};
691*24956598SShawn McCarney     bool checkStatusVout{false};
692*24956598SShawn McCarney     bool compareVoltageToLimit{false};
693*24956598SShawn McCarney     std::optional<GPIO> gpio{};
694*24956598SShawn McCarney 
695*24956598SShawn McCarney     // Test where page was not specified: Throws exception
696*24956598SShawn McCarney     {
697*24956598SShawn McCarney         std::optional<uint8_t> page{};
698*24956598SShawn McCarney         Rail rail{name,
699*24956598SShawn McCarney                   presence,
700*24956598SShawn McCarney                   page,
701*24956598SShawn McCarney                   isPowerSupplyRail,
702*24956598SShawn McCarney                   checkStatusVout,
703*24956598SShawn McCarney                   compareVoltageToLimit,
704*24956598SShawn McCarney                   gpio};
705*24956598SShawn McCarney 
706*24956598SShawn McCarney         MockDevice device{};
707*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit).Times(0);
708*24956598SShawn McCarney 
709*24956598SShawn McCarney         try
710*24956598SShawn McCarney         {
711*24956598SShawn McCarney             rail.getVoutUVFaultLimit(device);
712*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
713*24956598SShawn McCarney         }
714*24956598SShawn McCarney         catch (const std::exception& e)
715*24956598SShawn McCarney         {
716*24956598SShawn McCarney             EXPECT_STREQ(
717*24956598SShawn McCarney                 e.what(),
718*24956598SShawn McCarney                 "Unable to read VOUT_UV_FAULT_LIMIT value for rail VDD2: "
719*24956598SShawn McCarney                 "No PAGE number defined for rail VDD2");
720*24956598SShawn McCarney         }
721*24956598SShawn McCarney     }
722*24956598SShawn McCarney 
723*24956598SShawn McCarney     // Test where value read successfully
724*24956598SShawn McCarney     {
725*24956598SShawn McCarney         std::optional<uint8_t> page{2};
726*24956598SShawn McCarney         Rail rail{name,
727*24956598SShawn McCarney                   presence,
728*24956598SShawn McCarney                   page,
729*24956598SShawn McCarney                   isPowerSupplyRail,
730*24956598SShawn McCarney                   checkStatusVout,
731*24956598SShawn McCarney                   compareVoltageToLimit,
732*24956598SShawn McCarney                   gpio};
733*24956598SShawn McCarney 
734*24956598SShawn McCarney         MockDevice device{};
735*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
736*24956598SShawn McCarney             .Times(1)
737*24956598SShawn McCarney             .WillOnce(Return(0.9));
738*24956598SShawn McCarney 
739*24956598SShawn McCarney         EXPECT_EQ(rail.getVoutUVFaultLimit(device), 0.9);
740*24956598SShawn McCarney     }
741*24956598SShawn McCarney 
742*24956598SShawn McCarney     // Test where exception occurs trying to read value
743*24956598SShawn McCarney     {
744*24956598SShawn McCarney         std::optional<uint8_t> page{2};
745*24956598SShawn McCarney         Rail rail{name,
746*24956598SShawn McCarney                   presence,
747*24956598SShawn McCarney                   page,
748*24956598SShawn McCarney                   isPowerSupplyRail,
749*24956598SShawn McCarney                   checkStatusVout,
750*24956598SShawn McCarney                   compareVoltageToLimit,
751*24956598SShawn McCarney                   gpio};
752*24956598SShawn McCarney 
753*24956598SShawn McCarney         MockDevice device{};
754*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
755*24956598SShawn McCarney             .Times(1)
756*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
757*24956598SShawn McCarney 
758*24956598SShawn McCarney         try
759*24956598SShawn McCarney         {
760*24956598SShawn McCarney             rail.getVoutUVFaultLimit(device);
761*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
762*24956598SShawn McCarney         }
763*24956598SShawn McCarney         catch (const std::exception& e)
764*24956598SShawn McCarney         {
765*24956598SShawn McCarney             EXPECT_STREQ(
766*24956598SShawn McCarney                 e.what(),
767*24956598SShawn McCarney                 "Unable to read VOUT_UV_FAULT_LIMIT value for rail VDD2: "
768*24956598SShawn McCarney                 "File does not exist");
769*24956598SShawn McCarney         }
770*24956598SShawn McCarney     }
771*24956598SShawn McCarney }
772*24956598SShawn McCarney 
773*24956598SShawn McCarney TEST(RailTests, HasPgoodFault)
774*24956598SShawn McCarney {
775*24956598SShawn McCarney     std::string name{"VDD2"};
776*24956598SShawn McCarney     bool isPowerSupplyRail{false};
777*24956598SShawn McCarney 
778*24956598SShawn McCarney     // Test where presence check defined: Rail is not present
779*24956598SShawn McCarney     {
780*24956598SShawn McCarney         std::optional<std::string> presence{
781*24956598SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
782*24956598SShawn McCarney         std::optional<uint8_t> page{3};
783*24956598SShawn McCarney         bool checkStatusVout{true};
784*24956598SShawn McCarney         bool compareVoltageToLimit{false};
785*24956598SShawn McCarney         std::optional<GPIO> gpio{};
786*24956598SShawn McCarney         Rail rail{name,
787*24956598SShawn McCarney                   presence,
788*24956598SShawn McCarney                   page,
789*24956598SShawn McCarney                   isPowerSupplyRail,
790*24956598SShawn McCarney                   checkStatusVout,
791*24956598SShawn McCarney                   compareVoltageToLimit,
792*24956598SShawn McCarney                   gpio};
793*24956598SShawn McCarney 
794*24956598SShawn McCarney         MockDevice device{};
795*24956598SShawn McCarney 
796*24956598SShawn McCarney         MockServices services{};
797*24956598SShawn McCarney         EXPECT_CALL(services, isPresent(*presence))
798*24956598SShawn McCarney             .Times(1)
799*24956598SShawn McCarney             .WillOnce(Return(false));
800*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg("Rail VDD2 is not present")).Times(1);
801*24956598SShawn McCarney 
802*24956598SShawn McCarney         std::vector<int> gpioValues{};
803*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
804*24956598SShawn McCarney         EXPECT_FALSE(
805*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
806*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
807*24956598SShawn McCarney     }
808*24956598SShawn McCarney 
809*24956598SShawn McCarney     // Test where presence check defined: Rail is present
810*24956598SShawn McCarney     {
811*24956598SShawn McCarney         std::optional<std::string> presence{
812*24956598SShawn McCarney             "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2"};
813*24956598SShawn McCarney         std::optional<uint8_t> page{};
814*24956598SShawn McCarney         bool checkStatusVout{false};
815*24956598SShawn McCarney         bool compareVoltageToLimit{false};
816*24956598SShawn McCarney         std::optional<GPIO> gpio{};
817*24956598SShawn McCarney         Rail rail{name,
818*24956598SShawn McCarney                   presence,
819*24956598SShawn McCarney                   page,
820*24956598SShawn McCarney                   isPowerSupplyRail,
821*24956598SShawn McCarney                   checkStatusVout,
822*24956598SShawn McCarney                   compareVoltageToLimit,
823*24956598SShawn McCarney                   gpio};
824*24956598SShawn McCarney 
825*24956598SShawn McCarney         MockDevice device{};
826*24956598SShawn McCarney 
827*24956598SShawn McCarney         MockServices services{};
828*24956598SShawn McCarney         EXPECT_CALL(services, isPresent(*presence))
829*24956598SShawn McCarney             .Times(1)
830*24956598SShawn McCarney             .WillOnce(Return(true));
831*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg).Times(0);
832*24956598SShawn McCarney 
833*24956598SShawn McCarney         std::vector<int> gpioValues{};
834*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
835*24956598SShawn McCarney         EXPECT_FALSE(
836*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
837*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
838*24956598SShawn McCarney     }
839*24956598SShawn McCarney 
840*24956598SShawn McCarney     // Test where no checks are specified
841*24956598SShawn McCarney     {
842*24956598SShawn McCarney         std::optional<std::string> presence{};
843*24956598SShawn McCarney         std::optional<uint8_t> page{};
844*24956598SShawn McCarney         bool checkStatusVout{false};
845*24956598SShawn McCarney         bool compareVoltageToLimit{false};
846*24956598SShawn McCarney         std::optional<GPIO> gpio{};
847*24956598SShawn McCarney         Rail rail{name,
848*24956598SShawn McCarney                   presence,
849*24956598SShawn McCarney                   page,
850*24956598SShawn McCarney                   isPowerSupplyRail,
851*24956598SShawn McCarney                   checkStatusVout,
852*24956598SShawn McCarney                   compareVoltageToLimit,
853*24956598SShawn McCarney                   gpio};
854*24956598SShawn McCarney 
855*24956598SShawn McCarney         MockDevice device{};
856*24956598SShawn McCarney 
857*24956598SShawn McCarney         MockServices services{};
858*24956598SShawn McCarney 
859*24956598SShawn McCarney         std::vector<int> gpioValues{};
860*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
861*24956598SShawn McCarney         EXPECT_FALSE(
862*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
863*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
864*24956598SShawn McCarney     }
865*24956598SShawn McCarney 
866*24956598SShawn McCarney     // Test where 1 check defined: STATUS_VOUT: No fault detected
867*24956598SShawn McCarney     {
868*24956598SShawn McCarney         std::optional<std::string> presence{};
869*24956598SShawn McCarney         std::optional<uint8_t> page{2};
870*24956598SShawn McCarney         bool checkStatusVout{true};
871*24956598SShawn McCarney         bool compareVoltageToLimit{false};
872*24956598SShawn McCarney         std::optional<GPIO> gpio{};
873*24956598SShawn McCarney         Rail rail{name,
874*24956598SShawn McCarney                   presence,
875*24956598SShawn McCarney                   page,
876*24956598SShawn McCarney                   isPowerSupplyRail,
877*24956598SShawn McCarney                   checkStatusVout,
878*24956598SShawn McCarney                   compareVoltageToLimit,
879*24956598SShawn McCarney                   gpio};
880*24956598SShawn McCarney 
881*24956598SShawn McCarney         MockDevice device{};
882*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
883*24956598SShawn McCarney 
884*24956598SShawn McCarney         MockServices services{};
885*24956598SShawn McCarney 
886*24956598SShawn McCarney         std::vector<int> gpioValues{};
887*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
888*24956598SShawn McCarney         EXPECT_FALSE(
889*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
890*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
891*24956598SShawn McCarney     }
892*24956598SShawn McCarney 
893*24956598SShawn McCarney     // Test where 1 check defined: STATUS_VOUT: No fault detected, but warning
894*24956598SShawn McCarney     // bits set
895*24956598SShawn McCarney     {
896*24956598SShawn McCarney         std::optional<std::string> presence{};
897*24956598SShawn McCarney         std::optional<uint8_t> page{2};
898*24956598SShawn McCarney         bool checkStatusVout{true};
899*24956598SShawn McCarney         bool compareVoltageToLimit{false};
900*24956598SShawn McCarney         std::optional<GPIO> gpio{};
901*24956598SShawn McCarney         Rail rail{name,
902*24956598SShawn McCarney                   presence,
903*24956598SShawn McCarney                   page,
904*24956598SShawn McCarney                   isPowerSupplyRail,
905*24956598SShawn McCarney                   checkStatusVout,
906*24956598SShawn McCarney                   compareVoltageToLimit,
907*24956598SShawn McCarney                   gpio};
908*24956598SShawn McCarney 
909*24956598SShawn McCarney         MockDevice device{};
910*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x6a));
911*24956598SShawn McCarney 
912*24956598SShawn McCarney         MockServices services{};
913*24956598SShawn McCarney         EXPECT_CALL(
914*24956598SShawn McCarney             services,
915*24956598SShawn McCarney             logInfoMsg("Rail VDD2 has warning bits set in STATUS_VOUT: 0x6a"))
916*24956598SShawn McCarney             .Times(1);
917*24956598SShawn McCarney 
918*24956598SShawn McCarney         std::vector<int> gpioValues{};
919*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
920*24956598SShawn McCarney         EXPECT_FALSE(
921*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
922*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
923*24956598SShawn McCarney     }
924*24956598SShawn McCarney 
925*24956598SShawn McCarney     // Test where 1 check defined: STATUS_VOUT: Fault detected
926*24956598SShawn McCarney     // STATUS_WORD captured in additional data
927*24956598SShawn McCarney     {
928*24956598SShawn McCarney         std::optional<std::string> presence{};
929*24956598SShawn McCarney         std::optional<uint8_t> page{2};
930*24956598SShawn McCarney         bool checkStatusVout{true};
931*24956598SShawn McCarney         bool compareVoltageToLimit{false};
932*24956598SShawn McCarney         std::optional<GPIO> gpio{};
933*24956598SShawn McCarney         Rail rail{name,
934*24956598SShawn McCarney                   presence,
935*24956598SShawn McCarney                   page,
936*24956598SShawn McCarney                   isPowerSupplyRail,
937*24956598SShawn McCarney                   checkStatusVout,
938*24956598SShawn McCarney                   compareVoltageToLimit,
939*24956598SShawn McCarney                   gpio};
940*24956598SShawn McCarney 
941*24956598SShawn McCarney         MockDevice device{};
942*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x10));
943*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
944*24956598SShawn McCarney 
945*24956598SShawn McCarney         MockServices services{};
946*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
947*24956598SShawn McCarney             .Times(1);
948*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
949*24956598SShawn McCarney             .Times(1);
950*24956598SShawn McCarney         EXPECT_CALL(
951*24956598SShawn McCarney             services,
952*24956598SShawn McCarney             logErrorMsg("Rail VDD2 has fault bits set in STATUS_VOUT: 0x10"))
953*24956598SShawn McCarney             .Times(1);
954*24956598SShawn McCarney 
955*24956598SShawn McCarney         std::vector<int> gpioValues{};
956*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
957*24956598SShawn McCarney         EXPECT_TRUE(
958*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
959*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 3);
960*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
961*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_VOUT"], "0x10");
962*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
963*24956598SShawn McCarney     }
964*24956598SShawn McCarney 
965*24956598SShawn McCarney     // Test where 1 check defined: STATUS_VOUT: Exception thrown
966*24956598SShawn McCarney     {
967*24956598SShawn McCarney         std::optional<std::string> presence{};
968*24956598SShawn McCarney         std::optional<uint8_t> page{2};
969*24956598SShawn McCarney         bool checkStatusVout{true};
970*24956598SShawn McCarney         bool compareVoltageToLimit{false};
971*24956598SShawn McCarney         std::optional<GPIO> gpio{};
972*24956598SShawn McCarney         Rail rail{name,
973*24956598SShawn McCarney                   presence,
974*24956598SShawn McCarney                   page,
975*24956598SShawn McCarney                   isPowerSupplyRail,
976*24956598SShawn McCarney                   checkStatusVout,
977*24956598SShawn McCarney                   compareVoltageToLimit,
978*24956598SShawn McCarney                   gpio};
979*24956598SShawn McCarney 
980*24956598SShawn McCarney         MockDevice device{};
981*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2))
982*24956598SShawn McCarney             .Times(1)
983*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
984*24956598SShawn McCarney 
985*24956598SShawn McCarney         MockServices services{};
986*24956598SShawn McCarney 
987*24956598SShawn McCarney         std::vector<int> gpioValues{};
988*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
989*24956598SShawn McCarney         try
990*24956598SShawn McCarney         {
991*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData);
992*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
993*24956598SShawn McCarney         }
994*24956598SShawn McCarney         catch (const std::exception& e)
995*24956598SShawn McCarney         {
996*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
997*24956598SShawn McCarney                          "Unable to read STATUS_VOUT value for rail VDD2: "
998*24956598SShawn McCarney                          "File does not exist");
999*24956598SShawn McCarney         }
1000*24956598SShawn McCarney     }
1001*24956598SShawn McCarney 
1002*24956598SShawn McCarney     // Test where 1 check defined: GPIO: No fault detected
1003*24956598SShawn McCarney     // GPIO value is 1 and GPIO is active high
1004*24956598SShawn McCarney     {
1005*24956598SShawn McCarney         std::optional<std::string> presence{};
1006*24956598SShawn McCarney         std::optional<uint8_t> page{};
1007*24956598SShawn McCarney         bool checkStatusVout{false};
1008*24956598SShawn McCarney         bool compareVoltageToLimit{false};
1009*24956598SShawn McCarney         bool activeLow{false};
1010*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1011*24956598SShawn McCarney         Rail rail{name,
1012*24956598SShawn McCarney                   presence,
1013*24956598SShawn McCarney                   page,
1014*24956598SShawn McCarney                   isPowerSupplyRail,
1015*24956598SShawn McCarney                   checkStatusVout,
1016*24956598SShawn McCarney                   compareVoltageToLimit,
1017*24956598SShawn McCarney                   gpio};
1018*24956598SShawn McCarney 
1019*24956598SShawn McCarney         MockDevice device{};
1020*24956598SShawn McCarney 
1021*24956598SShawn McCarney         MockServices services{};
1022*24956598SShawn McCarney 
1023*24956598SShawn McCarney         std::vector<int> gpioValues{1, 1, 1, 1, 1, 1};
1024*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1025*24956598SShawn McCarney         EXPECT_FALSE(
1026*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1027*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
1028*24956598SShawn McCarney     }
1029*24956598SShawn McCarney 
1030*24956598SShawn McCarney     // Test where 1 check defined: GPIO: Fault detected
1031*24956598SShawn McCarney     // GPIO value is 0 and GPIO is active high
1032*24956598SShawn McCarney     // STATUS_WORD not captured since no PMBus page defined
1033*24956598SShawn McCarney     {
1034*24956598SShawn McCarney         std::optional<std::string> presence{};
1035*24956598SShawn McCarney         std::optional<uint8_t> page{};
1036*24956598SShawn McCarney         bool checkStatusVout{false};
1037*24956598SShawn McCarney         bool compareVoltageToLimit{false};
1038*24956598SShawn McCarney         bool activeLow{false};
1039*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1040*24956598SShawn McCarney         Rail rail{name,
1041*24956598SShawn McCarney                   presence,
1042*24956598SShawn McCarney                   page,
1043*24956598SShawn McCarney                   isPowerSupplyRail,
1044*24956598SShawn McCarney                   checkStatusVout,
1045*24956598SShawn McCarney                   compareVoltageToLimit,
1046*24956598SShawn McCarney                   gpio};
1047*24956598SShawn McCarney 
1048*24956598SShawn McCarney         MockDevice device{};
1049*24956598SShawn McCarney 
1050*24956598SShawn McCarney         MockServices services{};
1051*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1052*24956598SShawn McCarney             .Times(1);
1053*24956598SShawn McCarney         EXPECT_CALL(
1054*24956598SShawn McCarney             services,
1055*24956598SShawn McCarney             logErrorMsg(
1056*24956598SShawn McCarney                 "Rail VDD2 pgood GPIO line offset 3 has inactive value 0"))
1057*24956598SShawn McCarney             .Times(1);
1058*24956598SShawn McCarney 
1059*24956598SShawn McCarney         std::vector<int> gpioValues{1, 1, 1, 0, 1, 1};
1060*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1061*24956598SShawn McCarney         EXPECT_TRUE(
1062*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1063*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 3);
1064*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1065*24956598SShawn McCarney         EXPECT_EQ(additionalData["GPIO_LINE"], "3");
1066*24956598SShawn McCarney         EXPECT_EQ(additionalData["GPIO_VALUE"], "0");
1067*24956598SShawn McCarney     }
1068*24956598SShawn McCarney 
1069*24956598SShawn McCarney     // Test where 1 check defined: GPIO: Exception thrown: Invalid line offset
1070*24956598SShawn McCarney     {
1071*24956598SShawn McCarney         std::optional<std::string> presence{};
1072*24956598SShawn McCarney         std::optional<uint8_t> page{};
1073*24956598SShawn McCarney         bool checkStatusVout{false};
1074*24956598SShawn McCarney         bool compareVoltageToLimit{false};
1075*24956598SShawn McCarney         bool activeLow{false};
1076*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(6, activeLow)};
1077*24956598SShawn McCarney         Rail rail{name,
1078*24956598SShawn McCarney                   presence,
1079*24956598SShawn McCarney                   page,
1080*24956598SShawn McCarney                   isPowerSupplyRail,
1081*24956598SShawn McCarney                   checkStatusVout,
1082*24956598SShawn McCarney                   compareVoltageToLimit,
1083*24956598SShawn McCarney                   gpio};
1084*24956598SShawn McCarney 
1085*24956598SShawn McCarney         MockDevice device{};
1086*24956598SShawn McCarney 
1087*24956598SShawn McCarney         MockServices services{};
1088*24956598SShawn McCarney 
1089*24956598SShawn McCarney         std::vector<int> gpioValues{1, 1, 1, 1, 1, 1};
1090*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1091*24956598SShawn McCarney         try
1092*24956598SShawn McCarney         {
1093*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData);
1094*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
1095*24956598SShawn McCarney         }
1096*24956598SShawn McCarney         catch (const std::exception& e)
1097*24956598SShawn McCarney         {
1098*24956598SShawn McCarney             EXPECT_STREQ(e.what(), "Invalid GPIO line offset 6 for rail VDD2: "
1099*24956598SShawn McCarney                                    "Device only has 6 GPIO values");
1100*24956598SShawn McCarney         }
1101*24956598SShawn McCarney     }
1102*24956598SShawn McCarney 
1103*24956598SShawn McCarney     // Test where 1 check defined: READ_VOUT: No fault detected
1104*24956598SShawn McCarney     // Output voltage > UV limit
1105*24956598SShawn McCarney     {
1106*24956598SShawn McCarney         std::optional<std::string> presence{};
1107*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1108*24956598SShawn McCarney         bool checkStatusVout{false};
1109*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1110*24956598SShawn McCarney         std::optional<GPIO> gpio{};
1111*24956598SShawn McCarney         Rail rail{name,
1112*24956598SShawn McCarney                   presence,
1113*24956598SShawn McCarney                   page,
1114*24956598SShawn McCarney                   isPowerSupplyRail,
1115*24956598SShawn McCarney                   checkStatusVout,
1116*24956598SShawn McCarney                   compareVoltageToLimit,
1117*24956598SShawn McCarney                   gpio};
1118*24956598SShawn McCarney 
1119*24956598SShawn McCarney         MockDevice device{};
1120*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1121*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
1122*24956598SShawn McCarney             .Times(1)
1123*24956598SShawn McCarney             .WillOnce(Return(1.0));
1124*24956598SShawn McCarney 
1125*24956598SShawn McCarney         MockServices services{};
1126*24956598SShawn McCarney 
1127*24956598SShawn McCarney         std::vector<int> gpioValues{};
1128*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1129*24956598SShawn McCarney         EXPECT_FALSE(
1130*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1131*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
1132*24956598SShawn McCarney     }
1133*24956598SShawn McCarney 
1134*24956598SShawn McCarney     // Test where 1 check defined: READ_VOUT: Fault detected
1135*24956598SShawn McCarney     // Output voltage < UV limit
1136*24956598SShawn McCarney     {
1137*24956598SShawn McCarney         std::optional<std::string> presence{};
1138*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1139*24956598SShawn McCarney         bool checkStatusVout{false};
1140*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1141*24956598SShawn McCarney         std::optional<GPIO> gpio{};
1142*24956598SShawn McCarney         Rail rail{name,
1143*24956598SShawn McCarney                   presence,
1144*24956598SShawn McCarney                   page,
1145*24956598SShawn McCarney                   isPowerSupplyRail,
1146*24956598SShawn McCarney                   checkStatusVout,
1147*24956598SShawn McCarney                   compareVoltageToLimit,
1148*24956598SShawn McCarney                   gpio};
1149*24956598SShawn McCarney 
1150*24956598SShawn McCarney         MockDevice device{};
1151*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1152*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
1153*24956598SShawn McCarney             .Times(1)
1154*24956598SShawn McCarney             .WillOnce(Return(1.2));
1155*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1156*24956598SShawn McCarney 
1157*24956598SShawn McCarney         MockServices services{};
1158*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1159*24956598SShawn McCarney             .Times(1);
1160*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1161*24956598SShawn McCarney             .Times(1);
1162*24956598SShawn McCarney         EXPECT_CALL(
1163*24956598SShawn McCarney             services,
1164*24956598SShawn McCarney             logErrorMsg(
1165*24956598SShawn McCarney                 "Rail VDD2 output voltage 1.1V is <= UV fault limit 1.2V"))
1166*24956598SShawn McCarney             .Times(1);
1167*24956598SShawn McCarney 
1168*24956598SShawn McCarney         std::vector<int> gpioValues{};
1169*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1170*24956598SShawn McCarney         EXPECT_TRUE(
1171*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1172*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 4);
1173*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1174*24956598SShawn McCarney         EXPECT_EQ(additionalData["READ_VOUT"], "1.1");
1175*24956598SShawn McCarney         EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.2");
1176*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1177*24956598SShawn McCarney     }
1178*24956598SShawn McCarney 
1179*24956598SShawn McCarney     // Test where 1 check defined: READ_VOUT: Exception thrown
1180*24956598SShawn McCarney     {
1181*24956598SShawn McCarney         std::optional<std::string> presence{};
1182*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1183*24956598SShawn McCarney         bool checkStatusVout{false};
1184*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1185*24956598SShawn McCarney         std::optional<GPIO> gpio{};
1186*24956598SShawn McCarney         Rail rail{name,
1187*24956598SShawn McCarney                   presence,
1188*24956598SShawn McCarney                   page,
1189*24956598SShawn McCarney                   isPowerSupplyRail,
1190*24956598SShawn McCarney                   checkStatusVout,
1191*24956598SShawn McCarney                   compareVoltageToLimit,
1192*24956598SShawn McCarney                   gpio};
1193*24956598SShawn McCarney 
1194*24956598SShawn McCarney         MockDevice device{};
1195*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2))
1196*24956598SShawn McCarney             .Times(1)
1197*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
1198*24956598SShawn McCarney 
1199*24956598SShawn McCarney         MockServices services{};
1200*24956598SShawn McCarney 
1201*24956598SShawn McCarney         std::vector<int> gpioValues{};
1202*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1203*24956598SShawn McCarney         try
1204*24956598SShawn McCarney         {
1205*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData);
1206*24956598SShawn McCarney             ADD_FAILURE() << "Should not have reached this line.";
1207*24956598SShawn McCarney         }
1208*24956598SShawn McCarney         catch (const std::exception& e)
1209*24956598SShawn McCarney         {
1210*24956598SShawn McCarney             EXPECT_STREQ(e.what(),
1211*24956598SShawn McCarney                          "Unable to read READ_VOUT value for rail VDD2: "
1212*24956598SShawn McCarney                          "File does not exist");
1213*24956598SShawn McCarney         }
1214*24956598SShawn McCarney     }
1215*24956598SShawn McCarney 
1216*24956598SShawn McCarney     // Test where 3 checks defined: No fault detected
1217*24956598SShawn McCarney     // GPIO value is 0 and GPIO is active low
1218*24956598SShawn McCarney     {
1219*24956598SShawn McCarney         std::optional<std::string> presence{};
1220*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1221*24956598SShawn McCarney         bool checkStatusVout{true};
1222*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1223*24956598SShawn McCarney         bool activeLow{true};
1224*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1225*24956598SShawn McCarney         Rail rail{name,
1226*24956598SShawn McCarney                   presence,
1227*24956598SShawn McCarney                   page,
1228*24956598SShawn McCarney                   isPowerSupplyRail,
1229*24956598SShawn McCarney                   checkStatusVout,
1230*24956598SShawn McCarney                   compareVoltageToLimit,
1231*24956598SShawn McCarney                   gpio};
1232*24956598SShawn McCarney 
1233*24956598SShawn McCarney         MockDevice device{};
1234*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1235*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1236*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
1237*24956598SShawn McCarney             .Times(1)
1238*24956598SShawn McCarney             .WillOnce(Return(0.9));
1239*24956598SShawn McCarney 
1240*24956598SShawn McCarney         MockServices services{};
1241*24956598SShawn McCarney 
1242*24956598SShawn McCarney         std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1243*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1244*24956598SShawn McCarney         EXPECT_FALSE(
1245*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1246*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 0);
1247*24956598SShawn McCarney     }
1248*24956598SShawn McCarney 
1249*24956598SShawn McCarney     // Test where 3 checks defined: Fault detected via STATUS_VOUT
1250*24956598SShawn McCarney     {
1251*24956598SShawn McCarney         std::optional<std::string> presence{};
1252*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1253*24956598SShawn McCarney         bool checkStatusVout{true};
1254*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1255*24956598SShawn McCarney         bool activeLow{true};
1256*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1257*24956598SShawn McCarney         Rail rail{name,
1258*24956598SShawn McCarney                   presence,
1259*24956598SShawn McCarney                   page,
1260*24956598SShawn McCarney                   isPowerSupplyRail,
1261*24956598SShawn McCarney                   checkStatusVout,
1262*24956598SShawn McCarney                   compareVoltageToLimit,
1263*24956598SShawn McCarney                   gpio};
1264*24956598SShawn McCarney 
1265*24956598SShawn McCarney         MockDevice device{};
1266*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x10));
1267*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1268*24956598SShawn McCarney 
1269*24956598SShawn McCarney         MockServices services{};
1270*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1271*24956598SShawn McCarney             .Times(1);
1272*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1273*24956598SShawn McCarney             .Times(1);
1274*24956598SShawn McCarney         EXPECT_CALL(
1275*24956598SShawn McCarney             services,
1276*24956598SShawn McCarney             logErrorMsg("Rail VDD2 has fault bits set in STATUS_VOUT: 0x10"))
1277*24956598SShawn McCarney             .Times(1);
1278*24956598SShawn McCarney 
1279*24956598SShawn McCarney         std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1280*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1281*24956598SShawn McCarney         EXPECT_TRUE(
1282*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1283*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 3);
1284*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1285*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_VOUT"], "0x10");
1286*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1287*24956598SShawn McCarney     }
1288*24956598SShawn McCarney 
1289*24956598SShawn McCarney     // Test where 3 checks defined: Fault detected via GPIO
1290*24956598SShawn McCarney     // GPIO value is 1 and GPIO is active low
1291*24956598SShawn McCarney     {
1292*24956598SShawn McCarney         std::optional<std::string> presence{};
1293*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1294*24956598SShawn McCarney         bool checkStatusVout{true};
1295*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1296*24956598SShawn McCarney         bool activeLow{true};
1297*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1298*24956598SShawn McCarney         Rail rail{name,
1299*24956598SShawn McCarney                   presence,
1300*24956598SShawn McCarney                   page,
1301*24956598SShawn McCarney                   isPowerSupplyRail,
1302*24956598SShawn McCarney                   checkStatusVout,
1303*24956598SShawn McCarney                   compareVoltageToLimit,
1304*24956598SShawn McCarney                   gpio};
1305*24956598SShawn McCarney 
1306*24956598SShawn McCarney         MockDevice device{};
1307*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1308*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2)).Times(1).WillOnce(Return(0xbeef));
1309*24956598SShawn McCarney 
1310*24956598SShawn McCarney         MockServices services{};
1311*24956598SShawn McCarney         EXPECT_CALL(services, logInfoMsg("Rail VDD2 STATUS_WORD: 0xbeef"))
1312*24956598SShawn McCarney             .Times(1);
1313*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1314*24956598SShawn McCarney             .Times(1);
1315*24956598SShawn McCarney         EXPECT_CALL(
1316*24956598SShawn McCarney             services,
1317*24956598SShawn McCarney             logErrorMsg(
1318*24956598SShawn McCarney                 "Rail VDD2 pgood GPIO line offset 3 has inactive value 1"))
1319*24956598SShawn McCarney             .Times(1);
1320*24956598SShawn McCarney 
1321*24956598SShawn McCarney         std::vector<int> gpioValues{0, 0, 0, 1, 0, 0};
1322*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1323*24956598SShawn McCarney         EXPECT_TRUE(
1324*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1325*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 4);
1326*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1327*24956598SShawn McCarney         EXPECT_EQ(additionalData["GPIO_LINE"], "3");
1328*24956598SShawn McCarney         EXPECT_EQ(additionalData["GPIO_VALUE"], "1");
1329*24956598SShawn McCarney         EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef");
1330*24956598SShawn McCarney     }
1331*24956598SShawn McCarney 
1332*24956598SShawn McCarney     // Test where 3 checks defined: Fault detected via READ_VOUT
1333*24956598SShawn McCarney     // Output voltage == UV limit
1334*24956598SShawn McCarney     // STATUS_WORD not captured because reading it caused an exception
1335*24956598SShawn McCarney     {
1336*24956598SShawn McCarney         std::optional<std::string> presence{};
1337*24956598SShawn McCarney         std::optional<uint8_t> page{2};
1338*24956598SShawn McCarney         bool checkStatusVout{true};
1339*24956598SShawn McCarney         bool compareVoltageToLimit{true};
1340*24956598SShawn McCarney         bool activeLow{true};
1341*24956598SShawn McCarney         std::optional<GPIO> gpio{GPIO(3, activeLow)};
1342*24956598SShawn McCarney         Rail rail{name,
1343*24956598SShawn McCarney                   presence,
1344*24956598SShawn McCarney                   page,
1345*24956598SShawn McCarney                   isPowerSupplyRail,
1346*24956598SShawn McCarney                   checkStatusVout,
1347*24956598SShawn McCarney                   compareVoltageToLimit,
1348*24956598SShawn McCarney                   gpio};
1349*24956598SShawn McCarney 
1350*24956598SShawn McCarney         MockDevice device{};
1351*24956598SShawn McCarney         EXPECT_CALL(device, getStatusVout(2)).Times(1).WillOnce(Return(0x00));
1352*24956598SShawn McCarney         EXPECT_CALL(device, getReadVout(2)).Times(1).WillOnce(Return(1.1));
1353*24956598SShawn McCarney         EXPECT_CALL(device, getVoutUVFaultLimit(2))
1354*24956598SShawn McCarney             .Times(1)
1355*24956598SShawn McCarney             .WillOnce(Return(1.1));
1356*24956598SShawn McCarney         EXPECT_CALL(device, getStatusWord(2))
1357*24956598SShawn McCarney             .Times(1)
1358*24956598SShawn McCarney             .WillOnce(Throw(std::runtime_error{"File does not exist"}));
1359*24956598SShawn McCarney 
1360*24956598SShawn McCarney         MockServices services{};
1361*24956598SShawn McCarney         EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD2"))
1362*24956598SShawn McCarney             .Times(1);
1363*24956598SShawn McCarney         EXPECT_CALL(
1364*24956598SShawn McCarney             services,
1365*24956598SShawn McCarney             logErrorMsg(
1366*24956598SShawn McCarney                 "Rail VDD2 output voltage 1.1V is <= UV fault limit 1.1V"))
1367*24956598SShawn McCarney             .Times(1);
1368*24956598SShawn McCarney 
1369*24956598SShawn McCarney         std::vector<int> gpioValues{0, 0, 0, 0, 0, 0};
1370*24956598SShawn McCarney         std::map<std::string, std::string> additionalData{};
1371*24956598SShawn McCarney         EXPECT_TRUE(
1372*24956598SShawn McCarney             rail.hasPgoodFault(device, services, gpioValues, additionalData));
1373*24956598SShawn McCarney         EXPECT_EQ(additionalData.size(), 3);
1374*24956598SShawn McCarney         EXPECT_EQ(additionalData["RAIL_NAME"], "VDD2");
1375*24956598SShawn McCarney         EXPECT_EQ(additionalData["READ_VOUT"], "1.1");
1376*24956598SShawn McCarney         EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.1");
1377*24956598SShawn McCarney     }
1378*24956598SShawn McCarney }
1379