| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 1 | /** | 
|  | 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 |  | 
|  | 17 | #include "mock_services.hpp" | 
|  | 18 | #include "rail.hpp" | 
| Shawn McCarney | fc3f31f | 2024-04-23 17:02:44 -0500 | [diff] [blame] | 19 | #include "services.hpp" | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 20 | #include "standard_device.hpp" | 
|  | 21 |  | 
|  | 22 | #include <cstdint> | 
|  | 23 | #include <map> | 
|  | 24 | #include <memory> | 
|  | 25 | #include <optional> | 
|  | 26 | #include <string> | 
|  | 27 | #include <utility> | 
|  | 28 | #include <vector> | 
|  | 29 |  | 
|  | 30 | #include <gmock/gmock.h> | 
|  | 31 | #include <gtest/gtest.h> | 
|  | 32 |  | 
|  | 33 | using namespace phosphor::power::sequencer; | 
|  | 34 |  | 
|  | 35 | using ::testing::Return; | 
|  | 36 | using ::testing::Throw; | 
|  | 37 |  | 
|  | 38 | /** | 
|  | 39 | * @class StandardDeviceImpl | 
|  | 40 | * | 
|  | 41 | * Concrete subclass of the StandardDevice abstract class. | 
|  | 42 | * | 
|  | 43 | * This subclass is required for two reasons: | 
|  | 44 | * - StandardDevice has some pure virtual methods so it cannot be instantiated. | 
|  | 45 | * - The pure virtual methods provide the PMBus and GPIO information.  Mocking | 
|  | 46 | *   these makes it possible to test the pgood fault detection algorithm. | 
|  | 47 | * | 
|  | 48 | * This class is not intended to be used outside of this file.  It is | 
|  | 49 | * implementation detail for testing the the StandardDevice class. | 
|  | 50 | */ | 
|  | 51 | class StandardDeviceImpl : public StandardDevice | 
|  | 52 | { | 
|  | 53 | public: | 
|  | 54 | // Specify which compiler-generated methods we want | 
|  | 55 | StandardDeviceImpl() = delete; | 
|  | 56 | StandardDeviceImpl(const StandardDeviceImpl&) = delete; | 
|  | 57 | StandardDeviceImpl(StandardDeviceImpl&&) = delete; | 
|  | 58 | StandardDeviceImpl& operator=(const StandardDeviceImpl&) = delete; | 
|  | 59 | StandardDeviceImpl& operator=(StandardDeviceImpl&&) = delete; | 
|  | 60 | virtual ~StandardDeviceImpl() = default; | 
|  | 61 |  | 
|  | 62 | // Constructor just calls StandardDevice constructor | 
|  | 63 | explicit StandardDeviceImpl(const std::string& name, | 
|  | 64 | std::vector<std::unique_ptr<Rail>> rails) : | 
|  | 65 | StandardDevice(name, std::move(rails)) | 
|  | 66 | {} | 
|  | 67 |  | 
|  | 68 | // Mock pure virtual methods | 
| Shawn McCarney | fc3f31f | 2024-04-23 17:02:44 -0500 | [diff] [blame] | 69 | MOCK_METHOD(std::vector<int>, getGPIOValues, (Services & services), | 
|  | 70 | (override)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 71 | MOCK_METHOD(uint16_t, getStatusWord, (uint8_t page), (override)); | 
|  | 72 | MOCK_METHOD(uint8_t, getStatusVout, (uint8_t page), (override)); | 
|  | 73 | MOCK_METHOD(double, getReadVout, (uint8_t page), (override)); | 
|  | 74 | MOCK_METHOD(double, getVoutUVFaultLimit, (uint8_t page), (override)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 75 |  | 
|  | 76 | // Override empty implementation with mock so we can verify it is called | 
|  | 77 | MOCK_METHOD(void, prepareForPgoodFaultDetection, (Services & services), | 
|  | 78 | (override)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 79 | }; | 
|  | 80 |  | 
|  | 81 | /** | 
|  | 82 | * Creates a Rail object that checks for a pgood fault using STATUS_VOUT. | 
|  | 83 | * | 
|  | 84 | * @param name Unique name for the rail | 
|  | 85 | * @param isPowerSupplyRail Specifies whether the rail is produced by a | 
|  | 86 | power supply | 
|  | 87 | * @param pageNum PMBus PAGE number of the rail | 
|  | 88 | * @return Rail object | 
|  | 89 | */ | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 90 | std::unique_ptr<Rail> createRailStatusVout( | 
|  | 91 | const std::string& name, bool isPowerSupplyRail, uint8_t pageNum) | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 92 | { | 
|  | 93 | std::optional<std::string> presence{}; | 
|  | 94 | std::optional<uint8_t> page{pageNum}; | 
|  | 95 | bool checkStatusVout{true}; | 
|  | 96 | bool compareVoltageToLimit{false}; | 
|  | 97 | std::optional<GPIO> gpio{}; | 
|  | 98 | return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail, | 
|  | 99 | checkStatusVout, compareVoltageToLimit, gpio); | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | /** | 
|  | 103 | * Creates a Rail object that checks for a pgood fault using a GPIO. | 
|  | 104 | * | 
|  | 105 | * @param name Unique name for the rail | 
|  | 106 | * @param isPowerSupplyRail Specifies whether the rail is produced by a | 
|  | 107 | power supply | 
|  | 108 | * @param gpio GPIO line to read to determine the pgood status of the rail | 
|  | 109 | * @return Rail object | 
|  | 110 | */ | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 111 | std::unique_ptr<Rail> createRailGPIO( | 
|  | 112 | const std::string& name, bool isPowerSupplyRail, unsigned int gpioLine) | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 113 | { | 
|  | 114 | std::optional<std::string> presence{}; | 
|  | 115 | std::optional<uint8_t> page{}; | 
|  | 116 | bool checkStatusVout{false}; | 
|  | 117 | bool compareVoltageToLimit{false}; | 
|  | 118 | bool activeLow{false}; | 
|  | 119 | std::optional<GPIO> gpio{GPIO{gpioLine, activeLow}}; | 
|  | 120 | return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail, | 
|  | 121 | checkStatusVout, compareVoltageToLimit, gpio); | 
|  | 122 | } | 
|  | 123 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 124 | /** | 
|  | 125 | * Creates a Rail object that checks for a pgood fault using output voltage. | 
|  | 126 | * | 
|  | 127 | * @param name Unique name for the rail | 
|  | 128 | * @param isPowerSupplyRail Specifies whether the rail is produced by a | 
|  | 129 | power supply | 
|  | 130 | * @param pageNum PMBus PAGE number of the rail | 
|  | 131 | * @return Rail object | 
|  | 132 | */ | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 133 | std::unique_ptr<Rail> createRailOutputVoltage( | 
|  | 134 | const std::string& name, bool isPowerSupplyRail, uint8_t pageNum) | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 135 | { | 
|  | 136 | std::optional<std::string> presence{}; | 
|  | 137 | std::optional<uint8_t> page{pageNum}; | 
|  | 138 | bool checkStatusVout{false}; | 
|  | 139 | bool compareVoltageToLimit{true}; | 
|  | 140 | std::optional<GPIO> gpio{}; | 
|  | 141 | return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail, | 
|  | 142 | checkStatusVout, compareVoltageToLimit, gpio); | 
|  | 143 | } | 
|  | 144 |  | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 145 | TEST(StandardDeviceTests, Constructor) | 
|  | 146 | { | 
|  | 147 | // Empty vector of rails | 
|  | 148 | { | 
|  | 149 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 150 | StandardDeviceImpl device{"xyz_pseq", std::move(rails)}; | 
|  | 151 |  | 
|  | 152 | EXPECT_EQ(device.getName(), "xyz_pseq"); | 
|  | 153 | EXPECT_TRUE(device.getRails().empty()); | 
|  | 154 | } | 
|  | 155 |  | 
|  | 156 | // Non-empty vector of rails | 
|  | 157 | { | 
|  | 158 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 159 | rails.emplace_back(createRailGPIO("PSU", true, 3)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 160 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 161 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 162 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 163 |  | 
|  | 164 | EXPECT_EQ(device.getName(), "abc_pseq"); | 
|  | 165 | EXPECT_EQ(device.getRails().size(), 3); | 
|  | 166 | EXPECT_EQ(device.getRails()[0]->getName(), "PSU"); | 
|  | 167 | EXPECT_EQ(device.getRails()[1]->getName(), "VDD"); | 
|  | 168 | EXPECT_EQ(device.getRails()[2]->getName(), "VIO"); | 
|  | 169 | } | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | TEST(StandardDeviceTests, GetName) | 
|  | 173 | { | 
|  | 174 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 175 | StandardDeviceImpl device{"xyz_pseq", std::move(rails)}; | 
|  | 176 |  | 
|  | 177 | EXPECT_EQ(device.getName(), "xyz_pseq"); | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | TEST(StandardDeviceTests, GetRails) | 
|  | 181 | { | 
|  | 182 | // Empty vector of rails | 
|  | 183 | { | 
|  | 184 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 185 | StandardDeviceImpl device{"xyz_pseq", std::move(rails)}; | 
|  | 186 |  | 
|  | 187 | EXPECT_TRUE(device.getRails().empty()); | 
|  | 188 | } | 
|  | 189 |  | 
|  | 190 | // Non-empty vector of rails | 
|  | 191 | { | 
|  | 192 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 193 | rails.emplace_back(createRailGPIO("PSU", true, 3)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 194 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 195 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 196 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 197 |  | 
|  | 198 | EXPECT_EQ(device.getRails().size(), 3); | 
|  | 199 | EXPECT_EQ(device.getRails()[0]->getName(), "PSU"); | 
|  | 200 | EXPECT_EQ(device.getRails()[1]->getName(), "VDD"); | 
|  | 201 | EXPECT_EQ(device.getRails()[2]->getName(), "VIO"); | 
|  | 202 | } | 
|  | 203 | } | 
|  | 204 |  | 
|  | 205 | TEST(StandardDeviceTests, FindPgoodFault) | 
|  | 206 | { | 
|  | 207 | // No rail has a pgood fault | 
|  | 208 | { | 
|  | 209 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 210 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 211 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 212 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 213 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 214 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 215 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 216 | std::vector<int> gpioValues{1, 1, 1}; | 
|  | 217 | EXPECT_CALL(device, getGPIOValues) | 
|  | 218 | .Times(1) | 
|  | 219 | .WillOnce(Return(gpioValues)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 220 | EXPECT_CALL(device, getReadVout(5)).Times(1).WillOnce(Return(1.2)); | 
|  | 221 | EXPECT_CALL(device, getVoutUVFaultLimit(5)) | 
|  | 222 | .Times(1) | 
|  | 223 | .WillOnce(Return(1.1)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 224 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x00)); | 
|  | 225 |  | 
|  | 226 | MockServices services{}; | 
|  | 227 |  | 
|  | 228 | std::string powerSupplyError{}; | 
|  | 229 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 230 | std::string error = | 
|  | 231 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 232 | EXPECT_TRUE(error.empty()); | 
|  | 233 | EXPECT_EQ(additionalData.size(), 0); | 
|  | 234 | } | 
|  | 235 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 236 | // First rail has a pgood fault detected via GPIO | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 237 | // Is a PSU rail: No PSU error specified | 
|  | 238 | { | 
|  | 239 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 240 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 241 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 242 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 243 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 244 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 245 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 246 | std::vector<int> gpioValues{1, 1, 0}; | 
|  | 247 | EXPECT_CALL(device, getGPIOValues) | 
|  | 248 | .Times(1) | 
|  | 249 | .WillOnce(Return(gpioValues)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 250 | EXPECT_CALL(device, getReadVout(5)).Times(0); | 
|  | 251 | EXPECT_CALL(device, getVoutUVFaultLimit(5)).Times(0); | 
|  | 252 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x00)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 253 |  | 
|  | 254 | MockServices services{}; | 
|  | 255 | EXPECT_CALL(services, | 
|  | 256 | logInfoMsg("Device abc_pseq GPIO values: [1, 1, 0]")) | 
|  | 257 | .Times(1); | 
|  | 258 | EXPECT_CALL( | 
|  | 259 | services, | 
|  | 260 | logErrorMsg( | 
|  | 261 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 262 | .Times(1); | 
|  | 263 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail PSU")) | 
|  | 264 | .Times(1); | 
|  | 265 | EXPECT_CALL( | 
|  | 266 | services, | 
|  | 267 | logErrorMsg( | 
|  | 268 | "Rail PSU pgood GPIO line offset 2 has inactive value 0")) | 
|  | 269 | .Times(1); | 
|  | 270 |  | 
|  | 271 | std::string powerSupplyError{}; | 
|  | 272 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 273 | std::string error = | 
|  | 274 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 275 | EXPECT_EQ(error, | 
|  | 276 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
|  | 277 | EXPECT_EQ(additionalData.size(), 5); | 
|  | 278 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 279 | EXPECT_EQ(additionalData["GPIO_VALUES"], "[1, 1, 0]"); | 
|  | 280 | EXPECT_EQ(additionalData["RAIL_NAME"], "PSU"); | 
|  | 281 | EXPECT_EQ(additionalData["GPIO_LINE"], "2"); | 
|  | 282 | EXPECT_EQ(additionalData["GPIO_VALUE"], "0"); | 
|  | 283 | } | 
|  | 284 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 285 | // First rail has a pgood fault detected via GPIO | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 286 | // Is a PSU rail: PSU error specified | 
|  | 287 | { | 
|  | 288 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 289 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 290 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 291 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 292 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 293 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 294 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 295 | std::vector<int> gpioValues{1, 1, 0}; | 
|  | 296 | EXPECT_CALL(device, getGPIOValues) | 
|  | 297 | .Times(1) | 
|  | 298 | .WillOnce(Return(gpioValues)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 299 | EXPECT_CALL(device, getReadVout(5)).Times(0); | 
|  | 300 | EXPECT_CALL(device, getVoutUVFaultLimit(5)).Times(0); | 
|  | 301 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x00)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 302 |  | 
|  | 303 | MockServices services{}; | 
|  | 304 | EXPECT_CALL(services, | 
|  | 305 | logInfoMsg("Device abc_pseq GPIO values: [1, 1, 0]")) | 
|  | 306 | .Times(1); | 
|  | 307 | EXPECT_CALL( | 
|  | 308 | services, | 
|  | 309 | logErrorMsg( | 
|  | 310 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 311 | .Times(1); | 
|  | 312 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail PSU")) | 
|  | 313 | .Times(1); | 
|  | 314 | EXPECT_CALL( | 
|  | 315 | services, | 
|  | 316 | logErrorMsg( | 
|  | 317 | "Rail PSU pgood GPIO line offset 2 has inactive value 0")) | 
|  | 318 | .Times(1); | 
|  | 319 |  | 
|  | 320 | std::string powerSupplyError{"Undervoltage fault: PSU1"}; | 
|  | 321 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 322 | std::string error = | 
|  | 323 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 324 | EXPECT_EQ(error, powerSupplyError); | 
|  | 325 | EXPECT_EQ(additionalData.size(), 5); | 
|  | 326 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 327 | EXPECT_EQ(additionalData["GPIO_VALUES"], "[1, 1, 0]"); | 
|  | 328 | EXPECT_EQ(additionalData["RAIL_NAME"], "PSU"); | 
|  | 329 | EXPECT_EQ(additionalData["GPIO_LINE"], "2"); | 
|  | 330 | EXPECT_EQ(additionalData["GPIO_VALUE"], "0"); | 
|  | 331 | } | 
|  | 332 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 333 | // Second rail has a pgood fault detected via output voltage | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 334 | // Not a PSU rail: PSU error specified | 
|  | 335 | { | 
|  | 336 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 337 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 338 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 339 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 340 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 341 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 342 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 343 | std::vector<int> gpioValues{1, 1, 1}; | 
|  | 344 | EXPECT_CALL(device, getGPIOValues) | 
|  | 345 | .Times(1) | 
|  | 346 | .WillOnce(Return(gpioValues)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 347 | EXPECT_CALL(device, getReadVout(5)).Times(1).WillOnce(Return(1.1)); | 
|  | 348 | EXPECT_CALL(device, getVoutUVFaultLimit(5)) | 
|  | 349 | .Times(1) | 
|  | 350 | .WillOnce(Return(1.2)); | 
|  | 351 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x00)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 352 | EXPECT_CALL(device, getStatusWord(5)).Times(1).WillOnce(Return(0xbeef)); | 
|  | 353 |  | 
|  | 354 | MockServices services{}; | 
|  | 355 | EXPECT_CALL(services, | 
|  | 356 | logInfoMsg("Device abc_pseq GPIO values: [1, 1, 1]")) | 
|  | 357 | .Times(1); | 
|  | 358 | EXPECT_CALL( | 
|  | 359 | services, | 
|  | 360 | logErrorMsg( | 
|  | 361 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 362 | .Times(1); | 
|  | 363 | EXPECT_CALL(services, logInfoMsg("Rail VDD STATUS_WORD: 0xbeef")) | 
|  | 364 | .Times(1); | 
|  | 365 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD")) | 
|  | 366 | .Times(1); | 
|  | 367 | EXPECT_CALL( | 
|  | 368 | services, | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 369 | logErrorMsg( | 
|  | 370 | "Rail VDD output voltage 1.1V is <= UV fault limit 1.2V")) | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 371 | .Times(1); | 
|  | 372 |  | 
|  | 373 | std::string powerSupplyError{"Undervoltage fault: PSU1"}; | 
|  | 374 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 375 | std::string error = | 
|  | 376 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 377 | EXPECT_EQ(error, | 
|  | 378 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 379 | EXPECT_EQ(additionalData.size(), 6); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 380 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 381 | EXPECT_EQ(additionalData["GPIO_VALUES"], "[1, 1, 1]"); | 
|  | 382 | EXPECT_EQ(additionalData["RAIL_NAME"], "VDD"); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 383 | EXPECT_EQ(additionalData["READ_VOUT"], "1.1"); | 
|  | 384 | EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.2"); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 385 | EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef"); | 
|  | 386 | } | 
|  | 387 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 388 | // Third rail has a pgood fault detected via STATUS_VOUT | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 389 | // Device returns 0 GPIO values | 
|  | 390 | // Does not halt pgood fault detection because GPIO values not used by rails | 
|  | 391 | { | 
|  | 392 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 393 | rails.emplace_back(createRailStatusVout("PSU", true, 3)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 394 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 395 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 396 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 397 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 398 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 399 | std::vector<int> gpioValues{}; | 
|  | 400 | EXPECT_CALL(device, getGPIOValues) | 
|  | 401 | .Times(1) | 
|  | 402 | .WillOnce(Return(gpioValues)); | 
|  | 403 | EXPECT_CALL(device, getStatusVout(3)).Times(1).WillOnce(Return(0x00)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 404 | EXPECT_CALL(device, getReadVout(5)).Times(0); | 
|  | 405 | EXPECT_CALL(device, getVoutUVFaultLimit(5)).Times(0); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 406 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x11)); | 
|  | 407 | EXPECT_CALL(device, getStatusWord(7)).Times(1).WillOnce(Return(0xbeef)); | 
|  | 408 |  | 
|  | 409 | MockServices services{}; | 
|  | 410 | EXPECT_CALL( | 
|  | 411 | services, | 
|  | 412 | logErrorMsg( | 
|  | 413 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 414 | .Times(1); | 
|  | 415 | EXPECT_CALL(services, logInfoMsg("Rail VIO STATUS_WORD: 0xbeef")) | 
|  | 416 | .Times(1); | 
|  | 417 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VIO")) | 
|  | 418 | .Times(1); | 
|  | 419 | EXPECT_CALL( | 
|  | 420 | services, | 
|  | 421 | logErrorMsg("Rail VIO has fault bits set in STATUS_VOUT: 0x11")) | 
|  | 422 | .Times(1); | 
|  | 423 |  | 
|  | 424 | std::string powerSupplyError{}; | 
|  | 425 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 426 | std::string error = | 
|  | 427 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 428 | EXPECT_EQ(error, | 
|  | 429 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
|  | 430 | EXPECT_EQ(additionalData.size(), 4); | 
|  | 431 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 432 | EXPECT_EQ(additionalData["RAIL_NAME"], "VIO"); | 
|  | 433 | EXPECT_EQ(additionalData["STATUS_VOUT"], "0x11"); | 
|  | 434 | EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef"); | 
|  | 435 | } | 
|  | 436 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 437 | // Third rail has a pgood fault detected via STATUS_VOUT | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 438 | // Exception occurs trying to obtain GPIO values from device | 
|  | 439 | // Does not halt pgood fault detection because GPIO values not used by rails | 
|  | 440 | { | 
|  | 441 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 442 | rails.emplace_back(createRailStatusVout("PSU", true, 3)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 443 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 444 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 445 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 446 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 447 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 448 | EXPECT_CALL(device, getGPIOValues) | 
|  | 449 | .Times(1) | 
|  | 450 | .WillOnce(Throw(std::runtime_error{"Unable to acquire GPIO line"})); | 
|  | 451 | EXPECT_CALL(device, getStatusVout(3)).Times(1).WillOnce(Return(0x00)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 452 | EXPECT_CALL(device, getReadVout(5)).Times(0); | 
|  | 453 | EXPECT_CALL(device, getVoutUVFaultLimit(5)).Times(0); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 454 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x11)); | 
|  | 455 | EXPECT_CALL(device, getStatusWord(7)).Times(1).WillOnce(Return(0xbeef)); | 
|  | 456 |  | 
|  | 457 | MockServices services{}; | 
|  | 458 | EXPECT_CALL( | 
|  | 459 | services, | 
|  | 460 | logErrorMsg( | 
|  | 461 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 462 | .Times(1); | 
|  | 463 | EXPECT_CALL(services, logInfoMsg("Rail VIO STATUS_WORD: 0xbeef")) | 
|  | 464 | .Times(1); | 
|  | 465 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VIO")) | 
|  | 466 | .Times(1); | 
|  | 467 | EXPECT_CALL( | 
|  | 468 | services, | 
|  | 469 | logErrorMsg("Rail VIO has fault bits set in STATUS_VOUT: 0x11")) | 
|  | 470 | .Times(1); | 
|  | 471 |  | 
|  | 472 | std::string powerSupplyError{}; | 
|  | 473 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 474 | std::string error = | 
|  | 475 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 476 | EXPECT_EQ(error, | 
|  | 477 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
|  | 478 | EXPECT_EQ(additionalData.size(), 4); | 
|  | 479 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 480 | EXPECT_EQ(additionalData["RAIL_NAME"], "VIO"); | 
|  | 481 | EXPECT_EQ(additionalData["STATUS_VOUT"], "0x11"); | 
|  | 482 | EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef"); | 
|  | 483 | } | 
|  | 484 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 485 | // All three rails appear to have a pgood fault.  Verify third rail is | 
|  | 486 | // selected, even though it is last in the power on sequence, because it is | 
|  | 487 | // checked using STATUS_VOUT.  That check happens before the other checks. | 
|  | 488 | { | 
|  | 489 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 490 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
|  | 491 | rails.emplace_back(createRailGPIO("VDD", false, 1)); | 
|  | 492 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 493 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 494 |  | 
|  | 495 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
|  | 496 | std::vector<int> gpioValues{0, 0, 0}; | 
|  | 497 | EXPECT_CALL(device, getGPIOValues) | 
|  | 498 | .Times(1) | 
|  | 499 | .WillOnce(Return(gpioValues)); | 
|  | 500 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x11)); | 
|  | 501 | EXPECT_CALL(device, getStatusWord(7)).Times(1).WillOnce(Return(0xbeef)); | 
|  | 502 |  | 
|  | 503 | MockServices services{}; | 
|  | 504 | EXPECT_CALL(services, | 
|  | 505 | logInfoMsg("Device abc_pseq GPIO values: [0, 0, 0]")) | 
|  | 506 | .Times(1); | 
|  | 507 | EXPECT_CALL( | 
|  | 508 | services, | 
|  | 509 | logErrorMsg( | 
|  | 510 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 511 | .Times(1); | 
|  | 512 | EXPECT_CALL(services, logInfoMsg("Rail VIO STATUS_WORD: 0xbeef")) | 
|  | 513 | .Times(1); | 
|  | 514 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VIO")) | 
|  | 515 | .Times(1); | 
|  | 516 | EXPECT_CALL( | 
|  | 517 | services, | 
|  | 518 | logErrorMsg("Rail VIO has fault bits set in STATUS_VOUT: 0x11")) | 
|  | 519 | .Times(1); | 
|  | 520 |  | 
|  | 521 | std::string powerSupplyError{}; | 
|  | 522 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 523 | std::string error = | 
|  | 524 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 525 | EXPECT_EQ(error, | 
|  | 526 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
|  | 527 | EXPECT_EQ(additionalData.size(), 5); | 
|  | 528 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 529 | EXPECT_EQ(additionalData["GPIO_VALUES"], "[0, 0, 0]"); | 
|  | 530 | EXPECT_EQ(additionalData["RAIL_NAME"], "VIO"); | 
|  | 531 | EXPECT_EQ(additionalData["STATUS_VOUT"], "0x11"); | 
|  | 532 | EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef"); | 
|  | 533 | } | 
|  | 534 |  | 
|  | 535 | // Two rails appear to have a pgood fault.  One is found via output voltage | 
|  | 536 | // and one is found via a GPIO.  Verify the first rail in the sequence with | 
|  | 537 | // a fault is selected. | 
|  | 538 | { | 
|  | 539 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 540 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 541 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
|  | 542 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
|  | 543 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 544 |  | 
|  | 545 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
|  | 546 | std::vector<int> gpioValues{1, 1, 0}; | 
|  | 547 | EXPECT_CALL(device, getGPIOValues) | 
|  | 548 | .Times(1) | 
|  | 549 | .WillOnce(Return(gpioValues)); | 
|  | 550 | EXPECT_CALL(device, getStatusVout(7)).Times(1).WillOnce(Return(0x00)); | 
|  | 551 | EXPECT_CALL(device, getReadVout(5)).Times(1).WillOnce(Return(1.1)); | 
|  | 552 | EXPECT_CALL(device, getVoutUVFaultLimit(5)) | 
|  | 553 | .Times(1) | 
|  | 554 | .WillOnce(Return(1.2)); | 
|  | 555 | EXPECT_CALL(device, getStatusWord(5)).Times(1).WillOnce(Return(0xbeef)); | 
|  | 556 |  | 
|  | 557 | MockServices services{}; | 
|  | 558 | EXPECT_CALL(services, | 
|  | 559 | logInfoMsg("Device abc_pseq GPIO values: [1, 1, 0]")) | 
|  | 560 | .Times(1); | 
|  | 561 | EXPECT_CALL( | 
|  | 562 | services, | 
|  | 563 | logErrorMsg( | 
|  | 564 | "Pgood fault found in rail monitored by device abc_pseq")) | 
|  | 565 | .Times(1); | 
|  | 566 | EXPECT_CALL(services, logInfoMsg("Rail VDD STATUS_WORD: 0xbeef")) | 
|  | 567 | .Times(1); | 
|  | 568 | EXPECT_CALL(services, logErrorMsg("Pgood fault detected in rail VDD")) | 
|  | 569 | .Times(1); | 
|  | 570 | EXPECT_CALL( | 
|  | 571 | services, | 
|  | 572 | logErrorMsg( | 
|  | 573 | "Rail VDD output voltage 1.1V is <= UV fault limit 1.2V")) | 
|  | 574 | .Times(1); | 
|  | 575 |  | 
|  | 576 | std::string powerSupplyError{}; | 
|  | 577 | std::map<std::string, std::string> additionalData{}; | 
| Patrick Williams | f540219 | 2024-08-16 15:20:53 -0400 | [diff] [blame] | 578 | std::string error = | 
|  | 579 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 580 | EXPECT_EQ(error, | 
|  | 581 | "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault"); | 
|  | 582 | EXPECT_EQ(additionalData.size(), 6); | 
|  | 583 | EXPECT_EQ(additionalData["DEVICE_NAME"], "abc_pseq"); | 
|  | 584 | EXPECT_EQ(additionalData["GPIO_VALUES"], "[1, 1, 0]"); | 
|  | 585 | EXPECT_EQ(additionalData["RAIL_NAME"], "VDD"); | 
|  | 586 | EXPECT_EQ(additionalData["READ_VOUT"], "1.1"); | 
|  | 587 | EXPECT_EQ(additionalData["VOUT_UV_FAULT_LIMIT"], "1.2"); | 
|  | 588 | EXPECT_EQ(additionalData["STATUS_WORD"], "0xbeef"); | 
|  | 589 | } | 
|  | 590 |  | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 591 | // Exception is thrown during pgood fault detection | 
|  | 592 | { | 
|  | 593 | std::vector<std::unique_ptr<Rail>> rails{}; | 
|  | 594 | rails.emplace_back(createRailGPIO("PSU", true, 2)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 595 | rails.emplace_back(createRailOutputVoltage("VDD", false, 5)); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 596 | rails.emplace_back(createRailStatusVout("VIO", false, 7)); | 
|  | 597 | StandardDeviceImpl device{"abc_pseq", std::move(rails)}; | 
|  | 598 |  | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 599 | EXPECT_CALL(device, prepareForPgoodFaultDetection).Times(1); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 600 | std::vector<int> gpioValues{1, 1, 1}; | 
|  | 601 | EXPECT_CALL(device, getGPIOValues) | 
|  | 602 | .Times(1) | 
|  | 603 | .WillOnce(Return(gpioValues)); | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 604 | EXPECT_CALL(device, getReadVout(5)).Times(0); | 
|  | 605 | EXPECT_CALL(device, getVoutUVFaultLimit(5)).Times(0); | 
|  | 606 | EXPECT_CALL(device, getStatusVout(7)) | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 607 | .Times(1) | 
|  | 608 | .WillOnce(Throw(std::runtime_error{"File does not exist"})); | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 609 |  | 
|  | 610 | MockServices services{}; | 
|  | 611 |  | 
|  | 612 | std::string powerSupplyError{}; | 
|  | 613 | std::map<std::string, std::string> additionalData{}; | 
|  | 614 | try | 
|  | 615 | { | 
|  | 616 | device.findPgoodFault(services, powerSupplyError, additionalData); | 
|  | 617 | ADD_FAILURE() << "Should not have reached this line."; | 
|  | 618 | } | 
|  | 619 | catch (const std::exception& e) | 
|  | 620 | { | 
|  | 621 | EXPECT_STREQ( | 
|  | 622 | e.what(), | 
|  | 623 | "Unable to determine if a pgood fault occurred in device abc_pseq: " | 
| Shawn McCarney | 1627583 | 2024-06-27 10:14:11 -0500 | [diff] [blame] | 624 | "Unable to read STATUS_VOUT value for rail VIO: " | 
| Shawn McCarney | 472101c | 2024-04-17 16:31:09 -0500 | [diff] [blame] | 625 | "File does not exist"); | 
|  | 626 | } | 
|  | 627 | } | 
|  | 628 | } |