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