From e76844d484adfb274d01fcf538d704279cb8ae67 Mon Sep 17 00:00:00 2001 From: kongr45gpen <electrovesta@gmail.com> Date: Thu, 14 Mar 2019 05:14:38 +0200 Subject: [PATCH] Separate ErrorHandler logging into Platforms --- CMakeLists.txt | 3 ++- inc/ErrorHandler.hpp | 37 +++++++++++++++++++++------- src/ErrorHandler.cpp | 25 +------------------ src/Platform/x86/ErrorHandler.cpp | 40 +++++++++++++++++++++++++++++++ test/Services/ServiceTests.hpp | 22 +++++++++++++++++ test/TestPlatform.cpp | 20 ++++++++++++++++ 6 files changed, 113 insertions(+), 34 deletions(-) create mode 100644 src/Platform/x86/ErrorHandler.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 069449e4..a36a71fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,10 +30,11 @@ add_library(common OBJECT ) # Specify the .cpp files for the executables +file(GLOB x86_main_SRC "src/Platform/x86/*.cpp") add_executable(ecss_services src/main.cpp $<TARGET_OBJECTS:common> - src/Platform/x86/Service.cpp + ${x86_main_SRC} ) IF (EXISTS "${PROJECT_SOURCE_DIR}/lib/Catch2/CMakeLists.txt") diff --git a/inc/ErrorHandler.hpp b/inc/ErrorHandler.hpp index 25c65960..46dfa145 100644 --- a/inc/ErrorHandler.hpp +++ b/inc/ErrorHandler.hpp @@ -15,20 +15,13 @@ class Message; class ErrorHandler { private: /** - * Log the error to a logging facility. Currently, this just displays the error on the screen. - * - * @todo This function MUST be moved as platform-dependent code. Currently, it uses g++ specific - * functions for desktop. + * Log the error to a logging facility. Platform-dependent. */ template<typename ErrorType> static void logError(const Message &message, ErrorType errorType); /** - * Log an error without a Message to a logging facility. Currently, this just displays the error - * on the screen. - * - * @todo This function MUST be moved as platform-dependent code. Currently, it uses g++ specific - * functions for desktop. + * Log an error without a Message to a logging facility. Platform-dependent. */ template<typename ErrorType> static void logError(ErrorType errorType); @@ -212,6 +205,32 @@ public: reportError(message, errorCode); } } + + /** + * Convert a parameter given in C++ to an ErrorSource that can be easily used in comparisons. + * @tparam ErrorType One of the enums specified in ErrorHandler. + * @param error An error code of a specific type + * @return The corresponding ErrorSource + */ + template<typename ErrorType> + inline static ErrorSource findErrorSource(ErrorType error) { + // While this may seem like a "hacky" way to convert enums to ErrorSource, it should be + // optimised by the compiler to constant time. + + if (typeid(ErrorType) == typeid(AcceptanceErrorType)) { + return Acceptance; + } else if (typeid(ErrorType) == typeid(ExecutionStartErrorType)) { + return ExecutionStart; + } else if (typeid(ErrorType) == typeid(ExecutionProgressErrorType)) { + return ExecutionProgress; + } else if (typeid(ErrorType) == typeid(ExecutionCompletionErrorType)) { + return ExecutionCompletion; + } else if (typeid(ErrorType) == typeid(RoutingErrorType)) { + return Routing; + } else { + return Internal; + } + } }; #endif //PROJECT_ERRORHANDLER_HPP diff --git a/src/ErrorHandler.cpp b/src/ErrorHandler.cpp index d62eadd5..73ef5e06 100644 --- a/src/ErrorHandler.cpp +++ b/src/ErrorHandler.cpp @@ -43,28 +43,5 @@ void ErrorHandler::reportError(const Message &message, RoutingErrorType errorCod } void ErrorHandler::reportInternalError(ErrorHandler::InternalErrorType errorCode) { - logError(UnknownInternalError); -} - -template<typename ErrorType> -void ErrorHandler::logError(const Message &message, ErrorType errorType) { - std::cerr - /* - * Gets the error class name from the template - * Note: This is g++-dependent code and should only be used for debugging. - */ - << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) - << " Error " << "[" << static_cast<uint16_t>(message.serviceType) << "," << - static_cast<uint16_t>(message.messageType) << "]: " << errorType << std::endl; -} - -template<typename ErrorType> -void ErrorHandler::logError(ErrorType errorType) { - std::cerr - /* - * Gets the error class name from the template - * Note: This is g++-dependent code and should only be used for debugging. - */ - << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) - << " Error: " << errorType << std::endl; + logError(errorCode); } diff --git a/src/Platform/x86/ErrorHandler.cpp b/src/Platform/x86/ErrorHandler.cpp new file mode 100644 index 00000000..6119440c --- /dev/null +++ b/src/Platform/x86/ErrorHandler.cpp @@ -0,0 +1,40 @@ +/** + * This file specifies the logging utilities for x86 desktop platforms. These logging functions + * just print the error to screen (via stderr). + */ + +#include <iostream> +#include <cxxabi.h> +#include <ErrorHandler.hpp> +#include <Message.hpp> + +// TODO: Find a way to reduce the number of copies of this chunk +template void ErrorHandler::logError(const Message &, ErrorHandler::AcceptanceErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionStartErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionProgressErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionCompletionErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::RoutingErrorType); +template void ErrorHandler::logError(ErrorHandler::InternalErrorType); + +template<typename ErrorType> +void ErrorHandler::logError(const Message &message, ErrorType errorType) { + std::cerr + /* + * Gets the error class name from the template + * Note: This is g++-dependent code and should only be used for debugging. + */ + << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) + << " Error " << "[" << static_cast<uint16_t>(message.serviceType) << "," << + static_cast<uint16_t>(message.messageType) << "]: " << errorType << std::endl; +} + +template<typename ErrorType> +void ErrorHandler::logError(ErrorType errorType) { + std::cerr + /* + * Gets the error class name from the template + * Note: This is g++-dependent code and should only be used for debugging. + */ + << abi::__cxa_demangle(typeid(ErrorType).name(), nullptr, nullptr, nullptr) + << " Error: " << errorType << std::endl; +} diff --git a/test/Services/ServiceTests.hpp b/test/Services/ServiceTests.hpp index a160558a..ede8804c 100644 --- a/test/Services/ServiceTests.hpp +++ b/test/Services/ServiceTests.hpp @@ -2,6 +2,7 @@ #define ECSS_SERVICES_TESTS_SERVICES_SERVICETESTS_HPP #include <vector> +#include <map> #include <Message.hpp> /** @@ -10,8 +11,18 @@ * @todo See if members of this class can be made non-static */ class ServiceTests { + /** + * The list of Messages that have been sent as a result of all the processing. + */ static std::vector<Message> queuedMessages; + /** + * The list of Errors that the ErrorHandler caught + * @var A multimap with keys (ErrorSource, ErrorType) and values of 1 + * @todo If errors get more complex, this should hold the complete error information + */ + static std::multimap<std::pair<ErrorHandler::ErrorSource, uint16_t>, bool> thrownErrors; + public: /** * Get a message from the list of queued messages to send @@ -28,6 +39,17 @@ public: queuedMessages.push_back(message); } + /** + * Add one error to the list of occurred errors. + * + * @param errorSource The source of the error. + * @param errorCode The integer code of the error, coming directly from one of the ErrorCode + * enumerations in ErrorHandler. + */ + static void addError(ErrorHandler::ErrorSource errorSource, uint16_t errorCode) { + thrownErrors.emplace(std::make_pair(errorSource, errorCode), 1); + } + /** * Counts the number of messages in the queue */ diff --git a/test/TestPlatform.cpp b/test/TestPlatform.cpp index 10f9cdf3..192802cd 100644 --- a/test/TestPlatform.cpp +++ b/test/TestPlatform.cpp @@ -5,12 +5,32 @@ #include <Service.hpp> #include "Services/ServiceTests.hpp" +template void ErrorHandler::logError(const Message &, ErrorHandler::AcceptanceErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionStartErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionProgressErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::ExecutionCompletionErrorType); +template void ErrorHandler::logError(const Message &, ErrorHandler::RoutingErrorType); +template void ErrorHandler::logError(ErrorHandler::InternalErrorType); + std::vector<Message> ServiceTests::queuedMessages = std::vector<Message>(); +std::multimap<std::pair<ErrorHandler::ErrorSource, uint16_t>, bool> ServiceTests::thrownErrors = + std::multimap<std::pair<ErrorHandler::ErrorSource, uint16_t>, bool>(); void Service::storeMessage(const Message &message) { + // Just add the message to the queue ServiceTests::queue(message); } +template<typename ErrorType> +void ErrorHandler::logError(const Message &message, ErrorType errorType) { + logError(errorType); +} + +template<typename ErrorType> +void ErrorHandler::logError(ErrorType errorType) { + ServiceTests::addError(ErrorHandler::findErrorSource(errorType), errorType); +} + struct ServiceTestsListener : Catch::TestEventListenerBase { using TestEventListenerBase::TestEventListenerBase; // inherit constructor -- GitLab