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