diff --git a/3d_party/rapidjson/include/rapidjson/reader.h b/3d_party/rapidjson/include/rapidjson/reader.h index 206b261417b9bc15594fec165685339123b639c0..9b28b268530ca29101b4e351fd4228899a223e4e 100644 --- a/3d_party/rapidjson/include/rapidjson/reader.h +++ b/3d_party/rapidjson/include/rapidjson/reader.h @@ -1223,8 +1223,7 @@ class GenericReader { } i = i * 10 + static_cast<unsigned>(s.TakePush() - '0'); significandDigit++; - } - else + } else while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { @@ -1265,8 +1264,7 @@ class GenericReader { } i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0'); significandDigit++; - } - else + } else while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { diff --git a/common/cpp/include/common/error.h b/common/cpp/include/common/error.h index e4602afd5a948194d8d7eb2214a6c40d69945c15..71c32b6e80c816d207bb6639952419c70d67e7de 100644 --- a/common/cpp/include/common/error.h +++ b/common/cpp/include/common/error.h @@ -146,11 +146,11 @@ inline Error TextErrorWithType(const std::string& error, ErrorType error_type) { namespace ErrorTemplates { auto const kMemoryAllocationError = SimpleErrorTemplate { - "kMemoryAllocationError", ErrorType::kMemoryAllocationError -}; + "kMemoryAllocationError", ErrorType::kMemoryAllocationError + }; auto const kEndOfFile = SimpleErrorTemplate { - "End of file", ErrorType::kEndOfFile -}; + "End of file", ErrorType::kEndOfFile + }; } diff --git a/common/cpp/include/common/io_error.h b/common/cpp/include/common/io_error.h index 40c9d4dd7e2c62ad73531d0a4aa18ebbbdeff2d0..db3606b3b0a8ea5276a1489fc1b703168f96b379 100644 --- a/common/cpp/include/common/io_error.h +++ b/common/cpp/include/common/io_error.h @@ -72,68 +72,68 @@ static inline std::ostream& operator<<(std::ostream& os, const IOErrorTemplate& namespace IOErrorTemplates { auto const kUnknownIOError = IOErrorTemplate { - "Unknown Error", IOErrorType::kUnknownIOError -}; + "Unknown Error", IOErrorType::kUnknownIOError + }; auto const kFileNotFound = IOErrorTemplate { - "No such file or directory", IOErrorType::kFileNotFound -}; + "No such file or directory", IOErrorType::kFileNotFound + }; auto const kReadError = IOErrorTemplate { - "Read error", IOErrorType::kReadError -}; + "Read error", IOErrorType::kReadError + }; auto const kBadFileNumber = IOErrorTemplate { - "Bad file number", IOErrorType::kBadFileNumber -}; + "Bad file number", IOErrorType::kBadFileNumber + }; auto const kResourceTemporarilyUnavailable = IOErrorTemplate { - "Resource temporarily unavailable", IOErrorType::kResourceTemporarilyUnavailable -}; + "Resource temporarily unavailable", IOErrorType::kResourceTemporarilyUnavailable + }; auto const kPermissionDenied = IOErrorTemplate { - "Permission denied", IOErrorType::kPermissionDenied -}; + "Permission denied", IOErrorType::kPermissionDenied + }; auto const kUnsupportedAddressFamily = IOErrorTemplate { - "Unsupported address family", IOErrorType::kUnsupportedAddressFamily -}; + "Unsupported address family", IOErrorType::kUnsupportedAddressFamily + }; auto const kInvalidAddressFormat = IOErrorTemplate { - "Invalid address format", IOErrorType::kInvalidAddressFormat -}; + "Invalid address format", IOErrorType::kInvalidAddressFormat + }; auto const kAddressAlreadyInUse = IOErrorTemplate { - "Address already in use", IOErrorType::kAddressAlreadyInUse -}; + "Address already in use", IOErrorType::kAddressAlreadyInUse + }; auto const kConnectionRefused = IOErrorTemplate { - "Connection refused", IOErrorType::kConnectionRefused -}; + "Connection refused", IOErrorType::kConnectionRefused + }; auto const kConnectionResetByPeer = IOErrorTemplate { - "kConnectionResetByPeer", IOErrorType::kConnectionResetByPeer -}; + "kConnectionResetByPeer", IOErrorType::kConnectionResetByPeer + }; auto const kTimeout = IOErrorTemplate { - "kTimeout", IOErrorType::kTimeout -}; + "kTimeout", IOErrorType::kTimeout + }; auto const kFileAlreadyExists = IOErrorTemplate { - "kFileAlreadyExists", IOErrorType::kFileAlreadyExists -}; + "kFileAlreadyExists", IOErrorType::kFileAlreadyExists + }; auto const kNoSpaceLeft = IOErrorTemplate { - "kNoSpaceLeft", IOErrorType::kNoSpaceLeft -}; + "kNoSpaceLeft", IOErrorType::kNoSpaceLeft + }; auto const kSocketOperationOnNonSocket = IOErrorTemplate { - "kSocketOperationOnNonSocket", IOErrorType::kSocketOperationOnNonSocket -}; + "kSocketOperationOnNonSocket", IOErrorType::kSocketOperationOnNonSocket + }; auto const kInvalidMemoryAddress = IOErrorTemplate { - "kInvalidMemoryAddress", IOErrorType::kInvalidMemoryAddress -}; + "kInvalidMemoryAddress", IOErrorType::kInvalidMemoryAddress + }; auto const kUnableToResolveHostname = IOErrorTemplate { - "kUnableToResolveHostname", IOErrorType::kUnableToResolveHostname -}; + "kUnableToResolveHostname", IOErrorType::kUnableToResolveHostname + }; auto const kSocketOperationUnknownAtLevel = IOErrorTemplate { - "kSocketOperationUnknownAtLevel", IOErrorType::kSocketOperationUnknownAtLevel -}; + "kSocketOperationUnknownAtLevel", IOErrorType::kSocketOperationUnknownAtLevel + }; auto const kSocketOperationValueOutOfBound = IOErrorTemplate { - "kSocketOperationValueOutOfBound", IOErrorType::kSocketOperationValueOutOfBound -}; + "kSocketOperationValueOutOfBound", IOErrorType::kSocketOperationValueOutOfBound + }; auto const kAddressNotValid = IOErrorTemplate { - "Address not valid", IOErrorType::kAddressNotValid -}; + "Address not valid", IOErrorType::kAddressNotValid + }; } diff --git a/common/cpp/include/unittests/MockDatabase.h b/common/cpp/include/unittests/MockDatabase.h new file mode 100644 index 0000000000000000000000000000000000000000..b1bb10efc1915a9707f7b30fa85585673fc72f37 --- /dev/null +++ b/common/cpp/include/unittests/MockDatabase.h @@ -0,0 +1,37 @@ +#ifndef HIDRA2_MOCKDATABASE_H +#define HIDRA2_MOCKDATABASE_H + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "database/database.h" +#include "common/error.h" + +namespace hidra2 { + +class MockDatabase : public Database { + public: + Error Connect(const std::string& address, const std::string& database, + const std::string& collection ) override { + return Error{Connect_t(address, database, collection)}; + + } + Error Insert(const FileInfo& file, bool ignore_duplicates) const override { + return Error{Insert_t(file, ignore_duplicates)}; + } + + MOCK_METHOD3(Connect_t, SimpleError * (const std::string&, const std::string&, const std::string&)); + MOCK_CONST_METHOD2(Insert_t, SimpleError * (const FileInfo&, bool)); + + // stuff to test db destructor is called and avoid "uninteresting call" messages + MOCK_METHOD0(Die, void()); + virtual ~MockDatabase() override { + if (check_destructor) + Die(); + } + bool check_destructor{false}; +}; + +} + +#endif //HIDRA2_MOCKDATABASE_H diff --git a/common/cpp/src/http_client/CMakeLists.txt b/common/cpp/src/http_client/CMakeLists.txt index b274c9319e20e484c12d9f22f8668fda3f6a39f9..42e3f0659a252680128db9bf06b3c731f290ec05 100644 --- a/common/cpp/src/http_client/CMakeLists.txt +++ b/common/cpp/src/http_client/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME curl_http_client) set(SOURCE_FILES curl_http_client.cpp - ) + ../../include/unittests/MockDatabase.h) ################################ diff --git a/producer/api/include/producer/producer_error.h b/producer/api/include/producer/producer_error.h index cdcf69a742ad54dd6d248f654e56953ce6faf701..decf910834fe976b84b787e61e476bb22e17c8e1 100644 --- a/producer/api/include/producer/producer_error.h +++ b/producer/api/include/producer/producer_error.h @@ -53,23 +53,23 @@ class ProducerErrorTemplate : public SimpleErrorTemplate { namespace ProducerErrorTemplates { auto const kAlreadyConnected = ProducerErrorTemplate { - "Already connected", ProducerErrorType::kAlreadyConnected -}; + "Already connected", ProducerErrorType::kAlreadyConnected + }; auto const kConnectionNotReady = ProducerErrorTemplate { - "Connection not ready", ProducerErrorType::kConnectionNotReady -}; + "Connection not ready", ProducerErrorType::kConnectionNotReady + }; auto const kFileTooLarge = ProducerErrorTemplate { - "File too large", ProducerErrorType::kFileTooLarge -}; + "File too large", ProducerErrorType::kFileTooLarge + }; auto const kFileIdAlreadyInUse = ProducerErrorTemplate { - "File already in use", ProducerErrorType::kFileIdAlreadyInUse -}; + "File already in use", ProducerErrorType::kFileIdAlreadyInUse + }; auto const kUnknownServerError = ProducerErrorTemplate { - "Unknown server error", ProducerErrorType::kUnknownServerError -}; + "Unknown server error", ProducerErrorType::kUnknownServerError + }; }; diff --git a/receiver/CMakeLists.txt b/receiver/CMakeLists.txt index 6f5ee995cbb7c61e4178e5c3687602836b493292..a5d795a7ccf763b0735c11fc5c603bc6df582889 100644 --- a/receiver/CMakeLists.txt +++ b/receiver/CMakeLists.txt @@ -7,7 +7,8 @@ set(SOURCE_FILES src/request_handler_file_write.cpp src/statistics.cpp src/statistics_sender_influx_db.cpp - src/receiver_config.cpp src/receiver_config.h) + src/receiver_config.cpp + src/request_handler_db_write.cpp) ################################ @@ -19,7 +20,7 @@ add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:system_io> $< $<TARGET_OBJECTS:json_parser>) set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX) target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR} ${CURL_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(${TARGET_NAME} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} database) add_executable(${TARGET_NAME}-bin src/main.cpp) @@ -38,7 +39,9 @@ set(TEST_SOURCE_FILES unittests/test_statistics.cpp unittests/test_config.cpp unittests/test_request.cpp + unittests/test_request_factory.cpp unittests/test_request_handler_file_write.cpp + unittests/test_request_handler_db_writer.cpp unittests/test_statistics_sender_influx_db.cpp unittests/mock_receiver_config.cpp ) diff --git a/receiver/src/receiver_config.cpp b/receiver/src/receiver_config.cpp index ba4e4b250daea114344e47c6c8c6a300e9f6ab0d..984218ee0b60eef9f854962db0ff116a2d223396 100644 --- a/receiver/src/receiver_config.cpp +++ b/receiver/src/receiver_config.cpp @@ -17,6 +17,10 @@ Error ReceiverConfigFactory::SetConfigFromFile(std::string file_name) { (err = parser.GetString("MonitorDbAddress", &config.monitor_db_uri)) || (err = parser.GetUInt64("ListenPort", &config.listen_port)) || (err = parser.GetBool("WriteToDisk", &config.write_to_disk)) || + (err = parser.GetBool("WriteToDb", &config.write_to_db)) || + (err = parser.GetString("BrokerDbAddress", &config.broker_db_uri)) || + (err = parser.GetString("BrokerDbName", &config.broker_db_name)) || + (err = parser.GetString("MonitorDbName", &config.monitor_db_name)); return err; } diff --git a/receiver/src/receiver_config.h b/receiver/src/receiver_config.h index f0aa92adf8e6317c698f2a5621de6407ad25d4c2..e348dc704ea13276fe16da498c92d3710a134969 100644 --- a/receiver/src/receiver_config.h +++ b/receiver/src/receiver_config.h @@ -9,8 +9,12 @@ namespace hidra2 { struct ReceiverConfig { std::string monitor_db_uri; std::string monitor_db_name; + std::string broker_db_uri; + std::string broker_db_name; uint64_t listen_port = 0; bool write_to_disk = false; + bool write_to_db = false; + }; const ReceiverConfig* GetReceiverConfig(); diff --git a/receiver/src/receiver_error.h b/receiver/src/receiver_error.h index 42eb039d8e5720e23a98dfded74973b788233235..63da34f6fe47518ca7d55278a47e82b0f302d7ed 100644 --- a/receiver/src/receiver_error.h +++ b/receiver/src/receiver_error.h @@ -50,11 +50,11 @@ class ReceiverErrorTemplate : public SimpleErrorTemplate { namespace ReceiverErrorTemplates { auto const kInvalidOpCode = ReceiverErrorTemplate { - "Invalid Opcode", ReceiverErrorType::kInvalidOpCode -}; + "Invalid Opcode", ReceiverErrorType::kInvalidOpCode + }; auto const kBadRequest = ReceiverErrorTemplate { - "Bad request", ReceiverErrorType::kBadRequest -}; + "Bad request", ReceiverErrorType::kBadRequest + }; }; } diff --git a/receiver/src/request.cpp b/receiver/src/request.cpp index 19ac5ca8a7dfd394f652412dcdb56e069ae0b54c..30862496da685bada5aff6ad2e456bc284e9adcb 100644 --- a/receiver/src/request.cpp +++ b/receiver/src/request.cpp @@ -60,6 +60,11 @@ void Request::AddHandler(const RequestHandler* handler) { } +uint64_t Request::GetDataID() const { + return request_header_.data_id; +} + + uint64_t Request::GetDataSize() const { return request_header_.data_size; } @@ -72,7 +77,6 @@ std::string Request::GetFileName() const { return std::to_string(request_header_.data_id) + ".bin"; } - std::unique_ptr<Request> RequestFactory::GenerateRequest(const GenericNetworkRequestHeader& request_header, SocketDescriptor socket_fd, Error* err) const noexcept { @@ -80,16 +84,22 @@ std::unique_ptr<Request> RequestFactory::GenerateRequest(const GenericNetworkReq switch (request_header.op_code) { case Opcode::kNetOpcodeSendData: { auto request = std::unique_ptr<Request> {new Request{request_header, socket_fd}}; + if (GetReceiverConfig()->write_to_disk) { request->AddHandler(&request_handler_filewrite_); } + + if (GetReceiverConfig()->write_to_db) { + request->AddHandler(&request_handler_dbwrite_); + } + return request; } default: *err = ReceiverErrorTemplates::kInvalidOpCode.Generate(); return nullptr; } - } + } \ No newline at end of file diff --git a/receiver/src/request.h b/receiver/src/request.h index b32a9e580401fa666c3fbcc404f03c68f8fb8ae8..5b297b83d2b5a67290495148bea62051d834e025 100644 --- a/receiver/src/request.h +++ b/receiver/src/request.h @@ -6,6 +6,7 @@ #include "io/io.h" #include "request_handler.h" #include "request_handler_file_write.h" +#include "request_handler_db_write.h" #include "statistics.h" namespace hidra2 { @@ -20,6 +21,7 @@ class Request { void AddHandler(const RequestHandler*); const RequestHandlerList& GetListHandlers() const; virtual uint64_t GetDataSize() const; + virtual uint64_t GetDataID() const; virtual std::string GetFileName() const; virtual const FileData& GetData() const; @@ -39,8 +41,10 @@ class RequestFactory { SocketDescriptor socket_fd, Error* err) const noexcept; private: RequestHandlerFileWrite request_handler_filewrite_; + RequestHandlerDbWrite request_handler_dbwrite_; }; } #endif //HIDRA2_REQUEST_H + diff --git a/receiver/src/request_handler_db_write.cpp b/receiver/src/request_handler_db_write.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b3b73bfb0d8d8f47ca9ae73630ca802c45fa558d --- /dev/null +++ b/receiver/src/request_handler_db_write.cpp @@ -0,0 +1,43 @@ +#include "request_handler_db_write.h" +#include "request.h" +#include "receiver_config.h" + +namespace hidra2 { + +Error RequestHandlerDbWrite::ProcessRequest(const Request& request) const { + if (Error err = ConnectToDbIfNeeded() ) { + return err; + } + + FileInfo file_info; + file_info.name = request.GetFileName(); + file_info.size = request.GetDataSize(); + file_info.id = request.GetDataID(); + return db_client__->Insert(file_info, false); + +} + +RequestHandlerDbWrite::RequestHandlerDbWrite() { + DatabaseFactory factory; + Error err; + db_client__ = factory.Create(&err); +} + +StatisticEntity RequestHandlerDbWrite::GetStatisticEntity() const { + return StatisticEntity::kDatabase; +} + +Error RequestHandlerDbWrite::ConnectToDbIfNeeded() const { + if (!connected_to_db) { + Error err = db_client__->Connect(GetReceiverConfig()->broker_db_uri, GetReceiverConfig()->broker_db_name, + kDBCollectionName); + if (err) { + return err; + } + connected_to_db = true; + } + return nullptr; +} + + +} \ No newline at end of file diff --git a/receiver/src/request_handler_db_write.h b/receiver/src/request_handler_db_write.h new file mode 100644 index 0000000000000000000000000000000000000000..ddd57350abd5cb4bb35c6a20935c479dd252dbf0 --- /dev/null +++ b/receiver/src/request_handler_db_write.h @@ -0,0 +1,24 @@ +#ifndef HIDRA2_REQUEST_HANDLER_DB_WRITE_H +#define HIDRA2_REQUEST_HANDLER_DB_WRITE_H + +#include "request_handler.h" +#include "database/database.h" + +#include "io/io.h" + +namespace hidra2 { + +class RequestHandlerDbWrite final: public RequestHandler { + public: + RequestHandlerDbWrite(); + StatisticEntity GetStatisticEntity() const override; + Error ProcessRequest(const Request& request) const override; + std::unique_ptr<Database> db_client__; + private: + Error ConnectToDbIfNeeded() const; + mutable bool connected_to_db = false; +}; + +} + +#endif //HIDRA2_REQUEST_HANDLER_DB_WRITE_H diff --git a/receiver/unittests/mock_receiver_config.cpp b/receiver/unittests/mock_receiver_config.cpp index 7819fe13a934464ce8ddd2fbbb8f8abd90d7403c..c1d5108bfa7b5ac22a1605a03620aae5d5daa6dc 100644 --- a/receiver/unittests/mock_receiver_config.cpp +++ b/receiver/unittests/mock_receiver_config.cpp @@ -17,8 +17,12 @@ Error SetReceiverConfig (const ReceiverConfig& config) { auto config_string = std::string("{\"MonitorDbAddress\":") + "\"" + config.monitor_db_uri + "\""; config_string += "," + std::string("\"MonitorDbName\":") + "\"" + config.monitor_db_name + "\""; + config_string += "," + std::string("\"BrokerDbName\":") + "\"" + config.broker_db_name + "\""; + config_string += "," + std::string("\"BrokerDbAddress\":") + "\"" + config.broker_db_uri + "\""; config_string += "," + std::string("\"ListenPort\":") + std::to_string(config.listen_port); config_string += "," + std::string("\"WriteToDisk\":") + (config.write_to_disk ? "true" : "false"); + config_string += "," + std::string("\"WriteToDb\":") + (config.write_to_db ? "true" : "false"); + config_string += "}"; EXPECT_CALL(mock_io, ReadFileToString_t("fname", _)).WillOnce( diff --git a/receiver/unittests/test_config.cpp b/receiver/unittests/test_config.cpp index ea15cede3b0eb2ba3bb0511f4d3381ee575a1454..008b965a59949b4fdae28580caa528aea00996aa 100644 --- a/receiver/unittests/test_config.cpp +++ b/receiver/unittests/test_config.cpp @@ -53,7 +53,9 @@ TEST_F(ConfigTests, ReadSettings) { test_config.monitor_db_name = "db_test"; test_config.monitor_db_uri = "localhost:8086"; test_config.write_to_disk = true; - + test_config.write_to_db = true; + test_config.broker_db_uri = "localhost:27017"; + test_config.broker_db_name = "test"; auto err = hidra2::SetReceiverConfig(test_config); @@ -62,8 +64,11 @@ TEST_F(ConfigTests, ReadSettings) { ASSERT_THAT(err, Eq(nullptr)); ASSERT_THAT(config->monitor_db_uri, Eq("localhost:8086")); ASSERT_THAT(config->monitor_db_name, Eq("db_test")); + ASSERT_THAT(config->broker_db_uri, Eq("localhost:27017")); + ASSERT_THAT(config->broker_db_name, Eq("test")); ASSERT_THAT(config->listen_port, Eq(4200)); ASSERT_THAT(config->write_to_disk, true); + ASSERT_THAT(config->write_to_db, true); } diff --git a/receiver/unittests/test_request.cpp b/receiver/unittests/test_request.cpp index 1d1e175279e9c6f3a2588b6a014c48ad22f9969c..9a213b69bf16a9be2d3ab81055e220105191d574 100644 --- a/receiver/unittests/test_request.cpp +++ b/receiver/unittests/test_request.cpp @@ -6,6 +6,8 @@ #include "../src/request.h" #include "../src/request_handler.h" #include "../src/request_handler_file_write.h" +#include "../src/request_handler_db_write.h" +#include "database/database.h" #include "mock_statistics.h" #include "mock_receiver_config.h" @@ -40,7 +42,7 @@ using hidra2::StatisticEntity; using hidra2::ReceiverConfig; using hidra2::SetReceiverConfig; - +using hidra2::RequestFactory; namespace { @@ -58,47 +60,6 @@ class MockReqestHandler : public hidra2::RequestHandler { }; -class FactoryTests : public Test { - public: - hidra2::RequestFactory factory; - Error err{nullptr}; - GenericNetworkRequestHeader generic_request_header; - ReceiverConfig config; - void SetUp() override { - config.write_to_disk = true; - SetReceiverConfig(config); - } - void TearDown() override { - } -}; - -TEST_F(FactoryTests, ErrorOnWrongCode) { - generic_request_header.op_code = hidra2::Opcode::kNetOpcodeUnknownOp; - auto request = factory.GenerateRequest(generic_request_header, 1, &err); - - ASSERT_THAT(err, Ne(nullptr)); -} - -TEST_F(FactoryTests, ReturnsDataRequestOnkNetOpcodeSendDataCode) { - generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData; - auto request = factory.GenerateRequest(generic_request_header, 1, &err); - - ASSERT_THAT(err, Eq(nullptr)); - ASSERT_THAT(dynamic_cast<hidra2::Request*>(request.get()), Ne(nullptr)); - ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr)); -} - -TEST_F(FactoryTests, DoNotAddWriterIfNotWanted) { - generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData; - config.write_to_disk = false; - SetReceiverConfig(config); - - auto request = factory.GenerateRequest(generic_request_header, 1, &err); - ASSERT_THAT(err, Eq(nullptr)); - ASSERT_THAT(request->GetListHandlers().size(), Eq(0)); -} - - class RequestTests : public Test { public: @@ -212,6 +173,13 @@ TEST_F(RequestTests, GetDataIsNotNullptr) { } +TEST_F(RequestTests, GetDataID) { + auto id = request->GetDataID(); + + ASSERT_THAT(id, Eq(data_id_)); +} + + TEST_F(RequestTests, GetDataSize) { auto size = request->GetDataSize(); diff --git a/receiver/unittests/test_request_factory.cpp b/receiver/unittests/test_request_factory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec8b93855ee7104b04ed8b526f282b2806f7deb5 --- /dev/null +++ b/receiver/unittests/test_request_factory.cpp @@ -0,0 +1,106 @@ +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "unittests/MockIO.h" +#include "unittests/MockDatabase.h" +#include "../src/connection.h" +#include "../src/receiver_error.h" +#include "../src/request.h" +#include "../src/request_handler.h" +#include "../src/request_handler_file_write.h" +#include "../src/request_handler_db_write.h" +#include "database/database.h" + +#include "mock_statistics.h" +#include "mock_receiver_config.h" + + +using ::testing::Test; +using ::testing::Return; +using ::testing::_; +using ::testing::DoAll; +using ::testing::SetArgReferee; +using ::testing::Gt; +using ::testing::Eq; +using ::testing::Ne; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::InSequence; +using ::testing::SetArgPointee; +using ::hidra2::Error; +using ::hidra2::ErrorInterface; +using ::hidra2::GenericNetworkRequestHeader; +using ::hidra2::GenericNetworkResponse; +using ::hidra2::Opcode; +using ::hidra2::Connection; +using ::hidra2::MockIO; +using hidra2::Request; +using hidra2::MockStatistics; + +using hidra2::StatisticEntity; + +using hidra2::ReceiverConfig; +using hidra2::SetReceiverConfig; +using hidra2::RequestFactory; + +namespace { + + +class FactoryTests : public Test { + public: + RequestFactory factory; + Error err{nullptr}; + GenericNetworkRequestHeader generic_request_header; + ReceiverConfig config; + + void SetUp() override { + generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData; + config.write_to_disk = true; + config.write_to_db = true; + SetReceiverConfig(config); + } + void TearDown() override { + } +}; + +TEST_F(FactoryTests, ErrorOnWrongCode) { + generic_request_header.op_code = hidra2::Opcode::kNetOpcodeUnknownOp; + auto request = factory.GenerateRequest(generic_request_header, 1, &err); + + ASSERT_THAT(err, Ne(nullptr)); +} + +TEST_F(FactoryTests, ReturnsDataRequestOnkNetOpcodeSendDataCode) { + generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData; + auto request = factory.GenerateRequest(generic_request_header, 1, &err); + + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(dynamic_cast<hidra2::Request*>(request.get()), Ne(nullptr)); + ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr)); + ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerDbWrite*>(request->GetListHandlers().back()), Ne(nullptr)); +} + +TEST_F(FactoryTests, DoNotAddDiskWriterIfNotWanted) { + config.write_to_disk = false; + + SetReceiverConfig(config); + + auto request = factory.GenerateRequest(generic_request_header, 1, &err); + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(request->GetListHandlers().size(), Eq(1)); + ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerDbWrite*>(request->GetListHandlers().back()), Ne(nullptr)); +} + +TEST_F(FactoryTests, DoNotAddDbWriterIfNotWanted) { + config.write_to_db = false; + + SetReceiverConfig(config); + + auto request = factory.GenerateRequest(generic_request_header, 1, &err); + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(request->GetListHandlers().size(), Eq(1)); + ASSERT_THAT(dynamic_cast<const hidra2::RequestHandlerFileWrite*>(request->GetListHandlers()[0]), Ne(nullptr)); +} + + +} diff --git a/receiver/unittests/test_request_handler_db_writer.cpp b/receiver/unittests/test_request_handler_db_writer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..99075925a536429a92458a0c59bc1e731afbf040 --- /dev/null +++ b/receiver/unittests/test_request_handler_db_writer.cpp @@ -0,0 +1,194 @@ +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "unittests/MockIO.h" +#include "unittests/MockDatabase.h" + +#include "../src/receiver_error.h" +#include "../src/request.h" +#include "../src/request_handler.h" +#include "../src/request_handler_db_write.h" +#include "common/networking.h" +#include "../../common/cpp/src/database/mongodb_client.h" +#include "mock_receiver_config.h" +#include "common/data_structs.h" + + +using hidra2::FileInfo; +using ::testing::Test; +using ::testing::Return; +using ::testing::ReturnRef; +using ::testing::_; +using ::testing::DoAll; +using ::testing::SetArgReferee; +using ::testing::Gt; +using ::testing::Eq; +using ::testing::Ne; +using ::testing::Mock; +using ::testing::NiceMock; +using ::testing::InSequence; +using ::testing::SetArgPointee; +using ::hidra2::Error; +using ::hidra2::ErrorInterface; +using ::hidra2::FileDescriptor; +using ::hidra2::SocketDescriptor; +using ::hidra2::MockIO; +using hidra2::Request; +using hidra2::RequestHandlerDbWrite; +using ::hidra2::GenericNetworkRequestHeader; + +using hidra2::MockDatabase; +using hidra2::RequestFactory; +using hidra2::SetReceiverConfig; +using hidra2::ReceiverConfig; + + +namespace { + +class MockRequest: public Request { + public: + MockRequest(const GenericNetworkRequestHeader& request_header, SocketDescriptor socket_fd): + Request(request_header, socket_fd) {}; + + MOCK_CONST_METHOD0(GetFileName, std::string()); + MOCK_CONST_METHOD0(GetDataSize, uint64_t()); + MOCK_CONST_METHOD0(GetDataID, uint64_t()); + MOCK_CONST_METHOD0(GetData, const hidra2::FileData & ()); +}; + +class DbWriterHandlerTests : public Test { + public: + RequestHandlerDbWrite handler; + NiceMock<MockIO> mock_io; + std::unique_ptr<NiceMock<MockRequest>> mock_request; + NiceMock<MockDatabase> mock_db; + ReceiverConfig config; + void SetUp() override { + GenericNetworkRequestHeader request_header; + request_header.data_id = 2; + handler.db_client__ = std::unique_ptr<hidra2::Database> {&mock_db}; + mock_request.reset(new NiceMock<MockRequest> {request_header, 1}); + } + void TearDown() override { + handler.db_client__.release(); + } +}; + +TEST(DBWritewr, HandlerHasCorrectDbFactory) { + RequestHandlerDbWrite handler; + ASSERT_THAT(dynamic_cast<hidra2::MongoDBClient*>(handler.db_client__.get()), Ne(nullptr)); +} + + +TEST_F(DbWriterHandlerTests, CheckStatisticEntity) { + auto entity = handler.GetStatisticEntity(); + ASSERT_THAT(entity, Eq(hidra2::StatisticEntity::kDatabase)); +} + + +TEST_F(DbWriterHandlerTests, ProcessRequestCallsConnectDbWhenNotConnected) { + config.broker_db_name = "test"; + config.broker_db_uri = "127.0.0.1:27017"; + SetReceiverConfig(config); + + EXPECT_CALL(mock_db, Connect_t("127.0.0.1:27017", "test", hidra2::kDBCollectionName)). + WillOnce(testing::Return(nullptr)); + + auto err = handler.ProcessRequest(*mock_request); + ASSERT_THAT(err, Eq(nullptr)); +} + +TEST_F(DbWriterHandlerTests, ProcessRequestReturnsErrorWhenCannotConnect) { + + EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)). + WillOnce(testing::Return(new hidra2::SimpleError(""))); + + auto err = handler.ProcessRequest(*mock_request); + + ASSERT_THAT(err, Ne(nullptr)); + +} + + +TEST_F(DbWriterHandlerTests, ProcessRequestDoesNotCallConnectSecondTime) { + + EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)). + WillOnce(testing::Return(nullptr)); + + handler.ProcessRequest(*mock_request); + handler.ProcessRequest(*mock_request); +} + +MATCHER_P(CompareFileInfo, file, "") { + if (arg.size != file.size) return false; + if (arg.name != file.name) return false; + if (arg.id != file.id) return false; + + return true; +} + + + +TEST_F(DbWriterHandlerTests, CallsInsert) { + + EXPECT_CALL(mock_db, Connect_t(_, _, hidra2::kDBCollectionName)). + WillOnce(testing::Return(nullptr)); + + std::string expected_file_name = "2.bin"; + uint64_t expected_file_size = 10; + uint64_t expected_id = 15; + EXPECT_CALL(*mock_request, GetDataSize()) + .WillOnce(Return(expected_file_size)) + ; + + EXPECT_CALL(*mock_request, GetFileName()) + .WillOnce(Return(expected_file_name)) + ; + + EXPECT_CALL(*mock_request, GetDataID()) + .WillOnce(Return(expected_id)) + ; + + FileInfo file_info; + file_info.size = expected_file_size; + file_info.name = expected_file_name; + file_info.id = expected_id; + + + EXPECT_CALL(mock_db, Insert_t(CompareFileInfo(file_info), _)). + WillOnce(testing::Return(nullptr)); + + handler.ProcessRequest(*mock_request); +} + + +/* +TEST_F(DbWriterHandlerTests, CallsWriteFile) { + std::string expected_file_name = "2.bin"; + uint64_t expected_file_size = 10; + EXPECT_CALL(*mock_request, GetDataSize()) + .WillOnce(Return(expected_file_size)) + ; + + hidra2::FileData data; + EXPECT_CALL(*mock_request, GetData()) + .WillOnce(ReturnRef(data)) + ; + + EXPECT_CALL(*mock_request, GetFileName()) + .WillOnce(Return(expected_file_name)) + ; + + + EXPECT_CALL(mock_io, WriteDataToFile_t("files/" + expected_file_name, _, expected_file_size)) + .WillOnce( + Return(hidra2::IOErrorTemplates::kUnknownIOError.Generate().release()) + ); + + auto err = handler.ProcessRequest(*mock_request); + + ASSERT_THAT(err, Eq(hidra2::IOErrorTemplates::kUnknownIOError)); +} + +*/ +} \ No newline at end of file diff --git a/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt b/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt index 503b9e91b51343704ccd80b856da664d5c99aab7..3738e79d412d78df63f830582bb415c40510d043 100644 --- a/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt +++ b/tests/automatic/curl_http_client/curl_http_client_command/CMakeLists.txt @@ -19,7 +19,7 @@ target_link_libraries(${TARGET_NAME} test_common hidra2-worker) ################################ #add_test_setup_cleanup(${TARGET_NAME}) -add_integration_test(${TARGET_NAME} get_google "GET google.com moved 302") +add_integration_test(${TARGET_NAME} get_google "GET google.com moved 301") add_integration_test(${TARGET_NAME} get_badaddress "GET google.com/badaddress found 404") add_integration_test(${TARGET_NAME} get_badaddress2 "GET 111 clienterror 404") add_integration_test(${TARGET_NAME} post "POST httpbin.org/post testdata 200") diff --git a/tests/automatic/producer_receiver/check_monitoring/check_linux.sh b/tests/automatic/producer_receiver/check_monitoring/check_linux.sh index 3b4b82ec54b48718f5b00412ca0e9a83ddbbdd0e..5eeb022b926ff0efa59dbc3496a5af90c2749ef2 100644 --- a/tests/automatic/producer_receiver/check_monitoring/check_linux.sh +++ b/tests/automatic/producer_receiver/check_monitoring/check_linux.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash database_name=db_test +mongo_database_name=test_run set -e @@ -11,7 +12,7 @@ Cleanup() { influx -execute "drop database ${database_name}" kill $receiverid rm -rf files - + echo "db.dropDatabase()" | mongo ${mongo_database_name} } influx -execute "create database ${database_name}" diff --git a/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh b/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh index d7c69e6a25b6189b0d84220d635a15b386f29449..0c38e3337548bfc7f49630f374da1afc4482bf40 100644 --- a/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh +++ b/tests/automatic/producer_receiver/transfer_single_file/check_linux.sh @@ -4,10 +4,13 @@ set -e trap Cleanup EXIT +database_name=test_run + Cleanup() { echo cleanup rm -rf files kill $receiverid + echo "db.dropDatabase()" | mongo ${database_name} } nohup $2 receiver.json &>/dev/null & diff --git a/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat b/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat index ee15242cd4354e178f16d6e4059b635cf01b3db4..988e6881f534c81be333279ebf46f74481551822 100644 --- a/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat +++ b/tests/automatic/producer_receiver/transfer_single_file/check_windows.bat @@ -24,5 +24,8 @@ exit /b 1 :clean Taskkill /IM "%short_recv_name%" /F rmdir /S /Q files +SET database_name=test_run +SET mongo_exe="c:\Program Files\MongoDB\Server\3.6\bin\mongo.exe" +echo db.dropDatabase() | %mongo_exe% %database_name% diff --git a/tests/automatic/settings/receiver.json b/tests/automatic/settings/receiver.json index e23a556d1cd5a8c03ce0c32b37b7b73161bfa89d..5939e7d82c0811804e36472acafafa2b48d09f10 100644 --- a/tests/automatic/settings/receiver.json +++ b/tests/automatic/settings/receiver.json @@ -1,6 +1,9 @@ { "MonitorDbAddress":"localhost:8086", "MonitorDbName": "db_test", + "BrokerDbAddress":"localhost:27017", + "BrokerDbName": "test_run", "ListenPort":4200, - "WriteToDisk":true + "WriteToDisk":true, + "WriteToDb":true } \ No newline at end of file diff --git a/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp b/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp index cd9f6991b7b0284efe3761217db56baebeeb43fe..5746bce28e8ac7b1e2aba9199e1eefe8e85f690c 100644 --- a/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp +++ b/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp @@ -9,6 +9,7 @@ #include "database/database.h" #include "common/data_structs.h" +#include "unittests/MockDatabase.h" #include "../src/folder_db_importer.h" @@ -26,18 +27,7 @@ using ::testing::NiceMock; using ::testing::Ref; using ::testing::Return; -using hidra2::FolderToDbImporter; -using hidra2::Database; -using hidra2::DatabaseFactory; -using hidra2::IO; -using hidra2::kDBCollectionName; -using hidra2::FileInfos; -using hidra2::FileInfo; -using hidra2::MockIO; -using hidra2::Error; -using hidra2::TextError; -using hidra2::SimpleError; - +using namespace hidra2; namespace { @@ -45,12 +35,12 @@ namespace { TEST(FolderDBConverter, SetCorrectIO) { FolderToDbImporter converter{}; - ASSERT_THAT(dynamic_cast<hidra2::SystemIO*>(converter.io__.get()), Ne(nullptr)); + ASSERT_THAT(dynamic_cast<SystemIO*>(converter.io__.get()), Ne(nullptr)); } TEST(FolderDBConverter, SetCorrectDBFactory) { FolderToDbImporter converter{}; - ASSERT_THAT(dynamic_cast<hidra2::DatabaseFactory*>(converter.db_factory__.get()), Ne(nullptr)); + ASSERT_THAT(dynamic_cast<DatabaseFactory*>(converter.db_factory__.get()), Ne(nullptr)); } TEST(FolderDBConverter, SetNTasksCorrectly) { @@ -70,29 +60,6 @@ TEST(FolderDBConverter, SetNTasksCorrectly) { } -class MockDatabase : public Database { - public: - Error Connect(const std::string& address, const std::string& database, - const std::string& collection ) override { - return Error{Connect_t(address, database, collection)}; - - } - Error Insert(const FileInfo& file, bool ignore_duplicates) const override { - return Error{Insert_t(file, ignore_duplicates)}; - } - - MOCK_METHOD3(Connect_t, SimpleError * (const std::string&, const std::string&, const std::string&)); - MOCK_CONST_METHOD2(Insert_t, SimpleError * (const FileInfo&, bool)); - - // stuff to test db destructor is called and avoid "uninteresting call" messages - MOCK_METHOD0(Die, void()); - virtual ~MockDatabase() override { - if (check_destructor) - Die(); - } - bool check_destructor{false}; -}; - class MockDatabaseFactory : public DatabaseFactory { public: std::vector<NiceMock<MockDatabase>*> db;