Files
rtorrent/test/helpers/mock_compare.h
T
2026-07-26 19:53:18 +09:00

111 lines
3.2 KiB
C++

#ifndef LIBTORRENT_HELPERS_MOCK_COMPARE_H
#define LIBTORRENT_HELPERS_MOCK_COMPARE_H
#include <algorithm>
#include <map>
#include <type_traits>
#include <torrent/net/socket_address.h>
#include <torrent/system/event.h>
// Compare arguments to mock functions with what is expected. The lhs
// are the expected arguments, rhs are the ones called with.
template <typename Arg>
inline bool mock_compare_arg(Arg lhs, Arg rhs) { return lhs == rhs; }
template <int I, typename A, typename... Args>
std::enable_if_t<I == 1, int>
mock_compare_tuple(const std::tuple<A, Args...>& lhs, const std::tuple<Args...>& rhs) {
return mock_compare_arg(std::get<I>(lhs), std::get<I - 1>(rhs)) ? 0 : 1;
}
template <int I, typename A, typename... Args>
std::enable_if_t<1 < I, int>
mock_compare_tuple(const std::tuple<A, Args...>& lhs, const std::tuple<Args...>& rhs) {
auto res = mock_compare_tuple<I - 1>(lhs, rhs);
if (res != 0)
return res;
return mock_compare_arg(std::get<I>(lhs), std::get<I - 1>(rhs)) ? 0 : I;
}
//template <typename T, typename std::enable_if<!std::is_const<T>::value, int>::type = 0>
template <typename T>
struct mock_compare_map {
typedef std::map<const T*, const T*> values_type;
static T* begin_pointer() { return reinterpret_cast<T*>(0x1000); }
static T* end_pointer() { return reinterpret_cast<T*>(0x2000); }
static bool is_key(const T* k) {
return k >= begin_pointer() && k < end_pointer();
}
static bool has_key(const T* k) {
return values.find(k) != values.end();
}
static bool has_value(const T* v) {
return std::find_if(values.begin(), values.end(), [v](typename values_type::value_type& kv) { return v == kv.second; }) != values.end();
}
static const T* get(const T* k) {
auto itr = values.find(k);
CPPUNIT_ASSERT_MESSAGE("mock_compare_map get failed, not inserted", itr != values.end());
return itr->second;
}
static values_type values;
};
template<typename T>
typename mock_compare_map<T>::values_type mock_compare_map<T>::values;
template<typename T>
void mock_compare_add(T* v) {
mock_compare_map<T>::add_value(v);
}
//
// Specialize:
//
constexpr int mock_compare_gt_two_int = -0xFD30;
template <>
inline bool mock_compare_arg<int>(int lhs, int rhs) {
if (lhs == mock_compare_gt_two_int)
return rhs > 2;
if (rhs == mock_compare_gt_two_int)
return lhs > 2;
return lhs == rhs;
}
template <>
inline bool mock_compare_arg<sockaddr*>(sockaddr* lhs, sockaddr* rhs) {
return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs);
}
template <>
inline bool mock_compare_arg<const sockaddr*>(const sockaddr* lhs, const sockaddr* rhs) {
return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs);
}
template <>
inline bool mock_compare_arg<torrent::system::Event*>(torrent::system::Event* lhs, torrent::system::Event* rhs) {
if (mock_compare_map<torrent::system::Event>::is_key(lhs)) {
if (!mock_compare_map<torrent::system::Event>::has_value(rhs)) {
mock_compare_map<torrent::system::Event>::values[lhs] = rhs;
return true;
}
return mock_compare_map<torrent::system::Event>::has_key(lhs) && mock_compare_map<torrent::system::Event>::get(lhs) == rhs;
}
return lhs == rhs;
}
#endif