55#define BITCOIN_TEST_UTIL_FRAMEWORK_H
66#pragma once
77
8+ #include < crypto/hex_base.h>
9+ #include < test/util/common.h>
810#include < tinyformat.h>
911
1012#include < algorithm>
@@ -113,31 +115,34 @@ inline void log(LogLevel level, const char* fmt, Args&&... args)
113115 }
114116}
115117
116- /* * Types that implement the `<<` operator. Pointers are excluded: operator<< for
117- * char-like pointers calls strlen on the pointee, which is unsafe for raw memory. */
118118template <typename T>
119- concept streamable = !std::is_pointer_v<T> && requires (std::ostream& os, const T& value) { os << value; };
120-
121- /* * Types that implement a `ToString()` member returning `std::string`. */
122- template <typename T>
123- concept has_to_string = requires (const T& value) {
124- { value.ToString () } -> std::same_as<std::string>;
125- };
119+ concept streamable = requires (std::ostream& os, const T& value) { os << value; };
126120
127121template <typename T>
128122concept is_cstring = std::is_same_v<std::decay_t <T>, const char *> || std::is_same_v<std::decay_t <T>, char *>;
129123
130124template <typename T>
131125std::string stringify (const T& value)
132126{
133- if constexpr (streamable<T>) {
127+ if constexpr (pointer<T>) {
128+ if (!value) return " nullptr" ;
129+ std::ostringstream os;
130+ os << static_cast <const void *>(value);
131+ return os.str ();
132+ } else if constexpr (streamable<T>) {
134133 std::ostringstream os;
135134 os << value;
136135 return os.str ();
137- } else if constexpr (has_to_string<T>) {
138- return value.ToString ();
136+ } else if constexpr (has_hex_str<T>) {
137+ return HexStr (value);
138+ } else if constexpr (has_serialize<T>) {
139+ DataStream ds;
140+ ds << value;
141+ return HexStr (ds);
142+ } else if constexpr (pair_like<T>) {
143+ return " (" + stringify (value.first ) + " , " + stringify (value.second ) + " )" ;
139144 } else {
140- return typeid (T). name ( );
145+ static_assert ( sizeof (T) == 0 , " No stringify() for this type. " );
141146 }
142147}
143148
@@ -258,6 +263,10 @@ inline std::string current_test_full_name()
258263}
259264
260265
266+ template <std::ranges::range R1 , std::ranges::range R2 >
267+ requires std::equality_comparable_with<std::ranges::range_value_t <R1 >, std::ranges::range_value_t <R2 >>
268+ Result check_equal_ranges (const R1 & r1, const R2 & r2);
269+
261270/* * A captured expression is used to stringify the result before evaluation.
262271 * When an expression evaluates to `false`, the string is reported to the user. */
263272template <typename T>
@@ -280,16 +289,28 @@ struct CapturedExpression {
280289 template <typename U> \
281290 Result operator op (const U& rhs) const \
282291 { \
283- bool btc_test_result; \
284- if constexpr (is_cstring<T> && is_cstring<U>) { \
285- btc_test_result = (std::strcmp (lhs, rhs) op 0 ); \
286- } else if constexpr (std::is_integral_v<T> && std::is_integral_v<U> && \
287- std::is_signed_v<T> != std::is_signed_v<U>) { \
288- btc_test_result = cmp (lhs, rhs); \
292+ if constexpr (((#op)[0 ] == ' =' || (#op)[0 ] == ' !' ) && \
293+ std::ranges::range<T> && std::ranges::range<U> && \
294+ !std::is_convertible_v<T, std::string_view> && \
295+ !std::is_convertible_v<U, std::string_view>) { \
296+ if constexpr ((#op)[0 ] == ' =' ) { \
297+ return check_equal_ranges (lhs, rhs); \
298+ } else { \
299+ return Result::failed (" != on ranges is not supported" ); \
300+ } \
289301 } else { \
290- btc_test_result = static_cast <bool >(lhs op rhs); \
302+ bool btc_test_result; \
303+ if constexpr (is_cstring<T> && is_cstring<U>) { \
304+ btc_test_result = (std::strcmp (lhs, rhs) op 0 ); \
305+ } else if constexpr (std::is_integral_v<T> && std::is_integral_v<U> && \
306+ std::is_signed_v<T> != std::is_signed_v<U>) { \
307+ btc_test_result = cmp (lhs, rhs); \
308+ } else { \
309+ btc_test_result = static_cast <bool >(lhs op rhs); \
310+ } \
311+ return btc_test_result ? Result::ok () \
312+ : Result::failed (stringify (lhs) + " " #op " " + stringify (rhs)); \
291313 } \
292- return btc_test_result ? Result::ok () : Result::failed (stringify (lhs) + " " #op " " + stringify (rhs)); \
293314 }
294315
295316 DECOMPOSE_OP (==, std::cmp_equal)
0 commit comments