From ffab033a0dc21e3012fe3fa6483d3307b45ed0e4 Mon Sep 17 00:00:00 2001 From: Sergey Yakubov <sergey.yakubov@desy.de> Date: Sun, 11 Feb 2018 11:49:35 +0100 Subject: [PATCH] add Error class --- common/cpp/include/common/error.h | 37 ++++++ common/cpp/include/database/database.h | 31 ++--- common/cpp/include/system_wrappers/io.h | 24 ++-- .../cpp/include/system_wrappers/system_io.h | 8 +- common/cpp/include/unittests/MockIO.h | 23 ++-- common/cpp/src/database/database.cpp | 6 +- common/cpp/src/database/mongodb_client.cpp | 46 +++---- common/cpp/src/database/mongodb_client.h | 14 +-- common/cpp/src/system_io/system_io.cpp | 33 +++-- common/cpp/src/system_io/system_io_linux.cpp | 16 +-- .../cpp/src/system_io/system_io_windows.cpp | 36 +++--- .../worker/getnext_broker/getnext_broker.cpp | 6 +- .../worker/process_folder/process_folder.cpp | 17 ++- tests/common/cpp/src/testing.cpp | 17 ++- tests/mongo_db/connect/CMakeLists.txt | 4 +- tests/mongo_db/connect/connect_mongodb.cpp | 29 ++--- tests/mongo_db/insert/CMakeLists.txt | 4 +- tests/mongo_db/insert/insert_mongodb.cpp | 27 ++-- .../read_file_content/CMakeLists.txt | 2 +- .../read_file_content/read_file_content.cpp | 25 +--- .../read_files_in_folder/CMakeLists.txt | 2 +- .../read_folder_content.cpp | 27 ++-- .../content_multithread.cpp | 19 +-- .../curl_httpclient_get.cpp | 6 +- .../next_multithread_broker.cpp | 6 +- .../next_multithread_folder.cpp | 4 +- worker/api/cpp/CMakeLists.txt | 4 +- worker/api/cpp/include/worker/data_broker.h | 37 +++--- worker/api/cpp/src/broker_helpers.cpp | 31 ----- worker/api/cpp/src/broker_helpers.h | 17 --- worker/api/cpp/src/curl_http_client.cpp | 10 +- worker/api/cpp/src/curl_http_client.h | 2 +- worker/api/cpp/src/data_broker.cpp | 18 +-- worker/api/cpp/src/folder_data_broker.cpp | 37 +++--- worker/api/cpp/src/folder_data_broker.h | 6 +- worker/api/cpp/src/http_client.cpp | 24 ++-- worker/api/cpp/src/http_client.h | 4 +- worker/api/cpp/src/http_error.cpp | 7 ++ worker/api/cpp/src/http_error.h | 22 ++++ worker/api/cpp/src/server_data_broker.cpp | 31 +++-- worker/api/cpp/src/server_data_broker.h | 6 +- worker/api/cpp/unittests/MockHttpClient.h | 5 +- .../api/cpp/unittests/test_folder_broker.cpp | 76 ++++++----- .../api/cpp/unittests/test_server_broker.cpp | 26 ++-- worker/api/cpp/unittests/test_worker_api.cpp | 39 +++--- .../folder_to_db/src/folder_db_importer.cpp | 110 +++++----------- .../folder_to_db/src/folder_db_importer.h | 46 +++---- worker/tools/folder_to_db/src/main.cpp | 2 +- .../unittests/test_folder_to_db.cpp | 118 ++++++++++-------- 49 files changed, 565 insertions(+), 582 deletions(-) create mode 100644 common/cpp/include/common/error.h delete mode 100644 worker/api/cpp/src/broker_helpers.cpp delete mode 100644 worker/api/cpp/src/broker_helpers.h create mode 100644 worker/api/cpp/src/http_error.cpp create mode 100644 worker/api/cpp/src/http_error.h diff --git a/common/cpp/include/common/error.h b/common/cpp/include/common/error.h new file mode 100644 index 000000000..0973b90f6 --- /dev/null +++ b/common/cpp/include/common/error.h @@ -0,0 +1,37 @@ +#ifndef HIDRA2_ERROR_H +#define HIDRA2_ERROR_H + +#include <string> + +namespace hidra2 { + +class ErrorInterface { + public: + virtual std::string Explain() const noexcept = 0; + virtual void Set(const std::string& error) noexcept = 0; +}; + +using Error = std::unique_ptr<ErrorInterface>; + +class SimpleError: public ErrorInterface { + private: + std::string error_; + public: + explicit SimpleError(const std::string& error): error_{error} { + + } + std::string Explain() const noexcept override { + return error_; + } + void Set(const std::string& error)noexcept override { + error_ = error; + } + +}; + +inline Error TextError(const std::string& error) { + return Error{new SimpleError{error}}; +} + +} +#endif //HIDRA2_ERROR_H diff --git a/common/cpp/include/database/database.h b/common/cpp/include/database/database.h index 504b75006..1b8751307 100644 --- a/common/cpp/include/database/database.h +++ b/common/cpp/include/database/database.h @@ -4,34 +4,35 @@ #include <string> #include "common/data_structs.h" +#include "common/error.h" namespace hidra2 { -enum class DBError { - KUnknownError, - kConnectionError, - kInsertError, - kDuplicateID, - kAlreadyConnected, - kNotConnected, - kBadAddress, - kNoError, - kMemoryError -}; +namespace DBError { +auto const KUnknownError = "Inknown error"; +auto const kConnectionError = "Connection error"; +auto const kInsertError = "Insert error"; +auto const kDuplicateID = "Duplicate ID"; +auto const kAlreadyConnected = "Already connected"; +auto const kNotConnected = "Not connected"; +auto const kBadAddress = "Bad address"; +auto const kMemoryError = "Memory error"; + +} constexpr char kDBCollectionName[] = "data"; class Database { public: - virtual DBError Connect(const std::string& address, const std::string& database, - const std::string& collection ) = 0; - virtual DBError Insert(const FileInfo& file, bool ignore_duplicates) const = 0; + virtual Error Connect(const std::string& address, const std::string& database, + const std::string& collection ) = 0; + virtual Error Insert(const FileInfo& file, bool ignore_duplicates) const = 0; virtual ~Database() = default; }; class DatabaseFactory { public: - virtual std::unique_ptr<Database> Create(DBError* err) const noexcept; + virtual std::unique_ptr<Database> Create(Error* err) const noexcept; virtual ~DatabaseFactory() = default; }; diff --git a/common/cpp/include/system_wrappers/io.h b/common/cpp/include/system_wrappers/io.h index c38cdd982..9b73e407a 100644 --- a/common/cpp/include/system_wrappers/io.h +++ b/common/cpp/include/system_wrappers/io.h @@ -8,31 +8,31 @@ #include <chrono> #include "common/data_structs.h" +#include "common/error.h" namespace hidra2 { -enum class IOErrors { - kNoError, - kFileNotFound, - kReadError, - kPermissionDenied, - kUnknownError, - kMemoryAllocationError -}; +namespace IOErrors { +auto const kFileNotFound = "File not found"; +auto const kReadError = "Read error"; +auto const kPermissionDenied = "Permission denied"; +auto const kUnknownError = "Unknown error"; +auto const kMemoryAllocationError = "Memory Allocation Error"; +} -IOErrors IOErrorFromErrno(); +Error IOErrorFromErrno(); class IO { public: - virtual FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept = 0; - virtual uint64_t Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept = 0; + virtual FileData GetDataFromFile(const std::string& fname, uint64_t fsize, Error* err) const noexcept = 0; + virtual uint64_t Read(int fd, uint8_t* array, uint64_t fsize, Error* err) const noexcept = 0; virtual int open(const char* __file, int __oflag) const noexcept = 0; virtual int close(int __fd) const noexcept = 0; // this is not standard function - to be implemented differently in windows and linux - virtual FileInfos FilesInFolder(const std::string& folder, IOErrors* err) const = 0; + virtual FileInfos FilesInFolder(const std::string& folder, Error* err) const = 0; }; } diff --git a/common/cpp/include/system_wrappers/system_io.h b/common/cpp/include/system_wrappers/system_io.h index 7f74fd582..d15f5fc04 100644 --- a/common/cpp/include/system_wrappers/system_io.h +++ b/common/cpp/include/system_wrappers/system_io.h @@ -7,14 +7,14 @@ 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, Error* err) const noexcept override; int open(const char* __file, int __oflag) const noexcept override; int close(int __fd) const noexcept override; - uint64_t Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept override; - std::vector<FileInfo> FilesInFolder(const std::string& folder, IOErrors* err) const override; + uint64_t Read(int fd, uint8_t* array, uint64_t fsize, Error* err) const noexcept override; + std::vector<FileInfo> FilesInFolder(const std::string& folder, Error* err) const override; private: void CollectFileInformationRecursivly(const std::string& path, - std::vector<FileInfo>* files, IOErrors* err) const; + std::vector<FileInfo>* files, Error* err) const; int64_t read(int __fd, void* buf, size_t count) const noexcept; int64_t write(int __fd, const void* __buf, size_t __n) const noexcept; }; diff --git a/common/cpp/include/unittests/MockIO.h b/common/cpp/include/unittests/MockIO.h index fbe0b9510..fd60472ea 100644 --- a/common/cpp/include/unittests/MockIO.h +++ b/common/cpp/include/unittests/MockIO.h @@ -10,8 +10,11 @@ namespace hidra2 { class MockIO : public IO { public: - FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept override { - return FileData{GetDataFromFile_t(fname, fsize, err)}; + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, Error* err) const noexcept override { + SimpleError* error; + auto data = GetDataFromFile_t(fname, fsize, &error); + err->reset(error); + return FileData(data); } int open(const char* __file, int __oflag) const noexcept override { return 0; @@ -19,16 +22,22 @@ class MockIO : public IO { int close(int __fd) const noexcept override { return 0; } - uint64_t Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept override { + uint64_t Read(int fd, uint8_t* array, uint64_t fsize, Error* err) const noexcept override { return 0; } + FileInfos FilesInFolder(const std::string& folder, Error* err) const override { + SimpleError* error; + auto data = FilesInFolder_t(folder, &error); + err->reset(error); + return data; + } MOCK_CONST_METHOD3(GetDataFromFile_t, - uint8_t* (const std::string& fname, uint64_t fsize, IOErrors* err)); - MOCK_CONST_METHOD2(FilesInFolder, + uint8_t* (const std::string& fname, uint64_t fsize, SimpleError** err)); + MOCK_CONST_METHOD2(FilesInFolder_t, FileInfos( - const std::string& folder, IOErrors - *err)); + const std::string& folder, hidra2::SimpleError + ** err)); MOCK_CONST_METHOD3(read_t, int64_t(int diff --git a/common/cpp/src/database/database.cpp b/common/cpp/src/database/database.cpp index 5d4dfa61a..f30575e0f 100644 --- a/common/cpp/src/database/database.cpp +++ b/common/cpp/src/database/database.cpp @@ -3,13 +3,13 @@ namespace hidra2 { -std::unique_ptr<Database> DatabaseFactory::Create(DBError* err) const noexcept { +std::unique_ptr<Database> DatabaseFactory::Create(Error* err) const noexcept { std::unique_ptr<Database> p = nullptr; try { p.reset(new MongoDBClient()); - *err = DBError::kNoError; + *err = nullptr; } catch (...) { - *err = DBError::kMemoryError; + *err = TextError(DBError::kMemoryError); } return p; }; diff --git a/common/cpp/src/database/mongodb_client.cpp b/common/cpp/src/database/mongodb_client.cpp index 07e2b9bba..f9d22d084 100644 --- a/common/cpp/src/database/mongodb_client.cpp +++ b/common/cpp/src/database/mongodb_client.cpp @@ -13,7 +13,7 @@ MongoDbInstance::~MongoDbInstance() { mongoc_cleanup (); } -DBError MongoDBClient::Ping() { +Error MongoDBClient::Ping() { bson_t* command, reply; bson_error_t error; bool retval; @@ -25,21 +25,21 @@ DBError MongoDBClient::Ping() { bson_destroy (&reply); bson_destroy (command); - return !retval ? DBError::kConnectionError : DBError::kNoError; + return !retval ? TextError(DBError::kConnectionError) : nullptr; } MongoDBClient::MongoDBClient() { MongoDbInstance::Instantiate(); } -DBError MongoDBClient::InitializeClient(const string& address) { +Error MongoDBClient::InitializeClient(const string& address) { auto uri_str = DBAddress(address); client_ = mongoc_client_new (uri_str.c_str()); if (client_ == nullptr) { - return DBError::kBadAddress; + return TextError(DBError::kBadAddress); } - return DBError::kNoError; + return nullptr; } @@ -49,29 +49,29 @@ void MongoDBClient::InitializeCollection(const string& database_name, collection_name.c_str()); } -DBError MongoDBClient::TryConnectDatabase() { +Error MongoDBClient::TryConnectDatabase() { auto err = Ping(); - if (err == DBError::kNoError) { + if (err == nullptr) { connected_ = true; } return err; } -DBError MongoDBClient::Connect(const string& address, const string& database_name, - const string& collection_name) { +Error MongoDBClient::Connect(const string& address, const string& database_name, + const string& collection_name) { if (connected_) { - return DBError::kAlreadyConnected; + return TextError(DBError::kAlreadyConnected); } auto err = InitializeClient(address); - if (err != DBError::kNoError) { + if (err) { return err; } InitializeCollection(database_name, collection_name); err = TryConnectDatabase(); - if (err != DBError::kNoError) { + if (err) { CleanUp(); } return err; @@ -86,40 +86,40 @@ void MongoDBClient::CleanUp() { mongoc_client_destroy (client_); } -bson_p PrepareBsonDocument(const FileInfo& file, DBError* err) { +bson_p PrepareBsonDocument(const FileInfo& file, Error* err) { auto s = file.Json(); auto json = reinterpret_cast<const uint8_t*>(s.c_str()); auto bson = bson_new_from_json(json, -1, nullptr); if (!bson) { - *err = DBError::kInsertError; + *err = TextError(DBError::kInsertError); return nullptr; } - *err = DBError::kNoError; + *err = nullptr; return bson_p{bson}; } -DBError MongoDBClient::InsertBsonDocument(const bson_p& document, bool ignore_duplicates) const { +Error MongoDBClient::InsertBsonDocument(const bson_p& document, bool ignore_duplicates) const { bson_error_t mongo_err; if (!mongoc_collection_insert_one(collection_, document.get(), NULL, NULL, &mongo_err)) { if (mongo_err.code == MONGOC_ERROR_DUPLICATE_KEY) { - return ignore_duplicates ? DBError::kNoError : DBError::kDuplicateID; + return ignore_duplicates ? nullptr : TextError(DBError::kDuplicateID); } - return DBError::kInsertError; + return TextError(DBError::kInsertError); } - return DBError::kNoError; + return nullptr; } -DBError MongoDBClient::Insert(const FileInfo& file, bool ignore_duplicates) const { +Error MongoDBClient::Insert(const FileInfo& file, bool ignore_duplicates) const { if (!connected_) { - return DBError::kNotConnected; + return TextError(DBError::kNotConnected); } - DBError err; + Error err; auto document = PrepareBsonDocument(file, &err); - if (err != DBError::kNoError) { + if (err) { return err; } diff --git a/common/cpp/src/database/mongodb_client.h b/common/cpp/src/database/mongodb_client.h index 4144e8ec5..b9c4bc31d 100644 --- a/common/cpp/src/database/mongodb_client.h +++ b/common/cpp/src/database/mongodb_client.h @@ -36,9 +36,9 @@ using bson_p = std::unique_ptr<_bson_t, BsonDestroyFunctor>; class MongoDBClient final : public Database { public: MongoDBClient(); - DBError Connect(const std::string& address, const std::string& database, - const std::string& collection) override; - DBError Insert(const FileInfo& file, bool ignore_duplicates) const override; + Error Connect(const std::string& address, const std::string& database, + const std::string& collection) override; + Error Insert(const FileInfo& file, bool ignore_duplicates) const override; ~MongoDBClient() override; private: mongoc_client_t* client_{nullptr}; @@ -46,12 +46,12 @@ class MongoDBClient final : public Database { bool connected_{false}; void CleanUp(); std::string DBAddress(const std::string& address) const; - DBError InitializeClient(const std::string& address); + Error InitializeClient(const std::string& address); void InitializeCollection(const std::string& database_name, const std::string& collection_name); - DBError Ping(); - DBError TryConnectDatabase(); - DBError InsertBsonDocument(const bson_p& document, bool ignore_duplicates) const; + Error Ping(); + Error TryConnectDatabase(); + Error InsertBsonDocument(const bson_p& document, bool ignore_duplicates) const; }; } diff --git a/common/cpp/src/system_io/system_io.cpp b/common/cpp/src/system_io/system_io.cpp index 99b20e8bb..0339443e2 100644 --- a/common/cpp/src/system_io/system_io.cpp +++ b/common/cpp/src/system_io/system_io.cpp @@ -9,27 +9,26 @@ namespace hidra2 { -IOErrors IOErrorFromErrno() { - IOErrors err; +Error IOErrorFromErrno() { + const char* message; switch (errno) { case 0: - err = IOErrors::kNoError; - break; + return nullptr; case ENOENT: case ENOTDIR: - err = IOErrors::kFileNotFound; + message = IOErrors::kFileNotFound; break; case EACCES: - err = IOErrors::kPermissionDenied; + message = IOErrors::kPermissionDenied; break; default: - err = IOErrors::kUnknownError; + message = IOErrors::kUnknownError; break; } - return err; + return TextError(message); } -uint64_t SystemIO::Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept { +uint64_t SystemIO::Read(int fd, uint8_t* array, uint64_t fsize, Error* err) const noexcept { uint64_t totalbytes = 0; int64_t readbytes = 0; do { @@ -38,36 +37,36 @@ uint64_t SystemIO::Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) c } while (readbytes > 0 && totalbytes < fsize); if (totalbytes != fsize) { - *err = IOErrors::kReadError; + *err = TextError(IOErrors::kReadError); } return totalbytes; } -FileData SystemIO::GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept { +FileData SystemIO::GetDataFromFile(const std::string& fname, uint64_t fsize, Error* err) const noexcept { errno = 0; int fd = open(fname.c_str(), O_RDONLY); *err = IOErrorFromErrno(); - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { return nullptr; } uint8_t* data_array = nullptr; try { data_array = new uint8_t[fsize]; } catch (...) { - *err = IOErrors::kMemoryAllocationError; + *err = TextError(IOErrors::kMemoryAllocationError); return nullptr; } Read(fd, data_array, fsize, err); FileData data{data_array}; - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { close(fd); return nullptr; } errno = 0; close(fd); *err = IOErrorFromErrno(); - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { return nullptr; } @@ -96,10 +95,10 @@ void AssignIDs(FileInfos* file_list) { } -FileInfos SystemIO::FilesInFolder(const std::string& folder, IOErrors* err) const { +FileInfos SystemIO::FilesInFolder(const std::string& folder, Error* err) const { FileInfos files{}; CollectFileInformationRecursivly(folder, &files, err); - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { return {}; } StripBasePath(folder, &files); diff --git a/common/cpp/src/system_io/system_io_linux.cpp b/common/cpp/src/system_io/system_io_linux.cpp index e86e08594..abee2bf59 100644 --- a/common/cpp/src/system_io/system_io_linux.cpp +++ b/common/cpp/src/system_io/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, Error* err) { struct stat t_stat {}; errno = 0; int res = stat(fname.c_str(), &t_stat); @@ -56,13 +56,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, Error* err) { FileInfo file_info; SetFileName(path, name, &file_info); auto t_stat = FileStat(path + "/" + name, err); - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { return FileInfo{}; } @@ -74,22 +74,22 @@ FileInfo GetFileInfo(const string& path, const string& name, IOErrors* err) { } void ProcessFileEntity(const struct dirent* entity, const std::string& path, - FileInfos* files, IOErrors* err) { + FileInfos* files, Error* err) { - *err = IOErrors::kNoError; + *err = nullptr; if (entity->d_type != DT_REG) { return; } FileInfo file_info = GetFileInfo(path, entity->d_name, err); - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { return; } files->push_back(file_info); } void SystemIO::CollectFileInformationRecursivly(const std::string& path, - FileInfos* files, IOErrors* err) const { + FileInfos* files, Error* err) const { errno = 0; auto dir = opendir((path).c_str()); if (dir == nullptr) { @@ -108,7 +108,7 @@ void SystemIO::CollectFileInformationRecursivly(const std::string& path, } else { ProcessFileEntity(current_entity, path, files, err); } - if (*err != IOErrors::kNoError) { + if (*err != nullptr) { errno = 0; closedir(dir); return; diff --git a/common/cpp/src/system_io/system_io_windows.cpp b/common/cpp/src/system_io/system_io_windows.cpp index 9e08b483e..171ab2838 100644 --- a/common/cpp/src/system_io/system_io_windows.cpp +++ b/common/cpp/src/system_io/system_io_windows.cpp @@ -12,32 +12,32 @@ using std::chrono::system_clock; namespace hidra2 { -IOErrors IOErrorFromGetLastError() { - IOErrors err; +Error IOErrorFromGetLastError() { + const char* message; switch (GetLastError()) { case ERROR_SUCCESS : - err = IOErrors::kNoError; + message = IOErrors::kNoError; break; case ERROR_PATH_NOT_FOUND: case ERROR_FILE_NOT_FOUND: - err = IOErrors::kFileNotFound; + message = IOErrors::kFileNotFound; break; case ERROR_ACCESS_DENIED: - err = IOErrors::kPermissionDenied; + message = IOErrors::kPermissionDenied; break; default: - err = IOErrors::kUnknownError; + message = IOErrors::kUnknownError; break; } - return err; + return TextError(message); } -IOErrors CheckFileTime(const FILETIME& ft) { +Error CheckFileTime(const FILETIME& ft) { SYSTEMTIME st = {0}; if (!FileTimeToSystemTime(&ft, &st)) { return IOErrorFromGetLastError(); } - return IOErrors::kNoError; + return nullptr; } constexpr auto kShift = 11644473600ULL; @@ -52,10 +52,10 @@ uint64_t GetLinuxNanosecFromWindowsEpoch(ULARGE_INTEGER ull) { return (uint64_t)(ull.QuadPart % k100nsInSec) * 100; } -std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, IOErrors* err) { +std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, Error* err) { *err = CheckFileTime(ft); - if (*err != IOErrors::kNoError) { + if (*err) { return std::chrono::system_clock::time_point{}; } @@ -73,7 +73,7 @@ std::chrono::system_clock::time_point FileTime2TimePoint(const FILETIME& ft, IOE auto tp = system_clock::time_point {std::chrono::duration_cast<std::chrono::system_clock::duration>(d)}; - *err = IOErrors::kNoError; + *err = nullptr; return tp; } @@ -84,16 +84,16 @@ bool IsDirectory(const WIN32_FIND_DATA f) { } void ProcessFileEntity(const WIN32_FIND_DATA f, const std::string& path, - FileInfos* files, IOErrors* err) { + FileInfos* files, Errors* err) { - *err = IOErrors::kNoError; + *err = nullptr; if (f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { return; } FileInfo file_info; file_info.modify_date = FileTime2TimePoint(f.ftLastWriteTime, err); - if (*err != IOErrors::kNoError) { + if (*err) { return; } @@ -104,7 +104,7 @@ void ProcessFileEntity(const WIN32_FIND_DATA f, const std::string& path, void SystemIO::CollectFileInformationRecursivly(const std::string& path, - FileInfos* files, IOErrors* err) const { + FileInfos* files, Error* err) const { WIN32_FIND_DATA find_data; HANDLE handle = FindFirstFile((path + "\\*.*").c_str(), &find_data); if (handle == INVALID_HANDLE_VALUE) { @@ -118,14 +118,14 @@ void SystemIO::CollectFileInformationRecursivly(const std::string& path, } else { ProcessFileEntity(find_data, path, files, err); } - if (*err != IOErrors::kNoError) { + if (*err) { FindClose(handle); return; } } while (FindNextFile(handle, &find_data)); if (FindClose(handle)) { - *err = IOErrors ::kNoError; + *err = nullptr; } else { *err = IOErrorFromGetLastError(); } diff --git a/examples/worker/getnext_broker/getnext_broker.cpp b/examples/worker/getnext_broker/getnext_broker.cpp index 5013c4669..20237acb8 100644 --- a/examples/worker/getnext_broker/getnext_broker.cpp +++ b/examples/worker/getnext_broker/getnext_broker.cpp @@ -9,8 +9,8 @@ #include "hidra2_worker.h" -using hidra2::WorkerErrorCode; using std::chrono::high_resolution_clock; +using hidra2::Error; void WaitThreads(std::vector<std::thread>* threads) { for (auto& thread : *threads) { @@ -22,9 +22,9 @@ std::vector<std::thread> StartThreads(const std::string& server, const std::stri std::vector<int>* nfiles) { auto exec_next = [server, run_name, nfiles](int i) { hidra2::FileInfo fi; - hidra2::WorkerErrorCode err; + Error err; auto broker = hidra2::DataBrokerFactory::CreateServerBroker(server, run_name, &err); - while (broker->GetNext(&fi, nullptr) == WorkerErrorCode::kOK) { + while (broker->GetNext(&fi, nullptr) == nullptr) { (*nfiles)[i] ++; } }; diff --git a/examples/worker/process_folder/process_folder.cpp b/examples/worker/process_folder/process_folder.cpp index 40bf59482..da04b67c8 100644 --- a/examples/worker/process_folder/process_folder.cpp +++ b/examples/worker/process_folder/process_folder.cpp @@ -8,8 +8,8 @@ #include "hidra2_worker.h" -using hidra2::WorkerErrorCode; using std::chrono::high_resolution_clock; +using hidra2::Error; struct Statistics { std::chrono::milliseconds duration_scan; @@ -27,9 +27,9 @@ std::string ProcessCommandArguments(int argc, char* argv[]) { } std::unique_ptr<hidra2::DataBroker> CreateBroker(const std::string& folder) { - hidra2::WorkerErrorCode err; + Error err; auto broker = hidra2::DataBrokerFactory::CreateFolderBroker(folder, &err); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { std::cout << "Cannot create broker" << std::endl; exit(EXIT_FAILURE); } @@ -38,10 +38,9 @@ std::unique_ptr<hidra2::DataBroker> CreateBroker(const std::string& folder) { } void ConnectToBrocker(std::unique_ptr<hidra2::DataBroker>* broker, Statistics* statistics) { - hidra2::WorkerErrorCode err; high_resolution_clock::time_point t1 = high_resolution_clock::now(); - err = (*broker)->Connect(); - if (err != WorkerErrorCode::kOK) { + Error err = (*broker)->Connect(); + if (err != nullptr) { std::cout << "Cannot connect to broker" << std::endl; exit(EXIT_FAILURE); } @@ -50,18 +49,18 @@ void ConnectToBrocker(std::unique_ptr<hidra2::DataBroker>* broker, Statistics* s } void ReadAllData(std::unique_ptr<hidra2::DataBroker>* broker, Statistics* statistics) { - hidra2::WorkerErrorCode err; + Error err; hidra2::FileInfo file_info; hidra2::FileData file_data; high_resolution_clock::time_point t1 = high_resolution_clock::now(); int nfiles = 0; uint64_t size = 0; - while ((err = (*broker)->GetNext(&file_info, &file_data)) == WorkerErrorCode::kOK) { + while ((err = (*broker)->GetNext(&file_info, &file_data)) == nullptr) { nfiles++; size += file_info.size; } - if (err != WorkerErrorCode::kNoData) { + if (err->Explain() != hidra2::WorkerErrorMessage::kNoData) { std::cout << "Read error" << std::endl; exit(EXIT_FAILURE); } diff --git a/tests/common/cpp/src/testing.cpp b/tests/common/cpp/src/testing.cpp index c97231c9b..3d1a8e7e5 100644 --- a/tests/common/cpp/src/testing.cpp +++ b/tests/common/cpp/src/testing.cpp @@ -1,6 +1,7 @@ #include "testing.h" #include <iostream> +#include <algorithm> namespace hidra2 { @@ -32,8 +33,22 @@ void M_AssertEq(int expected, int got) { T_AssertEq(expected, got); } + +std::string EraseSpaces(const std::string& str) { + auto tmp = str; + auto end_pos = std::remove(tmp.begin(), tmp.end(), ' '); + tmp.erase(end_pos, tmp.end()); + return tmp; +} void M_AssertContains( const std::string& whole, const std::string& sub) { - if (whole.find(sub) == std::string::npos) { + auto whole_t = EraseSpaces(whole); + auto sub_t = EraseSpaces(sub); + + if (whole_t.find(sub_t) == std::string::npos) { + std::cerr << "Assert failed:\n" + << "Got (spaces erased):\t'" << whole_t << "'\n" + << "Expected containes (spaces erased):\t'" << sub_t << "'\n"; + exit(EXIT_FAILURE); } } diff --git a/tests/mongo_db/connect/CMakeLists.txt b/tests/mongo_db/connect/CMakeLists.txt index 6c2dc7c5b..8e8190485 100644 --- a/tests/mongo_db/connect/CMakeLists.txt +++ b/tests/mongo_db/connect/CMakeLists.txt @@ -14,7 +14,7 @@ target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR ################################ add_integration_test(${TARGET_NAME} connectOK "127.0.0.1 data test OK") -add_integration_test(${TARGET_NAME} connectFAILS "127.0.0.0 data test ConnectionError") -add_integration_test(${TARGET_NAME} connectBadAddress "#?ß// data test BadAddress") +add_integration_test(${TARGET_NAME} connectFAILS "127.0.0.0 data test Connectionerror") +add_integration_test(${TARGET_NAME} connectBadAddress "#?ß// data test Badaddress") diff --git a/tests/mongo_db/connect/connect_mongodb.cpp b/tests/mongo_db/connect/connect_mongodb.cpp index 74fab0b98..c39bdd15f 100644 --- a/tests/mongo_db/connect/connect_mongodb.cpp +++ b/tests/mongo_db/connect/connect_mongodb.cpp @@ -5,28 +5,17 @@ #include "testing.h" -using hidra2::M_AssertEq; -using hidra2::DBError; +using hidra2::M_AssertContains; +using hidra2::Error; - -void Assert(DBError error, const std::string& expect) { +void Assert(const Error& error, const std::string& expect) { std::string result; - switch (error) { - case DBError::kConnectionError: - result = "ConnectionError"; - break; - case DBError::kAlreadyConnected: - result = "AlreadyConnected"; - break; - case DBError::kBadAddress: - result = "BadAddress"; - break; - default: + if (error == nullptr) { result = "OK"; - break; + } else { + result = error->Explain(); } - - M_AssertEq(expect, result); + M_AssertContains(result, expect); } struct Args { @@ -53,9 +42,9 @@ int main(int argc, char* argv[]) { auto err = db.Connect(args.address, args.database_name, args.collection_name); Assert(err, args.keyword); - if (err == DBError::kNoError) { + if (err == nullptr) { err = db.Connect(args.address, args.database_name, args.collection_name); - Assert(err, "AlreadyConnected"); + Assert(err, hidra2::DBError::kAlreadyConnected); } return 0; } diff --git a/tests/mongo_db/insert/CMakeLists.txt b/tests/mongo_db/insert/CMakeLists.txt index 1ff3205b8..0bff4ed1e 100644 --- a/tests/mongo_db/insert/CMakeLists.txt +++ b/tests/mongo_db/insert/CMakeLists.txt @@ -15,8 +15,8 @@ target_include_directories(${TARGET_NAME} PUBLIC ${HIDRA2_CXX_COMMON_INCLUDE_DIR add_test_cleanup(${TARGET_NAME}) add_integration_test(${TARGET_NAME} insertOK "OK 1" "OK 2") add_integration_test(${TARGET_NAME} insertFailsWhenNotConnected - "NotConnected 3" - "NotConnected 4") + "Notconnected 3" + "Notconnected 4") add_integration_test(${TARGET_NAME} insertFailsForDuplicateID "DuplicateID 6" "DuplicateID 5") diff --git a/tests/mongo_db/insert/insert_mongodb.cpp b/tests/mongo_db/insert/insert_mongodb.cpp index a9194c3c8..fc49e83fc 100644 --- a/tests/mongo_db/insert/insert_mongodb.cpp +++ b/tests/mongo_db/insert/insert_mongodb.cpp @@ -5,29 +5,18 @@ #include "testing.h" -using hidra2::M_AssertEq; -using hidra2::DBError; +using hidra2::M_AssertContains; +using hidra2::Error; -void Assert(DBError error, const std::string& expect) { +void Assert(const Error& error, const std::string& expect) { std::string result; - switch (error) { - case DBError::kInsertError: - result = "InsertError"; - break; - case DBError::kNotConnected: - result = "NotConnected"; - break; - case DBError::kDuplicateID: - result = "DuplicateID"; - break; - - default: + if (error == nullptr) { result = "OK"; - break; + } else { + result = error->Explain(); } - - M_AssertEq(expect, result); + M_AssertContains(result, expect); } struct Args { @@ -55,7 +44,7 @@ int main(int argc, char* argv[]) { fi.relative_path = "relpath"; fi.modify_date = std::chrono::system_clock::now(); - if (args.keyword != "NotConnected") { + if (args.keyword != "Notconnected") { db.Connect("127.0.0.1", "data", "test"); } diff --git a/tests/system_io/read_file_content/CMakeLists.txt b/tests/system_io/read_file_content/CMakeLists.txt index 9b1b0b445..8109443ef 100644 --- a/tests/system_io/read_file_content/CMakeLists.txt +++ b/tests/system_io/read_file_content/CMakeLists.txt @@ -17,5 +17,5 @@ set_target_properties(${TARGET_NAME} PROPERTIES LINKER_LANGUAGE CXX) add_test_setup_cleanup(${TARGET_NAME}) add_integration_test(${TARGET_NAME} readfile "test/1 123") add_integration_test(${TARGET_NAME} filenotfound "test_notexist notfound") -add_integration_test(${TARGET_NAME} filenoaccess "file_noaccess noaccess") +add_integration_test(${TARGET_NAME} filenoaccess "file_noaccess Permissiondenied") 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 9d19970f3..065e94328 100644 --- a/tests/system_io/read_file_content/read_file_content.cpp +++ b/tests/system_io/read_file_content/read_file_content.cpp @@ -4,8 +4,6 @@ #include "testing.h" using hidra2::SystemIO; -using hidra2::IOErrors; -using hidra2::M_AssertEq; int main(int argc, char* argv[]) { if (argc != 3) { @@ -14,32 +12,19 @@ int main(int argc, char* argv[]) { } std::string expect{argv[2]}; - IOErrors err; + hidra2::Error 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: - result = "notfound"; - break; - case IOErrors::kNoError: + if (err == nullptr) { for(unsigned int i = 0; i < expect.size(); i++) result += data[i]; - break; - case IOErrors::kPermissionDenied: - result = "noaccess"; - break; - case IOErrors::kReadError: - result = "readerror"; - break; - - default: - result = ""; - break; + } else { + result = err->Explain(); } - M_AssertEq(expect, result); + hidra2::M_AssertContains(result, expect); return 0; } diff --git a/tests/system_io/read_files_in_folder/CMakeLists.txt b/tests/system_io/read_files_in_folder/CMakeLists.txt index b87f07381..a0065e1f8 100644 --- a/tests/system_io/read_files_in_folder/CMakeLists.txt +++ b/tests/system_io/read_files_in_folder/CMakeLists.txt @@ -23,5 +23,5 @@ ENDIF(WIN32) add_integration_test(${TARGET_NAME} foldernotfound "test_notexist notfound") -add_integration_test(${TARGET_NAME} foldernoaccess "test_noaccess1 noaccess") +add_integration_test(${TARGET_NAME} foldernoaccess "test_noaccess1 Permissiondenied") 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 71cdc303e..25ac8245b 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,9 +4,11 @@ #include "testing.h" using hidra2::SystemIO; -using hidra2::IOErrors; +using hidra2::Error; + using hidra2::M_AssertEq; +using hidra2::M_AssertContains; int main(int argc, char* argv[]) { if (argc != 3) { @@ -15,31 +17,22 @@ int main(int argc, char* argv[]) { } std::string expect{argv[2]}; - IOErrors err; + Error err; auto io = std::unique_ptr<SystemIO> {new SystemIO}; auto files = io->FilesInFolder(argv[1], &err); - std::string result; - int64_t id = 0; - switch (err) { - case IOErrors::kFileNotFound: - result = "notfound"; - break; - case IOErrors::kNoError: + std::string result{}; + if (err == nullptr) { + int64_t id = 0; for(auto file_info : files) { M_AssertEq(file_info.id, ++id); result += file_info.relative_path + file_info.base_name; } - break; - case IOErrors::kPermissionDenied: - result = "noaccess"; - break; - default: - result = ""; - break; + } else { + result = err->Explain(); } - M_AssertEq(expect, result); + M_AssertContains(result, expect); return 0; } diff --git a/tests/worker/connect_multithread/content_multithread.cpp b/tests/worker/connect_multithread/content_multithread.cpp index e4bfcceb8..ef63c6222 100644 --- a/tests/worker/connect_multithread/content_multithread.cpp +++ b/tests/worker/connect_multithread/content_multithread.cpp @@ -6,16 +6,19 @@ #include "testing.h" using hidra2::M_AssertEq; -using hidra2::WorkerErrorCode; -void Assert(std::vector<WorkerErrorCode>& errors, int nthreads) { +void Assert(std::vector<hidra2::Error>& errors, int nthreads) { int count_ok = (int) std::count(std::begin(errors), std::end(errors), - WorkerErrorCode::kOK); + nullptr); + + int count_already_connected = 0; + for (auto& error : errors) { + if (!error) continue; + if (error->Explain().find(hidra2::WorkerErrorMessage::kSourceAlreadyConnected) != std::string::npos) + count_already_connected++; + } - int count_already_connected = (int) std::count(std::begin(errors), - std::end(errors), - WorkerErrorCode::kSourceAlreadyConnected); M_AssertEq(1, count_ok); M_AssertEq(nthreads - 1, count_already_connected); } @@ -39,10 +42,10 @@ int main(int argc, char* argv[]) { auto args = GetArgs(argc, argv); - hidra2::WorkerErrorCode err; + hidra2::Error err; auto broker = hidra2::DataBrokerFactory::CreateFolderBroker(args.folder, &err); - std::vector<WorkerErrorCode>errors(args.nthreads, WorkerErrorCode::kUnknownIOError); + std::vector<hidra2::Error>errors(args.nthreads); std::vector<std::thread> threads; for (int i = 0; i < args.nthreads; i++) { diff --git a/tests/worker/curl_http_client_get/curl_httpclient_get.cpp b/tests/worker/curl_http_client_get/curl_httpclient_get.cpp index 1eb59073a..057c474f1 100644 --- a/tests/worker/curl_http_client_get/curl_httpclient_get.cpp +++ b/tests/worker/curl_http_client_get/curl_httpclient_get.cpp @@ -7,8 +7,6 @@ using hidra2::M_AssertEq; using hidra2::M_AssertContains; -using hidra2::WorkerErrorCode; - struct Args { std::string uri; int code; @@ -31,14 +29,14 @@ int main(int argc, char* argv[]) { auto args = GetArgs(argc, argv); - WorkerErrorCode err; + hidra2::Error err; auto broker = hidra2::DataBrokerFactory::CreateServerBroker(args.uri, "", &err); auto server_broker = static_cast<hidra2::ServerDataBroker*>(broker.get()); hidra2::HttpCode code; auto responce = server_broker->httpclient__->Get(args.uri, &code, &err); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { M_AssertEq("clienterror", args.answer); M_AssertContains(responce, "Could"); return 0; diff --git a/tests/worker/next_multithread_broker/next_multithread_broker.cpp b/tests/worker/next_multithread_broker/next_multithread_broker.cpp index 49d543ec1..c1def928f 100644 --- a/tests/worker/next_multithread_broker/next_multithread_broker.cpp +++ b/tests/worker/next_multithread_broker/next_multithread_broker.cpp @@ -8,8 +8,6 @@ using hidra2::M_AssertEq; using hidra2::M_AssertTrue; -using hidra2::WorkerErrorCode; - void Assert(std::vector<hidra2::FileInfos> file_infos, int nthreads, int nfiles) { std::vector<std::string> expect, result; for (int i = 1; i <= nfiles; i++) { @@ -47,13 +45,13 @@ Args GetArgs(int argc, char* argv[]) { } void GetAllFromBroker(const Args& args) { - hidra2::WorkerErrorCode err; + hidra2::Error err; auto broker = hidra2::DataBrokerFactory::CreateServerBroker(args.server, args.run_name, &err); std::vector<hidra2::FileInfos>file_infos(args.nthreads); auto exec_next = [&](int i) { hidra2::FileInfo fi; - while ((err = broker->GetNext(&fi, nullptr)) == WorkerErrorCode::kOK) { + while ((err = broker->GetNext(&fi, nullptr)) == nullptr) { file_infos[i].emplace_back(fi); } }; diff --git a/tests/worker/next_multithread_folder/next_multithread_folder.cpp b/tests/worker/next_multithread_folder/next_multithread_folder.cpp index 59b168fa4..95ec52494 100644 --- a/tests/worker/next_multithread_folder/next_multithread_folder.cpp +++ b/tests/worker/next_multithread_folder/next_multithread_folder.cpp @@ -8,8 +8,6 @@ using hidra2::M_AssertEq; using hidra2::M_AssertTrue; -using hidra2::WorkerErrorCode; - void Assert(std::vector<hidra2::FileInfo> file_infos, int nthreads) { int nfiles = (int) file_infos.size(); M_AssertEq(nthreads, nfiles); @@ -41,7 +39,7 @@ Args GetArgs(int argc, char* argv[]) { } void GetAllFromBroker(const Args& args) { - hidra2::WorkerErrorCode err; + hidra2::Error err; auto broker = hidra2::DataBrokerFactory::CreateFolderBroker(args.folder, &err); broker->Connect(); diff --git a/worker/api/cpp/CMakeLists.txt b/worker/api/cpp/CMakeLists.txt index 8404ee9e4..60aeac037 100644 --- a/worker/api/cpp/CMakeLists.txt +++ b/worker/api/cpp/CMakeLists.txt @@ -5,8 +5,8 @@ set(SOURCE_FILES src/http_client.cpp src/folder_data_broker.cpp src/server_data_broker.cpp - src/broker_helpers.cpp - src/curl_http_client.cpp) + src/curl_http_client.cpp + src/http_error.cpp) ################################ diff --git a/worker/api/cpp/include/worker/data_broker.h b/worker/api/cpp/include/worker/data_broker.h index 27e9435f1..e0859dcae 100644 --- a/worker/api/cpp/include/worker/data_broker.h +++ b/worker/api/cpp/include/worker/data_broker.h @@ -5,36 +5,37 @@ #include <string> #include "common/data_structs.h" +#include "common/error.h" namespace hidra2 { -enum class WorkerErrorCode { - kOK, - kMemoryError, - kEmptyDatasource, - kSourceNotFound, - kSourceNotConnected, - kSourceAlreadyConnected, - kErrorReadingSource, - kPermissionDenied, - kNoData, - kWrongInput, - kInternalError, - kUnknownIOError -}; +namespace WorkerErrorMessage { + +auto const kMemoryError = "Memory Error"; +auto const kEmptyDatasource = "Empty Data Source"; +auto const kSourceNotFound = "Source Not Found"; +auto const kSourceNotConnected = "Source Not Connacted"; +auto const kSourceAlreadyConnected = "Source Already Connected"; +auto const kErrorReadingSource = "Error Reading Source"; +auto const kPermissionDenied = "Permissionn Denied"; +auto const kNoData = "No Data"; +auto const kWrongInput = "Wrong Input"; +auto const kInternalError = "Internal Error"; +auto const kUnknownIOError = "Unknown IO Error"; +} class DataBroker { public: //! Connect to the data source - will scan file folders or connect to the database. // TODO: do we need this? - virtual WorkerErrorCode Connect() = 0; + virtual Error Connect() = 0; //! Receive next image. /*! \param info - where to store image metadata. Can be set to nullptr only image data is needed. \param data - where to store image data. Can be set to nullptr only image metadata is needed. \return Error if both pointers are nullptr or data cannot be read, WorkerErrorCode::OK otherwise. */ - virtual WorkerErrorCode GetNext(FileInfo* info, FileData* data) = 0; + virtual Error GetNext(FileInfo* info, FileData* data) = 0; virtual ~DataBroker() = default; // needed for unique_ptr to delete itself }; @@ -42,10 +43,10 @@ class DataBroker { class DataBrokerFactory { public: static std::unique_ptr<DataBroker> CreateFolderBroker(const std::string& source_name, - WorkerErrorCode* return_code) noexcept; + Error* error) noexcept; static std::unique_ptr<DataBroker> CreateServerBroker(const std::string& server_name, const std::string& source_name, - WorkerErrorCode* return_code) noexcept; + Error* error) noexcept; }; diff --git a/worker/api/cpp/src/broker_helpers.cpp b/worker/api/cpp/src/broker_helpers.cpp deleted file mode 100644 index c9e8dc8e2..000000000 --- a/worker/api/cpp/src/broker_helpers.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "broker_helpers.h" - -namespace hidra2 { - -WorkerErrorCode MapIOError(IOErrors io_err) { - WorkerErrorCode err; - switch (io_err) { // we do not use map due to performance reasons - case IOErrors::kNoError: - err = WorkerErrorCode::kOK; - break; - case IOErrors::kFileNotFound: - err = WorkerErrorCode::kSourceNotFound; - break; - case IOErrors::kPermissionDenied: - err = WorkerErrorCode::kPermissionDenied; - break; - case IOErrors::kReadError: - err = WorkerErrorCode::kErrorReadingSource; - break; - case IOErrors::kMemoryAllocationError: - err = WorkerErrorCode::kMemoryError; - break; - default: - err = WorkerErrorCode::kUnknownIOError; - break; - } - - return err; -} - -} diff --git a/worker/api/cpp/src/broker_helpers.h b/worker/api/cpp/src/broker_helpers.h deleted file mode 100644 index a6a0b555d..000000000 --- a/worker/api/cpp/src/broker_helpers.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HIDRA2_IO_MAP_H -#define HIDRA2_IO_MAP_H - - -#include "system_wrappers/system_io.h" -#include "worker/data_broker.h" - -namespace hidra2 { - -WorkerErrorCode MapIOError(IOErrors io_err); - -} - - -#endif //HIDRA2_IO_MAP_H - - diff --git a/worker/api/cpp/src/curl_http_client.cpp b/worker/api/cpp/src/curl_http_client.cpp index 39f6ebdfc..9d40c6ec6 100644 --- a/worker/api/cpp/src/curl_http_client.cpp +++ b/worker/api/cpp/src/curl_http_client.cpp @@ -49,18 +49,18 @@ std::string GetCurlError(CURL* curl, CURLcode res, const char* errbuf) { } } -WorkerErrorCode ProcessCurlResponce(CURL* curl, CURLcode res, const char* errbuf, - std::string* buffer, HttpCode* responce_code) { +Error ProcessCurlResponce(CURL* curl, CURLcode res, const char* errbuf, + std::string* buffer, HttpCode* responce_code) { if(res == CURLE_OK) { *responce_code = GetResponceCode(curl); - return WorkerErrorCode::kOK; + return nullptr; } else { *buffer = GetCurlError(curl, res, errbuf); - return WorkerErrorCode::kErrorReadingSource; + return TextError(WorkerErrorMessage::kErrorReadingSource); } } -std::string CurlHttpClient::Get(const std::string& uri, HttpCode* responce_code, WorkerErrorCode* err) const noexcept { +std::string CurlHttpClient::Get(const std::string& uri, HttpCode* responce_code, Error* err) const noexcept { std::lock_guard<std::mutex> lock{mutex_}; std::string buffer; diff --git a/worker/api/cpp/src/curl_http_client.h b/worker/api/cpp/src/curl_http_client.h index c971704f5..578c03337 100644 --- a/worker/api/cpp/src/curl_http_client.h +++ b/worker/api/cpp/src/curl_http_client.h @@ -12,7 +12,7 @@ namespace hidra2 { class CurlHttpClient final : public HttpClient { public: CurlHttpClient(); - std::string Get(const std::string& uri, HttpCode* responce_code, WorkerErrorCode* err) const noexcept override; + std::string Get(const std::string& uri, HttpCode* responce_code, Error* err) const noexcept override; virtual ~CurlHttpClient(); private: mutable std::mutex mutex_; diff --git a/worker/api/cpp/src/data_broker.cpp b/worker/api/cpp/src/data_broker.cpp index 11de4f01f..409799e2b 100644 --- a/worker/api/cpp/src/data_broker.cpp +++ b/worker/api/cpp/src/data_broker.cpp @@ -7,19 +7,21 @@ namespace hidra2 { template <typename Broker, typename ...Args> std::unique_ptr<DataBroker> Create(const std::string& source_name, - WorkerErrorCode* return_code, + Error* error, Args&& ... args) noexcept { if (source_name.empty()) { - *return_code = WorkerErrorCode::kEmptyDatasource; + error->reset(new SimpleError("Empty Data Source")); + //*return_code = WorkerErrorMessage::kEmptyDatasource; return nullptr; } std::unique_ptr<DataBroker> p = nullptr; try { p.reset(new Broker(source_name, std::forward<Args>(args)...)); - *return_code = WorkerErrorCode::kOK; + error->reset(nullptr); } catch (...) { // we do not test this part - *return_code = WorkerErrorCode::kMemoryError; + error->reset(new SimpleError("Memory error")); +// *return_code = WorkerErrorMessage::kMemoryError; } return p; @@ -27,14 +29,14 @@ std::unique_ptr<DataBroker> Create(const std::string& source_name, } std::unique_ptr<DataBroker> DataBrokerFactory::CreateFolderBroker(const std::string& source_name, - WorkerErrorCode* return_code) noexcept { - return Create<FolderDataBroker>(source_name, return_code); + Error* error) noexcept { + return Create<FolderDataBroker>(source_name, error); }; std::unique_ptr<DataBroker> DataBrokerFactory::CreateServerBroker(const std::string& server_name, const std::string& source_name, - WorkerErrorCode* return_code) noexcept { - return Create<ServerDataBroker>(server_name, return_code, source_name); + Error* error) noexcept { + return Create<ServerDataBroker>(server_name, error, source_name); } diff --git a/worker/api/cpp/src/folder_data_broker.cpp b/worker/api/cpp/src/folder_data_broker.cpp index 9c460c421..11e44d963 100644 --- a/worker/api/cpp/src/folder_data_broker.cpp +++ b/worker/api/cpp/src/folder_data_broker.cpp @@ -1,7 +1,6 @@ #include "folder_data_broker.h" #include "system_wrappers/system_io.h" -#include "broker_helpers.h" namespace hidra2 { @@ -10,59 +9,61 @@ FolderDataBroker::FolderDataBroker(const std::string& source_name) : current_file_{ -1} { } -WorkerErrorCode FolderDataBroker::Connect() { +Error FolderDataBroker::Connect() { std::lock_guard<std::mutex> lock{mutex_}; if (is_connected_) { - return WorkerErrorCode::kSourceAlreadyConnected; + return TextError(WorkerErrorMessage::kSourceAlreadyConnected); } - IOErrors io_err; - filelist_ = io__->FilesInFolder(base_path_, &io_err); + Error error; + filelist_ = io__->FilesInFolder(base_path_, &error); - if (io_err == IOErrors::kNoError) { + if (error == nullptr) { is_connected_ = true; + return nullptr; } - return MapIOError(io_err); + + return error; } -WorkerErrorCode FolderDataBroker::CanGetData(FileInfo* info, FileData* data, int nfile) const noexcept { +Error FolderDataBroker::CanGetData(FileInfo* info, FileData* data, int nfile) const noexcept { if (!is_connected_) { - return WorkerErrorCode::kSourceNotConnected; + return TextError(WorkerErrorMessage::kSourceNotConnected); } if (info == nullptr) { - return WorkerErrorCode::kWrongInput; + return TextError(WorkerErrorMessage::kWrongInput); } if (nfile >= (int) filelist_.size()) { - return WorkerErrorCode::kNoData; + return Error{TextError(WorkerErrorMessage::kNoData)}; } - return WorkerErrorCode::kOK; + return nullptr; } -WorkerErrorCode FolderDataBroker::GetNext(FileInfo* info, FileData* data) { +Error FolderDataBroker::GetNext(FileInfo* info, FileData* data) { // could probably use atomic here, but just to make sure (tests showed no performance difference) mutex_.lock(); int nfile_to_get = ++current_file_; mutex_.unlock(); auto err = CanGetData(info, data, nfile_to_get); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { return err; } *info = filelist_[nfile_to_get]; if (data == nullptr) { - return WorkerErrorCode::kOK; + return nullptr; } - IOErrors ioerr; - *data = io__->GetDataFromFile(info->FullName(base_path_), info->size, &ioerr); + Error error; + *data = io__->GetDataFromFile(info->FullName(base_path_), info->size, &error); - return MapIOError(ioerr); + return error; } diff --git a/worker/api/cpp/src/folder_data_broker.h b/worker/api/cpp/src/folder_data_broker.h index 2bcdcfbe5..4ffe1b211 100644 --- a/worker/api/cpp/src/folder_data_broker.h +++ b/worker/api/cpp/src/folder_data_broker.h @@ -13,8 +13,8 @@ namespace hidra2 { class FolderDataBroker final : public hidra2::DataBroker { public: explicit FolderDataBroker(const std::string& source_name); - WorkerErrorCode Connect() override; - WorkerErrorCode GetNext(FileInfo* info, FileData* data) override; + Error Connect() override; + Error GetNext(FileInfo* info, FileData* data) override; std::unique_ptr<hidra2::IO> io__; // modified in testings to mock system calls,otherwise do not touch @@ -23,7 +23,7 @@ class FolderDataBroker final : public hidra2::DataBroker { bool is_connected_; int current_file_; FileInfos filelist_; - WorkerErrorCode CanGetData(FileInfo* info, FileData* data, int nfile) const noexcept; + Error CanGetData(FileInfo* info, FileData* data, int nfile) const noexcept; std::mutex mutex_; }; diff --git a/worker/api/cpp/src/http_client.cpp b/worker/api/cpp/src/http_client.cpp index 1a61473fa..7b9c98368 100644 --- a/worker/api/cpp/src/http_client.cpp +++ b/worker/api/cpp/src/http_client.cpp @@ -1,23 +1,29 @@ #include "http_client.h" - +#include "http_error.h" namespace hidra2 { -WorkerErrorCode HttpCodeToWorkerError(const HttpCode& code) { +Error HttpCodeToWorkerError(const HttpCode& code) { + const char* message; switch (code) { case HttpCode::OK: - return WorkerErrorCode::kOK; + return nullptr; case HttpCode::BadRequest: - return WorkerErrorCode::kWrongInput; + message = WorkerErrorMessage::kWrongInput; + break; case HttpCode::InternalServerError: - return WorkerErrorCode::kErrorReadingSource; + message = WorkerErrorMessage::kErrorReadingSource; + break; case HttpCode::NoContent: - return WorkerErrorCode::kNoData; + message = WorkerErrorMessage::kNoData; + break; case HttpCode::NotFound: - return WorkerErrorCode::kSourceNotFound; + message = WorkerErrorMessage::kSourceNotFound; + break; default: - return WorkerErrorCode::kErrorReadingSource; + message = WorkerErrorMessage::kErrorReadingSource; + break; } - + return Error{new HttpError(message, code)}; } } diff --git a/worker/api/cpp/src/http_client.h b/worker/api/cpp/src/http_client.h index 41fa0ba97..725af4601 100644 --- a/worker/api/cpp/src/http_client.h +++ b/worker/api/cpp/src/http_client.h @@ -9,12 +9,12 @@ enum class HttpCode; class HttpClient { public: - virtual std::string Get(const std::string& uri, HttpCode* responce_code, WorkerErrorCode* err) const noexcept = 0; + virtual std::string Get(const std::string& uri, HttpCode* responce_code, Error* err) const noexcept = 0; virtual ~HttpClient() = default; }; -WorkerErrorCode HttpCodeToWorkerError(const HttpCode& code); +Error HttpCodeToWorkerError(const HttpCode& code); enum class HttpCode : int { Continue = 100, diff --git a/worker/api/cpp/src/http_error.cpp b/worker/api/cpp/src/http_error.cpp new file mode 100644 index 000000000..72189fc37 --- /dev/null +++ b/worker/api/cpp/src/http_error.cpp @@ -0,0 +1,7 @@ +#include "http_error.h" + +namespace hidra2 { + + + +} \ No newline at end of file diff --git a/worker/api/cpp/src/http_error.h b/worker/api/cpp/src/http_error.h new file mode 100644 index 000000000..2c3f5f362 --- /dev/null +++ b/worker/api/cpp/src/http_error.h @@ -0,0 +1,22 @@ +#ifndef HIDRA2_HTTP_ERROR_H +#define HIDRA2_HTTP_ERROR_H + +#include "common/error.h" +#include "http_client.h" + +namespace hidra2 { + +class HttpError: public SimpleError { + public: + HttpError(const std::string& error, HttpCode http_code): SimpleError{error}, http_code_{http_code} { + } + HttpCode GetCode() const { + return http_code_; + } + private: + HttpCode http_code_; +}; + +} + +#endif //HIDRA2_HTTP_ERROR_H diff --git a/worker/api/cpp/src/server_data_broker.cpp b/worker/api/cpp/src/server_data_broker.cpp index 612ea1060..8cd9c3efe 100644 --- a/worker/api/cpp/src/server_data_broker.cpp +++ b/worker/api/cpp/src/server_data_broker.cpp @@ -1,7 +1,6 @@ #include "server_data_broker.h" #include "system_wrappers/system_io.h" #include "curl_http_client.h" -#include "broker_helpers.h" namespace hidra2 { @@ -11,48 +10,48 @@ ServerDataBroker::ServerDataBroker(const std::string& server_uri, server_uri_{server_uri}, source_name_{source_name} { } -WorkerErrorCode ServerDataBroker::Connect() { - return WorkerErrorCode::kOK; +Error ServerDataBroker::Connect() { + return nullptr; } -WorkerErrorCode ServerDataBroker::GetFileInfoFromServer(FileInfo* info, const std::string& operation) { +Error ServerDataBroker::GetFileInfoFromServer(FileInfo* info, const std::string& operation) { std::string full_uri = server_uri_ + "/database/" + source_name_ + "/" + operation; - WorkerErrorCode err; + Error err; HttpCode code; auto responce = httpclient__->Get(full_uri, &code, &err); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { return err; } err = HttpCodeToWorkerError(code); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { return err; } if (!info->SetFromJson(responce)) { - return WorkerErrorCode::kErrorReadingSource; + return TextError(WorkerErrorMessage::kErrorReadingSource); } - return WorkerErrorCode::kOK; + return nullptr; } -WorkerErrorCode ServerDataBroker::GetNext(FileInfo* info, FileData* data) { +Error ServerDataBroker::GetNext(FileInfo* info, FileData* data) { if (info == nullptr) { - return WorkerErrorCode::kWrongInput; + return TextError(WorkerErrorMessage::kWrongInput); } auto err = GetFileInfoFromServer(info, "next"); - if (err != WorkerErrorCode::kOK) { + if (err != nullptr) { return err; } if (data == nullptr) { - return WorkerErrorCode::kOK; + return nullptr; } - IOErrors ioerr; - *data = io__->GetDataFromFile(info->FullName(""), info->size, &ioerr); - return hidra2::MapIOError(ioerr); + Error error; + *data = io__->GetDataFromFile(info->FullName(""), info->size, &error); + return error; } } \ No newline at end of file diff --git a/worker/api/cpp/src/server_data_broker.h b/worker/api/cpp/src/server_data_broker.h index 55cd97317..d77fff8bf 100644 --- a/worker/api/cpp/src/server_data_broker.h +++ b/worker/api/cpp/src/server_data_broker.h @@ -11,12 +11,12 @@ namespace hidra2 { class ServerDataBroker final : public hidra2::DataBroker { public: explicit ServerDataBroker(const std::string& server_uri, const std::string& source_name); - WorkerErrorCode Connect() override; - WorkerErrorCode GetNext(FileInfo* info, FileData* data) override; + Error Connect() override; + Error GetNext(FileInfo* info, FileData* data) override; std::unique_ptr<hidra2::IO> io__; // modified in testings to mock system calls,otherwise do not touch std::unique_ptr<hidra2::HttpClient> httpclient__; private: - WorkerErrorCode GetFileInfoFromServer(FileInfo* info, const std::string& operation); + Error GetFileInfoFromServer(FileInfo* info, const std::string& operation); std::string server_uri_; std::string source_name_; }; diff --git a/worker/api/cpp/unittests/MockHttpClient.h b/worker/api/cpp/unittests/MockHttpClient.h index 06ff805aa..a386321db 100644 --- a/worker/api/cpp/unittests/MockHttpClient.h +++ b/worker/api/cpp/unittests/MockHttpClient.h @@ -7,15 +7,16 @@ #include "../src/http_client.h" #include "worker/data_broker.h" + namespace hidra2 { class MockHttpClient : public HttpClient { public: - std::string Get(const std::string& uri, HttpCode* code, WorkerErrorCode* err) const noexcept override { + std::string Get(const std::string& uri, HttpCode* code, Error* err) const noexcept override { return Get_t(uri, code, err); } MOCK_CONST_METHOD3(Get_t, - std::string(const std::string& uri, HttpCode* code, WorkerErrorCode* err)); + std::string(const std::string& uri, HttpCode* code, Error* err)); }; diff --git a/worker/api/cpp/unittests/test_folder_broker.cpp b/worker/api/cpp/unittests/test_folder_broker.cpp index 9b3992237..d3a673f43 100644 --- a/worker/api/cpp/unittests/test_folder_broker.cpp +++ b/worker/api/cpp/unittests/test_folder_broker.cpp @@ -9,12 +9,13 @@ using hidra2::DataBrokerFactory; using hidra2::DataBroker; using hidra2::FolderDataBroker; -using hidra2::WorkerErrorCode; using hidra2::IO; -using hidra2::IOErrors; using hidra2::FileInfos; using hidra2::FileInfo; using hidra2::FileData; +using hidra2::Error; +using hidra2::TextError; +using hidra2::SimpleError; using ::testing::AtLeast; using ::testing::Eq; @@ -37,13 +38,16 @@ 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, SimpleError** err) const { + *err = nullptr; return nullptr; }; - FileData GetDataFromFile(const std::string& fname, uint64_t fsize, IOErrors* err) const noexcept override { - return FileData(GetDataFromFileProxy(fname, fsize, err)); + FileData GetDataFromFile(const std::string& fname, uint64_t fsize, Error* err) const noexcept override { + SimpleError* error; + auto data = GetDataFromFileProxy(fname, fsize, &error); + err->reset(error); + return FileData(data); }; int open(const char* __file, int __oflag) const noexcept override { @@ -54,11 +58,11 @@ class FakeIO: public IO { return 0; }; - uint64_t Read(int fd, uint8_t* array, uint64_t fsize, IOErrors* err) const noexcept override { + uint64_t Read(int fd, uint8_t* array, uint64_t fsize, Error* err) const noexcept override { return 0; }; - FileInfos FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kNoError; + FileInfos FilesInFolder(const std::string& folder, Error* err) const override { + *err = nullptr; FileInfos file_infos; FileInfo fi; fi.size = 100; @@ -74,32 +78,32 @@ class FakeIO: public IO { class IOFolderNotFound: public FakeIO { public: - FileInfos FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kFileNotFound; + FileInfos FilesInFolder(const std::string& folder, Error* err) const override { + *err = hidra2::TextError(hidra2::IOErrors::kFileNotFound); return {}; } }; class IOFolderUnknownError: public FakeIO { public: - FileInfos FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kUnknownError; + FileInfos FilesInFolder(const std::string& folder, Error* err) const override { + *err = hidra2::TextError(hidra2::IOErrors::kUnknownError); return {}; } }; class IOEmptyFolder: public FakeIO { public: - FileInfos FilesInFolder(const std::string& folder, IOErrors* err) const override { - *err = IOErrors::kNoError; + FileInfos FilesInFolder(const std::string& folder, Error* err) const override { + *err = nullptr; 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, Error* err) const noexcept override { + *err = hidra2::TextError(hidra2::IOErrors::kPermissionDenied); return {}; }; }; @@ -120,7 +124,7 @@ class FolderDataBrokerTests : public Test { TEST_F(FolderDataBrokerTests, CanConnect) { auto return_code = data_broker->Connect(); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(return_code, Eq(nullptr)); } TEST_F(FolderDataBrokerTests, CannotConnectTwice) { @@ -128,7 +132,7 @@ TEST_F(FolderDataBrokerTests, CannotConnectTwice) { auto return_code = data_broker->Connect(); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kSourceAlreadyConnected)); + ASSERT_THAT(return_code->Explain(), Eq(hidra2::WorkerErrorMessage::kSourceAlreadyConnected)); } @@ -137,7 +141,7 @@ TEST_F(FolderDataBrokerTests, CannotConnectWhenNoFolder) { auto return_code = data_broker->Connect(); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kSourceNotFound)); + ASSERT_THAT(return_code->Explain(), Eq(hidra2::IOErrors::kFileNotFound)); } TEST_F(FolderDataBrokerTests, ConnectReturnsUnknownIOError) { @@ -145,13 +149,13 @@ TEST_F(FolderDataBrokerTests, ConnectReturnsUnknownIOError) { auto return_code = data_broker->Connect(); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kUnknownIOError)); + ASSERT_THAT(return_code->Explain(), Eq(hidra2::IOErrors::kUnknownError)); } TEST_F(FolderDataBrokerTests, GetNextWithoutConnectReturnsError) { auto err = data_broker->GetNext(nullptr, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kSourceNotConnected)); + ASSERT_THAT(err->Explain(), Eq(hidra2::WorkerErrorMessage::kSourceNotConnected)); } TEST_F(FolderDataBrokerTests, GetNextWithNullPointersReturnsError) { @@ -159,7 +163,7 @@ TEST_F(FolderDataBrokerTests, GetNextWithNullPointersReturnsError) { auto err = data_broker->GetNext(nullptr, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kWrongInput)); + ASSERT_THAT(err->Explain(), Eq(hidra2::WorkerErrorMessage::kWrongInput)); } TEST_F(FolderDataBrokerTests, GetNextReturnsFileInfo) { @@ -168,7 +172,7 @@ TEST_F(FolderDataBrokerTests, GetNextReturnsFileInfo) { auto err = data_broker->GetNext(&fi, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(err, Eq(nullptr)); ASSERT_THAT(fi.base_name, Eq("1")); ASSERT_THAT(fi.size, Eq(100)); @@ -181,7 +185,7 @@ TEST_F(FolderDataBrokerTests, SecondNextReturnsAnotherFileInfo) { auto err = data_broker->GetNext(&fi, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(err, Eq(nullptr)); ASSERT_THAT(fi.base_name, Eq("2")); } @@ -191,7 +195,7 @@ TEST_F(FolderDataBrokerTests, GetNextFromEmptyFolderReturnsError) { FileInfo fi; auto err = data_broker->GetNext(&fi, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kNoData)); + ASSERT_THAT(err->Explain(), Eq(hidra2::WorkerErrorMessage::kNoData)); } @@ -202,13 +206,13 @@ TEST_F(FolderDataBrokerTests, GetNextReturnsErrorWhenFilePermissionsDenied) { FileData data; auto err = data_broker->GetNext(&fi, &data); - ASSERT_THAT(err, Eq(WorkerErrorCode::kPermissionDenied)); + ASSERT_THAT(err->Explain(), Eq(hidra2::IOErrors::kPermissionDenied)); } 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, SimpleError**)); }; @@ -230,7 +234,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>(static_cast<SimpleError*>(nullptr)), testing::Return(nullptr))); data_broker->GetNext(&fi, &data); } @@ -239,7 +243,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>(nullptr), testing::Return(new uint8_t[1] {'1'}))); data_broker->GetNext(&fi, &data); @@ -248,22 +252,26 @@ TEST_F(GetDataFromFileTests, GetNextReturnsDataAndInfo) { } + + TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotReadData) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kReadError), testing::Return(nullptr))); + WillOnce(DoAll(testing::SetArgPointee<2>(new SimpleError(hidra2::IOErrors::kReadError)), testing::Return(nullptr))); auto err = data_broker->GetNext(&fi, &data); - ASSERT_THAT(err, Eq(WorkerErrorCode::kErrorReadingSource)); + ASSERT_THAT(err->Explain(), Eq(hidra2::IOErrors::kReadError)); } + TEST_F(GetDataFromFileTests, GetNextReturnsErrorWhenCannotAllocateData) { EXPECT_CALL(mock, GetDataFromFileProxy(_, _, _)). - WillOnce(DoAll(testing::SetArgPointee<2>(IOErrors::kMemoryAllocationError), testing::Return(nullptr))); + WillOnce(DoAll(testing::SetArgPointee<2>(new SimpleError(hidra2::IOErrors::kMemoryAllocationError)), + testing::Return(nullptr))); auto err = data_broker->GetNext(&fi, &data); - ASSERT_THAT(err, Eq(WorkerErrorCode::kMemoryError)); + ASSERT_THAT(err->Explain(), Eq(hidra2::IOErrors::kMemoryAllocationError)); } diff --git a/worker/api/cpp/unittests/test_server_broker.cpp b/worker/api/cpp/unittests/test_server_broker.cpp index a4a542df9..4f0b6614f 100644 --- a/worker/api/cpp/unittests/test_server_broker.cpp +++ b/worker/api/cpp/unittests/test_server_broker.cpp @@ -8,18 +8,19 @@ #include "../src/curl_http_client.h" #include "unittests/MockIO.h" #include "MockHttpClient.h" +#include "../src/http_error.h" using hidra2::DataBrokerFactory; using hidra2::DataBroker; using hidra2::ServerDataBroker; -using hidra2::WorkerErrorCode; using hidra2::IO; -using hidra2::IOErrors; using hidra2::FileInfo; using hidra2::FileData; using hidra2::MockIO; using hidra2::MockHttpClient; using hidra2::HttpCode; +using hidra2::HttpError; +using hidra2::SimpleError; using ::testing::AtLeast; using ::testing::Eq; @@ -64,7 +65,7 @@ class ServerDataBrokerTests : public Test { void MockGet(const std::string& responce) { EXPECT_CALL(mock_http_client, Get_t(_, _, _)).WillOnce(DoAll( SetArgPointee<1>(HttpCode::OK), - SetArgPointee<2>(WorkerErrorCode::kOK), + SetArgPointee<2>(nullptr), Return(responce) )); } @@ -73,19 +74,19 @@ class ServerDataBrokerTests : public Test { TEST_F(ServerDataBrokerTests, CanConnect) { auto return_code = data_broker->Connect(); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(return_code, Eq(nullptr)); } TEST_F(ServerDataBrokerTests, GetNextReturnsErrorOnWrongInput) { auto return_code = data_broker->GetNext(nullptr, nullptr); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kWrongInput)); + ASSERT_THAT(return_code->Explain(), Eq(hidra2::WorkerErrorMessage::kWrongInput)); } TEST_F(ServerDataBrokerTests, GetNextUsesCorrectUri) { EXPECT_CALL(mock_http_client, Get_t("test/database/dbname/next", _, _)).WillOnce(DoAll( SetArgPointee<1>(HttpCode::OK), - SetArgPointee<2>(WorkerErrorCode::kOK), + SetArgPointee<2>(nullptr), Return(""))); data_broker->GetNext(&info, nullptr); } @@ -93,13 +94,13 @@ TEST_F(ServerDataBrokerTests, GetNextUsesCorrectUri) { TEST_F(ServerDataBrokerTests, GetNextReturnsErrorFromHttpClient) { EXPECT_CALL(mock_http_client, Get_t(_, _, _)).WillOnce(DoAll( SetArgPointee<1>(HttpCode::NotFound), - SetArgPointee<2>(WorkerErrorCode::kOK), + SetArgPointee<2>(nullptr), Return(""))); auto err = data_broker->GetNext(&info, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kSourceNotFound)); - + ASSERT_THAT(err->Explain(), Eq(hidra2::WorkerErrorMessage::kSourceNotFound)); + ASSERT_THAT(dynamic_cast<HttpError*>(err.get())->GetCode(), Eq(HttpCode::NotFound)); } FileInfo CreateFI() { @@ -120,7 +121,7 @@ TEST_F(ServerDataBrokerTests, GetNextReturnsFileInfo) { auto err = data_broker->GetNext(&info, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(err, Eq(nullptr)); ASSERT_THAT(info.base_name, Eq(to_send.base_name)); ASSERT_THAT(info.size, Eq(to_send.size)); @@ -134,7 +135,7 @@ TEST_F(ServerDataBrokerTests, GetNextReturnsParseError) { MockGet("error_responce"); auto err = data_broker->GetNext(&info, nullptr); - ASSERT_THAT(err, Eq(WorkerErrorCode::kErrorReadingSource)); + ASSERT_THAT(err->Explain(), Eq(hidra2::WorkerErrorMessage::kErrorReadingSource)); } @@ -153,12 +154,11 @@ TEST_F(ServerDataBrokerTests, GetNextCallsReadFromFile) { MockGet(json); EXPECT_CALL(mock_io, GetDataFromFile_t("relative_path/base_name", 100, _)). - WillOnce(DoAll(SetArgPointee<2>(IOErrors::kReadError), testing::Return(nullptr))); + WillOnce(DoAll(SetArgPointee<2>(new SimpleError{hidra2::IOErrors::kReadError}), testing::Return(nullptr))); FileData data; data_broker->GetNext(&info, &data); } - } diff --git a/worker/api/cpp/unittests/test_worker_api.cpp b/worker/api/cpp/unittests/test_worker_api.cpp index 31f67da9f..d555b769f 100644 --- a/worker/api/cpp/unittests/test_worker_api.cpp +++ b/worker/api/cpp/unittests/test_worker_api.cpp @@ -3,47 +3,52 @@ #include "worker/data_broker.h" #include "../src/folder_data_broker.h" #include "../src/server_data_broker.h" - +#include "common/error.h" using hidra2::DataBrokerFactory; using hidra2::DataBroker; using hidra2::FolderDataBroker; using hidra2::ServerDataBroker; -using hidra2::WorkerErrorCode; - +using hidra2::Error; using ::testing::Eq; using ::testing::Ne; using ::testing::Test; - namespace { -TEST(DataBrokerFactoryTests, CreateFolderDataSource) { - WorkerErrorCode return_code; +class DataBrokerFactoryTests : public Test { + public: + Error error; + void SetUp() override { + error.reset(new hidra2::SimpleError("SomeErrorToBeOverwritten")); + } +}; + + +TEST_F(DataBrokerFactoryTests, CreateFolderDataSource) { - auto data_broker = DataBrokerFactory::CreateFolderBroker("path/to/file", &return_code); + auto data_broker = DataBrokerFactory::CreateFolderBroker("path/to/file", &error); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(error, Eq(nullptr)); ASSERT_THAT(dynamic_cast<FolderDataBroker*>(data_broker.get()), Ne(nullptr)); } -TEST(DataBrokerFactoryTests, FailCreateDataSourceWithEmptySource) { - WorkerErrorCode return_code; +TEST_F(DataBrokerFactoryTests, FailCreateDataSourceWithEmptySource) { - auto data_broker = DataBrokerFactory::CreateFolderBroker("", &return_code); + auto data_broker = DataBrokerFactory::CreateFolderBroker("", &error); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kEmptyDatasource)); - ASSERT_THAT(data_broker.release(), Eq(nullptr)); +// ASSERT_THAT(error->Explain(), Eq(WorkerErrorMessage::kEmptyDatasource)); + ASSERT_THAT(error->Explain(), Eq("Empty Data Source")); + ASSERT_THAT(data_broker.get(), Eq(nullptr)); } -TEST(DataBrokerFactoryTests, CreateServerDataSource) { - WorkerErrorCode return_code; +TEST_F(DataBrokerFactoryTests, CreateServerDataSource) { - auto data_broker = DataBrokerFactory::CreateServerBroker("server", "database", &return_code); + auto data_broker = DataBrokerFactory::CreateServerBroker("server", "database", &error); - ASSERT_THAT(return_code, Eq(WorkerErrorCode::kOK)); + ASSERT_THAT(error, Eq(nullptr)); ASSERT_THAT(dynamic_cast<ServerDataBroker*>(data_broker.get()), Ne(nullptr)); } diff --git a/worker/tools/folder_to_db/src/folder_db_importer.cpp b/worker/tools/folder_to_db/src/folder_db_importer.cpp index 7ddeab6d3..916f06c10 100644 --- a/worker/tools/folder_to_db/src/folder_db_importer.cpp +++ b/worker/tools/folder_to_db/src/folder_db_importer.cpp @@ -11,101 +11,55 @@ namespace hidra2 { using std::chrono::high_resolution_clock; - -FolderToDbImportError MapIOError(IOErrors io_err) { - FolderToDbImportError err; - switch (io_err) { - case IOErrors::kNoError: - err = FolderToDbImportError::kOK; - break; - default: - err = FolderToDbImportError::kIOError; - break; - break; - } - return err; -} - -FolderToDbImportError MapDBError(DBError db_err) { - FolderToDbImportError err; - switch (db_err) { - case DBError::kNoError: - err = FolderToDbImportError::kOK; - break; - case DBError::kConnectionError: - err = FolderToDbImportError::kDBConnectionError; - break; - case DBError::kInsertError: - case DBError::kDuplicateID: - err = FolderToDbImportError::kImportError; - break; - case DBError::kMemoryError: - err = FolderToDbImportError::kMemoryError; - break; - - default: - err = FolderToDbImportError::kUnknownDbError; - break; - } - return err; -} - - FolderToDbImporter::FolderToDbImporter() : io__{new hidra2::SystemIO}, db_factory__{new hidra2::DatabaseFactory} { } -FolderToDbImportError FolderToDbImporter::ConnectToDb(const std::unique_ptr<hidra2::Database>& db) const { - DBError err = db->Connect(db_uri_, db_name_, kDBCollectionName); - return MapDBError(err); +Error FolderToDbImporter::ConnectToDb(const std::unique_ptr<hidra2::Database>& db) const { + return db->Connect(db_uri_, db_name_, kDBCollectionName); } -FolderToDbImportError FolderToDbImporter::ImportSingleFile(const std::unique_ptr<hidra2::Database>& db, - const FileInfo& file) const { - - auto err = db->Insert(file, ignore_duplicates_); - return MapDBError(err); +Error FolderToDbImporter::ImportSingleFile(const std::unique_ptr<hidra2::Database>& db, + const FileInfo& file) const { + return db->Insert(file, ignore_duplicates_); } -FolderToDbImportError FolderToDbImporter::ImportFilelistChunk(const std::unique_ptr<hidra2::Database>& db, - const FileInfos& file_list, uint64_t begin, uint64_t end) const { +Error FolderToDbImporter::ImportFilelistChunk(const std::unique_ptr<hidra2::Database>& db, + const FileInfos& file_list, uint64_t begin, uint64_t end) const { for (auto i = begin; i < end; i++) { auto err = ImportSingleFile(db, file_list[i]); - if (err != FolderToDbImportError::kOK) { + if (err != nullptr) { return err; } } - return FolderToDbImportError::kOK; + return nullptr; } -FolderToDbImportError FolderToDbImporter::PerformParallelTask(const FileInfos& file_list, uint64_t begin, - uint64_t end) const { - FolderToDbImportError err; +Error FolderToDbImporter::PerformParallelTask(const FileInfos& file_list, uint64_t begin, + uint64_t end) const { + Error err; auto db = CreateDbClient(&err); - if (err != FolderToDbImportError::kOK) { + if (err) { return err; } err = ConnectToDb(db); - if (err != FolderToDbImportError::kOK) { + if (err) { return err; } return ImportFilelistChunk(db, file_list, begin, end); } -std::unique_ptr<hidra2::Database> FolderToDbImporter::CreateDbClient(FolderToDbImportError* err) const { - DBError db_err; - auto db = db_factory__->Create(&db_err); - *err = MapDBError(db_err); - return db; +std::unique_ptr<hidra2::Database> FolderToDbImporter::CreateDbClient(Error* err) const { + return db_factory__->Create(err); } -FolderToDbImportError WaitParallelTasks(std::vector<std::future<FolderToDbImportError>>* res) { - FolderToDbImportError err{FolderToDbImportError::kOK}; +Error WaitParallelTasks(std::vector<std::future<Error>>* res) { + Error err{nullptr}; for (auto& fut : *res) { auto task_result = fut.get(); - if (task_result != FolderToDbImportError::kOK) { - err = task_result; + if (task_result != nullptr) { + err = std::move(task_result); } } return err; @@ -120,7 +74,7 @@ TaskSplitParameters ComputeSplitParameters(const FileInfos& file_list, int ntask } void FolderToDbImporter::ProcessNextChunk(const FileInfos& file_list, - std::vector<std::future<FolderToDbImportError>>* res, + std::vector<std::future<Error>>* res, TaskSplitParameters* p) const { p->next_chunk_size = p->chunk + (p->remainder ? 1 : 0); if (p->next_chunk_size == 0) return; @@ -134,10 +88,10 @@ void FolderToDbImporter::ProcessNextChunk(const FileInfos& file_list, if (p->remainder) p->remainder -= 1; } -FolderToDbImportError FolderToDbImporter::ImportFilelist(const FileInfos& file_list) const { +Error FolderToDbImporter::ImportFilelist(const FileInfos& file_list) const { auto split_parameters = ComputeSplitParameters(file_list, n_tasks_); - std::vector<std::future<FolderToDbImportError>>res; + std::vector<std::future<Error>>res; for (unsigned int i = 0; i < n_tasks_; i++) { ProcessNextChunk(file_list, &res, &split_parameters); } @@ -146,24 +100,22 @@ FolderToDbImportError FolderToDbImporter::ImportFilelist(const FileInfos& file_l } -FileInfos FolderToDbImporter::GetFilesInFolder(const std::string& folder, FolderToDbImportError* err) const { - IOErrors err_io; - auto file_list = io__->FilesInFolder(folder, &err_io); - *err = MapIOError(err_io); +FileInfos FolderToDbImporter::GetFilesInFolder(const std::string& folder, Error* err) const { + auto file_list = io__->FilesInFolder(folder, err); return file_list; } -FolderToDbImportError FolderToDbImporter::Convert(const std::string& uri, const std::string& folder, - const std::string& db_name, - FolderImportStatistics* statistics) const { +Error FolderToDbImporter::Convert(const std::string& uri, const std::string& folder, + const std::string& db_name, + FolderImportStatistics* statistics) const { db_uri_ = uri; db_name_ = db_name; auto time_begin = high_resolution_clock::now(); - FolderToDbImportError err; + Error err; auto file_list = GetFilesInFolder(folder, &err); - if (err != FolderToDbImportError::kOK) { + if (err) { return err; } @@ -173,7 +125,7 @@ FolderToDbImportError FolderToDbImporter::Convert(const std::string& uri, const auto time_end_import = high_resolution_clock::now(); - if (err == FolderToDbImportError::kOK && statistics) { + if (err == nullptr && statistics) { statistics->n_files_converted = file_list.size(); statistics->time_read_folder = std::chrono::duration_cast<std::chrono::nanoseconds>( time_end_read_folder - time_begin); statistics->time_import_files = std::chrono::duration_cast<std::chrono::nanoseconds> diff --git a/worker/tools/folder_to_db/src/folder_db_importer.h b/worker/tools/folder_to_db/src/folder_db_importer.h index 4097fd5c9..aecadd203 100644 --- a/worker/tools/folder_to_db/src/folder_db_importer.h +++ b/worker/tools/folder_to_db/src/folder_db_importer.h @@ -8,17 +8,17 @@ #include "system_wrappers/io.h" #include "database/database.h" - +#include "common/error.h" namespace hidra2 { -enum class FolderToDbImportError { - kOK, - kDBConnectionError, - kImportError, - kIOError, - kUnknownDbError, - kMemoryError -}; +namespace FolderToDbImportError { + +auto const kDBConnectionError = "DB Connection Error"; +auto const kImportError = "Import Error"; +auto const kUnknownDbError = "Unknown DB Error"; +auto const kMemoryError = "Memory error"; + +} struct FolderImportStatistics { uint64_t n_files_converted{0}; @@ -40,9 +40,9 @@ class FolderToDbImporter { //! Read folder content and write file to the database. We do not optimize //! the procedure via bulk write to see the performance of a //! single operation (and it is already fast enough) - FolderToDbImportError Convert(const std::string& uri, const std::string& folder, - const std::string& db_name, - FolderImportStatistics* statistics = nullptr) const; + Error Convert(const std::string& uri, const std::string& folder, + const std::string& db_name, + FolderImportStatistics* statistics = nullptr) const; unsigned int SetNParallelTasks(unsigned int ntasks, bool async = true); void IgnoreDuplicates(bool ignore_duplicates = true); @@ -56,18 +56,18 @@ class FolderToDbImporter { bool async_{true}; mutable std::string db_uri_ ; mutable std::string db_name_; - FolderToDbImportError ConnectToDb(const std::unique_ptr<hidra2::Database>& db) const; - FileInfos GetFilesInFolder(const std::string& folder, FolderToDbImportError* err) const; - FolderToDbImportError ImportFilelist(const FileInfos& file_list) const; - FolderToDbImportError PerformParallelTask(const FileInfos& file_list, uint64_t begin, - uint64_t end) const; - FolderToDbImportError ImportSingleFile(const std::unique_ptr<hidra2::Database>& db, - const FileInfo& file) const; - FolderToDbImportError ImportFilelistChunk(const std::unique_ptr<hidra2::Database>& db, - const FileInfos& file_list, uint64_t begin, uint64_t end) const; + Error ConnectToDb(const std::unique_ptr<hidra2::Database>& db) const; + FileInfos GetFilesInFolder(const std::string& folder, Error* err) const; + Error ImportFilelist(const FileInfos& file_list) const; + Error PerformParallelTask(const FileInfos& file_list, uint64_t begin, + uint64_t end) const; + Error ImportSingleFile(const std::unique_ptr<hidra2::Database>& db, + const FileInfo& file) const; + Error ImportFilelistChunk(const std::unique_ptr<hidra2::Database>& db, + const FileInfos& file_list, uint64_t begin, uint64_t end) const; - std::unique_ptr<Database> CreateDbClient(FolderToDbImportError* err) const; - void ProcessNextChunk(const FileInfos& file_list, std::vector<std::future<FolderToDbImportError>>* res, + std::unique_ptr<Database> CreateDbClient(Error* err) const; + void ProcessNextChunk(const FileInfos& file_list, std::vector<std::future<Error>>* res, TaskSplitParameters* p) const; }; diff --git a/worker/tools/folder_to_db/src/main.cpp b/worker/tools/folder_to_db/src/main.cpp index 1d6e3b57b..8e79fed17 100644 --- a/worker/tools/folder_to_db/src/main.cpp +++ b/worker/tools/folder_to_db/src/main.cpp @@ -83,7 +83,7 @@ int main(int argc, char* argv[]) { auto err = importer.Convert(import_params.uri, import_params.folder, import_params.db_name, &statistics); - if (err != hidra2::FolderToDbImportError::kOK) { + if (err != nullptr) { std::cout << "Error import to database" << std::endl; return 1; } 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 28ea39a6f..e7639f043 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 @@ -27,20 +27,22 @@ using ::testing::Ref; using ::testing::Return; using hidra2::FolderToDbImporter; -using hidra2::FolderToDbImportError; using hidra2::Database; using hidra2::DatabaseFactory; using hidra2::IO; -using hidra2::DBError; -using hidra2::IOErrors; using hidra2::kDBCollectionName; using hidra2::FileInfos; using hidra2::FileInfo; using hidra2::MockIO; +using hidra2::Error; +using hidra2::TextError; +using hidra2::SimpleError; + namespace { + TEST(FolderDBConverter, SetCorrectIO) { FolderToDbImporter converter{}; ASSERT_THAT(dynamic_cast<hidra2::SystemIO*>(converter.io__.get()), Ne(nullptr)); @@ -67,10 +69,20 @@ TEST(FolderDBConverter, SetNTasksCorrectly) { } + class MockDatabase : public Database { public: - MOCK_METHOD3(Connect, DBError (const std::string&, const std::string&, const std::string&)); - MOCK_CONST_METHOD2(Insert, DBError (const FileInfo&, bool)); + 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()); @@ -89,12 +101,12 @@ class MockDatabaseFactory : public DatabaseFactory { for (int i = 0; i < n; i++) { auto val = new NiceMock<MockDatabase>; db.push_back(val); - ON_CALL(*val, Connect(_, _, _)) - .WillByDefault(Return(DBError::kNoError)); + ON_CALL(*val, Connect_t(_, _, _)) + .WillByDefault(Return(nullptr)); } } - std::unique_ptr<Database> Create(DBError* err) const noexcept override { - *err = DBError::kNoError; + std::unique_ptr<Database> Create(Error* err) const noexcept override { + *err = nullptr; return std::unique_ptr<Database> {db[n++]}; } ~MockDatabaseFactory() { @@ -105,8 +117,8 @@ class MockDatabaseFactory : public DatabaseFactory { }; class FakeDatabaseFactory : public DatabaseFactory { - std::unique_ptr<Database> Create(DBError* err) const noexcept override { - *err = DBError::kMemoryError; + std::unique_ptr<Database> Create(Error* err) const noexcept override { + *err = hidra2::TextError(hidra2::DBError::kMemoryError); return {}; } }; @@ -141,8 +153,8 @@ class FolderDBConverterTests : public Test { folder = "folder"; db_name = "db_name"; uri = "db_address"; - ON_CALL(mock_io, FilesInFolder(_, _)). - WillByDefault(DoAll(testing::SetArgPointee<1>(IOErrors::kNoError), + ON_CALL(mock_io, FilesInFolder_t(_, _)). + WillByDefault(DoAll(testing::SetArgPointee<1>(nullptr), testing::Return(file_infos))); } void TearDown() override { @@ -151,26 +163,27 @@ class FolderDBConverterTests : public Test { }; + TEST_F(FolderDBConverterTests, ErrorWhenCannotConnect) { - EXPECT_CALL(*(mock_dbf->db[0]), Connect(uri, db_name, kDBCollectionName)). - WillOnce(testing::Return(DBError::kConnectionError)); + EXPECT_CALL(*(mock_dbf->db[0]), Connect_t(uri, db_name, kDBCollectionName)). + WillOnce(testing::Return(new SimpleError(hidra2::DBError::kConnectionError))); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kDBConnectionError)); + ASSERT_THAT(error, Ne(nullptr)); } TEST_F(FolderDBConverterTests, ErrorWhenCannotCreateDbParallel) { int nparallel = 3; - EXPECT_CALL(*(mock_dbf->db[0]), Connect(uri, _, _)). - WillOnce(testing::Return(DBError::kConnectionError)); - EXPECT_CALL(*(mock_dbf->db[1]), Connect(uri, _, _)). - WillOnce(testing::Return(DBError::kConnectionError)); - EXPECT_CALL(*(mock_dbf->db[2]), Connect(uri, _, _)). - WillOnce(testing::Return(DBError::kConnectionError)); + EXPECT_CALL(*(mock_dbf->db[0]), Connect_t(uri, _, _)). + WillOnce(testing::Return(new SimpleError(hidra2::DBError::kConnectionError))); + EXPECT_CALL(*(mock_dbf->db[1]), Connect_t(uri, _, _)). + WillOnce(testing::Return(new SimpleError(hidra2::DBError::kConnectionError))); + EXPECT_CALL(*(mock_dbf->db[2]), Connect_t(uri, _, _)). + WillOnce(testing::Return(new SimpleError(hidra2::DBError::kConnectionError))); converter.SetNParallelTasks(nparallel); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kDBConnectionError)); + ASSERT_THAT(error, Ne(nullptr)); } @@ -182,31 +195,32 @@ TEST_F(FolderDBConverterTests, DBDestructorCalled) { TEST_F(FolderDBConverterTests, ErrorWhenCannotGetFileList) { - EXPECT_CALL(mock_io, FilesInFolder(folder, _)). - WillOnce(DoAll(testing::SetArgPointee<1>(IOErrors::kReadError), + EXPECT_CALL(mock_io, FilesInFolder_t(folder, _)). + WillOnce(DoAll(testing::SetArgPointee<1>(new hidra2::SimpleError("err")), testing::Return(FileInfos {}))); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kIOError)); + ASSERT_THAT(error, Ne(nullptr)); } + + TEST_F(FolderDBConverterTests, PassesIgnoreDuplicates) { - EXPECT_CALL(*(mock_dbf->db[0]), Insert(_, true)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(_, true)).Times(3); converter.IgnoreDuplicates(true); converter.Convert(uri, folder, db_name); } - TEST_F(FolderDBConverterTests, ErrorWhenCannotImportFileListToDb) { - EXPECT_CALL(*(mock_dbf->db[0]), Insert(_, _)). - WillOnce(testing::Return(DBError::kInsertError)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(_, _)). + WillOnce(testing::Return(new SimpleError(hidra2::DBError::kInsertError))); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kImportError)); + ASSERT_THAT(error, Ne(nullptr)); } // a matcher to compare file_infos (size and basename only) for testing purposes @@ -221,53 +235,53 @@ MATCHER_P(CompareFileInfo, file, "") { TEST_F(FolderDBConverterTests, PassesFileListToInsert) { for (auto& file : file_infos) { - EXPECT_CALL(*(mock_dbf->db[0]), Insert(CompareFileInfo(file), _)). - WillOnce(testing::Return(DBError::kNoError)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(CompareFileInfo(file), _)). + WillOnce(testing::Return(nullptr)); } auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kOK)); + ASSERT_THAT(error, Eq(nullptr)); } TEST_F(FolderDBConverterTests, PassesFileListToInsertInParallel3by3) { - EXPECT_CALL(*(mock_dbf->db[0]), Insert(CompareFileInfo(file_infos[0]), _)). - WillOnce(testing::Return(DBError::kNoError)); - EXPECT_CALL(*(mock_dbf->db[1]), Insert(CompareFileInfo(file_infos[1]), _)). - WillOnce(testing::Return(DBError::kNoError)); - EXPECT_CALL(*(mock_dbf->db[2]), Insert(CompareFileInfo(file_infos[2]), _)). - WillOnce(testing::Return(DBError::kNoError)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(CompareFileInfo(file_infos[0]), _)). + WillOnce(testing::Return(nullptr)); + EXPECT_CALL(*(mock_dbf->db[1]), Insert_t(CompareFileInfo(file_infos[1]), _)). + WillOnce(testing::Return(nullptr)); + EXPECT_CALL(*(mock_dbf->db[2]), Insert_t(CompareFileInfo(file_infos[2]), _)). + WillOnce(testing::Return(nullptr)); converter.SetNParallelTasks(3, false); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kOK)); + ASSERT_THAT(error, Eq(nullptr)); } TEST_F(FolderDBConverterTests, PassesFileListToInsertInParallel3by2) { - EXPECT_CALL(*(mock_dbf->db[0]), Insert(CompareFileInfo(file_infos[0]), _)). - WillOnce(testing::Return(DBError::kNoError)); - EXPECT_CALL(*(mock_dbf->db[0]), Insert(CompareFileInfo(file_infos[1]), _)). - WillOnce(testing::Return(DBError::kNoError)); - EXPECT_CALL(*(mock_dbf->db[1]), Insert(CompareFileInfo(file_infos[2]), _)). - WillOnce(testing::Return(DBError::kNoError)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(CompareFileInfo(file_infos[0]), _)). + WillOnce(testing::Return(nullptr)); + EXPECT_CALL(*(mock_dbf->db[0]), Insert_t(CompareFileInfo(file_infos[1]), _)). + WillOnce(testing::Return(nullptr)); + EXPECT_CALL(*(mock_dbf->db[1]), Insert_t(CompareFileInfo(file_infos[2]), _)). + WillOnce(testing::Return(nullptr)); converter.SetNParallelTasks(2, false); auto error = converter.Convert(uri, folder, db_name); - ASSERT_THAT(error, Eq(FolderToDbImportError::kOK)); + ASSERT_THAT(error, Eq(nullptr)); } TEST_F(FolderDBConverterTests, ComputesStatistics) { - EXPECT_CALL(*mock_dbf->db[0], Insert(_, false)). + EXPECT_CALL(*mock_dbf->db[0], Insert_t(_, false)). Times(file_infos.size()). - WillRepeatedly(testing::Return(DBError::kNoError)); + WillRepeatedly(testing::Return(nullptr)); hidra2::FolderImportStatistics statistics; auto error = converter.Convert(uri, folder, db_name, &statistics); - ASSERT_THAT(error, Eq(FolderToDbImportError::kOK)); + ASSERT_THAT(error, Eq(nullptr)); ASSERT_THAT(statistics.n_files_converted, Eq(file_infos.size())); // tests may fail is function call is smaller than 1 ns ASSERT_THAT(statistics.time_read_folder.count(), Gt(0)); @@ -280,7 +294,7 @@ TEST_F(FolderDBConverterTests, ErrorWhenCannotCreateDB) { auto err = converter.Convert("", "", ""); - ASSERT_THAT(err, Eq(FolderToDbImportError::kMemoryError)); + ASSERT_THAT(err, Ne(nullptr)); } -- GitLab