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