From c88ea6a9a0a780e3905ff2f1c24c581e75bd62c5 Mon Sep 17 00:00:00 2001
From: Tobias Schmidl <5060861-schtobia@users.noreply.gitlab.com>
Date: Thu, 6 Oct 2022 05:10:49 +0200
Subject: [PATCH] monitor is complete

---
 collector.hpp | 14 --------
 monitor.hpp   | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++
 test.cpp      | 41 +++++++++++++++++++----
 3 files changed, 125 insertions(+), 20 deletions(-)
 delete mode 100644 collector.hpp
 create mode 100644 monitor.hpp

diff --git a/collector.hpp b/collector.hpp
deleted file mode 100644
index c7ffc2f..0000000
--- a/collector.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#pragma once
-#include <deque>
-namespace collector
-{
-	class Event
-	{};
-	class Collector
-	{
-		private:
-			std::deque<Event> _event_queue;
-		public:
-			const auto get_length() const { return _event_queue.size(); }
-	};
-}
diff --git a/monitor.hpp b/monitor.hpp
new file mode 100644
index 0000000..430a780
--- /dev/null
+++ b/monitor.hpp
@@ -0,0 +1,90 @@
+/**
+ * @file monitor.hpp
+ *  A dir_monitor wrapper for specific paths
+ *
+ * @author Tobias Schmidl
+ * @copyright Copyright © 2022, Tobias Schmidl
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+#include <dir_monitor/dir_monitor.hpp>
+#include <filesystem>
+#include <regex>
+
+namespace collector::monitor {
+
+class Monitor
+{
+  private:
+    boost::asio::dir_monitor _monitor;
+    std::filesystem::path _root_path;
+
+  public:
+    explicit Monitor(boost::asio::io_service& io_service,
+                     std::filesystem::path&& root_path)
+      : _monitor(io_service)
+      , _root_path(std::move(root_path))
+    {
+        _monitor.add_directory(_root_path);
+        for (const auto& dir_entry :
+             std::filesystem::recursive_directory_iterator(_root_path)) {
+            if (dir_entry.is_directory())
+                _monitor.add_directory(dir_entry.path());
+        }
+    }
+
+    explicit Monitor(boost::asio::io_service& io_service,
+                     const std::filesystem::path& root_path)
+      : _monitor(io_service)
+      , _root_path(root_path)
+    {
+        _monitor.add_directory(_root_path);
+        for (const auto& dir_entry :
+             std::filesystem::recursive_directory_iterator(_root_path)) {
+            if (dir_entry.is_directory())
+                _monitor.add_directory(dir_entry.path());
+        }
+    }
+
+    /**
+     * watches any for any event that matches the given search_pattern
+     */
+    boost::asio::dir_monitor_event watch(const std::regex& search_pattern)
+    {
+        boost::asio::dir_monitor_event monitored_event;
+        do {
+            monitored_event = _monitor.monitor();
+        } while (!std::regex_match(
+          monitored_event.path.filename().generic_string(), search_pattern));
+        return monitored_event;
+    }
+
+    /**
+     * watches any for the specified event_type that also matches the given
+     * search_pattern
+     */
+    boost::asio::dir_monitor_event watch(
+      const std::regex& search_pattern,
+      const boost::asio::dir_monitor_event::event_type event_type)
+    {
+        boost::asio::dir_monitor_event monitored_event;
+        do {
+            monitored_event = _monitor.monitor();
+        } while (
+          !std::regex_match(monitored_event.path.filename().generic_string(),
+                            search_pattern) ||
+          monitored_event.type != event_type);
+        return monitored_event;
+    }
+
+    const auto& get_root_path() const { return _root_path; }
+    virtual ~Monitor() = default;
+
+    Monitor() = delete;
+    Monitor(Monitor&& other) = delete;
+    Monitor(const Monitor& other) = delete;
+    Monitor& operator=(Monitor&& other) = delete;
+    Monitor& operator=(const Monitor& other) = delete;
+};
+}
diff --git a/test.cpp b/test.cpp
index 173af0f..570ef94 100644
--- a/test.cpp
+++ b/test.cpp
@@ -1,13 +1,42 @@
-#include "collector.hpp"
+/**
+ * @file test.cpp
+ *  The unit test executable
+ *
+ * @author Tobias Schmidl
+ * @copyright Copyright © 2022, Tobias Schmidl
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "monitor.hpp"
 #include "version.hpp"
+#include "collector.hpp"
 #define BOOST_TEST_MODULE Collector test
 #include <boost/test/unit_test.hpp>
+#include <chrono>
+#include <fstream>
+#include <future>
+#include <thread>
 
-using namespace collector;
+using namespace collector::monitor;
+using namespace collector::collector;
+using namespace std::chrono_literals;
 
-BOOST_AUTO_TEST_CASE(collector_test)
+boost::asio::io_service service;
+
+BOOST_AUTO_TEST_CASE(monitor_test)
 {
-    BOOST_TEST_MESSAGE( "Test version " << VERSION );
-    Collector foo;
-    BOOST_TEST(foo.get_length() == 0u);
+    BOOST_TEST_MESSAGE("Test version " << VERSION);
+    const std::filesystem::path test_file{ "test_file" };
+    std::filesystem::remove(test_file);
+    const auto create_file_result = std::async([&test_file]() {
+        std::this_thread::sleep_for(2s);
+        std::ofstream{ test_file };
+    });
+    Monitor monitor(service, std::filesystem::current_path());
+    const auto& watch_result =
+      monitor.watch(std::regex(test_file.generic_string()),
+                    boost::asio::dir_monitor_event::event_type::added);
+    BOOST_TEST(std::filesystem::equivalent(test_file,
+                                           watch_result.path.generic_string()));
+    std::filesystem::remove(test_file);
 }