Add inotify watch support

Added code to register for inotify events on the needed
path and the user callback on events

Change-Id: I90529f8e96fcbecfe0a1b943c3c435dab79222c3
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/test/Makefile.am b/test/Makefile.am
index 5c70fbe..5a1e712 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,7 +2,7 @@
 
 TESTS = $(check_PROGRAMS)
 
-check_PROGRAMS = test test_dns_updater
+check_PROGRAMS = test test_dns_updater test_watch
 
 test_SOURCES = \
 	test_util.cpp \
@@ -13,6 +13,7 @@
 	test_vlan_interface.cpp
 
 test_dns_updater_SOURCES = test_dns_updater.cpp
+test_watch_SOURCES = test_watch.cpp
 
 generic_cpp_flags = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS)
 
@@ -37,6 +38,10 @@
 test_dns_updater_CXXFLAGS = ${generic_cxx_flags}
 test_dns_updater_LDFLAGS  = ${generic_ld_flags}
 
+test_watch_CPPFLAGS = ${generic_cpp_flags}
+test_watch_CXXFLAGS = ${generic_cxx_flags}
+test_watch_LDFLAGS  = ${generic_ld_flags}
+
 test_LDADD = $(top_builddir)/ethernet_interface.o \
 			$(top_builddir)/network_manager.o \
 			$(top_builddir)/network_config.o \
@@ -52,3 +57,4 @@
 			$(top_builddir)/xyz/openbmc_project/Network/IP/Create/phosphor_network_manager-server.o
 
 test_dns_updater_LDADD = $(top_builddir)/dns_updater.o
+test_watch_LDADD = $(top_builddir)/watch.o
diff --git a/test/test_watch.cpp b/test/test_watch.cpp
new file mode 100644
index 0000000..dac43b3
--- /dev/null
+++ b/test/test_watch.cpp
@@ -0,0 +1,90 @@
+#include "watch.hpp"
+#include "types.hpp"
+
+#include <gtest/gtest.h>
+
+#include <fstream>
+#include <experimental/filesystem>
+
+static constexpr auto TRIGGER_FILE = "/tmp/netif_state";
+
+namespace fs = std::experimental::filesystem;
+
+class WatchTest : public ::testing::Test
+{
+    public:
+        // systemd event handler
+        sd_event* events;
+
+        // Need this so that events can be initialized.
+        int rc;
+
+        // Gets called as part of each TEST_F construction
+        WatchTest()
+            : rc(sd_event_default(&events)),
+              eventPtr(events)
+        {
+            // Create a file containing DNS entries like in netif/state
+            std::ofstream file(TRIGGER_FILE);
+            file << "";
+
+            // Check for successful creation of
+            // event handler
+            EXPECT_GE(rc, 0);
+        }
+
+        // Gets called as part of each TEST_F destruction
+        ~WatchTest()
+        {
+            if (fs::exists(TRIGGER_FILE))
+            {
+                fs::remove(TRIGGER_FILE);
+            }
+        }
+
+        // unique_ptr for sd_event
+        phosphor::network::EventPtr eventPtr;
+
+        // Count of callback invocation
+        int count = 0;
+
+        // This is supposed to get hit twice
+        // Once at the beginning to see if there is anything
+        // and the second time when the data is fired.
+        void callBackHandler(const fs::path& file)
+        {
+            count++;
+
+            // Expect that the file is what we wanted
+            EXPECT_EQ(file, TRIGGER_FILE);
+        }
+};
+
+/** @brief Makes sure that the inotify event is fired
+ */
+TEST_F(WatchTest, validateEventNotification)
+{
+    // Create a watch object and register the handler
+    phosphor::network::inotify::Watch watch(eventPtr, TRIGGER_FILE,
+            std::bind(&WatchTest::callBackHandler, this,
+                std::placeholders::_1));
+
+    // Reading the event post subscription
+    callBackHandler(TRIGGER_FILE);
+
+    // Callback function must have hit by now
+    EXPECT_EQ(1, count);
+
+    // Make a run and see that no changes
+    sd_event_run(eventPtr.get(), 10);
+    EXPECT_EQ(1, count);
+
+    // Pump the data and get notification
+    {
+        std::ofstream file(TRIGGER_FILE);
+        file <<"DNS=1.2.3.4\n";
+    }
+
+    sd_event_run(eventPtr.get(), 10);
+    EXPECT_EQ(2, count);
+}