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