Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions score/mw/com/test/common_test_resources/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,15 @@ cc_library(
"fail_test.h",
],
features = COMPILER_WARNING_FEATURES,
implementation_deps = [
"@score_baselibs//score/language/futurecpp",
],
visibility = [
"//score/mw/com/test:__subpackages__",
],
deps = [
"@score_baselibs//score/result",
],
)

cc_library(
Expand Down Expand Up @@ -154,6 +160,7 @@ cc_library(
"//score/mw/com/test:__subpackages__",
],
deps = [
":fail_test",
"//score/mw/com",
"//score/mw/com/test/common_test_resources:test_error_domain",
"@boost.program_options",
Expand Down
56 changes: 34 additions & 22 deletions score/mw/com/test/common_test_resources/command_line_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#ifndef SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_COMMAND_LINE_PARSER_H
#define SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_COMMAND_LINE_PARSER_H

#include "score/mw/com/test/common_test_resources/fail_test.h"
#include "score/mw/com/test/common_test_resources/test_error_domain.h"
#include <boost/program_options.hpp>

#include <charconv>
#include <score/optional.hpp>

#include "score/result/result.h"

#include <boost/program_options.hpp>
#include <charconv>
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
Expand All @@ -30,7 +31,8 @@ namespace score::mw::com::test

using CommandLineArgsMapType = std::unordered_map<std::string, std::string>;

/// \brief Get a value represented as a string, from an arguments map and parse it into the appropriate type
/// \brief Get a value represented as a string (if it exists), from an arguments map and parse it into the appropriate
/// type
///
/// \tparam ReturnType Target type of the parsed argument. Must be std::string, integral or floating point type.
/// \param args Map of provided command line arguments, where the key is the argument name and the value is the argument
Expand All @@ -41,11 +43,11 @@ using CommandLineArgsMapType = std::unordered_map<std::string, std::string>;
template <typename ReturnType>
auto GetValueIfProvided(const CommandLineArgsMapType& args, const std::string& arg_string) -> Result<ReturnType>
{
std::cout << "Trying to get value for argument: " << arg_string << std::endl;
if (args.count(arg_string) == 0U)
{
std::string error_msg = "could not find the requested parameter: " + arg_string;
return score::MakeUnexpected<ReturnType>(
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed, error_msg));
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed, "Could not find the requested parameter."));
}

std::string value_str = args.at(arg_string);
Expand All @@ -66,9 +68,8 @@ auto GetValueIfProvided(const CommandLineArgsMapType& args, const std::string& a
}
return score::MakeUnexpected<ReturnType>(
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing of: " + arg_string + " . Provided value " + value_str +
"could not be parsed into bool! Boolean fields can only have one of the following values: "
"true, 1, false, 0 \n"));
"Failed during parsing. Provided value could not be parsed into bool! Boolean fields can only "
"have one of the following values: true, 1, false, 0."));
}
else if constexpr (std::is_integral_v<ReturnType>)
{
Expand All @@ -81,26 +82,23 @@ auto GetValueIfProvided(const CommandLineArgsMapType& args, const std::string& a

if (conversion_result.ec == std::errc::invalid_argument)
{
return score::MakeUnexpected<ReturnType>(MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing of: " + arg_string +
" . Provided value " + value_str +
"could not be parsed into the required type!\n"));
return score::MakeUnexpected<ReturnType>(
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing. Provided value could not be parsed into the required type!"));
}

if (conversion_result.ec == std::errc::result_out_of_range)
{
return score::MakeUnexpected<ReturnType>(MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing of: " + arg_string +
" . Provided value " + value_str +
"Is Larger than requested type!\n"));
return score::MakeUnexpected<ReturnType>(
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing. Provided value is Larger than requested type!"));
}

if (conversion_result.ec != std::errc{})
{
return score::MakeUnexpected<ReturnType>(
MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing of: " + arg_string + " . Provided value " + value_str +
"could not be parsed into the required type for an unknown reason!\n"));
return score::MakeUnexpected<ReturnType>(MakeError(TestErrorCode::kParsingCommandLineArgumentFailed,
"Failed during parsing. Provided value could not be "
"parsed into the required type for an unknown reason!"));
}

return parsed_value;
Expand All @@ -112,6 +110,20 @@ auto GetValueIfProvided(const CommandLineArgsMapType& args, const std::string& a
}
}

/// \brief Get a value represented as a string, from an arguments map and parse it into the appropriate type.
///
/// Same as `GetValueIfProvided`, but terminates the program if the argument is not provided or could not be parsed.
template <typename ReturnType>
auto GetValue(const CommandLineArgsMapType& args, const std::string& arg_string) -> ReturnType
{
auto value_opt = GetValueIfProvided<ReturnType>(args, arg_string);
if (!value_opt.has_value())
{
FailTest("Failed to get value for argument. Error: ", value_opt.error());
}
return value_opt.value();
}

/// \brief A generic command line parser which can parse any kind of arguments and return an argument value map.
///
/// Every argument is parsed as a string and stored in the map with the argument name as key.
Expand Down
39 changes: 36 additions & 3 deletions score/mw/com/test/common_test_resources/fail_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,50 @@

#include "score/mw/com/test/common_test_resources/fail_test.h"

#include "score/assert.hpp"

#include <cstdlib>
#include <functional>
#include <iostream>
#include <optional>

namespace score::mw::com::test
{
namespace
{

thread_local std::optional<std::function<void()>> g_fail_test_exit_function{};

}

namespace score::mw::com::test::detail
namespace detail
{

void FailTest(std::stringstream&& strstr)
{
if (g_fail_test_exit_function.has_value())
{
std::invoke(g_fail_test_exit_function.value());
g_fail_test_exit_function.reset();
}
strstr << "\033[0m \033[1m\033[41mTEST FAILED\033[0m\n";
std::cerr << strstr.str() << std::flush;
std::cout << strstr.str() << std::flush;
std::_Exit(EXIT_FAILURE);
}

} // namespace score::mw::com::test::detail
} // namespace detail

ExitFunctionGuard::ExitFunctionGuard(ExitFunction exit_function)
{
SCORE_LANGUAGE_FUTURECPP_ASSERT_MESSAGE(!g_fail_test_exit_function.has_value(),
"A test exit function is already set for this thread! Only one "
"ExitFunctionGuard can be created per thread.");
g_fail_test_exit_function.emplace(std::move(exit_function));
}

ExitFunctionGuard::~ExitFunctionGuard()
{
std::invoke(g_fail_test_exit_function.value());
g_fail_test_exit_function.reset();
}
} // namespace score::mw::com::test
33 changes: 32 additions & 1 deletion score/mw/com/test/common_test_resources/fail_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#ifndef SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_FAIL_TEST_H
#define SCORE_MW_COM_TEST_COMMON_TEST_RESOURCES_FAIL_TEST_H

#include "score/result/error.h"

#include <functional>
#include <sstream>
#include <utility>

Expand All @@ -21,12 +24,23 @@ namespace score::mw::com::test

namespace detail
{

void FailTest(std::stringstream&& strstr);

template <typename Start, typename... Tail>
void FailTest(std::stringstream&& strstr, Start&& start, Tail&&... tail)
{
strstr << std::forward<Start>(start);
// Since score::result::Error does not have an operator<< overload for a stringstream and no method to convert it to
// a string, we manually stringify it here.
if constexpr (std::is_same_v<std::decay_t<Start>, score::result::Error>)
{
strstr << start.Message() << " / " << start.UserMessage();
}
else
{
strstr << std::forward<Start>(start);
}

if constexpr (sizeof...(Tail) > 0U)
{
FailTest(std::move(strstr), std::forward<Tail>(tail)...);
Expand All @@ -36,8 +50,25 @@ void FailTest(std::stringstream&& strstr, Start&& start, Tail&&... tail)
FailTest(std::move(strstr));
}
}

} // namespace detail

/// \brief RAII guard to set a test exit function that will be called when FailTest is invoked or when the guard is
/// destroyed.
class ExitFunctionGuard
{
public:
using ExitFunction = std::function<void()>;

explicit ExitFunctionGuard(ExitFunction exit_function);
~ExitFunctionGuard();

ExitFunctionGuard(const ExitFunctionGuard&) = delete;
ExitFunctionGuard& operator=(const ExitFunctionGuard&) = delete;
ExitFunctionGuard(ExitFunctionGuard&&) = delete;
ExitFunctionGuard& operator=(ExitFunctionGuard&&) = delete;
};

/// \brief Fail a test by exiting the program with EXIT_FAILURE and printing a message to stderr.
/// \param args variadic number of arguments, each one must be streamable to a standard stringstream.
template <typename... Args>
Expand Down
21 changes: 0 additions & 21 deletions score/mw/com/test/methods/BUILD

This file was deleted.

10 changes: 2 additions & 8 deletions score/mw/com/test/methods/basic_acceptance_test/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ cc_library(
implementation_deps = [
":test_method_datatype",
"//score/mw/com",
"//score/mw/com/test/methods/methods_test_resources:method_consumer",
"//score/mw/com/test/methods/methods_test_resources:process_synchronizer",
"//score/mw/com/test/methods/methods_test_resources:proxy_container",
],
)

Expand All @@ -54,8 +54,8 @@ cc_library(
implementation_deps = [
":test_method_datatype",
"//score/mw/com",
"//score/mw/com/test/methods/methods_test_resources:method_provider",
"//score/mw/com/test/methods/methods_test_resources:process_synchronizer",
"//score/mw/com/test/methods/methods_test_resources:skeleton_container",
],
deps = [
"@score_baselibs//score/language/futurecpp",
Expand Down Expand Up @@ -145,9 +145,3 @@ pkg_application(
"//score/mw/com/test/methods/basic_acceptance_test:__subpackages__",
],
)

test_suite(
name = "component_tests",
tests = [],
visibility = ["//score/mw/com/test/methods:__pkg__"],
)
Loading
Loading