145 lines
5.4 KiB
C++
145 lines
5.4 KiB
C++
// GNU Lesser General Public License v3.0
|
|
// Copyright (c) 2023 Bart Beumer <bart@4beumer.nl>
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU Lesser General Public License v3.0 as published by
|
|
// the Free Software Foundation.
|
|
//
|
|
#include "bmrshared/invoke.hpp"
|
|
#include "MockDataSource.hpp"
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
#include <type_traits>
|
|
|
|
using ::testing::An;
|
|
using ::testing::ElementsAre;
|
|
using ::testing::Return;
|
|
using ::testing::SetArgReferee;
|
|
using ::testing::TypedEq;
|
|
|
|
using bmrshared::flexible_value;
|
|
using bmrshared::MockDataSource;
|
|
|
|
namespace
|
|
{
|
|
// Compile-time test of some helper templates.
|
|
|
|
static_assert(std::is_same<typename bmrshared::detail::tuple_keepelemsfront<std::tuple<int, char>, 0>::tuple,
|
|
std::tuple<>>::value);
|
|
static_assert(std::is_same<typename bmrshared::detail::tuple_keepelemsfront<std::tuple<int, char>, 1>::tuple,
|
|
std::tuple<int>>::value);
|
|
static_assert(std::is_same<typename bmrshared::detail::tuple_keepelemsfront<std::tuple<int, char>, 2>::tuple,
|
|
std::tuple<int, char>>::value);
|
|
|
|
static_assert(std::is_same<typename bmrshared::detail::tuple_rmelemsback<std::tuple<int, char>, 0>::tuple,
|
|
std::tuple<int, char>>::value);
|
|
static_assert(std::is_same<typename bmrshared::detail::tuple_rmelemsback<std::tuple<int, char>, 1>::tuple,
|
|
std::tuple<int>>::value);
|
|
static_assert(
|
|
std::is_same<typename bmrshared::detail::tuple_rmelemsback<std::tuple<int, char>, 2>::tuple, std::tuple<>>::value);
|
|
|
|
|
|
class TestAddition
|
|
{
|
|
public:
|
|
uint64_t AddNumbers(uint64_t left, uint64_t right) { return left + (right * 2); }
|
|
uint64_t AddNumbersConst(uint64_t left, uint64_t right) const { return left + (right * 2); }
|
|
};
|
|
} // namespace
|
|
|
|
|
|
TEST(InvokeTest, Ok_Callable)
|
|
{
|
|
auto fn = [](int64_t a, int64_t b)
|
|
{
|
|
return (a + (b * 2));
|
|
};
|
|
std::array<std::string, 2> names = {"a", "b"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"a", "b"}));
|
|
EXPECT_CALL(mockSrc, Get("a", An<int64_t&>())).WillRepeatedly(SetArgReferee<1>(42));
|
|
EXPECT_CALL(mockSrc, Get("b", An<int64_t&>())).WillRepeatedly(SetArgReferee<1>(21));
|
|
|
|
flexible_value returnValue = bmrshared::invoke(fn, names, mockSrc);
|
|
EXPECT_EQ(returnValue.as<int64_t>(), 84);
|
|
}
|
|
|
|
TEST(InvokeTest, Ok_Callable_LastArg)
|
|
{
|
|
auto fn = [](int64_t a, int64_t b, int64_t lastArg)
|
|
{
|
|
return ((lastArg * 4) + a + (b * 2));
|
|
};
|
|
std::array<std::string, 2> names = {"a", "b"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"a", "b"}));
|
|
EXPECT_CALL(mockSrc, Get("a", An<int64_t&>())).WillRepeatedly(SetArgReferee<1>(42));
|
|
EXPECT_CALL(mockSrc, Get("b", An<int64_t&>())).WillRepeatedly(SetArgReferee<1>(21));
|
|
|
|
flexible_value returnValue = bmrshared::invoke(fn, names, mockSrc, 1000);
|
|
EXPECT_EQ(returnValue.as<int64_t>(), 4084);
|
|
}
|
|
|
|
TEST(InvokeTest, Ok_Ptr_Member)
|
|
{
|
|
std::array<std::string, 2> names = {"left", "right"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"left", "right"}));
|
|
EXPECT_CALL(mockSrc, Get("left", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(100));
|
|
EXPECT_CALL(mockSrc, Get("right", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(20));
|
|
|
|
TestAddition functor;
|
|
flexible_value returnValue = bmrshared::invoke(functor, &TestAddition::AddNumbers, names, mockSrc);
|
|
EXPECT_EQ(returnValue.as<uint64_t>(), 140);
|
|
}
|
|
|
|
TEST(InvokeTest, Ok_Ptr_Const_Member_Const)
|
|
{
|
|
std::array<std::string, 2> names = {"left", "right"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"left", "right"}));
|
|
EXPECT_CALL(mockSrc, Get("left", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(100));
|
|
EXPECT_CALL(mockSrc, Get("right", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(20));
|
|
|
|
const TestAddition functor;
|
|
flexible_value returnValue = bmrshared::invoke(functor, &TestAddition::AddNumbersConst, names, mockSrc);
|
|
EXPECT_EQ(returnValue.as<uint64_t>(), 140);
|
|
}
|
|
|
|
TEST(InvokeTest, Ok_Ptr_Member_Const)
|
|
{
|
|
std::array<std::string, 2> names = {"left", "right"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"left", "right"}));
|
|
EXPECT_CALL(mockSrc, Get("left", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(100));
|
|
EXPECT_CALL(mockSrc, Get("right", An<uint64_t&>())).WillRepeatedly(SetArgReferee<1>(20));
|
|
|
|
TestAddition functor;
|
|
flexible_value returnValue = bmrshared::invoke(functor, &TestAddition::AddNumbersConst, names, mockSrc);
|
|
EXPECT_EQ(returnValue.as<uint64_t>(), 140);
|
|
}
|
|
|
|
TEST(InvokeTest, Ok_ExtraArgumentByRefChanged)
|
|
{
|
|
auto fn = [](int64_t a, int64_t& lastArg)
|
|
{
|
|
lastArg = a;
|
|
return true;
|
|
};
|
|
std::array<std::string, 1> names = {"a"};
|
|
|
|
MockDataSource mockSrc;
|
|
EXPECT_CALL(mockSrc, GetKeys()).WillRepeatedly(Return(std::vector<std::string>{"a"}));
|
|
EXPECT_CALL(mockSrc, Get("a", An<int64_t&>())).WillRepeatedly(SetArgReferee<1>(42));
|
|
|
|
int64_t lastArg = 0;
|
|
flexible_value returnValue = bmrshared::invoke(fn, names, mockSrc, lastArg);
|
|
EXPECT_EQ(returnValue.as<bool>(), true);
|
|
EXPECT_EQ(lastArg, 42);
|
|
}
|