1 /** 2 * Copyright © 2019 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "action_environment.hpp" 17 #include "device.hpp" 18 #include "i2c_interface.hpp" 19 #include "id_map.hpp" 20 #include "mock_services.hpp" 21 #include "mocked_i2c_interface.hpp" 22 #include "phase_fault.hpp" 23 #include "rule.hpp" 24 25 #include <cstddef> // for size_t 26 #include <exception> 27 #include <memory> 28 #include <stdexcept> 29 #include <utility> 30 #include <vector> 31 32 #include <gtest/gtest.h> 33 34 using namespace phosphor::power::regulators; 35 36 TEST(ActionEnvironmentTests, Constructor) 37 { 38 // Create IDMap 39 IDMap idMap{}; 40 41 // Create mock services. 42 MockServices services{}; 43 44 // Create Device and add to IDMap 45 std::unique_ptr<i2c::I2CInterface> i2cInterface = 46 i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED); 47 Device reg1{ 48 "regulator1", true, 49 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 50 std::move(i2cInterface)}; 51 idMap.addDevice(reg1); 52 53 // Verify object state after constructor 54 try 55 { 56 ActionEnvironment env{idMap, "regulator1", services}; 57 EXPECT_EQ(env.getAdditionalErrorData().size(), 0); 58 EXPECT_EQ(env.getDevice().getID(), "regulator1"); 59 EXPECT_EQ(env.getDeviceID(), "regulator1"); 60 EXPECT_EQ(env.getPhaseFaults().size(), 0); 61 EXPECT_EQ(env.getRuleDepth(), 0); 62 EXPECT_EQ(env.getVolts().has_value(), false); 63 } 64 catch (const std::exception& error) 65 { 66 ADD_FAILURE() << "Should not have caught exception."; 67 } 68 } 69 70 TEST(ActionEnvironmentTests, AddAdditionalErrorData) 71 { 72 IDMap idMap{}; 73 MockServices services{}; 74 ActionEnvironment env{idMap, "", services}; 75 EXPECT_EQ(env.getAdditionalErrorData().size(), 0); 76 77 env.addAdditionalErrorData("foo", "foo_value"); 78 env.addAdditionalErrorData("bar", "bar_value"); 79 EXPECT_EQ(env.getAdditionalErrorData().size(), 2); 80 EXPECT_EQ(env.getAdditionalErrorData().at("foo"), "foo_value"); 81 EXPECT_EQ(env.getAdditionalErrorData().at("bar"), "bar_value"); 82 } 83 84 TEST(ActionEnvironmentTests, AddPhaseFault) 85 { 86 IDMap idMap{}; 87 MockServices services{}; 88 ActionEnvironment env{idMap, "", services}; 89 EXPECT_EQ(env.getPhaseFaults().size(), 0); 90 91 // Add N phase fault 92 env.addPhaseFault(PhaseFaultType::n); 93 EXPECT_EQ(env.getPhaseFaults().size(), 1); 94 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n), 1); 95 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n_plus_1), 0); 96 97 // Add N+1 phase fault 98 env.addPhaseFault(PhaseFaultType::n_plus_1); 99 EXPECT_EQ(env.getPhaseFaults().size(), 2); 100 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n), 1); 101 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n_plus_1), 1); 102 103 // Add N+1 phase fault again; should be ignored since stored in a std::set 104 env.addPhaseFault(PhaseFaultType::n_plus_1); 105 EXPECT_EQ(env.getPhaseFaults().size(), 2); 106 } 107 108 TEST(ActionEnvironmentTests, DecrementRuleDepth) 109 { 110 IDMap idMap{}; 111 MockServices services{}; 112 ActionEnvironment env{idMap, "", services}; 113 EXPECT_EQ(env.getRuleDepth(), 0); 114 env.incrementRuleDepth("set_voltage_rule"); 115 env.incrementRuleDepth("set_voltage_rule"); 116 EXPECT_EQ(env.getRuleDepth(), 2); 117 env.decrementRuleDepth(); 118 EXPECT_EQ(env.getRuleDepth(), 1); 119 env.decrementRuleDepth(); 120 EXPECT_EQ(env.getRuleDepth(), 0); 121 env.decrementRuleDepth(); 122 EXPECT_EQ(env.getRuleDepth(), 0); 123 } 124 125 TEST(ActionEnvironmentTests, GetAdditionalErrorData) 126 { 127 IDMap idMap{}; 128 MockServices services{}; 129 ActionEnvironment env{idMap, "", services}; 130 EXPECT_EQ(env.getAdditionalErrorData().size(), 0); 131 132 env.addAdditionalErrorData("foo", "foo_value"); 133 EXPECT_EQ(env.getAdditionalErrorData().size(), 1); 134 EXPECT_EQ(env.getAdditionalErrorData().at("foo"), "foo_value"); 135 136 env.addAdditionalErrorData("bar", "bar_value"); 137 EXPECT_EQ(env.getAdditionalErrorData().size(), 2); 138 EXPECT_EQ(env.getAdditionalErrorData().at("bar"), "bar_value"); 139 } 140 141 TEST(ActionEnvironmentTests, GetDevice) 142 { 143 // Create IDMap 144 IDMap idMap{}; 145 146 // Create mock services. 147 MockServices services{}; 148 149 // Create Device and add to IDMap 150 std::unique_ptr<i2c::I2CInterface> i2cInterface = 151 i2c::create(1, 0x70, i2c::I2CInterface::InitialState::CLOSED); 152 Device reg1{ 153 "regulator1", true, 154 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 155 std::move(i2cInterface)}; 156 idMap.addDevice(reg1); 157 158 ActionEnvironment env{idMap, "regulator1", services}; 159 160 // Test where current device ID is in the IDMap 161 try 162 { 163 Device& device = env.getDevice(); 164 EXPECT_EQ(device.getID(), "regulator1"); 165 EXPECT_EQ(&device, ®1); 166 } 167 catch (const std::exception& error) 168 { 169 ADD_FAILURE() << "Should not have caught exception."; 170 } 171 172 // Test where current device ID is not in the IDMap 173 env.setDeviceID("regulator2"); 174 try 175 { 176 env.getDevice(); 177 ADD_FAILURE() << "Should not have reached this line."; 178 } 179 catch (const std::invalid_argument& ia_error) 180 { 181 EXPECT_STREQ(ia_error.what(), 182 "Unable to find device with ID \"regulator2\""); 183 } 184 catch (const std::exception& error) 185 { 186 ADD_FAILURE() << "Should not have caught exception."; 187 } 188 } 189 190 TEST(ActionEnvironmentTests, GetDeviceID) 191 { 192 IDMap idMap{}; 193 MockServices services{}; 194 ActionEnvironment env{idMap, "", services}; 195 EXPECT_EQ(env.getDeviceID(), ""); 196 env.setDeviceID("regulator1"); 197 EXPECT_EQ(env.getDeviceID(), "regulator1"); 198 } 199 200 TEST(ActionEnvironmentTests, GetPhaseFaults) 201 { 202 IDMap idMap{}; 203 MockServices services{}; 204 ActionEnvironment env{idMap, "", services}; 205 EXPECT_EQ(env.getPhaseFaults().size(), 0); 206 207 env.addPhaseFault(PhaseFaultType::n); 208 env.addPhaseFault(PhaseFaultType::n_plus_1); 209 EXPECT_EQ(env.getPhaseFaults().size(), 2); 210 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n), 1); 211 EXPECT_EQ(env.getPhaseFaults().count(PhaseFaultType::n_plus_1), 1); 212 } 213 214 TEST(ActionEnvironmentTests, GetRule) 215 { 216 // Create IDMap 217 IDMap idMap{}; 218 219 // Create mock services. 220 MockServices services{}; 221 222 Rule setVoltageRule{"set_voltage_rule", 223 std::vector<std::unique_ptr<Action>>{}}; 224 idMap.addRule(setVoltageRule); 225 226 ActionEnvironment env{idMap, "", services}; 227 228 // Test where rule ID is in the IDMap 229 try 230 { 231 Rule& rule = env.getRule("set_voltage_rule"); 232 EXPECT_EQ(rule.getID(), "set_voltage_rule"); 233 EXPECT_EQ(&rule, &setVoltageRule); 234 } 235 catch (const std::exception& error) 236 { 237 ADD_FAILURE() << "Should not have caught exception."; 238 } 239 240 // Test where rule ID is not in the IDMap 241 try 242 { 243 env.getRule("set_voltage_rule2"); 244 ADD_FAILURE() << "Should not have reached this line."; 245 } 246 catch (const std::invalid_argument& ia_error) 247 { 248 EXPECT_STREQ(ia_error.what(), 249 "Unable to find rule with ID \"set_voltage_rule2\""); 250 } 251 catch (const std::exception& error) 252 { 253 ADD_FAILURE() << "Should not have caught exception."; 254 } 255 } 256 257 TEST(ActionEnvironmentTests, GetRuleDepth) 258 { 259 IDMap idMap{}; 260 MockServices services{}; 261 ActionEnvironment env{idMap, "", services}; 262 EXPECT_EQ(env.getRuleDepth(), 0); 263 env.incrementRuleDepth("set_voltage_rule"); 264 EXPECT_EQ(env.getRuleDepth(), 1); 265 env.incrementRuleDepth("set_voltage_rule"); 266 EXPECT_EQ(env.getRuleDepth(), 2); 267 env.decrementRuleDepth(); 268 EXPECT_EQ(env.getRuleDepth(), 1); 269 env.decrementRuleDepth(); 270 EXPECT_EQ(env.getRuleDepth(), 0); 271 } 272 273 TEST(ActionEnvironmentTests, GetServices) 274 { 275 IDMap idMap{}; 276 MockServices services{}; 277 ActionEnvironment env{idMap, "", services}; 278 EXPECT_EQ(&(env.getServices()), &services); 279 } 280 281 TEST(ActionEnvironmentTests, GetVolts) 282 { 283 IDMap idMap{}; 284 MockServices services{}; 285 ActionEnvironment env{idMap, "", services}; 286 EXPECT_EQ(env.getVolts().has_value(), false); 287 env.setVolts(1.31); 288 EXPECT_EQ(env.getVolts().has_value(), true); 289 EXPECT_EQ(env.getVolts().value(), 1.31); 290 } 291 292 TEST(ActionEnvironmentTests, IncrementRuleDepth) 293 { 294 IDMap idMap{}; 295 MockServices services{}; 296 ActionEnvironment env{idMap, "", services}; 297 EXPECT_EQ(env.getRuleDepth(), 0); 298 299 // Test where rule depth has not exceeded maximum 300 try 301 { 302 for (size_t i = 1; i <= env.maxRuleDepth; ++i) 303 { 304 env.incrementRuleDepth("set_voltage_rule"); 305 EXPECT_EQ(env.getRuleDepth(), i); 306 } 307 } 308 catch (const std::exception& error) 309 { 310 ADD_FAILURE() << "Should not have caught exception."; 311 } 312 313 // Test where rule depth has exceeded maximum 314 try 315 { 316 env.incrementRuleDepth("set_voltage_rule"); 317 } 318 catch (const std::runtime_error& r_error) 319 { 320 EXPECT_STREQ(r_error.what(), 321 "Maximum rule depth exceeded by rule set_voltage_rule."); 322 } 323 catch (const std::exception& error) 324 { 325 ADD_FAILURE() << "Should not have caught exception."; 326 } 327 } 328 329 TEST(ActionEnvironmentTests, SetDeviceID) 330 { 331 IDMap idMap{}; 332 MockServices services{}; 333 ActionEnvironment env{idMap, "regulator1", services}; 334 EXPECT_EQ(env.getDeviceID(), "regulator1"); 335 env.setDeviceID("regulator2"); 336 EXPECT_EQ(env.getDeviceID(), "regulator2"); 337 } 338 339 TEST(ActionEnvironmentTests, SetVolts) 340 { 341 try 342 { 343 IDMap idMap{}; 344 MockServices services{}; 345 ActionEnvironment env{idMap, "", services}; 346 EXPECT_EQ(env.getVolts().has_value(), false); 347 env.setVolts(2.35); 348 EXPECT_EQ(env.getVolts().has_value(), true); 349 EXPECT_EQ(env.getVolts().value(), 2.35); 350 } 351 catch (const std::exception& error) 352 { 353 ADD_FAILURE() << "Should not have caught exception."; 354 } 355 } 356