Add gtest cases to test callback handler

Change-Id: If6c1e1616bcf73441648c8e0cb20017a4b218f70
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/test/Makefile.am b/test/Makefile.am
new file mode 100644
index 0000000..db82844
--- /dev/null
+++ b/test/Makefile.am
@@ -0,0 +1,12 @@
+AM_CPPFLAGS = -I$(top_srcdir)
+
+# Run all 'check' test programs
+TESTS = $(check_PROGRAMS)
+
+# # Build/add utest to test suite
+check_PROGRAMS = utest
+utest_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS) $(SDBUSPLUS_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
+utest_CXXFLAGS = $(PTHREAD_CFLAGS)
+utest_LDFLAGS = -lgtest_main -lgtest $(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) $(SYSTEMD_LIBS) $(SDBUSPLUS_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS)
+utest_SOURCES = utest.cpp
+utest_LDADD = $(top_builddir)/monitor.o
diff --git a/test/utest.cpp b/test/utest.cpp
new file mode 100644
index 0000000..78e1b7e
--- /dev/null
+++ b/test/utest.cpp
@@ -0,0 +1,123 @@
+#include <iostream>
+#include <sys/types.h>
+#include <chrono>
+#include <string>
+#include <linux/input.h>
+#include <gtest/gtest.h>
+#include "monitor.hpp"
+
+using namespace phosphor::gpio;
+
+// Exit helper. Ideally should be class but need
+// this to be used inside a static method.
+bool completed {};
+
+class GpioTest : public ::testing::Test
+{
+    public:
+        static constexpr auto DEVICE = "/tmp/test_fifo";
+
+        // systemd event handler
+        sd_event* events;
+
+        // Really needed just for the constructor
+        decltype(input_event::code) code = 10;
+
+        // Really needed just for the constructor
+        decltype(input_event::value) value = 10;
+
+        // Need this so that events can be initialized.
+        int rc;
+
+        // Gets called as part of each TEST_F construction
+        GpioTest()
+              : rc(sd_event_default(&events))
+        {
+            // Check for successful creation of event handler
+            EXPECT_GE(rc, 0);
+
+            // FIFO created to simulate data available
+            EXPECT_EQ(0, mknod(DEVICE, S_IFIFO|0666, 0));
+        }
+
+        // Gets called as part of each TEST_F destruction
+        ~GpioTest()
+        {
+            EXPECT_EQ(0, remove(DEVICE));
+
+            events = sd_event_unref(events);
+            EXPECT_EQ(events, nullptr);
+        }
+
+        // Callback handler on data
+        static int callbackHandler(sd_event_source* es, int fd,
+                                   uint32_t revents, void* userData)
+        {
+            std::cout <<"Event fired" << std::endl;
+            completed = true;
+            return 0;
+        }
+};
+
+/** @brief Makes sure that event never comes for 3 seconds
+ */
+TEST_F(GpioTest, noEventIn3Seconds)
+{
+    using namespace std::chrono;
+
+    phosphor::gpio::EventPtr eventP { events };
+    events = nullptr;
+
+    const std::string emptyTarget = "";
+    Monitor gpio(DEVICE, code, value, emptyTarget,
+                 eventP, callbackHandler);
+
+    // Waiting 3 seconds and check if the completion status is set
+    int count = 0;
+    while(count < 3)
+    {
+        // Returns -0- on timeout and positive number on dispatch
+        auto sleepTime = duration_cast<microseconds>(seconds(1));
+        if(!sd_event_run(eventP.get(), sleepTime.count()))
+        {
+            count++;
+        }
+    }
+    EXPECT_EQ(false, completed);
+
+    // 3 to cater to another uptick that happens prior to breaking.
+    EXPECT_EQ(3, count);
+}
+
+/** @brief Pump data in the middle and expect the callback to be invoked */
+TEST_F(GpioTest, pumpDataAndExpectCallBack)
+{
+    using namespace std::chrono;
+
+    phosphor::gpio::EventPtr eventP { events };
+    events = nullptr;
+
+    const std::string emptyTarget = "";
+    Monitor gpio(DEVICE, code, value, emptyTarget,
+                 eventP, callbackHandler);
+
+    // Pump the data in the middle
+    int count = 0;
+    while(count < 2 && !completed)
+    {
+        if (count == 1)
+        {
+            auto pumpData = std::string("echo 'foo' > ") + DEVICE;
+            EXPECT_GE(0, system(pumpData.c_str()));
+        }
+
+        // Returns -0- on timeout
+        auto sleepTime = duration_cast<microseconds>(seconds(1));
+        if(!sd_event_run(eventP.get(), sleepTime.count()))
+        {
+            count++;
+        }
+    }
+    EXPECT_EQ(true, completed);
+    EXPECT_EQ(1, count);
+}