1 #include <iostream> 2 #include <sys/types.h> 3 #include <chrono> 4 #include <string> 5 #include <linux/input.h> 6 #include <gtest/gtest.h> 7 #include "monitor.hpp" 8 #include "evdev.hpp" 9 10 using namespace phosphor::gpio; 11 12 // Exit helper. Ideally should be class but need 13 // this to be used inside a static method. 14 bool completed {}; 15 16 class GpioTest : public ::testing::Test 17 { 18 public: 19 static constexpr auto DEVICE = "/tmp/test_fifo"; 20 21 // systemd event handler 22 sd_event* events; 23 24 // Really needed just for the constructor 25 decltype(input_event::code) code = 10; 26 27 // Really needed just for the constructor 28 decltype(input_event::value) value = 10; 29 30 // Need this so that events can be initialized. 31 int rc; 32 33 // Gets called as part of each TEST_F construction 34 GpioTest() 35 : rc(sd_event_default(&events)) 36 { 37 // Check for successful creation of event handler 38 EXPECT_GE(rc, 0); 39 40 // FIFO created to simulate data available 41 EXPECT_EQ(0, mknod(DEVICE, S_IFIFO|0666, 0)); 42 } 43 44 // Gets called as part of each TEST_F destruction 45 ~GpioTest() 46 { 47 EXPECT_EQ(0, remove(DEVICE)); 48 49 events = sd_event_unref(events); 50 EXPECT_EQ(events, nullptr); 51 } 52 53 // Callback handler on data 54 static int callbackHandler(sd_event_source* es, int fd, 55 uint32_t revents, void* userData) 56 { 57 std::cout <<"Event fired" << std::endl; 58 completed = true; 59 return 0; 60 } 61 }; 62 63 /** @brief Makes sure that event never comes for 3 seconds 64 */ 65 TEST_F(GpioTest, noEventIn3Seconds) 66 { 67 using namespace std::chrono; 68 69 phosphor::gpio::EventPtr eventP { events }; 70 events = nullptr; 71 72 const std::string emptyTarget = ""; 73 Monitor gpio(DEVICE, code, value, emptyTarget, 74 eventP, false, callbackHandler, false); 75 76 // Waiting 3 seconds and check if the completion status is set 77 int count = 0; 78 while(count < 3) 79 { 80 // Returns -0- on timeout and positive number on dispatch 81 auto sleepTime = duration_cast<microseconds>(seconds(1)); 82 if(!sd_event_run(eventP.get(), sleepTime.count())) 83 { 84 count++; 85 } 86 } 87 EXPECT_EQ(false, completed); 88 89 // 3 to cater to another uptick that happens prior to breaking. 90 EXPECT_EQ(3, count); 91 } 92 93 /** @brief Pump data in the middle and expect the callback to be invoked */ 94 TEST_F(GpioTest, pumpDataAndExpectCallBack) 95 { 96 using namespace std::chrono; 97 98 phosphor::gpio::EventPtr eventP { events }; 99 events = nullptr; 100 101 const std::string emptyTarget = ""; 102 Monitor gpio(DEVICE, code, value, emptyTarget, 103 eventP, false, callbackHandler, false); 104 105 // Pump the data in the middle 106 int count = 0; 107 while(count < 2 && !completed) 108 { 109 if (count == 1) 110 { 111 auto pumpData = std::string("echo 'foo' > ") + DEVICE; 112 EXPECT_GE(0, system(pumpData.c_str())); 113 } 114 115 // Returns -0- on timeout 116 auto sleepTime = duration_cast<microseconds>(seconds(1)); 117 if(!sd_event_run(eventP.get(), sleepTime.count())) 118 { 119 count++; 120 } 121 } 122 EXPECT_EQ(true, completed); 123 EXPECT_EQ(1, count); 124 } 125