1 #include "physical.hpp" 2 3 #include <sys/param.h> 4 5 #include <sdbusplus/bus.hpp> 6 7 #include <gmock/gmock.h> 8 #include <gtest/gtest.h> 9 10 constexpr auto LED_OBJ = "/foo/bar/led"; 11 12 using Action = sdbusplus::xyz::openbmc_project::Led::server::Physical::Action; 13 namespace fs = std::experimental::filesystem; 14 15 fs::path create_sandbox() 16 { 17 /* If your tests need to touch the filesystem, always use mkdtemp() or 18 * mkstemp() for creating directories and files. Tests can be run in 19 * parallel with `make -j`, and if use the same path in multiple tests they 20 * will stomp on eachother and likely fail. 21 */ 22 static constexpr auto tmplt = "/tmp/MockLed.XXXXXX"; 23 char buffer[MAXPATHLEN] = {0}; 24 25 strncpy(buffer, tmplt, sizeof(buffer) - 1); 26 auto dir = mkdtemp(buffer); 27 if (!dir) 28 { 29 throw std::system_error(errno, std::system_category()); 30 } 31 32 /* We want to limit behaviours to mocks, and if methods aren't mocked they 33 * may fall back to their base class implementation. Stop read/write to 34 * directory to prevent streams from creating files. 35 */ 36 if (chmod(dir, S_IXUSR | S_IXGRP) == -1) 37 { 38 throw std::system_error(errno, std::system_category()); 39 } 40 41 return fs::path(dir); 42 } 43 44 class MockLed : public phosphor::led::SysfsLed 45 { 46 public: 47 /* Use a no-args ctor here to avoid headaches with {Nice,Strict}Mock */ 48 MockLed() : SysfsLed(create_sandbox()) 49 { 50 } 51 52 virtual ~MockLed() 53 { 54 chmod(root.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); 55 fs::remove_all(root); 56 } 57 58 MOCK_METHOD0(getBrightness, unsigned long()); 59 MOCK_METHOD1(setBrightness, void(unsigned long value)); 60 MOCK_METHOD0(getMaxBrightness, unsigned long()); 61 MOCK_METHOD0(getTrigger, std::string()); 62 MOCK_METHOD1(setTrigger, void(const std::string& trigger)); 63 MOCK_METHOD0(getDelayOn, unsigned long()); 64 MOCK_METHOD1(setDelayOn, void(unsigned long ms)); 65 MOCK_METHOD0(getDelayOff, unsigned long()); 66 MOCK_METHOD1(setDelayOff, void(unsigned long ms)); 67 }; 68 69 using ::testing::InSequence; 70 using ::testing::NiceMock; 71 using ::testing::Return; 72 using ::testing::Throw; 73 74 TEST(Physical, ctor_none_trigger) 75 { 76 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 77 /* NiceMock ignores calls to methods with no expectations defined */ 78 NiceMock<MockLed> led; 79 ON_CALL(led, getTrigger()).WillByDefault(Return("none")); 80 phosphor::led::Physical phy(bus, LED_OBJ, led); 81 } 82 83 TEST(Physical, ctor_timer_trigger) 84 { 85 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 86 NiceMock<MockLed> led; 87 EXPECT_CALL(led, getTrigger()).WillOnce(Return("timer")); 88 EXPECT_CALL(led, getDelayOn()).WillOnce(Return(500)); 89 EXPECT_CALL(led, getDelayOff()).WillOnce(Return(500)); 90 phosphor::led::Physical phy(bus, LED_OBJ, led); 91 } 92 93 TEST(Physical, off) 94 { 95 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 96 NiceMock<MockLed> led; 97 ON_CALL(led, getTrigger()).WillByDefault(Return("none")); 98 phosphor::led::Physical phy(bus, LED_OBJ, led); 99 phy.state(Action::Off); 100 } 101 102 TEST(Physical, on) 103 { 104 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 105 NiceMock<MockLed> led; 106 ON_CALL(led, getTrigger()).WillByDefault(Return("none")); 107 phosphor::led::Physical phy(bus, LED_OBJ, led); 108 phy.state(Action::On); 109 } 110 111 TEST(Physical, blink) 112 { 113 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 114 NiceMock<MockLed> led; 115 EXPECT_CALL(led, getTrigger()).WillOnce(Return("none")); 116 EXPECT_CALL(led, setTrigger("timer")); 117 EXPECT_CALL(led, setDelayOn(500)); 118 EXPECT_CALL(led, setDelayOff(500)); 119 phosphor::led::Physical phy(bus, LED_OBJ, led); 120 phy.state(Action::Blink); 121 } 122 123 TEST(Physical, ctor_none_trigger_asserted_brightness) 124 { 125 sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); 126 NiceMock<MockLed> led; 127 EXPECT_CALL(led, getTrigger()).WillRepeatedly(Return("none")); 128 constexpr auto val = phosphor::led::ASSERT; 129 EXPECT_CALL(led, getBrightness()).WillRepeatedly(Return(val)); 130 phosphor::led::Physical phy(bus, LED_OBJ, led); 131 } 132 133 TEST(Physical, on_to_off) 134 { 135 InSequence s; 136 137 auto bus = sdbusplus::bus::new_default(); 138 NiceMock<MockLed> led; 139 EXPECT_CALL(led, getTrigger()).Times(1).WillOnce(Return("none")); 140 constexpr auto deasserted = phosphor::led::DEASSERT; 141 EXPECT_CALL(led, getBrightness()).WillOnce(Return(deasserted)); 142 constexpr auto asserted = phosphor::led::ASSERT; 143 EXPECT_CALL(led, setBrightness(asserted)); 144 EXPECT_CALL(led, setBrightness(deasserted)); 145 phosphor::led::Physical phy(bus, LED_OBJ, led); 146 phy.state(Action::On); 147 phy.state(Action::Off); 148 } 149