xref: /openbmc/phosphor-gpio-monitor/test/utest.cpp (revision dace680fa404d7c02a68db105fd7b958b4681442)
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
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
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
56     static int callbackHandler(sd_event_source* es, int fd, uint32_t revents,
57                                void* userData)
58     {
59         std::cout << "Event fired" << std::endl;
60         completed = true;
61         return 0;
62     }
63 };
64 
65 /** @brief Makes sure that event never comes for 3 seconds
66  */
67 TEST_F(GpioTest, noEventIn3Seconds)
68 {
69     using namespace std::chrono;
70 
71     phosphor::gpio::EventPtr eventP{events};
72     events = nullptr;
73 
74     const std::string emptyTarget = "";
75     Monitor gpio(DEVICE, code, value, emptyTarget, eventP, false,
76                  callbackHandler, false);
77 
78     // Waiting 3 seconds and check if the completion status is set
79     int count = 0;
80     while (count < 3)
81     {
82         // Returns -0- on timeout and positive number on dispatch
83         auto sleepTime = duration_cast<microseconds>(seconds(1));
84         if (!sd_event_run(eventP.get(), sleepTime.count()))
85         {
86             count++;
87         }
88     }
89     EXPECT_EQ(false, completed);
90 
91     // 3 to cater to another uptick that happens prior to breaking.
92     EXPECT_EQ(3, count);
93 }
94 
95 /** @brief Pump data in the middle and expect the callback to be invoked */
96 TEST_F(GpioTest, pumpDataAndExpectCallBack)
97 {
98     using namespace std::chrono;
99 
100     phosphor::gpio::EventPtr eventP{events};
101     events = nullptr;
102 
103     const std::string emptyTarget = "";
104     Monitor gpio(DEVICE, code, value, emptyTarget, eventP, false,
105                  callbackHandler, false);
106 
107     // Pump the data in the middle
108     int count = 0;
109     while (count < 2 && !completed)
110     {
111         if (count == 1)
112         {
113             auto pumpData = std::string("echo 'foo' > ") + DEVICE;
114             EXPECT_GE(0, system(pumpData.c_str()));
115         }
116 
117         // Returns -0- on timeout
118         auto sleepTime = duration_cast<microseconds>(seconds(1));
119         if (!sd_event_run(eventP.get(), sleepTime.count()))
120         {
121             count++;
122         }
123     }
124     EXPECT_EQ(true, completed);
125     EXPECT_EQ(1, count);
126 }
127