diff --git a/producer/event_monitor_producer/src/common.h b/producer/event_monitor_producer/src/common.h new file mode 100644 index 0000000000000000000000000000000000000000..374caa9019adfbf04cf682eb9a8c65c2fceefded --- /dev/null +++ b/producer/event_monitor_producer/src/common.h @@ -0,0 +1,25 @@ +#ifndef ASAPO_EVENT_MONITOR_PRODUCER_COMMON_H +#define ASAPO_EVENT_MONITOR_PRODUCER_COMMON_H + +#include <cstdint> +#include <string> +#include <vector> + +namespace asapo { + +enum class EventType { + closed, + renamed_from +}; + +struct FileEvent { + EventType type; + uint64_t size; + std::string name; +}; + +using FileEvents = std::vector<FileEvent>; + +} + +#endif //ASAPO_EVENT_MONITOR_PRODUCER_COMMON_H diff --git a/producer/event_monitor_producer/src/event_detector.h b/producer/event_monitor_producer/src/event_detector.h index 0be06648e3c4b5edc8bbca45ec738c6034d4eab4..dd1b9ec8aee7cd0f3d73eb378b792725bfef82f3 100644 --- a/producer/event_monitor_producer/src/event_detector.h +++ b/producer/event_monitor_producer/src/event_detector.h @@ -2,13 +2,15 @@ #define ASAPO_EVENT_DETECTOR_H #include <memory> -#include "producer/common.h" +#include "asapo_producer.h" namespace asapo { class AbstractEventDetector { public: virtual Error GetNextEvent(EventHeader* event_header) = 0; + virtual Error StartMonitoring() = 0; + virtual ~AbstractEventDetector() = default; }; using EventDetector = std::unique_ptr<AbstractEventDetector>; diff --git a/producer/event_monitor_producer/src/event_monitor_error.h b/producer/event_monitor_producer/src/event_monitor_error.h new file mode 100644 index 0000000000000000000000000000000000000000..8b05cd8fdb772d1d99602f963eea4b2149f2c507 --- /dev/null +++ b/producer/event_monitor_producer/src/event_monitor_error.h @@ -0,0 +1,70 @@ +#ifndef ASAPO_EventMonitor_ERROR_H +#define ASAPO_EventMonitor_ERROR_H + +#include "common/error.h" + +namespace asapo { + +enum class EventMonitorErrorType { + kNoNewEvent, + kSystemError +}; + +class EventMonitorError : public SimpleError { + private: + EventMonitorErrorType error_type_; + public: + EventMonitorError(const std::string& error, EventMonitorErrorType error_type) : SimpleError(error, + ErrorType::kHidraError) { + error_type_ = error_type; + } + + EventMonitorErrorType GetEventMonitorErrorType() const noexcept { + return error_type_; + } +}; + +class EventMonitorErrorTemplate : public SimpleErrorTemplate { + protected: + EventMonitorErrorType error_type_; + public: + EventMonitorErrorTemplate(const std::string& error, EventMonitorErrorType error_type) : SimpleErrorTemplate(error, + ErrorType::kHidraError) { + error_type_ = error_type; + } + + inline EventMonitorErrorType GetEventMonitorErrorType() const noexcept { + return error_type_; + } + + inline Error Generate() const noexcept override { + return Error(new EventMonitorError(error_, error_type_)); + } + + inline bool operator==(const Error& rhs) const override { + return SimpleErrorTemplate::operator==(rhs) + && GetEventMonitorErrorType() == ((EventMonitorError*) rhs.get())->GetEventMonitorErrorType(); + } +}; + +static inline std::ostream& operator<<(std::ostream& os, const EventMonitorErrorTemplate& err) { + return os << err.Text(); +} + + +namespace EventMonitorErrorTemplates { +auto const kNoNewEvent = EventMonitorErrorTemplate { + "no new event", EventMonitorErrorType::kNoNewEvent +}; + +auto const kSystemError = EventMonitorErrorTemplate { + "system error", EventMonitorErrorType::kSystemError +}; + + + +}; +} + +#endif //ASAPO_EventMonitor_ERROR_H + diff --git a/producer/event_monitor_producer/src/eventmon_config.cpp b/producer/event_monitor_producer/src/eventmon_config.cpp index b5ac647a22eeb34269936398cb1914e948795fe3..66082225ff0a0e29806f0468369e6cd77834d0eb 100644 --- a/producer/event_monitor_producer/src/eventmon_config.cpp +++ b/producer/event_monitor_producer/src/eventmon_config.cpp @@ -20,6 +20,8 @@ Error EventMonConfigFactory::ParseConfigFile(std::string file_name) { (err = parser.GetString("Mode", &config.mode_str)) || (err = parser.GetUInt64("NThreads", &config.nthreads)) || (err = parser.GetString("LogLevel", &config.log_level_str)); + (err = parser.GetArrayString("MonitoredFolders", &config.monitored_folders)); + return err; } @@ -29,6 +31,7 @@ Error EventMonConfigFactory::CheckConfig() { (err = CheckMode()) || (err = CheckLogLevel()) || (err = CheckNThreads()); +//todo: check monitored folders exist? return err; } diff --git a/producer/event_monitor_producer/src/eventmon_config.h b/producer/event_monitor_producer/src/eventmon_config.h index ea3c6d1a291ce76335a990540a63b6a254e3a519..90f986fa2f4992fda71f9f0d6fd31c72a4350627 100644 --- a/producer/event_monitor_producer/src/eventmon_config.h +++ b/producer/event_monitor_producer/src/eventmon_config.h @@ -4,7 +4,7 @@ #include "io/io.h" #include "common/error.h" #include "logger/logger.h" -#include "producer/common.h" +#include "asapo_producer.h" #include "eventmon_config_factory.h" namespace asapo { @@ -16,6 +16,7 @@ struct EventMonConfig { uint64_t nthreads = 1; std::string beamtime_id; RequestHandlerType mode = RequestHandlerType::kTcp; + std::vector<std::string> monitored_folders; private: std::string log_level_str; std::string mode_str; diff --git a/producer/event_monitor_producer/src/eventmon_main.cpp b/producer/event_monitor_producer/src/eventmon_main.cpp index e2894cf9feeb831bb1b406584041fe60b12fd183..e8e8b1f1b59541a0b629cc7e554e1db2b69406dc 100644 --- a/producer/event_monitor_producer/src/eventmon_main.cpp +++ b/producer/event_monitor_producer/src/eventmon_main.cpp @@ -65,6 +65,11 @@ int main (int argc, char* argv[]) { asapo::EventDetectorFactory factory; auto event_detector = factory.CreateEventDetector(); + err = event_detector->StartMonitoring(); + if (err) { + return EXIT_FAILURE; + } + int i = 0; while (true && i < 1000) { asapo::EventHeader event_header; diff --git a/producer/event_monitor_producer/src/folder_event_detector.cpp b/producer/event_monitor_producer/src/folder_event_detector.cpp index 833d508b4f3c7aa23f9453262c83f134bae48f0b..ff62551caec7cd03831ccd6f46e2a77b86e779a7 100644 --- a/producer/event_monitor_producer/src/folder_event_detector.cpp +++ b/producer/event_monitor_producer/src/folder_event_detector.cpp @@ -1,15 +1,47 @@ #include "folder_event_detector.h" #include "io/io_factory.h" #include "eventmon_logger.h" +#include "event_monitor_error.h" namespace asapo { +FolderEventDetector::FolderEventDetector(const EventMonConfig* config) : system_folder_watch__{new SystemFolderWatch()}, +config_{config}{ +} + Error FolderEventDetector::GetNextEvent(EventHeader* event_header) { + if (!monitoring_started_) { + auto err = TextError("monitoring is not started yet"); + return err; + } + + Error err; + auto file_events = system_folder_watch__->GetFileEventList(&err); + if (err) { + return err; + } + if (file_events.size() == 0) { + return EventMonitorErrorTemplates::kNoNewEvent.Generate(); + } + + FileEvent file_event = file_events[0]; + event_header->file_size = file_event.size; + event_header->file_name = std::move(file_event.name); return nullptr; } -FolderEventDetector::FolderEventDetector(const EventMonConfig* config) : system_folder_watch__{new SystemFolderWatch()}, -log__{GetDefaultEventMonLogger()}, config_{config}{ +Error FolderEventDetector::StartMonitoring() { + if (monitoring_started_) { + return nullptr; + } + + auto err = system_folder_watch__->StartFolderMonitor(config_->monitored_folders); + if (err) { + return err; + } + + monitoring_started_ = true; + return nullptr; } } \ No newline at end of file diff --git a/producer/event_monitor_producer/src/folder_event_detector.h b/producer/event_monitor_producer/src/folder_event_detector.h index 1d0901e582c48b8529b7cf66e5752ea8ec6ba380..c6748aa69b1a65a49098f93a3b03aa5e3e668a4d 100644 --- a/producer/event_monitor_producer/src/folder_event_detector.h +++ b/producer/event_monitor_producer/src/folder_event_detector.h @@ -4,7 +4,6 @@ #include "event_detector.h" #include "eventmon_config.h" #include "io/io.h" -#include "logger/logger.h" #include "system_folder_watch.h" @@ -13,11 +12,12 @@ namespace asapo { class FolderEventDetector : public AbstractEventDetector { public: Error GetNextEvent(EventHeader* event_header) override; + Error StartMonitoring() override; FolderEventDetector(const EventMonConfig* config); std::unique_ptr<SystemFolderWatch> system_folder_watch__; - const AbstractLogger* log__; private: const EventMonConfig* config_; + bool monitoring_started_= false; }; } diff --git a/producer/event_monitor_producer/src/system_folder_watch_linux.cpp b/producer/event_monitor_producer/src/system_folder_watch_linux.cpp index 57291cf353d74f5d4c06fc8b314f05eb0d5f9a50..996c40e11eb9dbd4eb9543ba74def68ac41c3a21 100644 --- a/producer/event_monitor_producer/src/system_folder_watch_linux.cpp +++ b/producer/event_monitor_producer/src/system_folder_watch_linux.cpp @@ -2,4 +2,15 @@ namespace asapo { +Error SystemFolderWatch::StartFolderMonitor(const std::vector<std::string> &monitored_folders) { + return nullptr; +} + +FileEvents SystemFolderWatch::GetFileEventList(Error* err) { + FileEvents events; + *err = nullptr; + return events; +} + + } \ No newline at end of file diff --git a/producer/event_monitor_producer/src/system_folder_watch_linux.h b/producer/event_monitor_producer/src/system_folder_watch_linux.h index e948f1aa3d73c647c3d856d922d8b21bba4ae8fc..e7f64aca4643e9dbef0f174248ab50605ffb27f0 100644 --- a/producer/event_monitor_producer/src/system_folder_watch_linux.h +++ b/producer/event_monitor_producer/src/system_folder_watch_linux.h @@ -1,10 +1,20 @@ #ifndef ASAPO_SYSTEM_FOLDER_WATCH_LINUX_H #define ASAPO_SYSTEM_FOLDER_WATCH_LINUX_H +#include <vector> +#include <string> + +#include "common/error.h" +#include "preprocessor/definitions.h" +#include "asapo_producer.h" +#include "common.h" + namespace asapo { class SystemFolderWatch { - + public: + VIRTUAL Error StartFolderMonitor(const std::vector<std::string>& monitored_folders); + VIRTUAL FileEvents GetFileEventList(Error* err); }; } diff --git a/producer/event_monitor_producer/unittests/MockSystemFolderWatch.h b/producer/event_monitor_producer/unittests/MockSystemFolderWatch.h deleted file mode 100644 index e79d9951d532b7a4b2e790e75417255ce22248fe..0000000000000000000000000000000000000000 --- a/producer/event_monitor_producer/unittests/MockSystemFolderWatch.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ASAPO_MOCKSYSTEMFOLDERWATCH_H -#define ASAPO_MOCKSYSTEMFOLDERWATCH_H - -#include <gtest/gtest.h> -#include <gmock/gmock.h> - -#include "../src/system_folder_watch.h" - -namespace asapo { - -class MockSystemFolderWatch : public SystemFolderWatch { -}; - -} - - -#endif //ASAPO_MOCKSYSTEMFOLDERWATCH_H diff --git a/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp b/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp index ecf5a3d10fe3874856ebc49d37eac9f64a7d3a77..a031b4889b70c0a95f881a99bfb74f59ba70f980 100644 --- a/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp +++ b/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp @@ -48,6 +48,15 @@ Error SetFolderMonConfig (const EventMonConfig& config) { config_string += "," + std::string("\"Mode\":") + "\"" + mode + "\""; config_string += "," + std::string("\"NThreads\":") + std::to_string(config.nthreads); config_string += "," + std::string("\"LogLevel\":") + "\"" + log_level + "\""; + std::string mon_folders; + for (auto folder:config.monitored_folders) { + mon_folders+="\""+folder+"\""+","; + } + if (mon_folders.size()) { + mon_folders.pop_back(); + } + + config_string += "," + std::string("\"MonitoredFolders\":") + "[" + mon_folders + "]"; config_string += "," + std::string("\"Tag\":") + "\"" + config.tag + "\""; config_string += "," + std::string("\"AsapoEndpoint\":") + "\"" + config.asapo_endpoint + "\""; diff --git a/producer/event_monitor_producer/unittests/mock_system_folder_watch.h b/producer/event_monitor_producer/unittests/mock_system_folder_watch.h new file mode 100644 index 0000000000000000000000000000000000000000..92a696b3de1517ae6407d1920295bc53de6c293d --- /dev/null +++ b/producer/event_monitor_producer/unittests/mock_system_folder_watch.h @@ -0,0 +1,36 @@ +#ifndef ASAPO_MOCKSYSTEMFOLDERWATCH_H +#define ASAPO_MOCKSYSTEMFOLDERWATCH_H + +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "../src/system_folder_watch.h" +#include "io/io.h" + +namespace asapo { + +class MockSystemFolderWatch : public SystemFolderWatch { + public: + MOCK_METHOD1(StartFolderMonitor_t, ErrorInterface* (const std::vector<std::string>& monitored_folders)); + + Error StartFolderMonitor(const std::vector<std::string>& monitored_folders) override { + return Error{StartFolderMonitor_t(monitored_folders)}; + + } + + MOCK_METHOD1(GetFileEventList_t, FileEvents (ErrorInterface** error)); + + FileEvents GetFileEventList(Error* err) override { + ErrorInterface* error = nullptr; + auto data = GetFileEventList_t(&error); + err->reset(error); + return data; + }; + + +}; + +} + + +#endif //ASAPO_MOCKSYSTEMFOLDERWATCH_H diff --git a/producer/event_monitor_producer/unittests/test_eventmon_config.cpp b/producer/event_monitor_producer/unittests/test_eventmon_config.cpp index 779d7d9c1943eea48d19c4d3ebbaa3ff78d2b10a..7b65865eecc7ada780a27788c8808f52e3f28633 100644 --- a/producer/event_monitor_producer/unittests/test_eventmon_config.cpp +++ b/producer/event_monitor_producer/unittests/test_eventmon_config.cpp @@ -20,6 +20,8 @@ using ::testing::SaveArg; using ::testing::SaveArgPointee; using ::testing::InSequence; using ::testing::SetArgPointee; +using testing::ElementsAre; + using ::asapo::Error; using ::asapo::ErrorInterface; using ::asapo::FileDescriptor; @@ -54,7 +56,7 @@ TEST_F(ConfigTests, ReadSettingsOK) { test_config.beamtime_id = "test"; test_config.asapo_endpoint = "uri:001"; test_config.mode = asapo::RequestHandlerType::kTcp; - + test_config.monitored_folders={"test1","test2"}; auto err = asapo::SetFolderMonConfig(test_config); auto config = asapo::GetEventMonConfig(); @@ -66,6 +68,8 @@ TEST_F(ConfigTests, ReadSettingsOK) { ASSERT_THAT(config->beamtime_id, Eq("test")); ASSERT_THAT(config->asapo_endpoint, Eq("uri:001")); ASSERT_THAT(config->mode, Eq(asapo::RequestHandlerType::kTcp)); + ASSERT_THAT(config->monitored_folders, ElementsAre("test1","test2")); + } TEST_F(ConfigTests, ReadSettingsChecksNthreads) { diff --git a/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp b/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp index d8d0e2ff67f2eee280ddd1a5cda9f36266e750ce..868a9a6bbe4efce6e8df4b35dd6bdfa741d7efd8 100644 --- a/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp +++ b/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp @@ -2,11 +2,12 @@ #include <gmock/gmock.h> #include "../src/folder_event_detector.h" +#include "../src/event_monitor_error.h" +#include "../src/common.h" #include "unittests/MockIO.h" -#include "unittests/MockLogger.h" -#include "MockSystemFolderWatch.h" +#include "mock_system_folder_watch.h" @@ -26,6 +27,7 @@ using ::testing::HasSubstr; using ::asapo::Error; using ::asapo::FileDescriptor; using ::asapo::ErrorInterface; +using asapo::FileEvents; using asapo::FolderEventDetector; @@ -42,38 +44,124 @@ TEST(FolderEventDetector, Constructor) { class FolderEventDetectorTests : public testing::Test { public: Error err; - ::testing::NiceMock<asapo::MockLogger> mock_logger; ::testing::NiceMock<asapo::MockSystemFolderWatch> mock_system_folder_watch; asapo::EventMonConfig test_config; FolderEventDetector detector{&test_config}; std::vector<std::string> expected_folders{"test1","test2"}; void SetUp() override { -// test_config.expected_folders = expected_folders; + test_config.monitored_folders = expected_folders; err = nullptr; detector.system_folder_watch__ = std::unique_ptr<asapo::SystemFolderWatch> {&mock_system_folder_watch}; - detector.log__ = &mock_logger; } void TearDown() override { detector.system_folder_watch__.release(); } + void MockStartMonitoring(); + }; + +void FolderEventDetectorTests::MockStartMonitoring() { + EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders)) + .WillOnce( + Return(nullptr) + ); +} + + + +TEST_F(FolderEventDetectorTests, StartsFolderMonitoringOK) { + EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders)) + .WillOnce( + Return(nullptr) + ); + auto err = detector.StartMonitoring(); + ASSERT_THAT(err, Eq(nullptr)); +} + +TEST_F(FolderEventDetectorTests, StartFolderMonitoringInitiatesOnlyOnce) { + EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders)) + .WillOnce( + Return(nullptr) + ); + auto err = detector.StartMonitoring(); + ASSERT_THAT(err, Eq(nullptr)); + err = detector.StartMonitoring(); + ASSERT_THAT(err, Eq(nullptr)); +} + +TEST_F(FolderEventDetectorTests, StartFolderMonitoringReturnsError) { + EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders)) + .Times(2) + .WillOnce( + Return(asapo::ErrorTemplates::kMemoryAllocationError.Generate().release()) + ) + .WillOnce( + Return(nullptr) + ) + ; + auto err = detector.StartMonitoring(); + ASSERT_THAT(err, Ne(nullptr)); + err = detector.StartMonitoring(); + ASSERT_THAT(err, Eq(nullptr)); +} + +TEST_F(FolderEventDetectorTests, GetNextReturnsErrorIfMonitoringNotStarted) { + auto err = detector.GetNextEvent(nullptr); + ASSERT_THAT(err, Ne(nullptr)); +} + +TEST_F(FolderEventDetectorTests, GetNextCallsSystemGetNextFirstTimeNoEvents) { + MockStartMonitoring(); + asapo::EventHeader event_header; + EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)); -}; -TEST_F(FolderEventDetectorTests, GetNextEventCallsGetFolderEvents) { + detector.StartMonitoring(); -// EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders, receiver.kMaxUnacceptedConnectionsBacklog, _)) -// .WillOnce(DoAll( -// SetArgPointee<2>(asapo::IOErrorTemplates::kUnknownIOError.Generate().release()), -// Return(0) -// )); + auto err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(asapo::EventMonitorErrorTemplates::kNoNewEvent)); +} + +TEST_F(FolderEventDetectorTests, GetNextEventError) { + MockStartMonitoring(); + asapo::EventHeader event_header; + EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).WillOnce( + DoAll( + SetArgPointee<0>(asapo::EventMonitorErrorTemplates::kSystemError.Generate().release()), + Return(FileEvents{}) + )); - //EXPECT_CALL(mock_logger, Error(HasSubstr("prepare listener"))); -// ASSERT_THAT(err, Eq(asapo::IOErrorTemplates::kUnknownIOError)); + detector.StartMonitoring(); + + auto err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(asapo::EventMonitorErrorTemplates::kSystemError)); } + +TEST_F(FolderEventDetectorTests, GetNextEventOK) { + MockStartMonitoring(); + asapo::EventHeader event_header; + EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).WillOnce( + DoAll( + SetArgPointee<0>(nullptr), + Return(FileEvents{asapo::FileEvent{asapo::EventType::closed,10,"test"}}) + )); + + + + detector.StartMonitoring(); + + auto err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(nullptr)); + + ASSERT_THAT(event_header.file_name, Eq("test")); + ASSERT_THAT(event_header.file_size, Eq(10)); + +} + + }