From a23149fa7627a96fbbf3e38353bcdad496f0adda Mon Sep 17 00:00:00 2001
From: Sergey Yakubov <sergey.yakubov@desy.de>
Date: Wed, 5 Sep 2018 17:39:05 +0200
Subject: [PATCH] continue windows folder monitor

---
 common/cpp/include/io/io.h                    |   2 +-
 common/cpp/include/unittests/MockIO.h         |  13 ++-
 common/cpp/src/system_io/system_io.h          |   2 +-
 .../event_monitor_producer/CMakeLists.txt     |   8 +-
 .../src/single_folder_monitor.cpp             |  13 ---
 .../src/single_folder_monitor.h               |  19 ----
 .../src/single_folder_watch_windows.cpp       |  30 +++++
 .../src/single_folder_watch_windows.h         |  26 +++++
 .../src/system_folder_watch_windows.cpp       |  17 +--
 .../src/system_folder_watch_windows.h         |   4 +-
 .../event_monitor_producer/src/watch_io.cpp   |  24 ++++
 .../event_monitor_producer/src/watch_io.h     |  22 ++++
 .../unittests/mock_watch_io.h                 |  26 +++++
 .../test_single_folder_watch_windows.cpp      | 107 ++++++++++++++++++
 14 files changed, 261 insertions(+), 52 deletions(-)
 delete mode 100644 producer/event_monitor_producer/src/single_folder_monitor.cpp
 delete mode 100644 producer/event_monitor_producer/src/single_folder_monitor.h
 create mode 100644 producer/event_monitor_producer/src/single_folder_watch_windows.cpp
 create mode 100644 producer/event_monitor_producer/src/single_folder_watch_windows.h
 create mode 100644 producer/event_monitor_producer/src/watch_io.cpp
 create mode 100644 producer/event_monitor_producer/src/watch_io.h
 create mode 100644 producer/event_monitor_producer/unittests/mock_watch_io.h
 create mode 100644 producer/event_monitor_producer/unittests/test_single_folder_watch_windows.cpp

diff --git a/common/cpp/include/io/io.h b/common/cpp/include/io/io.h
index 6d5c7e5c8..d40a2cb86 100644
--- a/common/cpp/include/io/io.h
+++ b/common/cpp/include/io/io.h
@@ -101,7 +101,7 @@ class IO {
     virtual SubDirList      GetSubDirectories(const std::string& path, Error* err) const = 0;
     virtual std::vector<FileInfo>   FilesInFolder   (const std::string& folder, Error* err) const = 0;
     virtual std::string     ReadFileToString        (const std::string& fname, Error* err) const = 0;
-
+    virtual Error GetLastError() const = 0;
 };
 
 }
diff --git a/common/cpp/include/unittests/MockIO.h b/common/cpp/include/unittests/MockIO.h
index 2e374027c..c7a9ed8db 100644
--- a/common/cpp/include/unittests/MockIO.h
+++ b/common/cpp/include/unittests/MockIO.h
@@ -173,7 +173,15 @@ class MockIO : public IO {
 
     MOCK_CONST_METHOD3(GetDataFromFile_t, uint8_t* (const std::string& fname, uint64_t* fsize, ErrorInterface** err));
 
-    Error WriteDataToFile(const std::string& root_folder, const std::string& fname, const FileData& data,
+
+    Error GetLastError() const override {
+        return Error{GetLastError_t()};
+    }
+
+    MOCK_CONST_METHOD0(GetLastError_t, ErrorInterface* ());
+
+
+  Error WriteDataToFile(const std::string& root_folder, const std::string& fname, const FileData& data,
                           size_t length, bool create_directories) const override {
         return Error{WriteDataToFile_t(root_folder, fname, data.get(), length, create_directories)};
 
@@ -223,6 +231,9 @@ class MockIO : public IO {
         return data;
     }
     MOCK_CONST_METHOD2(ReadFileToString_t, std::string(const std::string& fname, ErrorInterface** err));
+
+
+
 };
 
 }
diff --git a/common/cpp/src/system_io/system_io.h b/common/cpp/src/system_io/system_io.h
index 314eb74ca..00ff32d82 100644
--- a/common/cpp/src/system_io/system_io.h
+++ b/common/cpp/src/system_io/system_io.h
@@ -25,7 +25,6 @@ class SystemIO final : public IO {
 
     //void CollectFileInformationRecursively(const std::string& path, std::vector<FileInfo>* files, IOErrors* err) const;
     int FileOpenModeToPosixFileOpenMode(int open_flags) const;
-    Error GetLastError() const;
 
     short AddressFamilyToPosixFamily      (AddressFamilies address_family) const;
     int SocketTypeToPosixType           (SocketTypes socket_type) const;
@@ -111,6 +110,7 @@ class SystemIO final : public IO {
     SubDirList      GetSubDirectories(const std::string& path, Error* err) const override;
     std::string     ReadFileToString(const std::string& fname, Error* err) const override;
     Error           RemoveFile(const std::string& fname) const override;
+    Error           GetLastError() const override;
 
 };
 }
diff --git a/producer/event_monitor_producer/CMakeLists.txt b/producer/event_monitor_producer/CMakeLists.txt
index 8809a6224..c817b0eaf 100644
--- a/producer/event_monitor_producer/CMakeLists.txt
+++ b/producer/event_monitor_producer/CMakeLists.txt
@@ -7,7 +7,10 @@ set(SOURCE_FILES
 )
 
 IF(WIN32)
-    set(SOURCE_FILES ${SOURCE_FILES} src/system_folder_watch_windows.cpp src/single_folder_monitor.cpp)
+    set(SOURCE_FILES ${SOURCE_FILES} src/system_folder_watch_windows.cpp
+            src/single_folder_watch_windows.cpp
+            src/watch_io.cpp
+            )
 ELSEIF(UNIX)
     set(SOURCE_FILES ${SOURCE_FILES} src/system_folder_watch_linux.cpp src/inotify_event.cpp src/inotify_linux.cpp)
 ENDIF(WIN32)
@@ -56,7 +59,8 @@ set(TEST_SOURCE_FILES
 IF(UNIX)
 set(TEST_SOURCE_FILES ${TEST_SOURCE_FILES} unittests/test_system_folder_watch_linux.cpp)
 ELSE()
-set(TEST_SOURCE_FILES ${TEST_SOURCE_FILES} unittests/test_system_folder_watch_windows.cpp)
+set(TEST_SOURCE_FILES ${TEST_SOURCE_FILES} unittests/test_system_folder_watch_windows.cpp
+        unittests/test_single_folder_watch_windows.cpp)
 ENDIF(UNIX)
 
 
diff --git a/producer/event_monitor_producer/src/single_folder_monitor.cpp b/producer/event_monitor_producer/src/single_folder_monitor.cpp
deleted file mode 100644
index 390e0fef8..000000000
--- a/producer/event_monitor_producer/src/single_folder_monitor.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#include "single_folder_monitor.h"
-
-namespace asapo {
-
-SingleFolderMonitor::SingleFolderMonitor(std::string root_folder, std::string folder) : root_folder_{std::move(root_folder)},
-                                                                                        folder_{std::move(folder)} {
-
-}
-
-void SingleFolderMonitor::Monitor() {
-}
-
-}
diff --git a/producer/event_monitor_producer/src/single_folder_monitor.h b/producer/event_monitor_producer/src/single_folder_monitor.h
deleted file mode 100644
index 0a537984d..000000000
--- a/producer/event_monitor_producer/src/single_folder_monitor.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef ASAPO_SINGLE_FOLDER_MONITOR_H
-#define ASAPO_SINGLE_FOLDER_MONITOR_H
-
-#include <string>
-
-namespace asapo {
-
-class SingleFolderMonitor {
-  public:
-    explicit SingleFolderMonitor(std::string root_folder,std::string folder);
-    void Monitor();
- private:
-  std::string root_folder_;
-  std::string folder_;
-};
-
-}
-
-#endif //ASAPO_SINGLE_FOLDER_MONITOR_H
diff --git a/producer/event_monitor_producer/src/single_folder_watch_windows.cpp b/producer/event_monitor_producer/src/single_folder_watch_windows.cpp
new file mode 100644
index 000000000..e0c3300f4
--- /dev/null
+++ b/producer/event_monitor_producer/src/single_folder_watch_windows.cpp
@@ -0,0 +1,30 @@
+#include "single_folder_watch_windows.h"
+
+#include "eventmon_logger.h"
+namespace asapo {
+
+SingleFolderWatch::SingleFolderWatch(std::string root_folder, std::string folder) : watch_io__{new WatchIO()},
+                                                                                    log__{GetDefaultEventMonLogger()},
+                                                                                    root_folder_{std::move(root_folder)},
+                                                                                        folder_{std::move(folder)}
+                                                                                    {
+}
+
+Error SingleFolderWatch::Init()  {
+    std::string full_path = this->root_folder_ + kPathSeparator + this->folder_;
+    Error err;
+    handle_ = this->watch_io__->Init(full_path.c_str(), &err);
+    if (err) {
+        this->log__->Error("cannot add folder watch for "+full_path+": "+err->Explain());
+        return err;
+    }
+    return nullptr;
+}
+
+void SingleFolderWatch::Watch() {
+    if (!Init()) {
+        return;
+    }
+}
+
+}
diff --git a/producer/event_monitor_producer/src/single_folder_watch_windows.h b/producer/event_monitor_producer/src/single_folder_watch_windows.h
new file mode 100644
index 000000000..f2fef6262
--- /dev/null
+++ b/producer/event_monitor_producer/src/single_folder_watch_windows.h
@@ -0,0 +1,26 @@
+#ifndef ASAPO_SINGLE_FOLDER_MONITOR_H
+#define ASAPO_SINGLE_FOLDER_MONITOR_H
+
+#include <string>
+
+#include "watch_io.h"
+#include "logger/logger.h"
+
+namespace asapo {
+
+class SingleFolderWatch {
+  public:
+    explicit SingleFolderWatch(std::string root_folder,std::string folder);
+    void Watch();
+    std::unique_ptr<WatchIO> watch_io__;
+    const AbstractLogger* log__;
+ private:
+  std::string root_folder_;
+  std::string folder_;
+  Error Init();
+  HANDLE handle_;
+};
+
+}
+
+#endif //ASAPO_SINGLE_FOLDER_MONITOR_H
diff --git a/producer/event_monitor_producer/src/system_folder_watch_windows.cpp b/producer/event_monitor_producer/src/system_folder_watch_windows.cpp
index 7c9367877..0157164d9 100644
--- a/producer/event_monitor_producer/src/system_folder_watch_windows.cpp
+++ b/producer/event_monitor_producer/src/system_folder_watch_windows.cpp
@@ -4,7 +4,7 @@
 #include <memory>
 
 #include "io/io_factory.h"
-#include "single_folder_monitor.h"
+#include "single_folder_watch_windows.h"
 
 namespace asapo {
 
@@ -12,24 +12,15 @@ Error SystemFolderWatch::StartFolderMonitor(const std::string& root_folder,
                                             const std::vector<std::string>& monitored_folders) {
     for (auto& folder:monitored_folders ) {
     auto thread = io__->NewThread([root_folder, folder] {
-      auto folder_monitor = std::unique_ptr<SingleFolderMonitor>(new SingleFolderMonitor(root_folder, folder));
-      folder_monitor->Monitor();
+      auto folder_watch = std::unique_ptr<SingleFolderWatch>(new SingleFolderWatch(root_folder, folder));
+      folder_watch->Watch();
     });
 
     if (thread) {
         thread->detach();
     }
     }
-/*
-    HANDLE hDir = CreateFile(
-        root_folder.c_str(),
-        FILE_LIST_DIRECTORY,
-        FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
-        NULL,
-        OPEN_EXISTING,
-        FILE_FLAG_BACKUP_SEMANTICS,
-        NULL);
-*/
+
     return nullptr;
 }
 
diff --git a/producer/event_monitor_producer/src/system_folder_watch_windows.h b/producer/event_monitor_producer/src/system_folder_watch_windows.h
index b4d936e30..a302b98a9 100644
--- a/producer/event_monitor_producer/src/system_folder_watch_windows.h
+++ b/producer/event_monitor_producer/src/system_folder_watch_windows.h
@@ -18,8 +18,8 @@ class SystemFolderWatch {
   SystemFolderWatch();
   VIRTUAL Error StartFolderMonitor(const std::string& root_folder,
                                      const std::vector<std::string>& monitored_folders);
-    VIRTUAL FilesToSend GetFileList(Error* err);
-    std::unique_ptr<IO> io__;
+  VIRTUAL FilesToSend GetFileList(Error* err);
+  std::unique_ptr<IO> io__;
   private:
 
 };
diff --git a/producer/event_monitor_producer/src/watch_io.cpp b/producer/event_monitor_producer/src/watch_io.cpp
new file mode 100644
index 000000000..d484a95b3
--- /dev/null
+++ b/producer/event_monitor_producer/src/watch_io.cpp
@@ -0,0 +1,24 @@
+#include "watch_io.h"
+#include "io/io_factory.h"
+namespace asapo {
+
+HANDLE WatchIO::Init(const char* folder, Error* err) {
+    HANDLE hDir = CreateFile(
+        folder,
+        FILE_LIST_DIRECTORY,
+        FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+        NULL,
+        OPEN_EXISTING,
+        FILE_FLAG_BACKUP_SEMANTICS,
+        NULL);
+    if (hDir == INVALID_HANDLE_VALUE ) {
+        *err = io_->GetLastError();
+    }
+    return hDir;
+}
+
+WatchIO::WatchIO() :io_{GenerateDefaultIO()}{
+
+}
+
+}
\ No newline at end of file
diff --git a/producer/event_monitor_producer/src/watch_io.h b/producer/event_monitor_producer/src/watch_io.h
new file mode 100644
index 000000000..aa60c7ee0
--- /dev/null
+++ b/producer/event_monitor_producer/src/watch_io.h
@@ -0,0 +1,22 @@
+#ifndef ASAPO_WATCH_IO_H
+#define ASAPO_WATCH_IO_H
+
+#include <windows.h>
+
+#include "preprocessor/definitions.h"
+#include "common/error.h"
+#include "io/io.h"
+
+namespace asapo {
+
+class WatchIO {
+ public:
+  explicit WatchIO();
+  VIRTUAL HANDLE Init(const char* folder, Error* err);
+ private:
+  std::unique_ptr<IO>io_;
+};
+
+}
+
+#endif //ASAPO_WATCH_IO_H
diff --git a/producer/event_monitor_producer/unittests/mock_watch_io.h b/producer/event_monitor_producer/unittests/mock_watch_io.h
new file mode 100644
index 000000000..dd08c057a
--- /dev/null
+++ b/producer/event_monitor_producer/unittests/mock_watch_io.h
@@ -0,0 +1,26 @@
+#ifndef ASAPO_MOCKSYSTEMFOLDERWATCH_H
+#define ASAPO_MOCKSYSTEMFOLDERWATCH_H
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "../src/watch_io.h"
+
+namespace asapo {
+
+class MockWatchIO : public WatchIO {
+  public:
+   HANDLE Init(const char* folder, Error* err) override {
+       ErrorInterface* error = nullptr;
+       auto handle = Init_t(folder,&error);
+       err->reset(error);
+       return handle;
+   }
+
+  MOCK_METHOD2(Init_t, HANDLE (const char* folder, ErrorInterface** err));
+};
+
+}
+
+
+#endif //ASAPO_MOCKSYSTEMFOLDERWATCH_H
diff --git a/producer/event_monitor_producer/unittests/test_single_folder_watch_windows.cpp b/producer/event_monitor_producer/unittests/test_single_folder_watch_windows.cpp
new file mode 100644
index 000000000..f7887c6f7
--- /dev/null
+++ b/producer/event_monitor_producer/unittests/test_single_folder_watch_windows.cpp
@@ -0,0 +1,107 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "../src/single_folder_watch_windows.h"
+#include "../src/event_monitor_error.h"
+#include "../src/common.h"
+
+#include "preprocessor/definitions.h"
+
+#include "unittests/MockIO.h"
+#include "unittests/MockLogger.h"
+
+#include "mock_watch_io.h"
+
+using ::testing::Return;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::SetArgReferee;
+using ::testing::SetArgPointee;
+using ::testing::Gt;
+using ::testing::Eq;
+using ::testing::Ne;
+using ::testing::Mock;
+using ::testing::InSequence;
+using ::testing::HasSubstr;
+using testing::StrEq;
+
+using ::asapo::Error;
+using ::asapo::ErrorInterface;
+using asapo::FilesToSend;
+using asapo::SingleFolderWatch;
+using asapo::FileInfos;
+using asapo::FileInfo;
+
+namespace {
+
+
+TEST(SingleFolderWatch, Constructor) {
+    SingleFolderWatch watch{"",""};
+    ASSERT_THAT(dynamic_cast<asapo::WatchIO*>(watch.watch_io__.get()), Ne(nullptr));
+}
+
+FileInfos CreateTestFileInfos() {
+    FileInfos file_infos;
+    FileInfo fi;
+    fi.size = 100;
+    fi.name = "file1";
+    file_infos.push_back(fi);
+    fi.name = "subfolder/file2";
+    file_infos.push_back(fi);
+    return file_infos;
+}
+
+
+class SingleFolderWatchTests : public testing::Test {
+  public:
+    Error err;
+    ::testing::NiceMock<asapo::MockWatchIO> mock_watch_io;
+    testing::NiceMock<asapo::MockLogger> mock_logger;
+    std::string expected_root_folder = "c:\\tmp";
+    std::string expected_folder{"test1"};
+    HANDLE expected_handle = HANDLE(1);
+    SingleFolderWatch watch{expected_root_folder,expected_folder};
+    void SetUp() override {
+        watch.watch_io__ = std::unique_ptr<asapo::WatchIO> {&mock_watch_io};
+        watch.log__ = &mock_logger;
+    }
+    void TearDown() override {
+        watch.watch_io__.release();
+    }
+};
+
+
+TEST_F(SingleFolderWatchTests, InitWatchOnWatch) {
+    EXPECT_CALL(mock_watch_io, Init_t(StrEq(expected_root_folder+asapo::kPathSeparator+expected_folder),_)).
+        WillOnce(DoAll(
+        SetArgPointee<1>(nullptr),
+        Return(expected_handle)
+                 )
+    );
+
+    watch.Watch();
+}
+
+TEST_F(SingleFolderWatchTests, InitErrorOnWatch) {
+    EXPECT_CALL(mock_watch_io, Init_t(StrEq(expected_root_folder+asapo::kPathSeparator+expected_folder),_)).
+        WillOnce(DoAll(
+        SetArgPointee<1>(asapo::IOErrorTemplates::kFileNotFound.Generate().release()),
+        Return(INVALID_HANDLE_VALUE)
+                 )
+    );
+
+    EXPECT_CALL(mock_logger, Error(AllOf(
+        HasSubstr("cannot add"),
+        HasSubstr(expected_root_folder),
+        HasSubstr(expected_folder),
+        HasSubstr("file")
+       )
+    ));
+
+    watch.Watch();
+}
+
+
+
+
+}
\ No newline at end of file
-- 
GitLab