diff --git a/CMakeLists.txt b/CMakeLists.txt index 3821b8e..7dd8ad3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(adl VERSION 0.1.0 LANGUAGES CXX) set(GLOBAL PROPERTY SONAME 0) +set(GLOBAL PROPERTY PROJECT_BRIEF "Abstract Domain Library, a C++ library implementing the octagon domain in CPU and GPU.") # For C++14 support set(CMAKE_CXX_STANDARD 14) @@ -53,6 +54,8 @@ target_sources(${api} INTERFACE "${api_dir_root}/adl.cfg.hpp" "${api_dir_root}/adl/config.hpp" "${api_dir_root}/adl/intl.hpp" + "${api_dir_root}/adl/error.fwd.hpp" + "${api_dir_root}/adl/error.hpp" # adl/util "${api_dir_root}/adl/util.hpp" @@ -102,12 +105,32 @@ set(test_dir_root "${CMAKE_CURRENT_SOURCE_DIR}/test") set(test_dir_unit "${CMAKE_CURRENT_SOURCE_DIR}/test/unit") add_executable(${test} "${test_dir_unit}/main.unit.cpp" + + # adl + "${test_dir_unit}/adl/config.unit.cpp" + "${test_dir_unit}/adl/intl.unit.cpp" + "${test_dir_unit}/adl/error.unit.cpp" ) target_link_libraries(${test} ${test_iapi}) enable_testing() add_test(NAME ${test} COMMAND "./${test}") +# +# [ DOCUMENTATION GENERATION ] +# + + +find_package(Doxygen) +if(DOXYGEN_FOUND) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) +endif(DOXYGEN_FOUND) + # # [ CMAKE DEBUGGING ] # diff --git a/Doxyfile b/Doxyfile.in similarity index 99% rename from Doxyfile rename to Doxyfile.in index dff0783..2983c0d 100644 --- a/Doxyfile +++ b/Doxyfile.in @@ -32,19 +32,19 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = adl +PROJECT_NAME = @PROJECT_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.1.0 +PROJECT_NUMBER = @PROJECT_VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "Abstract Domain Library, a C++ library implementing the octagon domain in CPU and GPU." +PROJECT_BRIEF = @PROJECT_BRIEF@ # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = build/docs +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/docs # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -790,7 +790,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = include +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -889,7 +889,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = *.fwd.hpp # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -2040,7 +2040,7 @@ ENABLE_PREPROCESSING = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # the macro expansion is limited to the macros specified with the PREDEFINED and @@ -2080,7 +2080,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = @PROJECT_NAME@_BUILDING_DOCS # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/include/adl.cfg.hpp b/include/adl.cfg.hpp index bd2340c..ebad14a 100644 --- a/include/adl.cfg.hpp +++ b/include/adl.cfg.hpp @@ -5,48 +5,6 @@ #ifndef adl__cfg__hpp__ #define adl__cfg__hpp__ - -// -// [[ DOCUMENTATION ]] -// - -/** - * @def adl_NO_EXCEPTIONS - * If defined, sets adl_CONFIG_IS_USING_EXCEPTIONS to @c false. - * @sa adl_CONFIG_IS_USING_EXCEPTIONS - */ - -/** - * @def adl_DEBUG - * If defined, sets adl_CONFIG_IS_DEBUG to @c true. - * @sa adl_CONFIG_IS_DEBUG - */ - -/** - * @def adl_STRIPPED - * If defined, sets adl_CONFIG_IS_STRIPPED_BINARY to @c true. - * @sa adl_CONFIG_IS_STRIPPED_BINARY - */ - -/** - * @def adl_CONFIG_IS_USING_EXCEPTIONS - * Determines if the library will default to throw exceptions on errors or not. The API is prepared to handle - * both cases, and some dependencies (e.g. OpenCL's cl2.hpp) may follow suit automatically. - */ - -/** - * @def adl_CONFIG_IS_DEBUG - * If @c true, enables more runtime information. This flag acts more like an instruction for the implementation to - * output more information and than to reduce the binary size. For that, adl_STRIPPED should be defined. - */ - -/** - * @def adl_CONFIG_IS_STRIPPED_BINARY - * If @c true, enables symbol stripping (at the language and TU level). - * Stripping removes additional debugging information and additional symbols. The resulting binary is therefore smaller. - * As of now, it disables error conditions' descriptions. - */ - // // [[ CONFIGURABLE DEFINITIONS ]] // @@ -62,6 +20,8 @@ #define adl_CONFIG_VERSION_ABI 0 // Increased at each breaking change, major bump certainly bumps ABI version, minor bump should not (but may?) lead to abi bump +#ifndef adl_BUILDING_DOCS + // // [[ PREPROCESSOR FLAGS ]] // @@ -223,4 +183,56 @@ #define adl_IMPL inline +#else + +#define adl_API +#define adl_IAPI +#define adl_VAR +#define adl_IVAR +#define adl_CLASS +#define adl_ICLASS +#define adl_IMPL inline + +// +// [[ DOCUMENTATION ]] +// + +/** + * User-provided: If defined, sets adl_CONFIG_IS_USING_EXCEPTIONS to @c false. + * @sa adl_CONFIG_IS_USING_EXCEPTIONS + */ +#define adl_NO_EXCEPTIONS + +/** + * User-provided: If defined, sets adl_CONFIG_IS_DEBUG to @c true. + * @sa adl_CONFIG_IS_DEBUG + */ +#define adl_DEBUG + +/** + * User-provided: If defined, sets adl_CONFIG_IS_STRIPPED_BINARY to @c true. + * @sa adl_CONFIG_IS_STRIPPED_BINARY + */ +#define adl_STRIPPED + +/** + * Determines if the library will default to throw exceptions on errors or not. The API is prepared to handle + * both cases, and some dependencies (e.g. OpenCL's cl2.hpp) may follow suit automatically. + */ +#define adl_CONFIG_IS_USING_EXCEPTIONS + +/** + * If @c true, enables more runtime information. This flag acts more like an instruction for the implementation to + * output more information and than to reduce the binary size. For that, adl_STRIPPED should be defined. + */ +#define adl_CONFIG_IS_DEBUG + +/** + * If @c true, enables symbol stripping (at the language and TU level). + * Stripping removes additional debugging information and additional symbols. The resulting binary is therefore smaller. + * As of now, it disables error conditions' descriptions. + */ +#define adl_CONFIG_IS_STRIPPED_BINARY + +#endif // adl_BUILDING_DOCS #endif // adl__cfg__hpp__ diff --git a/include/adl.fwd.hpp b/include/adl.fwd.hpp index 81091ef..2f711c2 100644 --- a/include/adl.fwd.hpp +++ b/include/adl.fwd.hpp @@ -2,15 +2,9 @@ /** * @file adl.fwd.hpp */ -#pragma once #ifndef adl__fwd__hpp__ #define adl__fwd__hpp__ -#include "adl.cfg.hpp" -adl_BEGIN_ROOT_MODULE - - -adl_END_ROOT_MODULE #endif // adl__fwd__hpp__ diff --git a/include/adl.hpp b/include/adl.hpp index ef6a697..a1b5eff 100644 --- a/include/adl.hpp +++ b/include/adl.hpp @@ -2,7 +2,6 @@ /** * @file adl.hpp */ -#pragma once #ifndef adl__hpp__ #define adl__hpp__ @@ -11,6 +10,7 @@ // Utility components/modules #include "adl/config.hpp" #include "adl/intl.hpp" +#include "adl/error.hpp" // Main modules #include "adl/util.hpp" diff --git a/include/adl/config.hpp b/include/adl/config.hpp index 14258c9..1d913a0 100644 --- a/include/adl/config.hpp +++ b/include/adl/config.hpp @@ -2,23 +2,25 @@ /** * @file config.hpp */ -#pragma once #ifndef adl__config__hpp__ #define adl__config__hpp__ #include "adl.cfg.hpp" -adl_BEGIN_MAIN_MODULE(config) +adl_BEGIN_ROOT_MODULE -constexpr char const* const name = adl_CONFIG_NAME_STR; -namespace version { - constexpr char const* const name = adl_CONFIG_VERSION_STR; - constexpr int const major = adl_CONFIG_VERSION_MAJOR; - constexpr int const minor = adl_CONFIG_VERSION_MINOR; - constexpr int const patch = adl_CONFIG_VERSION_PATCH; - constexpr int const abi = adl_CONFIG_VERSION_ABI; +namespace config { + + constexpr char const* const name = adl_CONFIG_NAME_STR; + namespace version { + constexpr char const* const name = adl_CONFIG_VERSION_STR; + constexpr int const major = adl_CONFIG_VERSION_MAJOR; + constexpr int const minor = adl_CONFIG_VERSION_MINOR; + constexpr int const patch = adl_CONFIG_VERSION_PATCH; + constexpr int const abi = adl_CONFIG_VERSION_ABI; + } } -adl_END_MAIN_MODULE +adl_END_ROOT_MODULE #endif //adl__config__hpp__ diff --git a/include/adl/error.fwd.hpp b/include/adl/error.fwd.hpp new file mode 100644 index 0000000..224298c --- /dev/null +++ b/include/adl/error.fwd.hpp @@ -0,0 +1,45 @@ +// $flisboac 2017-03-19 +/** + * @file error.fwd.hpp + */ +#ifndef adl__error__fwd__hpp__ +#define adl__error__fwd__hpp__ + + +#include +#include + +#include "adl.cfg.hpp" + + +adl_BEGIN_ROOT_MODULE + +// +// error.hpp +// + +template using enable_if_error_context_enum_t = std::enable_if_t< + std::is_error_condition_enum::value, T>; +template using enable_if_error_enum_t = std::enable_if_t< + std::is_error_condition_enum::value || std::is_error_code_enum::value, T>; + +using error_id_type = int; // will always be int, for compatibility with and everything else that's an error code +using error_condition = std::error_condition; // will not change, but for library use we have error_info +using error_code = std::error_code; // will not change + +enum class error_kind_id; +using error_id = std::errc; // may be substituted in the future (and by that I mean before v1.0) by a custom enum class, but keeping the enum values already in use. + +using error_category = std::error_category; + class library_error_kind_category; + class external_error_category; + using library_error_category = decltype(std::generic_category()); // when we get a custom error_id, library_category will have its own class as well +using error_info = error_condition; // In the future, error_info will be its own class, with the same interface as in error_condition and possibly additional contextual information (a la boost::exception). + +class exception; // everything is a runtime_exception unless stated otherwise, language errors are not encapsulated (e.g. std::bad_*) + class client_exception; // errors that have origins on user-provided data or intervention (e.g. invalid arguments, etc) + class internal_exception; // error originated from the system, may be recoverable but it's not caused by users of the library + +adl_END_ROOT_MODULE + +#endif //adl__error__fwd__hpp__ diff --git a/include/adl/error.hpp b/include/adl/error.hpp new file mode 100644 index 0000000..ec2526f --- /dev/null +++ b/include/adl/error.hpp @@ -0,0 +1,328 @@ +// $flisboac 2017-03-01 +/** + * @file error.hpp + */ +#ifndef adl__error__hpp__ +#define adl__error__hpp__ + + +#include +#include +#include +#include +#include + +#include "adl/error.fwd.hpp" + +#include "adl/config.hpp" +#include "adl/intl.hpp" + + +adl_BEGIN_ROOT_MODULE + +enum class error_kind_id : error_id_type { + warning = -2, + ok = 0, + client_error, + error + // No critical_error for now +}; + + +template > + constexpr error_id_type error_enum_to_int(T elem) noexcept; +template > + error_info make_error_info(T enum_value); +adl_API library_error_category const& library_category() noexcept; +adl_API library_error_kind_category const& error_kind_category() noexcept; +adl_API external_error_category const& external_category() noexcept; +adl_API error_info const& done(error_info const& error); + +class adl_CLASS library_error_kind_category : public error_category { +private: + using superclass_ = error_category; +public: + using error_category::error_category; + virtual ~library_error_kind_category() {} + + virtual const char* name() const noexcept; + virtual std::string message(error_id_type value) const; + virtual bool equivalent(error_id_type value, error_condition const& einfo) const noexcept; +}; + + +class adl_CLASS external_error_category : public error_category { +private: + using superclass_ = error_category; +public: + using error_category::error_category; + virtual ~external_error_category() {} + + virtual const char* name() const noexcept; + virtual std::string message(error_id_type value) const; + virtual bool equivalent(error_id_type value, error_condition const& einfo) const noexcept; +}; + + +class adl_CLASS exception : public std::runtime_error { +private: + using superclass_ = std::runtime_error; +public: + exception(const exception&) = default; + virtual exception& operator=(const exception& rhs) = default; + virtual ~exception() {} + + exception(error_info context); + exception(error_info context, const char* what) noexcept; + exception(error_info context, std::string const& what) noexcept; + + const error_info& error() const noexcept; + virtual std::string message() const; + +private: + error_info error_; +}; + +class adl_CLASS client_exception : public exception { +public: + using exception::exception; +}; + +class adl_CLASS internal_exception : public exception { +public: + using exception::exception; +}; + + +adl_END_ROOT_MODULE + +namespace std { + +template <> struct is_error_condition_enum : std::true_type {}; + +adl_API std::error_condition make_error_condition(adl::error_kind_id id) { + return std::error_condition(static_cast(id), adl::error_kind_category()); +} + +} + + +// +// [[ TEMPLATE IMPLEMENTATION ]] +// + + +adl_BEGIN_ROOT_MODULE + + +template +constexpr error_id_type error_enum_to_int(T elem) noexcept { + return static_cast(elem); +}; + +template +adl_IMPL error_info make_error_info(T enum_value) { + return std::make_error_condition(enum_value); +}; + + +adl_END_ROOT_MODULE + + +// +// [[ NON-TEMPLATE IMPLEMENTATION ]] +// + + +adl_BEGIN_ROOT_MODULE + +// functions + +adl_IMPL const library_error_kind_category& error_kind_category() noexcept { + static library_error_kind_category category; + return category; +} + +adl_IMPL const library_error_category& library_category() noexcept { + return std::generic_category(); +} + +adl_IMPL const external_error_category& external_category() noexcept { + static external_error_category category; + return category; +} + +adl_IMPL error_info const& done(error_info const& error) { + error_info error_kind = make_error_info(error_kind_id::error); + error_info client_error_kind = make_error_info(error_kind_id::client_error); + + if (error_kind == error) { + throw internal_exception(error); + } else if (client_error_kind == error) { + throw client_exception(error); + } + + return error; +} + +// library_error_kind_category + +adl_IMPL const char* library_error_kind_category::name() const noexcept { + return "adl::error_kind"; +} + +adl_IMPL std::string library_error_kind_category::message(error_id_type value) const { + #if !adl_CONFIG_IS_STRIPPED_BINARY + using namespace literals::intl_; + switch (value) { + case error_enum_to_int(error_kind_id::warning): return "A warning has been raised."_intl; + case error_enum_to_int(error_kind_id::ok): return ""; + case error_enum_to_int(error_kind_id::client_error): return "A recoverable error ocurred."_intl; + case error_enum_to_int(error_kind_id::error): return "An error ocurred."_intl; + } + return "Unknown error kind."; + #else + return ""; + #endif +} + +adl_IMPL bool library_error_kind_category::equivalent(error_id_type value, error_condition const& einfo) const noexcept { + bool equivalent = false; + if (einfo.category() == error_kind_category()) { + equivalent = superclass_::equivalent(value, einfo); + } else if (einfo.category() == library_category()) { + // NOTE Only valid as long as there's no custom class for library_category. + switch (value) { + case error_enum_to_int(error_kind_id::ok): + equivalent = !einfo; + break; + case error_enum_to_int(error_kind_id::error): + equivalent = !!einfo; + break; + } + } else { + equivalent = (einfo == default_error_condition(value)); + } + return equivalent; +} + +// external_error_category + +adl_IMPL const char* external_error_category::name() const noexcept{ + return "adl::external_category"; +} + +adl_IMPL std::string external_error_category::message(error_id_type value) const { + #if !adl_CONFIG_IS_STRIPPED_BINARY + using namespace literals::intl_; + std::string msg; + if (value != 0) { + msg = "An error or warning ocurred."_intl; + } else { + msg = "Success."_intl; + } + return msg; + #else + return ""; + #endif +} + +adl_IMPL bool external_error_category::equivalent(error_id_type value, error_condition const& einfo) const noexcept { + if (einfo.category() == error_kind_category()) { + if (value != 0) { + return error_kind_category().equivalent(einfo.value(), std::make_error_condition(error_kind_id::error)); + } else { + return error_kind_category().equivalent(einfo.value(), std::make_error_condition(error_kind_id::ok)); + } + // NOTE Critical and client error conditions are to be included by subclasses of external_error_category. + } + return superclass_::equivalent(value, einfo); +} + +// exception + +adl_IMPL exception::exception(error_info context) : + superclass_(context.message()), error_(context) +{} + +adl_IMPL exception::exception(error_info context, const char* what) noexcept : + superclass_(what), error_(context) +{} + +adl_IMPL exception::exception(error_info context, std::string const& what) noexcept : + superclass_(what), error_(context) +{} + +adl_IMPL const error_info& exception::error() const noexcept { + return error_; +} + +adl_IMPL std::string exception::message() const { + return error_.message(); +} + +adl_END_ROOT_MODULE + + +// +// [[[ DOCUMENTATION ]]] +// + +adl_BEGIN_ROOT_MODULE + +// error_kind_id + +/** + * @enum error_kind_id + * Enumerates all types of errors that are relevant to the library. + * + * The library uses this enumeration for determining when a specific error condition (or error code) value is subject + * to special treatment. The library uses `std::error_category` machinery to convert codes from different places into + * something it can work with. + */ + +/** + * @var error_kind_id::warning + * + * The code for abnormal situations that can be ignored or recovered from. In other words, it is intended to + * represent operations that are not entirely successful, and is used to notify both the user and the library's + * implementation of that fact. The state of the program should continue to be valid and usable after raising a + * warning; if that's not the case, an error must be raised instead. Also, because of the said reasoning, warning + * conditions should not be eligible for exception throwing, except in cases where the user forces warnings to + * be treated as errors. + * + * If warnings are treated as errors, its default exception class should be `adl::internal_exception`. + */ + +/** + * @var error_kind_id::ok + * The code for normal situations or completely ignored conditions. + */ + +/** + * @var error_kind_id::client_error + * A client error is a recoverable condition caused by misuse of the library, to some extent. Cases such as + * missing parameters and invalid inputs can be considered client errors, and their recovery stays entirely at the + * client's discretion. The library's state should still be valid and usable after a client error occurs, so as to + * allow the client to correct the faulty conditions. + * + * The default exception class for client errors is `adl::client_exception`. + * + * @see `adl::client_exception` + */ + +/** + * @var error_kind_id::error + * The default code for faulty conditions. These may be recoverable or not, and that depends solely + * on domain knowledge (e.g. read the operation's description, it should give a clue on the after-state of the + * library). When confronted with an error-kind code, the library will most likely raise an exception or + * cancel the operation. + * + * The default exception class for errors is `adl::internal_exception`. + * + * @see adl::internal_exception + */ + +adl_END_ROOT_MODULE + +#endif // adl__error_info__hpp__ diff --git a/include/adl/intl.hpp b/include/adl/intl.hpp index b9f8dab..82ea3c3 100644 --- a/include/adl/intl.hpp +++ b/include/adl/intl.hpp @@ -2,7 +2,6 @@ /** * @file intl.hpp */ -#pragma once #ifndef adl__intl__hpp__ #define adl__intl__hpp__ diff --git a/include/adl/oct.fwd.hpp b/include/adl/oct.fwd.hpp index 85d3083..f4ffd71 100644 --- a/include/adl/oct.fwd.hpp +++ b/include/adl/oct.fwd.hpp @@ -2,7 +2,6 @@ /** * @file oct.fwd.hpp.hpp */ -#pragma once #ifndef adl__oct__fwd__hpp__ #define adl__oct__fwd__hpp__ diff --git a/include/adl/oct.hpp b/include/adl/oct.hpp index b51d216..51ce67b 100644 --- a/include/adl/oct.hpp +++ b/include/adl/oct.hpp @@ -2,7 +2,6 @@ /** * @file oct.hpp */ -#pragma once #ifndef adl__oct__hpp__ #define adl__oct__hpp__ diff --git a/include/adl/oct/domain_space.hpp b/include/adl/oct/domain_space.hpp index 85766f9..453f750 100644 --- a/include/adl/oct/domain_space.hpp +++ b/include/adl/oct/domain_space.hpp @@ -2,7 +2,6 @@ /** * @file domain_space.hpp */ -#pragma once #ifndef adl__oct__domain_space__hpp__ #define adl__oct__domain_space__hpp__ diff --git a/include/adl/oct/dsl.hpp b/include/adl/oct/dsl.hpp index 75c28bb..25622f7 100644 --- a/include/adl/oct/dsl.hpp +++ b/include/adl/oct/dsl.hpp @@ -2,7 +2,6 @@ /** * @file dsl.hpp.hpp */ -#pragma once #ifndef adl__oct__dsl__hpp__ #define adl__oct__dsl__hpp__ diff --git a/include/adl/util.fwd.hpp b/include/adl/util.fwd.hpp index 97802f6..996120f 100644 --- a/include/adl/util.fwd.hpp +++ b/include/adl/util.fwd.hpp @@ -2,7 +2,6 @@ /** * @file util.fwd.hpp */ -#pragma once #ifndef adl__util__fwd__hpp__ #define adl__util__fwd__hpp__ diff --git a/include/adl/util.hpp b/include/adl/util.hpp index d56ac31..0b4c07f 100644 --- a/include/adl/util.hpp +++ b/include/adl/util.hpp @@ -2,7 +2,6 @@ /** * @file util.hpp */ -#pragma once #ifndef adl__util__hpp__ #define adl__util__hpp__ diff --git a/test/include/adl_catch/macros.hpp b/test/include/adl_catch/macros.hpp index c32780d..68214c3 100644 --- a/test/include/adl_catch/macros.hpp +++ b/test/include/adl_catch/macros.hpp @@ -9,5 +9,6 @@ #include "catch.hpp" #define REQUIRE_SECTION(test__, name__) SECTION( (name__) ) { REQUIRE( (test__) ); } +#define REQUIRE_SECTION_THROWS_AS(test__, exception__, name__) SECTION( (name__) ) { REQUIRE_THROWS_AS( (test__), exception__ ); } #endif //adl_catch__macros__hpp__ diff --git a/test/unit/adl/config.unit.cpp b/test/unit/adl/config.unit.cpp new file mode 100644 index 0000000..657a230 --- /dev/null +++ b/test/unit/adl/config.unit.cpp @@ -0,0 +1,3 @@ +// $flisboac 2017-03-19 +#include "adl_catch.hpp" +#include "adl/config.hpp" diff --git a/test/unit/adl/error.unit.cpp b/test/unit/adl/error.unit.cpp new file mode 100644 index 0000000..d2d2e7c --- /dev/null +++ b/test/unit/adl/error.unit.cpp @@ -0,0 +1,30 @@ +// $flisboac 2017-03-19 +#include "adl_catch.hpp" +#include "adl/error.hpp" + +TEST_CASE("adl/error.hpp", "[adl][adl/error]") { + + SECTION("adl::error_info") { + const adl::error_info warning_kind = adl::make_error_info(adl::error_kind_id::warning); + const adl::error_info ok_kind = adl::make_error_info(adl::error_kind_id::ok); + const adl::error_info error_kind = adl::make_error_info(adl::error_kind_id::error); + const adl::error_info client_error_kind = adl::make_error_info(adl::error_kind_id::client_error); + + const adl::error_info no_error; + const adl::error_info some_error = adl::error_id::function_not_supported; + + REQUIRE_SECTION((warning_kind == warning_kind), "error should equal itself"); + + REQUIRE_SECTION((ok_kind == no_error), "no-error info should be an adl::error_kind_id::ok"); + REQUIRE_SECTION((no_error != error_kind), "no-error info should not be an adl::error_kind_id::error"); + REQUIRE_SECTION((no_error != client_error_kind), "no-error info should not be an adl::error_kind_id::client_error"); + REQUIRE_SECTION((no_error != warning_kind), "no-error info should not be an adl::error_kind_id::warning"); + + REQUIRE_SECTION((some_error != ok_kind), "an error-kind error info should be an adl::error_kind_id::ok"); + REQUIRE_SECTION((some_error == error_kind), "an error-kind error info should not be an adl::error_kind_id::error"); + REQUIRE_SECTION((some_error != client_error_kind), "an error-kind error info should not be an adl::error_kind_id::client_error"); + REQUIRE_SECTION((some_error != warning_kind), "an error info-kind error should not be an adl::error_kind_id::warning"); + + REQUIRE_SECTION_THROWS_AS((adl::done(some_error)), adl::internal_exception, "an error-kind error_info should throw adl::internal_exception"); + } +} diff --git a/test/unit/adl/intl.unit.cpp b/test/unit/adl/intl.unit.cpp new file mode 100644 index 0000000..ec342d3 --- /dev/null +++ b/test/unit/adl/intl.unit.cpp @@ -0,0 +1,3 @@ +// $flisboac 2017-03-19 +#include "adl_catch.hpp" +#include "adl/intl.hpp" diff --git a/test/unit/main.unit.cpp b/test/unit/main.unit.cpp index 178916e..0c7c351 100644 --- a/test/unit/main.unit.cpp +++ b/test/unit/main.unit.cpp @@ -1,3 +1,2 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -