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.hpp" 17 #include "chassis.hpp" 18 #include "configuration.hpp" 19 #include "device.hpp" 20 #include "i2c_interface.hpp" 21 #include "id_map.hpp" 22 #include "mock_action.hpp" 23 #include "mock_error_logging.hpp" 24 #include "mock_journal.hpp" 25 #include "mock_sensors.hpp" 26 #include "mock_services.hpp" 27 #include "mocked_i2c_interface.hpp" 28 #include "presence_detection.hpp" 29 #include "rail.hpp" 30 #include "rule.hpp" 31 #include "sensor_monitoring.hpp" 32 #include "sensors.hpp" 33 #include "system.hpp" 34 #include "test_sdbus_error.hpp" 35 #include "test_utils.hpp" 36 37 #include <memory> 38 #include <optional> 39 #include <string> 40 #include <utility> 41 #include <vector> 42 43 #include <gmock/gmock.h> 44 #include <gtest/gtest.h> 45 46 using namespace phosphor::power::regulators; 47 using namespace phosphor::power::regulators::test_utils; 48 49 using ::testing::A; 50 using ::testing::Ref; 51 using ::testing::Return; 52 using ::testing::Throw; 53 using ::testing::TypedEq; 54 55 static const std::string chassisInvPath{ 56 "/xyz/openbmc_project/inventory/system/chassis"}; 57 58 TEST(DeviceTests, Constructor) 59 { 60 // Test where only required parameters are specified 61 { 62 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 63 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 64 Device device{ 65 "vdd_reg", true, 66 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 67 std::move(i2cInterface)}; 68 EXPECT_EQ(device.getID(), "vdd_reg"); 69 EXPECT_EQ(device.isRegulator(), true); 70 EXPECT_EQ( 71 device.getFRU(), 72 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"); 73 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 74 EXPECT_EQ(device.getPresenceDetection(), nullptr); 75 EXPECT_EQ(device.getConfiguration(), nullptr); 76 EXPECT_EQ(device.getRails().size(), 0); 77 } 78 79 // Test where all parameters are specified 80 { 81 // Create I2CInterface 82 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 83 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 84 85 // Create PresenceDetection 86 std::vector<std::unique_ptr<Action>> actions{}; 87 actions.push_back(std::make_unique<MockAction>()); 88 std::unique_ptr<PresenceDetection> presenceDetection = 89 std::make_unique<PresenceDetection>(std::move(actions)); 90 91 // Create Configuration 92 std::optional<double> volts{}; 93 actions.clear(); 94 actions.push_back(std::make_unique<MockAction>()); 95 actions.push_back(std::make_unique<MockAction>()); 96 std::unique_ptr<Configuration> configuration = 97 std::make_unique<Configuration>(volts, std::move(actions)); 98 99 // Create vector of Rail objects 100 std::vector<std::unique_ptr<Rail>> rails{}; 101 rails.push_back(std::make_unique<Rail>("vdd0")); 102 rails.push_back(std::make_unique<Rail>("vdd1")); 103 104 // Create Device 105 Device device{ 106 "vdd_reg", 107 false, 108 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 109 std::move(i2cInterface), 110 std::move(presenceDetection), 111 std::move(configuration), 112 std::move(rails)}; 113 EXPECT_EQ(device.getID(), "vdd_reg"); 114 EXPECT_EQ(device.isRegulator(), false); 115 EXPECT_EQ( 116 device.getFRU(), 117 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1"); 118 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 119 EXPECT_NE(device.getPresenceDetection(), nullptr); 120 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 121 EXPECT_NE(device.getConfiguration(), nullptr); 122 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), false); 123 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 124 EXPECT_EQ(device.getRails().size(), 2); 125 } 126 } 127 128 TEST(DeviceTests, AddToIDMap) 129 { 130 std::unique_ptr<PresenceDetection> presenceDetection{}; 131 std::unique_ptr<Configuration> configuration{}; 132 133 // Create vector of Rail objects 134 std::vector<std::unique_ptr<Rail>> rails{}; 135 rails.push_back(std::make_unique<Rail>("vdd0")); 136 rails.push_back(std::make_unique<Rail>("vdd1")); 137 138 // Create Device 139 Device device{ 140 "vdd_reg", 141 false, 142 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 143 std::move(createI2CInterface()), 144 std::move(presenceDetection), 145 std::move(configuration), 146 std::move(rails)}; 147 148 // Add Device and Rail objects to an IDMap 149 IDMap idMap{}; 150 device.addToIDMap(idMap); 151 152 // Verify Device is in the IDMap 153 EXPECT_NO_THROW(idMap.getDevice("vdd_reg")); 154 EXPECT_THROW(idMap.getDevice("vio_reg"), std::invalid_argument); 155 156 // Verify all Rails are in the IDMap 157 EXPECT_NO_THROW(idMap.getRail("vdd0")); 158 EXPECT_NO_THROW(idMap.getRail("vdd1")); 159 EXPECT_THROW(idMap.getRail("vdd2"), std::invalid_argument); 160 } 161 162 TEST(DeviceTests, ClearCache) 163 { 164 // Test where Device does not contain a PresenceDetection object 165 try 166 { 167 Device device{ 168 "vdd_reg", false, 169 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 170 std::move(createI2CInterface())}; 171 device.clearCache(); 172 } 173 catch (...) 174 { 175 ADD_FAILURE() << "Should not have caught exception."; 176 } 177 178 // Test where Device contains a PresenceDetection object 179 { 180 // Create PresenceDetection 181 std::vector<std::unique_ptr<Action>> actions{}; 182 std::unique_ptr<PresenceDetection> presenceDetection = 183 std::make_unique<PresenceDetection>(std::move(actions)); 184 PresenceDetection* presenceDetectionPtr = presenceDetection.get(); 185 186 // Create Device 187 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 188 std::unique_ptr<Device> device = std::make_unique<Device>( 189 "reg1", true, 190 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 191 std::move(i2cInterface), std::move(presenceDetection)); 192 Device* devicePtr = device.get(); 193 194 // Create Chassis that contains Device 195 std::vector<std::unique_ptr<Device>> devices{}; 196 devices.emplace_back(std::move(device)); 197 std::unique_ptr<Chassis> chassis = 198 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 199 Chassis* chassisPtr = chassis.get(); 200 201 // Create System that contains Chassis 202 std::vector<std::unique_ptr<Rule>> rules{}; 203 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 204 chassisVec.emplace_back(std::move(chassis)); 205 System system{std::move(rules), std::move(chassisVec)}; 206 207 // Cache presence value in PresenceDetection 208 MockServices services{}; 209 presenceDetectionPtr->execute(services, system, *chassisPtr, 210 *devicePtr); 211 EXPECT_TRUE(presenceDetectionPtr->getCachedPresence().has_value()); 212 213 // Clear cached data in Device 214 devicePtr->clearCache(); 215 216 // Verify presence value no longer cached in PresenceDetection 217 EXPECT_FALSE(presenceDetectionPtr->getCachedPresence().has_value()); 218 } 219 } 220 221 TEST(DeviceTests, ClearErrorHistory) 222 { 223 // Create SensorMonitoring. Will fail with a DBus exception. 224 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 225 EXPECT_CALL(*action, execute) 226 .WillRepeatedly(Throw(TestSDBusError{"Unable to set sensor value"})); 227 std::vector<std::unique_ptr<Action>> actions{}; 228 actions.emplace_back(std::move(action)); 229 std::unique_ptr<SensorMonitoring> sensorMonitoring = 230 std::make_unique<SensorMonitoring>(std::move(actions)); 231 232 // Create Rail 233 std::unique_ptr<Configuration> configuration{}; 234 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 235 "vddr1", std::move(configuration), std::move(sensorMonitoring)); 236 237 // Create Device that contains Rail 238 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 239 std::make_unique<i2c::MockedI2CInterface>(); 240 std::unique_ptr<PresenceDetection> presenceDetection{}; 241 std::unique_ptr<Configuration> deviceConfiguration{}; 242 std::vector<std::unique_ptr<Rail>> rails{}; 243 rails.emplace_back(std::move(rail)); 244 std::unique_ptr<Device> device = std::make_unique<Device>( 245 "reg1", true, 246 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 247 std::move(i2cInterface), std::move(presenceDetection), 248 std::move(deviceConfiguration), std::move(rails)); 249 Device* devicePtr = device.get(); 250 251 // Create Chassis that contains Device 252 std::vector<std::unique_ptr<Device>> devices{}; 253 devices.emplace_back(std::move(device)); 254 std::unique_ptr<Chassis> chassis = 255 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 256 Chassis* chassisPtr = chassis.get(); 257 258 // Create System that contains Chassis 259 std::vector<std::unique_ptr<Rule>> rules{}; 260 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 261 chassisVec.emplace_back(std::move(chassis)); 262 System system{std::move(rules), std::move(chassisVec)}; 263 264 // Create mock services 265 MockServices services{}; 266 267 // Expect Sensors service to be called 5+5=10 times 268 MockSensors& sensors = services.getMockSensors(); 269 EXPECT_CALL(sensors, startRail).Times(10); 270 EXPECT_CALL(sensors, setValue).Times(0); 271 EXPECT_CALL(sensors, endRail).Times(10); 272 273 // Expect Journal service to be called 3+3=6 times to log error messages 274 MockJournal& journal = services.getMockJournal(); 275 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 276 .Times(6); 277 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(6); 278 279 // Expect ErrorLogging service to be called 1+1=2 times to log a DBus error 280 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 281 EXPECT_CALL(errorLogging, logDBusError).Times(2); 282 283 // Monitor sensors 5 times. Should fail every time, write to journal 3 284 // times, and log one error. 285 for (int i = 1; i <= 5; ++i) 286 { 287 devicePtr->monitorSensors(services, system, *chassisPtr); 288 } 289 290 // Clear error history 291 devicePtr->clearErrorHistory(); 292 293 // Monitor sensors 5 times again. Should fail every time, write to journal 294 // 3 times, and log one error. 295 for (int i = 1; i <= 5; ++i) 296 { 297 devicePtr->monitorSensors(services, system, *chassisPtr); 298 } 299 } 300 301 TEST(DeviceTests, Close) 302 { 303 // Test where works: I2C interface is not open 304 { 305 // Create mock I2CInterface 306 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 307 std::make_unique<i2c::MockedI2CInterface>(); 308 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(false)); 309 EXPECT_CALL(*i2cInterface, close).Times(0); 310 311 // Create mock services. No logError should occur. 312 MockServices services{}; 313 MockJournal& journal = services.getMockJournal(); 314 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 315 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 316 .Times(0); 317 318 // Create Device 319 Device device{ 320 "vdd_reg", true, 321 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 322 std::move(i2cInterface)}; 323 324 // Close Device 325 device.close(services); 326 } 327 328 // Test where works: I2C interface is open 329 { 330 // Create mock I2CInterface 331 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 332 std::make_unique<i2c::MockedI2CInterface>(); 333 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 334 EXPECT_CALL(*i2cInterface, close).Times(1); 335 336 // Create mock services. No logError should occur. 337 MockServices services{}; 338 MockJournal& journal = services.getMockJournal(); 339 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 340 EXPECT_CALL(journal, logError(A<const std::vector<std::string>&>())) 341 .Times(0); 342 343 // Create Device 344 Device device{ 345 "vdd_reg", true, 346 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 347 std::move(i2cInterface)}; 348 349 // Close Device 350 device.close(services); 351 } 352 353 // Test where fails: closing I2C interface fails 354 { 355 // Create mock I2CInterface 356 std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 357 std::make_unique<i2c::MockedI2CInterface>(); 358 EXPECT_CALL(*i2cInterface, isOpen).Times(1).WillOnce(Return(true)); 359 EXPECT_CALL(*i2cInterface, close) 360 .Times(1) 361 .WillOnce(Throw( 362 i2c::I2CException{"Failed to close", "/dev/i2c-1", 0x70})); 363 364 // Create mock services. Expect logError() and logI2CError() to be 365 // called. 366 MockServices services{}; 367 MockErrorLogging& errorLogging = services.getMockErrorLogging(); 368 MockJournal& journal = services.getMockJournal(); 369 std::vector<std::string> expectedErrMessagesException{ 370 "I2CException: Failed to close: bus /dev/i2c-1, addr 0x70"}; 371 EXPECT_CALL(journal, logError("Unable to close device vdd_reg")) 372 .Times(1); 373 EXPECT_CALL(journal, logError(expectedErrMessagesException)).Times(1); 374 EXPECT_CALL(errorLogging, 375 logI2CError(Entry::Level::Notice, Ref(journal), 376 "/dev/i2c-1", 0x70, 0)) 377 .Times(1); 378 379 // Create Device 380 Device device{ 381 "vdd_reg", true, 382 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 383 std::move(i2cInterface)}; 384 385 // Close Device 386 device.close(services); 387 } 388 } 389 390 TEST(DeviceTests, Configure) 391 { 392 // Test where device is not present 393 { 394 // Create mock services. No logging should occur. 395 MockServices services{}; 396 MockJournal& journal = services.getMockJournal(); 397 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 398 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 399 400 // Create PresenceDetection. Indicates device is not present. 401 std::unique_ptr<MockAction> presAction = std::make_unique<MockAction>(); 402 EXPECT_CALL(*presAction, execute).Times(1).WillOnce(Return(false)); 403 std::vector<std::unique_ptr<Action>> presActions{}; 404 presActions.emplace_back(std::move(presAction)); 405 std::unique_ptr<PresenceDetection> presenceDetection = 406 std::make_unique<PresenceDetection>(std::move(presActions)); 407 408 // Create Configuration. Action inside it should not be executed. 409 std::optional<double> volts{}; 410 std::unique_ptr<MockAction> confAction = std::make_unique<MockAction>(); 411 EXPECT_CALL(*confAction, execute).Times(0); 412 std::vector<std::unique_ptr<Action>> confActions{}; 413 confActions.emplace_back(std::move(confAction)); 414 std::unique_ptr<Configuration> configuration = 415 std::make_unique<Configuration>(volts, std::move(confActions)); 416 417 // Create Device 418 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 419 std::unique_ptr<Device> device = std::make_unique<Device>( 420 "reg1", true, 421 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 422 std::move(i2cInterface), std::move(presenceDetection), 423 std::move(configuration)); 424 Device* devicePtr = device.get(); 425 426 // Create Chassis that contains Device 427 std::vector<std::unique_ptr<Device>> devices{}; 428 devices.emplace_back(std::move(device)); 429 std::unique_ptr<Chassis> chassis = 430 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 431 Chassis* chassisPtr = chassis.get(); 432 433 // Create System that contains Chassis 434 std::vector<std::unique_ptr<Rule>> rules{}; 435 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 436 chassisVec.emplace_back(std::move(chassis)); 437 System system{std::move(rules), std::move(chassisVec)}; 438 439 // Call configure(). Should do nothing. 440 devicePtr->configure(services, system, *chassisPtr); 441 } 442 443 // Test where Configuration and Rails were not specified in constructor 444 { 445 // Create mock services. No logging should occur. 446 MockServices services{}; 447 MockJournal& journal = services.getMockJournal(); 448 EXPECT_CALL(journal, logDebug(A<const std::string&>())).Times(0); 449 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 450 451 // Create Device 452 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 453 std::unique_ptr<Device> device = std::make_unique<Device>( 454 "reg1", true, 455 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 456 std::move(i2cInterface)); 457 Device* devicePtr = device.get(); 458 459 // Create Chassis that contains Device 460 std::vector<std::unique_ptr<Device>> devices{}; 461 devices.emplace_back(std::move(device)); 462 std::unique_ptr<Chassis> chassis = 463 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 464 Chassis* chassisPtr = chassis.get(); 465 466 // Create System that contains Chassis 467 std::vector<std::unique_ptr<Rule>> rules{}; 468 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 469 chassisVec.emplace_back(std::move(chassis)); 470 System system{std::move(rules), std::move(chassisVec)}; 471 472 // Call configure(). 473 devicePtr->configure(services, system, *chassisPtr); 474 } 475 476 // Test where Configuration and Rails were specified in constructor 477 { 478 std::vector<std::unique_ptr<Rail>> rails{}; 479 480 // Create mock services. Expect logDebug() to be called. 481 // For the Device and both Rails, should execute the Configuration 482 // and log a debug message. 483 MockServices services{}; 484 MockJournal& journal = services.getMockJournal(); 485 EXPECT_CALL(journal, logDebug("Configuring reg1")).Times(1); 486 EXPECT_CALL(journal, logDebug("Configuring vdd0: volts=1.300000")) 487 .Times(1); 488 EXPECT_CALL(journal, logDebug("Configuring vio0: volts=3.200000")) 489 .Times(1); 490 EXPECT_CALL(journal, logError(A<const std::string&>())).Times(0); 491 492 // Create Rail vdd0 493 { 494 // Create Configuration for Rail 495 std::optional<double> volts{1.3}; 496 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 497 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 498 std::vector<std::unique_ptr<Action>> actions{}; 499 actions.emplace_back(std::move(action)); 500 std::unique_ptr<Configuration> configuration = 501 std::make_unique<Configuration>(volts, std::move(actions)); 502 503 // Create Rail 504 std::unique_ptr<Rail> rail = 505 std::make_unique<Rail>("vdd0", std::move(configuration)); 506 rails.emplace_back(std::move(rail)); 507 } 508 509 // Create Rail vio0 510 { 511 // Create Configuration for Rail 512 std::optional<double> volts{3.2}; 513 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 514 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 515 std::vector<std::unique_ptr<Action>> actions{}; 516 actions.emplace_back(std::move(action)); 517 std::unique_ptr<Configuration> configuration = 518 std::make_unique<Configuration>(volts, std::move(actions)); 519 520 // Create Rail 521 std::unique_ptr<Rail> rail = 522 std::make_unique<Rail>("vio0", std::move(configuration)); 523 rails.emplace_back(std::move(rail)); 524 } 525 526 // Create Configuration for Device 527 std::optional<double> volts{}; 528 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 529 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 530 std::vector<std::unique_ptr<Action>> actions{}; 531 actions.emplace_back(std::move(action)); 532 std::unique_ptr<Configuration> configuration = 533 std::make_unique<Configuration>(volts, std::move(actions)); 534 535 // Create Device 536 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 537 std::unique_ptr<PresenceDetection> presenceDetection{}; 538 std::unique_ptr<Device> device = std::make_unique<Device>( 539 "reg1", true, 540 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 541 std::move(i2cInterface), std::move(presenceDetection), 542 std::move(configuration), std::move(rails)); 543 Device* devicePtr = device.get(); 544 545 // Create Chassis that contains Device 546 std::vector<std::unique_ptr<Device>> devices{}; 547 devices.emplace_back(std::move(device)); 548 std::unique_ptr<Chassis> chassis = 549 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 550 Chassis* chassisPtr = chassis.get(); 551 552 // Create System that contains Chassis 553 std::vector<std::unique_ptr<Rule>> rules{}; 554 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 555 chassisVec.emplace_back(std::move(chassis)); 556 System system{std::move(rules), std::move(chassisVec)}; 557 558 // Call configure(). 559 devicePtr->configure(services, system, *chassisPtr); 560 } 561 } 562 563 TEST(DeviceTests, GetConfiguration) 564 { 565 // Test where Configuration was not specified in constructor 566 { 567 Device device{ 568 "vdd_reg", true, 569 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 570 std::move(createI2CInterface())}; 571 EXPECT_EQ(device.getConfiguration(), nullptr); 572 } 573 574 // Test where Configuration was specified in constructor 575 { 576 std::unique_ptr<PresenceDetection> presenceDetection{}; 577 578 // Create Configuration 579 std::optional<double> volts{3.2}; 580 std::vector<std::unique_ptr<Action>> actions{}; 581 actions.push_back(std::make_unique<MockAction>()); 582 actions.push_back(std::make_unique<MockAction>()); 583 std::unique_ptr<Configuration> configuration = 584 std::make_unique<Configuration>(volts, std::move(actions)); 585 586 // Create Device 587 Device device{ 588 "vdd_reg", 589 true, 590 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 591 std::move(createI2CInterface()), 592 std::move(presenceDetection), 593 std::move(configuration)}; 594 EXPECT_NE(device.getConfiguration(), nullptr); 595 EXPECT_EQ(device.getConfiguration()->getVolts().has_value(), true); 596 EXPECT_EQ(device.getConfiguration()->getVolts().value(), 3.2); 597 EXPECT_EQ(device.getConfiguration()->getActions().size(), 2); 598 } 599 } 600 601 TEST(DeviceTests, GetFRU) 602 { 603 Device device{ 604 "vdd_reg", true, 605 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 606 std::move(createI2CInterface())}; 607 EXPECT_EQ(device.getFRU(), 608 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2"); 609 } 610 611 TEST(DeviceTests, GetI2CInterface) 612 { 613 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 614 i2c::I2CInterface* i2cInterfacePtr = i2cInterface.get(); 615 Device device{ 616 "vdd_reg", true, 617 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 618 std::move(i2cInterface)}; 619 EXPECT_EQ(&(device.getI2CInterface()), i2cInterfacePtr); 620 } 621 622 TEST(DeviceTests, GetID) 623 { 624 Device device{ 625 "vdd_reg", false, 626 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 627 std::move(createI2CInterface())}; 628 EXPECT_EQ(device.getID(), "vdd_reg"); 629 } 630 631 TEST(DeviceTests, GetPresenceDetection) 632 { 633 // Test where PresenceDetection was not specified in constructor 634 { 635 Device device{ 636 "vdd_reg", true, 637 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 638 std::move(createI2CInterface())}; 639 EXPECT_EQ(device.getPresenceDetection(), nullptr); 640 } 641 642 // Test where PresenceDetection was specified in constructor 643 { 644 // Create PresenceDetection 645 std::vector<std::unique_ptr<Action>> actions{}; 646 actions.push_back(std::make_unique<MockAction>()); 647 std::unique_ptr<PresenceDetection> presenceDetection = 648 std::make_unique<PresenceDetection>(std::move(actions)); 649 650 // Create Device 651 Device device{ 652 "vdd_reg", false, 653 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 654 std::move(createI2CInterface()), std::move(presenceDetection)}; 655 EXPECT_NE(device.getPresenceDetection(), nullptr); 656 EXPECT_EQ(device.getPresenceDetection()->getActions().size(), 1); 657 } 658 } 659 660 TEST(DeviceTests, GetRails) 661 { 662 // Test where no rails were specified in constructor 663 { 664 Device device{ 665 "vdd_reg", true, 666 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 667 std::move(createI2CInterface())}; 668 EXPECT_EQ(device.getRails().size(), 0); 669 } 670 671 // Test where rails were specified in constructor 672 { 673 std::unique_ptr<PresenceDetection> presenceDetection{}; 674 std::unique_ptr<Configuration> configuration{}; 675 676 // Create vector of Rail objects 677 std::vector<std::unique_ptr<Rail>> rails{}; 678 rails.push_back(std::make_unique<Rail>("vdd0")); 679 rails.push_back(std::make_unique<Rail>("vdd1")); 680 681 // Create Device 682 Device device{ 683 "vdd_reg", 684 false, 685 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 686 std::move(createI2CInterface()), 687 std::move(presenceDetection), 688 std::move(configuration), 689 std::move(rails)}; 690 EXPECT_EQ(device.getRails().size(), 2); 691 EXPECT_EQ(device.getRails()[0]->getID(), "vdd0"); 692 EXPECT_EQ(device.getRails()[1]->getID(), "vdd1"); 693 } 694 } 695 696 TEST(DeviceTests, IsPresent) 697 { 698 // Test where PresenceDetection not specified in constructor 699 { 700 // Create Device 701 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 702 std::unique_ptr<Device> device = std::make_unique<Device>( 703 "reg1", true, 704 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 705 std::move(i2cInterface)); 706 Device* devicePtr = device.get(); 707 708 // Create Chassis that contains Device 709 std::vector<std::unique_ptr<Device>> devices{}; 710 devices.emplace_back(std::move(device)); 711 std::unique_ptr<Chassis> chassis = 712 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 713 Chassis* chassisPtr = chassis.get(); 714 715 // Create System that contains Chassis 716 std::vector<std::unique_ptr<Rule>> rules{}; 717 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 718 chassisVec.emplace_back(std::move(chassis)); 719 System system{std::move(rules), std::move(chassisVec)}; 720 721 // Create MockServices 722 MockServices services{}; 723 724 // Since no PresenceDetection defined, isPresent() should return true 725 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr)); 726 } 727 728 // Test where PresenceDetection was specified in constructor: Is present 729 { 730 // Create PresenceDetection. Indicates device is present. 731 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 732 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 733 std::vector<std::unique_ptr<Action>> actions{}; 734 actions.emplace_back(std::move(action)); 735 std::unique_ptr<PresenceDetection> presenceDetection = 736 std::make_unique<PresenceDetection>(std::move(actions)); 737 738 // Create Device 739 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 740 std::unique_ptr<Device> device = std::make_unique<Device>( 741 "reg1", true, 742 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 743 std::move(i2cInterface), std::move(presenceDetection)); 744 Device* devicePtr = device.get(); 745 746 // Create Chassis that contains Device 747 std::vector<std::unique_ptr<Device>> devices{}; 748 devices.emplace_back(std::move(device)); 749 std::unique_ptr<Chassis> chassis = 750 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 751 Chassis* chassisPtr = chassis.get(); 752 753 // Create System that contains Chassis 754 std::vector<std::unique_ptr<Rule>> rules{}; 755 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 756 chassisVec.emplace_back(std::move(chassis)); 757 System system{std::move(rules), std::move(chassisVec)}; 758 759 // Create MockServices 760 MockServices services{}; 761 762 // PresenceDetection::execute() and isPresent() should return true 763 EXPECT_TRUE(devicePtr->isPresent(services, system, *chassisPtr)); 764 } 765 766 // Test where PresenceDetection was specified in constructor: Is not present 767 { 768 // Create PresenceDetection. Indicates device is not present. 769 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 770 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 771 std::vector<std::unique_ptr<Action>> actions{}; 772 actions.emplace_back(std::move(action)); 773 std::unique_ptr<PresenceDetection> presenceDetection = 774 std::make_unique<PresenceDetection>(std::move(actions)); 775 776 // Create Device 777 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 778 std::unique_ptr<Device> device = std::make_unique<Device>( 779 "reg1", true, 780 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 781 std::move(i2cInterface), std::move(presenceDetection)); 782 Device* devicePtr = device.get(); 783 784 // Create Chassis that contains Device 785 std::vector<std::unique_ptr<Device>> devices{}; 786 devices.emplace_back(std::move(device)); 787 std::unique_ptr<Chassis> chassis = 788 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 789 Chassis* chassisPtr = chassis.get(); 790 791 // Create System that contains Chassis 792 std::vector<std::unique_ptr<Rule>> rules{}; 793 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 794 chassisVec.emplace_back(std::move(chassis)); 795 System system{std::move(rules), std::move(chassisVec)}; 796 797 // Create MockServices 798 MockServices services{}; 799 800 // PresenceDetection::execute() and isPresent() should return false 801 EXPECT_FALSE(devicePtr->isPresent(services, system, *chassisPtr)); 802 } 803 } 804 805 TEST(DeviceTests, IsRegulator) 806 { 807 Device device{ 808 "vdd_reg", false, 809 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 810 std::move(createI2CInterface())}; 811 EXPECT_EQ(device.isRegulator(), false); 812 } 813 814 TEST(DeviceTests, MonitorSensors) 815 { 816 // Test where device is not present 817 { 818 // Create mock services. No Sensors methods should be called. 819 MockServices services{}; 820 MockSensors& sensors = services.getMockSensors(); 821 EXPECT_CALL(sensors, startRail).Times(0); 822 EXPECT_CALL(sensors, setValue).Times(0); 823 EXPECT_CALL(sensors, endRail).Times(0); 824 825 // Create SensorMonitoring. Action inside it should not be executed. 826 std::unique_ptr<MockAction> sensAction = std::make_unique<MockAction>(); 827 EXPECT_CALL(*sensAction, execute).Times(0); 828 std::vector<std::unique_ptr<Action>> sensActions{}; 829 sensActions.emplace_back(std::move(sensAction)); 830 std::unique_ptr<SensorMonitoring> sensorMonitoring = 831 std::make_unique<SensorMonitoring>(std::move(sensActions)); 832 833 // Create Rail 834 std::unique_ptr<Configuration> configuration{}; 835 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 836 "vddr1", std::move(configuration), std::move(sensorMonitoring)); 837 838 // Create PresenceDetection. Indicates device is not present. 839 std::unique_ptr<MockAction> presAction = std::make_unique<MockAction>(); 840 EXPECT_CALL(*presAction, execute).Times(1).WillOnce(Return(false)); 841 std::vector<std::unique_ptr<Action>> presActions{}; 842 presActions.emplace_back(std::move(presAction)); 843 std::unique_ptr<PresenceDetection> presenceDetection = 844 std::make_unique<PresenceDetection>(std::move(presActions)); 845 846 // Create Device 847 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 848 std::unique_ptr<Configuration> deviceConfiguration{}; 849 std::vector<std::unique_ptr<Rail>> rails{}; 850 rails.emplace_back(std::move(rail)); 851 std::unique_ptr<Device> device = std::make_unique<Device>( 852 "reg1", true, 853 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 854 std::move(i2cInterface), std::move(presenceDetection), 855 std::move(deviceConfiguration), std::move(rails)); 856 Device* devicePtr = device.get(); 857 858 // Create Chassis that contains Device 859 std::vector<std::unique_ptr<Device>> devices{}; 860 devices.emplace_back(std::move(device)); 861 std::unique_ptr<Chassis> chassis = 862 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 863 Chassis* chassisPtr = chassis.get(); 864 865 // Create System that contains Chassis 866 std::vector<std::unique_ptr<Rule>> rules{}; 867 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 868 chassisVec.emplace_back(std::move(chassis)); 869 System system{std::move(rules), std::move(chassisVec)}; 870 871 // Call monitorSensors(). Should do nothing. 872 devicePtr->monitorSensors(services, system, *chassisPtr); 873 } 874 875 // Test where Rails were not specified in constructor 876 { 877 // Create mock services. No Sensors methods should be called. 878 MockServices services{}; 879 MockSensors& sensors = services.getMockSensors(); 880 EXPECT_CALL(sensors, startRail).Times(0); 881 EXPECT_CALL(sensors, setValue).Times(0); 882 EXPECT_CALL(sensors, endRail).Times(0); 883 884 // Create Device 885 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 886 std::unique_ptr<Device> device = std::make_unique<Device>( 887 "reg1", true, 888 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 889 std::move(i2cInterface)); 890 Device* devicePtr = device.get(); 891 892 // Create Chassis that contains Device 893 std::vector<std::unique_ptr<Device>> devices{}; 894 devices.emplace_back(std::move(device)); 895 std::unique_ptr<Chassis> chassis = 896 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 897 Chassis* chassisPtr = chassis.get(); 898 899 // Create System that contains Chassis 900 std::vector<std::unique_ptr<Rule>> rules{}; 901 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 902 chassisVec.emplace_back(std::move(chassis)); 903 System system{std::move(rules), std::move(chassisVec)}; 904 905 // Call monitorSensors(). Should do nothing. 906 devicePtr->monitorSensors(services, system, *chassisPtr); 907 } 908 909 // Test where Rails were specified in constructor 910 { 911 // Create mock services. Set Sensors service expectations. 912 MockServices services{}; 913 MockSensors& sensors = services.getMockSensors(); 914 EXPECT_CALL(sensors, startRail("vdd0", 915 "/xyz/openbmc_project/inventory/system/" 916 "chassis/motherboard/reg1", 917 chassisInvPath)) 918 .Times(1); 919 EXPECT_CALL(sensors, startRail("vio0", 920 "/xyz/openbmc_project/inventory/system/" 921 "chassis/motherboard/reg1", 922 chassisInvPath)) 923 .Times(1); 924 EXPECT_CALL(sensors, setValue).Times(0); 925 EXPECT_CALL(sensors, endRail(false)).Times(2); 926 927 std::vector<std::unique_ptr<Rail>> rails{}; 928 929 // Create Rail vdd0 930 { 931 // Create SensorMonitoring for Rail 932 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 933 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 934 std::vector<std::unique_ptr<Action>> actions{}; 935 actions.emplace_back(std::move(action)); 936 std::unique_ptr<SensorMonitoring> sensorMonitoring = 937 std::make_unique<SensorMonitoring>(std::move(actions)); 938 939 // Create Rail 940 std::unique_ptr<Configuration> configuration{}; 941 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 942 "vdd0", std::move(configuration), std::move(sensorMonitoring)); 943 rails.emplace_back(std::move(rail)); 944 } 945 946 // Create Rail vio0 947 { 948 // Create SensorMonitoring for Rail 949 std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 950 EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 951 std::vector<std::unique_ptr<Action>> actions{}; 952 actions.emplace_back(std::move(action)); 953 std::unique_ptr<SensorMonitoring> sensorMonitoring = 954 std::make_unique<SensorMonitoring>(std::move(actions)); 955 956 // Create Rail 957 std::unique_ptr<Configuration> configuration{}; 958 std::unique_ptr<Rail> rail = std::make_unique<Rail>( 959 "vio0", std::move(configuration), std::move(sensorMonitoring)); 960 rails.emplace_back(std::move(rail)); 961 } 962 963 // Create Device that contains Rails 964 std::unique_ptr<i2c::I2CInterface> i2cInterface = createI2CInterface(); 965 std::unique_ptr<PresenceDetection> presenceDetection{}; 966 std::unique_ptr<Configuration> configuration{}; 967 std::unique_ptr<Device> device = std::make_unique<Device>( 968 "reg1", true, 969 "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg1", 970 std::move(i2cInterface), std::move(presenceDetection), 971 std::move(configuration), std::move(rails)); 972 Device* devicePtr = device.get(); 973 974 // Create Chassis that contains Device 975 std::vector<std::unique_ptr<Device>> devices{}; 976 devices.emplace_back(std::move(device)); 977 std::unique_ptr<Chassis> chassis = 978 std::make_unique<Chassis>(1, chassisInvPath, std::move(devices)); 979 Chassis* chassisPtr = chassis.get(); 980 981 // Create System that contains Chassis 982 std::vector<std::unique_ptr<Rule>> rules{}; 983 std::vector<std::unique_ptr<Chassis>> chassisVec{}; 984 chassisVec.emplace_back(std::move(chassis)); 985 System system{std::move(rules), std::move(chassisVec)}; 986 987 // Call monitorSensors(). Should monitor sensors in both rails. 988 devicePtr->monitorSensors(services, system, *chassisPtr); 989 } 990 } 991