xref: /openbmc/phosphor-gpio-monitor/test/utest.cpp (revision ba8de42135766deab2125a784a89d3e51bc2e194)
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