1bfe2c25aSShawn McCarney /** 2bfe2c25aSShawn McCarney * Copyright © 2020 IBM Corporation 3bfe2c25aSShawn McCarney * 4bfe2c25aSShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe2c25aSShawn McCarney * you may not use this file except in compliance with the License. 6bfe2c25aSShawn McCarney * You may obtain a copy of the License at 7bfe2c25aSShawn McCarney * 8bfe2c25aSShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0 9bfe2c25aSShawn McCarney * 10bfe2c25aSShawn McCarney * Unless required by applicable law or agreed to in writing, software 11bfe2c25aSShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS, 12bfe2c25aSShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe2c25aSShawn McCarney * See the License for the specific language governing permissions and 14bfe2c25aSShawn McCarney * limitations under the License. 15bfe2c25aSShawn McCarney */ 16bfe2c25aSShawn McCarney #include "action.hpp" 17*462e5926SBob King #include "chassis.hpp" 18*462e5926SBob King #include "compare_presence_action.hpp" 19*462e5926SBob King #include "device.hpp" 20*462e5926SBob King #include "i2c_interface.hpp" 21bfe2c25aSShawn McCarney #include "mock_action.hpp" 22*462e5926SBob King #include "mock_journal.hpp" 23*462e5926SBob King #include "mock_presence_service.hpp" 24*462e5926SBob King #include "mock_services.hpp" 25*462e5926SBob King #include "mocked_i2c_interface.hpp" 26bfe2c25aSShawn McCarney #include "presence_detection.hpp" 27*462e5926SBob King #include "rule.hpp" 28*462e5926SBob King #include "system.hpp" 29bfe2c25aSShawn McCarney 30bfe2c25aSShawn McCarney #include <memory> 31*462e5926SBob King #include <stdexcept> 32*462e5926SBob King #include <string> 33*462e5926SBob King #include <tuple> 34bfe2c25aSShawn McCarney #include <utility> 35bfe2c25aSShawn McCarney #include <vector> 36bfe2c25aSShawn McCarney 37*462e5926SBob King #include <gmock/gmock.h> 38bfe2c25aSShawn McCarney #include <gtest/gtest.h> 39bfe2c25aSShawn McCarney 40bfe2c25aSShawn McCarney using namespace phosphor::power::regulators; 41bfe2c25aSShawn McCarney 42*462e5926SBob King using ::testing::Return; 43*462e5926SBob King using ::testing::Throw; 44*462e5926SBob King 45*462e5926SBob King /** 46*462e5926SBob King * Creates the parent objects that normally contain a PresenceDetection object. 47*462e5926SBob King * 48*462e5926SBob King * A PresenceDetection object is normally contained within a hierarchy of 49*462e5926SBob King * System, Chassis, and Device objects. These objects are required in order to 50*462e5926SBob King * call the execute() method. 51*462e5926SBob King * 52*462e5926SBob King * Creates the System, Chassis, and Device objects. The PresenceDetection 53*462e5926SBob King * object is moved into the Device object. 54*462e5926SBob King * 55*462e5926SBob King * @param detection PresenceDetection object to move into object hierarchy 56*462e5926SBob King * @return Pointers to the System, Chassis, and Device objects. The Chassis and 57*462e5926SBob King * Device objects are contained within the System object and will be 58*462e5926SBob King * automatically destructed. 59*462e5926SBob King */ 60*462e5926SBob King std::tuple<std::unique_ptr<System>, Chassis*, Device*> 61*462e5926SBob King createParentObjects(std::unique_ptr<PresenceDetection> detection) 62*462e5926SBob King { 63*462e5926SBob King // Create mock I2CInterface 64*462e5926SBob King std::unique_ptr<i2c::MockedI2CInterface> i2cInterface = 65*462e5926SBob King std::make_unique<i2c::MockedI2CInterface>(); 66*462e5926SBob King 67*462e5926SBob King // Create Device that contains PresenceDetection 68*462e5926SBob King std::unique_ptr<Device> device = std::make_unique<Device>( 69*462e5926SBob King "vdd_reg", true, 70*462e5926SBob King "/xyz/openbmc_project/inventory/system/chassis/motherboard/reg2", 71*462e5926SBob King std::move(i2cInterface), std::move(detection)); 72*462e5926SBob King Device* devicePtr = device.get(); 73*462e5926SBob King 74*462e5926SBob King // Create Chassis that contains Device 75*462e5926SBob King std::vector<std::unique_ptr<Device>> devices{}; 76*462e5926SBob King devices.emplace_back(std::move(device)); 77*462e5926SBob King std::unique_ptr<Chassis> chassis = 78*462e5926SBob King std::make_unique<Chassis>(1, std::move(devices)); 79*462e5926SBob King Chassis* chassisPtr = chassis.get(); 80*462e5926SBob King 81*462e5926SBob King // Create System that contains Chassis 82*462e5926SBob King std::vector<std::unique_ptr<Rule>> rules{}; 83*462e5926SBob King std::vector<std::unique_ptr<Chassis>> chassisVec{}; 84*462e5926SBob King chassisVec.emplace_back(std::move(chassis)); 85*462e5926SBob King std::unique_ptr<System> system = 86*462e5926SBob King std::make_unique<System>(std::move(rules), std::move(chassisVec)); 87*462e5926SBob King 88*462e5926SBob King return std::make_tuple(std::move(system), chassisPtr, devicePtr); 89*462e5926SBob King } 90*462e5926SBob King 91bfe2c25aSShawn McCarney TEST(PresenceDetectionTests, Constructor) 92bfe2c25aSShawn McCarney { 93bfe2c25aSShawn McCarney std::vector<std::unique_ptr<Action>> actions{}; 94*462e5926SBob King actions.emplace_back(std::make_unique<MockAction>()); 95bfe2c25aSShawn McCarney 96*462e5926SBob King PresenceDetection detection{std::move(actions)}; 97*462e5926SBob King EXPECT_EQ(detection.getActions().size(), 1); 98*462e5926SBob King EXPECT_FALSE(detection.getCachedPresence().has_value()); 99*462e5926SBob King } 100*462e5926SBob King 101*462e5926SBob King TEST(PresenceDetectionTests, ClearCache) 102*462e5926SBob King { 103*462e5926SBob King // Create MockAction that will return true once 104*462e5926SBob King std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 105*462e5926SBob King EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(true)); 106*462e5926SBob King 107*462e5926SBob King // Create PresenceDetection 108*462e5926SBob King std::vector<std::unique_ptr<Action>> actions{}; 109*462e5926SBob King actions.emplace_back(std::move(action)); 110*462e5926SBob King PresenceDetection* detection = new PresenceDetection(std::move(actions)); 111*462e5926SBob King 112*462e5926SBob King // Create parent System, Chassis, and Device objects 113*462e5926SBob King auto [system, chassis, device] = 114*462e5926SBob King createParentObjects(std::unique_ptr<PresenceDetection>{detection}); 115*462e5926SBob King 116*462e5926SBob King // Verify that initially no presence value is cached 117*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 118*462e5926SBob King 119*462e5926SBob King // Call execute() which should obtain and cache presence value 120*462e5926SBob King MockServices services{}; 121*462e5926SBob King EXPECT_TRUE(detection->execute(services, *system, *chassis, *device)); 122*462e5926SBob King 123*462e5926SBob King // Verify true presence value was cached 124*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 125*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().value()); 126*462e5926SBob King 127*462e5926SBob King // Clear cached presence value 128*462e5926SBob King detection->clearCache(); 129*462e5926SBob King 130*462e5926SBob King // Verify that no presence value is cached 131*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 132bfe2c25aSShawn McCarney } 133bfe2c25aSShawn McCarney 134bfe2c25aSShawn McCarney TEST(PresenceDetectionTests, Execute) 135bfe2c25aSShawn McCarney { 136*462e5926SBob King // Create ComparePresenceAction 137*462e5926SBob King std::unique_ptr<ComparePresenceAction> action = 138*462e5926SBob King std::make_unique<ComparePresenceAction>( 139*462e5926SBob King "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2", 140*462e5926SBob King true); 141*462e5926SBob King 142*462e5926SBob King // Create PresenceDetection 143*462e5926SBob King std::vector<std::unique_ptr<Action>> actions{}; 144*462e5926SBob King actions.emplace_back(std::move(action)); 145*462e5926SBob King PresenceDetection* detection = new PresenceDetection(std::move(actions)); 146*462e5926SBob King 147*462e5926SBob King // Create parent System, Chassis, and Device objects 148*462e5926SBob King auto [system, chassis, device] = 149*462e5926SBob King createParentObjects(std::unique_ptr<PresenceDetection>{detection}); 150*462e5926SBob King 151*462e5926SBob King // Test where works: Present: Value is not cached 152*462e5926SBob King { 153*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 154*462e5926SBob King 155*462e5926SBob King // Create MockServices. MockPresenceService::isPresent() should return 156*462e5926SBob King // true. 157*462e5926SBob King MockServices services{}; 158*462e5926SBob King MockPresenceService& presenceService = 159*462e5926SBob King services.getMockPresenceService(); 160*462e5926SBob King EXPECT_CALL(presenceService, 161*462e5926SBob King isPresent("/xyz/openbmc_project/inventory/system/chassis/" 162*462e5926SBob King "motherboard/cpu2")) 163*462e5926SBob King .Times(1) 164*462e5926SBob King .WillOnce(Return(true)); 165*462e5926SBob King 166*462e5926SBob King // Execute PresenceDetection 167*462e5926SBob King EXPECT_TRUE(detection->execute(services, *system, *chassis, *device)); 168*462e5926SBob King 169*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 170*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().value()); 171*462e5926SBob King } 172*462e5926SBob King 173*462e5926SBob King // Test where works: Present: Value is cached 174*462e5926SBob King { 175*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 176*462e5926SBob King 177*462e5926SBob King // Create MockServices. MockPresenceService::isPresent() should not be 178*462e5926SBob King // called. 179*462e5926SBob King MockServices services{}; 180*462e5926SBob King MockPresenceService& presenceService = 181*462e5926SBob King services.getMockPresenceService(); 182*462e5926SBob King EXPECT_CALL(presenceService, isPresent).Times(0); 183*462e5926SBob King 184*462e5926SBob King // Execute PresenceDetection 185*462e5926SBob King EXPECT_TRUE(detection->execute(services, *system, *chassis, *device)); 186*462e5926SBob King } 187*462e5926SBob King 188*462e5926SBob King // Test where works: Not present: Value is not cached 189*462e5926SBob King { 190*462e5926SBob King // Clear cached presence value 191*462e5926SBob King detection->clearCache(); 192*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 193*462e5926SBob King 194*462e5926SBob King // Create MockServices. MockPresenceService::isPresent() should return 195*462e5926SBob King // false. 196*462e5926SBob King MockServices services{}; 197*462e5926SBob King MockPresenceService& presenceService = 198*462e5926SBob King services.getMockPresenceService(); 199*462e5926SBob King EXPECT_CALL(presenceService, 200*462e5926SBob King isPresent("/xyz/openbmc_project/inventory/system/chassis/" 201*462e5926SBob King "motherboard/cpu2")) 202*462e5926SBob King .Times(1) 203*462e5926SBob King .WillOnce(Return(false)); 204*462e5926SBob King 205*462e5926SBob King // Execute PresenceDetection 206*462e5926SBob King EXPECT_FALSE(detection->execute(services, *system, *chassis, *device)); 207*462e5926SBob King 208*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 209*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().value()); 210*462e5926SBob King } 211*462e5926SBob King 212*462e5926SBob King // Test where works: Not present: Value is cached 213*462e5926SBob King { 214*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 215*462e5926SBob King 216*462e5926SBob King // Create MockServices. MockPresenceService::isPresent() should not be 217*462e5926SBob King // called. 218*462e5926SBob King MockServices services{}; 219*462e5926SBob King MockPresenceService& presenceService = 220*462e5926SBob King services.getMockPresenceService(); 221*462e5926SBob King EXPECT_CALL(presenceService, isPresent).Times(0); 222*462e5926SBob King 223*462e5926SBob King // Execute PresenceDetection 224*462e5926SBob King EXPECT_FALSE(detection->execute(services, *system, *chassis, *device)); 225*462e5926SBob King } 226*462e5926SBob King 227*462e5926SBob King // Test where fails 228*462e5926SBob King { 229*462e5926SBob King // Clear cached presence value 230*462e5926SBob King detection->clearCache(); 231*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 232*462e5926SBob King 233*462e5926SBob King // Create MockServices. MockPresenceService::isPresent() should throw 234*462e5926SBob King // an exception. 235*462e5926SBob King MockServices services{}; 236*462e5926SBob King MockPresenceService& presenceService = 237*462e5926SBob King services.getMockPresenceService(); 238*462e5926SBob King EXPECT_CALL(presenceService, 239*462e5926SBob King isPresent("/xyz/openbmc_project/inventory/system/chassis/" 240*462e5926SBob King "motherboard/cpu2")) 241*462e5926SBob King .Times(1) 242*462e5926SBob King .WillOnce( 243*462e5926SBob King Throw(std::runtime_error{"DBusError: Invalid object path."})); 244*462e5926SBob King 245*462e5926SBob King // Define expected journal messages that should be passed to MockJournal 246*462e5926SBob King MockJournal& journal = services.getMockJournal(); 247*462e5926SBob King std::vector<std::string> exceptionMessages{ 248*462e5926SBob King "DBusError: Invalid object path.", 249*462e5926SBob King "ActionError: compare_presence: { fru: " 250*462e5926SBob King "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu2, " 251*462e5926SBob King "value: true }"}; 252*462e5926SBob King EXPECT_CALL(journal, logError(exceptionMessages)).Times(1); 253*462e5926SBob King EXPECT_CALL(journal, 254*462e5926SBob King logError("Unable to determine presence of vdd_reg")) 255*462e5926SBob King .Times(1); 256*462e5926SBob King 257*462e5926SBob King // Execute PresenceDetection. Should return true when an error occurs. 258*462e5926SBob King EXPECT_TRUE(detection->execute(services, *system, *chassis, *device)); 259*462e5926SBob King 260*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 261*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().value()); 262*462e5926SBob King } 263bfe2c25aSShawn McCarney } 264bfe2c25aSShawn McCarney 265bfe2c25aSShawn McCarney TEST(PresenceDetectionTests, GetActions) 266bfe2c25aSShawn McCarney { 267bfe2c25aSShawn McCarney std::vector<std::unique_ptr<Action>> actions{}; 268bfe2c25aSShawn McCarney 269bfe2c25aSShawn McCarney MockAction* action1 = new MockAction{}; 270*462e5926SBob King actions.emplace_back(std::unique_ptr<MockAction>{action1}); 271bfe2c25aSShawn McCarney 272bfe2c25aSShawn McCarney MockAction* action2 = new MockAction{}; 273*462e5926SBob King actions.emplace_back(std::unique_ptr<MockAction>{action2}); 274bfe2c25aSShawn McCarney 275*462e5926SBob King PresenceDetection detection{std::move(actions)}; 276*462e5926SBob King EXPECT_EQ(detection.getActions().size(), 2); 277*462e5926SBob King EXPECT_EQ(detection.getActions()[0].get(), action1); 278*462e5926SBob King EXPECT_EQ(detection.getActions()[1].get(), action2); 279*462e5926SBob King } 280*462e5926SBob King 281*462e5926SBob King TEST(PresenceDetectionTests, GetCachedPresence) 282*462e5926SBob King { 283*462e5926SBob King // Create MockAction that will return false once 284*462e5926SBob King std::unique_ptr<MockAction> action = std::make_unique<MockAction>(); 285*462e5926SBob King EXPECT_CALL(*action, execute).Times(1).WillOnce(Return(false)); 286*462e5926SBob King 287*462e5926SBob King // Create PresenceDetection 288*462e5926SBob King std::vector<std::unique_ptr<Action>> actions{}; 289*462e5926SBob King actions.emplace_back(std::move(action)); 290*462e5926SBob King PresenceDetection* detection = new PresenceDetection(std::move(actions)); 291*462e5926SBob King 292*462e5926SBob King // Create parent System, Chassis, and Device objects 293*462e5926SBob King auto [system, chassis, device] = 294*462e5926SBob King createParentObjects(std::unique_ptr<PresenceDetection>{detection}); 295*462e5926SBob King 296*462e5926SBob King // Verify that initially no presence value is cached 297*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 298*462e5926SBob King 299*462e5926SBob King // Call execute() which should obtain and cache presence value 300*462e5926SBob King MockServices services{}; 301*462e5926SBob King EXPECT_FALSE(detection->execute(services, *system, *chassis, *device)); 302*462e5926SBob King 303*462e5926SBob King // Verify false presence value was cached 304*462e5926SBob King EXPECT_TRUE(detection->getCachedPresence().has_value()); 305*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().value()); 306*462e5926SBob King 307*462e5926SBob King // Clear cached presence value 308*462e5926SBob King detection->clearCache(); 309*462e5926SBob King 310*462e5926SBob King // Verify that no presence value is cached 311*462e5926SBob King EXPECT_FALSE(detection->getCachedPresence().has_value()); 312bfe2c25aSShawn McCarney } 313