#ifndef LIBTORRENT_HELPERS_MOCK_COMPARE_H #define LIBTORRENT_HELPERS_MOCK_COMPARE_H #include #include #include #include #include // Compare arguments to mock functions with what is expected. The lhs // are the expected arguments, rhs are the ones called with. template inline bool mock_compare_arg(Arg lhs, Arg rhs) { return lhs == rhs; } template std::enable_if_t mock_compare_tuple(const std::tuple& lhs, const std::tuple& rhs) { return mock_compare_arg(std::get(lhs), std::get(rhs)) ? 0 : 1; } template std::enable_if_t<1 < I, int> mock_compare_tuple(const std::tuple& lhs, const std::tuple& rhs) { auto res = mock_compare_tuple(lhs, rhs); if (res != 0) return res; return mock_compare_arg(std::get(lhs), std::get(rhs)) ? 0 : I; } //template ::value, int>::type = 0> template struct mock_compare_map { typedef std::map values_type; static T* begin_pointer() { return reinterpret_cast(0x1000); } static T* end_pointer() { return reinterpret_cast(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 mock_compare_map::values_type mock_compare_map::values; template void mock_compare_add(T* v) { mock_compare_map::add_value(v); } // // Specialize: // constexpr int mock_compare_gt_two_int = -0xFD30; template <> inline bool mock_compare_arg(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* lhs, sockaddr* rhs) { return lhs != nullptr && rhs != nullptr && torrent::sa_equal(lhs, rhs); } template <> inline bool mock_compare_arg(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* lhs, torrent::system::Event* rhs) { if (mock_compare_map::is_key(lhs)) { if (!mock_compare_map::has_value(rhs)) { mock_compare_map::values[lhs] = rhs; return true; } return mock_compare_map::has_key(lhs) && mock_compare_map::get(lhs) == rhs; } return lhs == rhs; } #endif