From f515c1f3a3c576dd8a44475b72376f5c48addef6 Mon Sep 17 00:00:00 2001 From: Sergey Yakubov <sergey.yakubov@desy.de> Date: Fri, 5 Jan 2018 16:20:55 +0100 Subject: [PATCH] start working on convert tool --- CMakeLists.txt | 5 + common/cpp/include/common/file_info.h | 2 +- common/cpp/include/database/database.h | 24 ++++ common/cpp/include/database/mongo_database.h | 17 +++ common/cpp/include/system_wrappers/io.h | 8 +- .../cpp/include/system_wrappers/system_io.h | 8 +- common/cpp/include/unittests/MockIO.h | 55 +++++++++ common/cpp/src/system_io.cpp | 30 ++--- common/cpp/src/system_io_linux.cpp | 16 +-- common/cpp/src/system_io_windows.cpp | 28 ++--- .../read_file_content/read_file_content.cpp | 12 +- .../read_folder_content.cpp | 10 +- worker/api/cpp/src/folder_data_broker.cpp | 18 +-- .../api/cpp/unittests/test_folder_broker.cpp | 40 +++--- worker/tools/CMakeLists.txt | 2 + worker/tools/folder_to_db/CMakeLists.txt | 21 ++++ .../folder_to_db/src/FolderDBConverter.cpp | 55 +++++++++ .../folder_to_db/src/FolderDBConverter.h | 28 +++++ .../unittests/test_folder_to_db.cpp | 116 ++++++++++++++++++ 19 files changed, 409 insertions(+), 86 deletions(-) create mode 100644 common/cpp/include/database/database.h create mode 100644 common/cpp/include/database/mongo_database.h create mode 100644 common/cpp/include/unittests/MockIO.h create mode 100644 worker/tools/CMakeLists.txt create mode 100644 worker/tools/folder_to_db/CMakeLists.txt create mode 100644 worker/tools/folder_to_db/src/FolderDBConverter.cpp create mode 100644 worker/tools/folder_to_db/src/FolderDBConverter.h create mode 100644 worker/tools/folder_to_db/unittests/test_folder_to_db.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ee7afc36..eeade3b9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,11 @@ include(testing_cpp) add_subdirectory(producer/api) add_subdirectory(common/cpp) add_subdirectory(worker/api/cpp) + +if(BUILD_WORKER_TOOLS) + add_subdirectory(worker/tools) +endif() + IF(UNIX) add_subdirectory(receiver) ENDIF(UNIX) diff --git a/common/cpp/include/common/file_info.h b/common/cpp/include/common/file_info.h index 88bd4f4af..16031c85c 100644 --- a/common/cpp/include/common/file_info.h +++ b/common/cpp/include/common/file_info.h @@ -2,8 +2,8 @@ #define HIDRA2_FILE_INFO_H #include <cinttypes> -#include <memory> #include <chrono> +#include <memory> namespace hidra2 { diff --git a/common/cpp/include/database/database.h b/common/cpp/include/database/database.h new file mode 100644 index 000000000..40f908fcf --- /dev/null +++ b/common/cpp/include/database/database.h @@ -0,0 +1,24 @@ +#ifndef HIDRA2_DATABASE_H +#define HIDRA2_DATABASE_H + +#include <string> + +namespace hidra2 { + +enum class DBError { + kNoError, + kConnectionError +}; + +constexpr char kDBName[] = "data"; + +class Database { + public: + virtual DBError Connect(const std::string& address, const std::string& database, + const std::string& collection ) = 0; + virtual ~Database() = default; +}; + +} + +#endif //HIDRA2_DATABASE_H diff --git a/common/cpp/include/database/mongo_database.h b/common/cpp/include/database/mongo_database.h new file mode 100644 index 000000000..e9ec8be63 --- /dev/null +++ b/common/cpp/include/database/mongo_database.h @@ -0,0 +1,17 @@ +#ifndef HIDRA2_MONGO_DATABASE_H +#define HIDRA2_MONGO_DATABASE_H + +#include "database.h" + +namespace hidra2 { + +class MongoDB final: public Database { + public: + virtual DBError Connect(const std::string& address, const std::string& database, + const std::string& collection ) override {}; + virtual ~MongoDB() override {}; +}; + +} + +#endif //HIDRA2_MONGO_DATABASE_H diff --git a/common/cpp/include/system_wrappers/io.h b/common/cpp/include/system_wrappers/io.h index 88bb23570..f9df7cfae 100644 --- a/common/cpp/include/system_wrappers/io.h +++ b/common/cpp/include/system_wrappers/io.h @@ -11,7 +11,7 @@ namespace hidra2 { -enum class IOErrors { +enum class IOError { kNoError, kFileNotFound, kReadError, @@ -20,13 +20,13 @@ enum class IOErrors { kMemoryAllocationError }; -IOErrors IOErrorFromErrno(); +IOError IOErrorFromErrno(); class IO { public: - virtual FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept = 0; + virtual FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept = 0; virtual int open(const char* __file, int __oflag) const noexcept = 0; virtual int close(int __fd) const noexcept = 0; @@ -34,7 +34,7 @@ class IO { virtual int64_t write(int __fd, const void* __buf, size_t __n) const noexcept = 0; // this is not standard function - to be implemented differently in windows and linux - virtual std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const = 0; + virtual std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const = 0; }; } diff --git a/common/cpp/include/system_wrappers/system_io.h b/common/cpp/include/system_wrappers/system_io.h index 6c2c62646..f5ef95f04 100644 --- a/common/cpp/include/system_wrappers/system_io.h +++ b/common/cpp/include/system_wrappers/system_io.h @@ -7,16 +7,16 @@ namespace hidra2 { class SystemIO final : public IO { public: - FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept override; + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept override; int open(const char* __file, int __oflag) const noexcept override; int close(int __fd) const noexcept override; int64_t read(int __fd, void* buf, size_t count) const noexcept override; int64_t write(int __fd, const void* __buf, size_t __n) const noexcept override; - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override; + std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const override; private: - void ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept; + void ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOError* err) const noexcept; void CollectFileInformationRecursivly(const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) const; + std::vector<FileInfo>* files, IOError* err) const; }; } diff --git a/common/cpp/include/unittests/MockIO.h b/common/cpp/include/unittests/MockIO.h new file mode 100644 index 000000000..9c71d3236 --- /dev/null +++ b/common/cpp/include/unittests/MockIO.h @@ -0,0 +1,55 @@ +#ifndef HIDRA2_COMMON__MOCKIO_H +#define HIDRA2_COMMON__MOCKIO_H + +#include <gtest/gtest.h> +#include <gmock/gmock.h> + +#include "system_wrappers/io.h" + +namespace hidra2 { + +class MockIO : public IO { + public: + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept override { + return GetDataFromFile_t(fname, fsize, err); + } + int open(const char* __file, int __oflag) const noexcept override { + return open_t(__file, __oflag); + } + int close(int __fd) const noexcept override { + return close_t(__fd); + } + int64_t read(int __fd, void* buf, size_t count) const noexcept override { + return read_t(__fd, buf, count); + } + int64_t write(int __fd, const void* __buf, size_t __n) const noexcept override { + return write_t(__fd, __buf, __n); + } + MOCK_CONST_METHOD3(GetDataFromFile_t, + FileData(const std::string& fname, uint64_t fsize, IOError* err)); + MOCK_CONST_METHOD2(FilesInFolder, + std::vector<FileInfo>( + const std::string& folder, IOError + *err)); + + MOCK_CONST_METHOD3(read_t, + int64_t(int + __fd, void* buf, size_t + count)); + + MOCK_CONST_METHOD3(write_t, + int64_t(int + __fd, + const void* __buf, size_t + __n)); + + MOCK_CONST_METHOD2(open_t, + int(const char* __file, int __oflag)); + + MOCK_CONST_METHOD1(close_t, + int(int __fd)); +}; + +} + +#endif //HIDRA2_COMMON__MOCKIO_H \ No newline at end of file diff --git a/common/cpp/src/system_io.cpp b/common/cpp/src/system_io.cpp index 6ee383e0c..22780881e 100644 --- a/common/cpp/src/system_io.cpp +++ b/common/cpp/src/system_io.cpp @@ -9,27 +9,27 @@ namespace hidra2 { -IOErrors IOErrorFromErrno() { - IOErrors err; +IOError IOErrorFromErrno() { + IOError err; switch (errno) { case 0: - err = IOErrors::kNoError; + err = IOError::kNoError; break; case ENOENT: case ENOTDIR: - err = IOErrors::kFileNotFound; + err = IOError::kFileNotFound; break; case EACCES: - err = IOErrors::kPermissionDenied; + err = IOError::kPermissionDenied; break; default: - err = IOErrors::kUnknownError; + err = IOError::kUnknownError; break; } return err; } -void SystemIO::ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept { +void SystemIO::ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOError* err) const noexcept { uint64_t totalbytes = 0; int64_t readbytes = 0; do { @@ -38,34 +38,34 @@ void SystemIO::ReadWholeFile(int fd, uint8_t* array, uint64_t fsize, IOErrors* e } while (readbytes > 0 && totalbytes < fsize); if (totalbytes != fsize) { - *err = IOErrors::kReadError; + *err = IOError::kReadError; } } -FileData SystemIO::GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept { +FileData SystemIO::GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept { int fd = open(fname.c_str(), O_RDONLY); *err = IOErrorFromErrno(); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return nullptr; } uint8_t* data_array = nullptr; try { data_array = new uint8_t[fsize]; } catch (...) { - *err = IOErrors::kMemoryAllocationError; + *err = IOError::kMemoryAllocationError; return nullptr; } ReadWholeFile(fd, data_array, fsize, err); FileData data{data_array}; - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { close(fd); return nullptr; } close(fd); *err = IOErrorFromErrno(); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return nullptr; } @@ -86,10 +86,10 @@ void StripBasePath(const std::string& folder, std::vector<FileInfo>* file_list) } } -std::vector<FileInfo> SystemIO::FilesInFolder(const std::string& folder, IOErrors* err) const { +std::vector<FileInfo> SystemIO::FilesInFolder(const std::string& folder, IOError* err) const { std::vector<FileInfo> files{}; CollectFileInformationRecursivly(folder, &files, err); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return {}; } StripBasePath(folder, &files); diff --git a/common/cpp/src/system_io_linux.cpp b/common/cpp/src/system_io_linux.cpp index 3c1bc09bb..45452107b 100644 --- a/common/cpp/src/system_io_linux.cpp +++ b/common/cpp/src/system_io_linux.cpp @@ -46,7 +46,7 @@ void SetFileName(const string& path, const string& name, FileInfo* file_info) { file_info->base_name = name; } -struct stat FileStat(const string& fname, IOErrors* err) { +struct stat FileStat(const string& fname, IOError* err) { struct stat t_stat {}; int res = stat(fname.c_str(), &t_stat); if (res < 0) { @@ -55,13 +55,13 @@ struct stat FileStat(const string& fname, IOErrors* err) { return t_stat; } -FileInfo GetFileInfo(const string& path, const string& name, IOErrors* err) { +FileInfo GetFileInfo(const string& path, const string& name, IOError* err) { FileInfo file_info; SetFileName(path, name, &file_info); auto t_stat = FileStat(path + "/" + name, err); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return FileInfo{}; } @@ -73,15 +73,15 @@ FileInfo GetFileInfo(const string& path, const string& name, IOErrors* err) { } void ProcessFileEntity(const struct dirent* entity, const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) { + std::vector<FileInfo>* files, IOError* err) { - *err = IOErrors::kNoError; + *err = IOError::kNoError; if (entity->d_type != DT_REG) { return; } FileInfo file_info = GetFileInfo(path, entity->d_name, err); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return; } @@ -89,7 +89,7 @@ void ProcessFileEntity(const struct dirent* entity, const std::string& path, } void SystemIO::CollectFileInformationRecursivly(const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) const { + std::vector<FileInfo>* files, IOError* err) const { auto dir = opendir((path).c_str()); if (dir == nullptr) { *err = IOErrorFromErrno(); @@ -103,7 +103,7 @@ void SystemIO::CollectFileInformationRecursivly(const std::string& path, } else { ProcessFileEntity(current_entity, path, files, err); } - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { closedir(dir); return; } diff --git a/common/cpp/src/system_io_windows.cpp b/common/cpp/src/system_io_windows.cpp index 5653ce87c..ed1d3752e 100644 --- a/common/cpp/src/system_io_windows.cpp +++ b/common/cpp/src/system_io_windows.cpp @@ -12,27 +12,27 @@ using std::chrono::system_clock; namespace hidra2 { -IOErrors IOErrorFromGetLastError() { - IOErrors err; +IOError IOErrorFromGetLastError() { + IOError err; switch (GetLastError()) { case ERROR_SUCCESS : - err = IOErrors::kNoError; + err = IOError::kNoError; break; case ERROR_PATH_NOT_FOUND: case ERROR_FILE_NOT_FOUND: - err = IOErrors::kFileNotFound; + err = IOError::kFileNotFound; break; case ERROR_ACCESS_DENIED: - err = IOErrors::kPermissionDenied; + err = IOError::kPermissionDenied; break; default: - err = IOErrors::kUnknownError; + err = IOError::kUnknownError; break; } return err; } -std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, IOErrors* err) { +std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, IOError* err) { SYSTEMTIME st = {0}; if (!FileTimeToSystemTime(&ft, &st)) { *err = IOErrorFromGetLastError(); @@ -48,7 +48,7 @@ std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, IOE auto tp = std::chrono::system_clock::from_time_t(secs); tp += ms; - *err = IOErrors::kNoError; + *err = IOError::kNoError; return tp; } @@ -59,16 +59,16 @@ bool IsDirectory(const WIN32_FIND_DATA f) { } void ProcessFileEntity(const WIN32_FIND_DATA f, const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) { + std::vector<FileInfo>* files, IOError* err) { - *err = IOErrors::kNoError; + *err = IOError::kNoError; if (f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { return; } FileInfo file_info; file_info.modify_date = FileTime2TimePoint(f.ftLastWriteTime, err); - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { return; } @@ -79,7 +79,7 @@ void ProcessFileEntity(const WIN32_FIND_DATA f, const std::string& path, void SystemIO::CollectFileInformationRecursivly(const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) const { + std::vector<FileInfo>* files, IOError* err) const { WIN32_FIND_DATA find_data; HANDLE handle = FindFirstFile((path + "\\*.*").c_str(), &find_data); if (handle == INVALID_HANDLE_VALUE) { @@ -93,14 +93,14 @@ void SystemIO::CollectFileInformationRecursivly(const std::string& path, } else { ProcessFileEntity(find_data, path, files, err); } - if (*err != IOErrors::kNoError) { + if (*err != IOError::kNoError) { FindClose(handle); return; } } while (FindNextFile(handle, &find_data)); if (FindClose(handle)) { - *err = IOErrors ::kNoError; + *err = IOError ::kNoError; } else { *err = IOErrorFromGetLastError(); } diff --git a/tests/system_io/read_file_content/read_file_content.cpp b/tests/system_io/read_file_content/read_file_content.cpp index 7853299e7..ab0ecc130 100644 --- a/tests/system_io/read_file_content/read_file_content.cpp +++ b/tests/system_io/read_file_content/read_file_content.cpp @@ -4,7 +4,7 @@ #include "testing.h" using hidra2::SystemIO; -using hidra2::IOErrors; +using hidra2::IOError; using hidra2::M_AssertEq; int main(int argc, char* argv[]) { @@ -14,24 +14,24 @@ int main(int argc, char* argv[]) { } std::string expect{argv[2]}; - IOErrors err; + IOError err; auto io = std::unique_ptr<SystemIO> {new SystemIO}; auto data = io->GetDataFromFile(argv[1], expect.size(), &err); std::string result; switch (err) { - case IOErrors::kFileNotFound: + case IOError::kFileNotFound: result = "notfound"; break; - case IOErrors::kNoError: + case IOError::kNoError: for(int i = 0; i < expect.size(); i++) result += data[i]; break; - case IOErrors::kPermissionDenied: + case IOError::kPermissionDenied: result = "noaccess"; break; - case IOErrors::kReadError: + case IOError::kReadError: result = "readerror"; break; diff --git a/tests/system_io/read_files_in_folder/read_folder_content.cpp b/tests/system_io/read_files_in_folder/read_folder_content.cpp index 4df949413..926126dc9 100644 --- a/tests/system_io/read_files_in_folder/read_folder_content.cpp +++ b/tests/system_io/read_files_in_folder/read_folder_content.cpp @@ -4,7 +4,7 @@ #include "testing.h" using hidra2::SystemIO; -using hidra2::IOErrors; +using hidra2::IOError; using hidra2::M_AssertEq; @@ -15,20 +15,20 @@ int main(int argc, char* argv[]) { } std::string expect{argv[2]}; - IOErrors err; + IOError err; auto io = std::unique_ptr<SystemIO> {new SystemIO}; auto files = io->FilesInFolder(argv[1], &err); std::string result; switch (err) { - case IOErrors::kFileNotFound: + case IOError::kFileNotFound: result = "notfound"; break; - case IOErrors::kNoError: + case IOError::kNoError: for(auto file_info : files) result += file_info.relative_path + file_info.base_name; break; - case IOErrors::kPermissionDenied: + case IOError::kPermissionDenied: result = "noaccess"; break; default: diff --git a/worker/api/cpp/src/folder_data_broker.cpp b/worker/api/cpp/src/folder_data_broker.cpp index a6c263c44..bcb6eafd1 100644 --- a/worker/api/cpp/src/folder_data_broker.cpp +++ b/worker/api/cpp/src/folder_data_broker.cpp @@ -4,22 +4,22 @@ namespace hidra2 { -WorkerErrorCode MapIOError(IOErrors io_err) { +WorkerErrorCode MapIOError(IOError io_err) { WorkerErrorCode err; switch (io_err) { // we do not use map due to performance reasons - case IOErrors::kNoError: + case IOError::kNoError: err = WorkerErrorCode::kOK; break; - case IOErrors::kFileNotFound: + case IOError::kFileNotFound: err = WorkerErrorCode::kSourceNotFound; break; - case IOErrors::kPermissionDenied: + case IOError::kPermissionDenied: err = WorkerErrorCode::kPermissionDenied; break; - case IOErrors::kReadError: + case IOError::kReadError: err = WorkerErrorCode::kErrorReadingSource; break; - case IOErrors::kMemoryAllocationError: + case IOError::kMemoryAllocationError: err = WorkerErrorCode::kMemoryError; break; default: @@ -43,10 +43,10 @@ WorkerErrorCode FolderDataBroker::Connect() { return WorkerErrorCode::kSourceAlreadyConnected; } - IOErrors io_err; + IOError io_err; filelist_ = io__->FilesInFolder(base_path_, &io_err); - if (io_err == IOErrors::kNoError) { + if (io_err == IOError::kNoError) { is_connected_ = true; } return MapIOError(io_err); @@ -88,7 +88,7 @@ WorkerErrorCode FolderDataBroker::GetNext(FileInfo* info, FileData* data) { return WorkerErrorCode::kOK; } - IOErrors ioerr; + IOError ioerr; *data = io__->GetDataFromFile(base_path_ + "/" + file_info.relative_path + (file_info.relative_path.empty() ? "" : "/") + file_info.base_name, file_info.size, &ioerr); diff --git a/worker/api/cpp/unittests/test_folder_broker.cpp b/worker/api/cpp/unittests/test_folder_broker.cpp index 7da3645ce..324ec46bc 100644 --- a/worker/api/cpp/unittests/test_folder_broker.cpp +++ b/worker/api/cpp/unittests/test_folder_broker.cpp @@ -11,7 +11,7 @@ using hidra2::DataBroker; using hidra2::FolderDataBroker; using hidra2::WorkerErrorCode; using hidra2::IO; -using hidra2::IOErrors; +using hidra2::IOError; using hidra2::FileInfo; using hidra2::FileData; @@ -36,12 +36,12 @@ TEST(FolderDataBroker, SetCorrectIO) { class FakeIO: public IO { public: - virtual uint8_t* GetDataFromFileProxy(const std::string& fname, uint64_t fsize, IOErrors* err) const { - *err = IOErrors::kNoError; + virtual uint8_t* GetDataFromFileProxy(const std::string& fname, uint64_t fsize, IOError* err) const { + *err = IOError::kNoError; return nullptr; }; - FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept override { + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept override { return FileData(GetDataFromFileProxy(fname, fsize, err)); }; @@ -58,8 +58,8 @@ class FakeIO: public IO { int64_t write(int __fd, const void* __buf, size_t __n) const noexcept override { return 0; }; - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kNoError; + std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const override { + *err = IOError::kNoError; std::vector<FileInfo> file_infos; FileInfo fi; fi.size = 100; @@ -76,32 +76,32 @@ class FakeIO: public IO { class IOFolderNotFound: public FakeIO { public: - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kFileNotFound; + std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const override { + *err = IOError::kFileNotFound; return {}; } }; class IOFodlerUnknownError: public FakeIO { public: - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kUnknownError; + std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const override { + *err = IOError::kUnknownError; return {}; } }; class IOEmptyFodler: public FakeIO { public: - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kNoError; + std::vector<FileInfo> FilesInFolder(const std::string& folder, IOError* err) const override { + *err = IOError::kNoError; return {}; } }; class IOCannotOpenFile: public FakeIO { public: - FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept override { - *err = IOErrors::kPermissionDenied; + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOError* err) const noexcept override { + *err = IOError::kPermissionDenied; return {}; }; }; @@ -211,7 +211,7 @@ TEST_F(FolderDataBrokerTests, GetNextReturnsErrorWhenFilePermissionsDenied) { class OpenFileMock : public FakeIO { public: - MOCK_CONST_METHOD3(GetDataFromFileProxy, uint8_t* (const std::string&, uint64_t, IOErrors*)); + MOCK_CONST_METHOD3(GetDataFromFileProxy, uint8_t* (const std::string&, uint64_t, IOError*)); }; @@ -233,7 +233,7 @@ class GetDataFromFileTests : public Test { TEST_F(GetDataFromFileTests, GetNextCallsGetDataFileWithFileName) { EXPECT_CALL(mock, GetDataFromFileProxy("/path/to/file/1", _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kNoError), testing::Return(nullptr))); + WillOnce(DoAll(testing::SetArgPointee<2>(IOError::kNoError), testing::Return(nullptr))); data_broker->GetNext(&fi, &data); } @@ -242,7 +242,7 @@ TEST_F(GetDataFromFileTests, GetNextCallsGetDataFileWithFileName) { TEST_F(GetDataFromFileTests, GetNextReturnsDataAndInfo) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kNoError), testing::Return(new uint8_t[1] {'1'}))); + WillOnce(DoAll(testing::SetArgPointee<2>(IOError::kNoError), testing::Return(new uint8_t[1] {'1'}))); data_broker->GetNext(&fi, &data); @@ -253,7 +253,7 @@ TEST_F(GetDataFromFileTests, GetNextReturnsDataAndInfo) { TEST_F(GetDataFromFileTests, GetNextReturnsOnlyData) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kNoError), testing::Return(new uint8_t[1] {'1'}))); + WillOnce(DoAll(testing::SetArgPointee<2>(IOError::kNoError), testing::Return(new uint8_t[1] {'1'}))); data_broker->GetNext(nullptr, &data); @@ -263,7 +263,7 @@ TEST_F(GetDataFromFileTests, GetNextReturnsOnlyData) { TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotReadData) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kReadError), testing::Return(nullptr))); + WillOnce(DoAll(testing::SetArgPointee<2>(IOError::kReadError), testing::Return(nullptr))); auto err = data_broker->GetNext(&fi, &data); @@ -272,7 +272,7 @@ TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotReadData) { TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotAllocateData) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kMemoryAllocationError), testing::Return(nullptr))); + WillOnce(DoAll(testing::SetArgPointee<2>(IOError::kMemoryAllocationError), testing::Return(nullptr))); auto err = data_broker->GetNext(&fi, &data); diff --git a/worker/tools/CMakeLists.txt b/worker/tools/CMakeLists.txt new file mode 100644 index 000000000..1d90f764c --- /dev/null +++ b/worker/tools/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(folder_to_db) + diff --git a/worker/tools/folder_to_db/CMakeLists.txt b/worker/tools/folder_to_db/CMakeLists.txt new file mode 100644 index 000000000..f93fca48d --- /dev/null +++ b/worker/tools/folder_to_db/CMakeLists.txt @@ -0,0 +1,21 @@ +set(TARGET_NAME folder2db) + +set(SOURCE_FILES src/FolderDBConverter.cpp) + + +################################ +# Library +################################ +add_library(${TARGET_NAME} STATIC ${SOURCE_FILES} $<TARGET_OBJECTS:common>) + +target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/common/cpp/include) + + +################################ +# Testing +################################ +set(TEST_SOURCE_FILES unittests/test_folder_to_db.cpp) +set(TEST_LIBRARIES "${TARGET_NAME}") + + +gtest(${TARGET_NAME} "${TEST_SOURCE_FILES}" "${TEST_LIBRARIES}") diff --git a/worker/tools/folder_to_db/src/FolderDBConverter.cpp b/worker/tools/folder_to_db/src/FolderDBConverter.cpp new file mode 100644 index 000000000..286937f5c --- /dev/null +++ b/worker/tools/folder_to_db/src/FolderDBConverter.cpp @@ -0,0 +1,55 @@ +#include "FolderDBConverter.h" + +#include "system_wrappers/system_io.h" +#include "database/mongo_database.h" + +namespace hidra2 { + +FolderDBConverterError MapIOError(IOError io_err) { + FolderDBConverterError err; + switch (io_err) { + case IOError::kNoError: + err = FolderDBConverterError::kOK; + break; + default: + err = FolderDBConverterError::kIOError; + break; + } + return err; +} + +FolderDBConverterError MapDBError(DBError db_err) { + FolderDBConverterError err; + switch (db_err) { + case DBError::kNoError: + err = FolderDBConverterError::kOK; + break; + case DBError::kConnectionError: + err = FolderDBConverterError::kDBConnectionError; + break; + } + return err; +} + + + +FolderDBConverter::FolderDBConverter() : + io__{new hidra2::SystemIO}, db__{new hidra2::MongoDB} { +} + +FolderDBConverterError FolderDBConverter::Convert(const std::string& uri, const std::string& folder) { + DBError err_db = db__->Connect(uri, kDBName, folder); + if (err_db != DBError::kNoError) { + return MapDBError(err_db); + } + + IOError err_io; + auto file_list = io__->FilesInFolder(folder,&err_io); + if (err_io != IOError::kNoError){ + return MapIOError(err_io); + } + + return FolderDBConverterError::kOK; +} + +} \ No newline at end of file diff --git a/worker/tools/folder_to_db/src/FolderDBConverter.h b/worker/tools/folder_to_db/src/FolderDBConverter.h new file mode 100644 index 000000000..d78be1e87 --- /dev/null +++ b/worker/tools/folder_to_db/src/FolderDBConverter.h @@ -0,0 +1,28 @@ +#ifndef HIDRA2_FOLDERDBCONVERTER_H +#define HIDRA2_FOLDERDBCONVERTER_H + +#include "system_wrappers/io.h" +#include "database/database.h" + +namespace hidra2 { + +enum class FolderDBConverterError { + kOK, + kDBConnectionError, + kIOError +}; + +class FolderDBConverter { + public: + explicit FolderDBConverter(); + + FolderDBConverterError Convert(const std::string& uri, const std::string& folder); + + std::unique_ptr<hidra2::IO> io__; // modified in testings to mock system calls,otherwise do not touch + std::unique_ptr<hidra2::Database> db__; // modified in testings to mock system calls,otherwise do not touch + +}; + +} + +#endif //HIDRA2_FOLDERDBCONVERTER_H 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 new file mode 100644 index 000000000..92fb23afc --- /dev/null +++ b/worker/tools/folder_to_db/unittests/test_folder_to_db.cpp @@ -0,0 +1,116 @@ +#include <gmock/gmock.h> +#include "gtest/gtest.h" + +#include "system_wrappers/io.h" +#include "system_wrappers/system_io.h" + + +#include "database/database.h" +#include "database/mongo_database.h" + +#include "common/file_info.h" + +#include "../src/FolderDBConverter.h" + +#include "unittests/MockIO.h" + + +using ::testing::AtLeast; +using ::testing::Eq; +using ::testing::Ne; +using ::testing::Test; +using ::testing::_; +using ::testing::Mock; +using ::testing::NiceMock; + +using hidra2::FolderDBConverter; +using hidra2::FolderDBConverterError; +using hidra2::Database; +using hidra2::IO; +using hidra2::DBError; +using hidra2::IOError; +using hidra2::kDBName; +using hidra2::FileInfo; +using hidra2::MockIO; + + +namespace { + +TEST(FolderDBConverter, SetCorrectIO) { + FolderDBConverter converter{}; + ASSERT_THAT(dynamic_cast<hidra2::SystemIO*>(converter.io__.get()), Ne(nullptr)); +} + +TEST(FolderDBConverter, SetCorrectDB) { + FolderDBConverter converter{}; + ASSERT_THAT(dynamic_cast<hidra2::MongoDB*>(converter.db__.get()), Ne(nullptr)); +} + +class MockDatabase : public Database { + public: + MOCK_METHOD3(Connect, DBError (const std::string&, const std::string&, const std::string&)); + + // 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 FolderDBConverterTests : public Test { + public: + FolderDBConverter converter{}; + NiceMock<MockDatabase> mock_db; + NiceMock<MockIO> mock_io; + + void SetUp() override { + converter.db__ = std::unique_ptr<Database> {&mock_db}; + converter.io__ = std::unique_ptr<IO> {&mock_io}; + + } + void TearDown() override { + converter.db__.release(); + converter.io__.release(); + + } +}; + + +TEST_F(FolderDBConverterTests, ErrorWhenCannotConnect) { + + std::string uri{"db_address"}; + + + EXPECT_CALL(mock_db, Connect(uri, kDBName, "")). + WillOnce(testing::Return(DBError::kConnectionError)); + + auto error = converter.Convert(uri, ""); + ASSERT_THAT(error, Eq(FolderDBConverterError::kDBConnectionError)); +} + +TEST_F(FolderDBConverterTests, DBDestructorCalled) { + mock_db.check_destructor = true; + EXPECT_CALL(mock_db, Die()); +} + +TEST_F(FolderDBConverterTests, ErrorWhenCannotGetFileList) { + + std::string folder{"folder"}; + + EXPECT_CALL(mock_io, FilesInFolder(folder, _)). + WillOnce(DoAll(testing::SetArgPointee<1>(IOError::kReadError), testing::Return(std::vector<FileInfo>{}))); + + + auto error = converter.Convert("", folder); + ASSERT_THAT(error, Eq(FolderDBConverterError::kIOError)); + +} + + + +} -- GitLab