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