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