ksi_testing/lib/SOSTestUtils/sos_testing.hpp
Bartosz Wieczorek e3630007ba init
2024-04-19 08:30:53 +02:00

111 lines
3.1 KiB
C++

#pragma once
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <ESOS_Exception.h>
#include <stdexcept>
#include <string>
#include <utility>
#include <memory>
namespace testing::internal {
template < typename F >
class MockFunctionNamed;
template < typename R, typename... Args >
class MockFunctionNamed< R(Args...) > {
public:
MockFunctionNamed(const MockFunctionNamed &) = delete;
MockFunctionNamed & operator=(const MockFunctionNamed &) = delete;
std::function< R(Args...) > AsStdFunction() {
return [this](Args... args) -> R { return this->Call(std::forward< Args >(args)...); };
}
// Implementation detail: the expansion of the MOCK_METHOD macro.
R Call(Args... args) {
mock_.SetOwnerAndName(this, _name.c_str());
return mock_.Invoke(std::forward< Args >(args)...);
}
MockSpec< R(Args...) > gmock_Call(Matcher< Args >... m) {
mock_.RegisterOwner(this);
return mock_.With(std::move(m)...);
}
MockSpec< R(Args...) > gmock_Call(const WithoutMatchers &, R (*)(Args...)) {
return this->gmock_Call(::testing::A< Args >()...);
}
protected:
MockFunctionNamed(std::string name) : _name{"Call{" + name + "}"} {}
~MockFunctionNamed() = default;
private:
std::string _name;
FunctionMocker< R(Args...) > mock_;
};
} // namespace testing::internal
namespace testing {
template < typename F >
class MockFunctionNamed : public internal::MockFunctionNamed< internal::SignatureOfT< F > > {
using Base = internal::MockFunctionNamed< internal::SignatureOfT< F > >;
public:
MockFunctionNamed(std::string name) : Base{std::move(name)} {}
};
} // namespace testing
template < class Function >
std::function< void() > single_call(Function function) {
auto shared_exception_ptr = std::make_shared< std::exception_ptr >();
auto was_called = std::make_shared< bool >(false);
return [shared_exception_ptr, was_called, function]() {
if(*shared_exception_ptr) {
std::rethrow_exception(*shared_exception_ptr);
}
if(*was_called) {
return;
}
*was_called = true;
try {
std::invoke(function);
} catch(...) {
*shared_exception_ptr = std::current_exception();
std::rethrow_exception(*shared_exception_ptr);
}
};
}
class ESOS_Error_testable {
std::string description, usermsg;
public:
ESOS_Error_testable(ESOS_Exception & e) : description{e.GetDesc().c_str()}, usermsg{e.GetUserMsg().c_str()} {}
const std::string & GetDesc() const {
return description;
}
const std::string & GetUserMsg() const {
return usermsg;
}
};
template < typename Fun >
auto rethrow_esos_as_testable_esos_exception(Fun && f) {
try {
return f();
} catch(ESOS_Exception & esos_error) {
throw ESOS_Error_testable{esos_error};
} catch(...) {
throw std::runtime_error{""};
}
}
template < typename Callable >
auto single_rethrow_esos_exception(Callable && C) {
return single_call([&]() { rethrow_esos_as_testable_esos_exception(std::forward< Callable >(C)); });
}