1*58b9f456SAndroid Build Coastguard Worker #ifndef TEST_SUPPORT_VERBOSE_ASSERT 2*58b9f456SAndroid Build Coastguard Worker #define TEST_SUPPORT_VERBOSE_ASSERT 3*58b9f456SAndroid Build Coastguard Worker 4*58b9f456SAndroid Build Coastguard Worker #include <iostream> 5*58b9f456SAndroid Build Coastguard Worker #include <cstdio> 6*58b9f456SAndroid Build Coastguard Worker #include <sstream> 7*58b9f456SAndroid Build Coastguard Worker #include <string> 8*58b9f456SAndroid Build Coastguard Worker #include "test_macros.h" 9*58b9f456SAndroid Build Coastguard Worker 10*58b9f456SAndroid Build Coastguard Worker namespace verbose_assert { 11*58b9f456SAndroid Build Coastguard Worker 12*58b9f456SAndroid Build Coastguard Worker typedef std::basic_ostream<char>&(EndLType)(std::basic_ostream<char>&); 13*58b9f456SAndroid Build Coastguard Worker 14*58b9f456SAndroid Build Coastguard Worker template <class Stream, class Tp, 15*58b9f456SAndroid Build Coastguard Worker class = decltype(std::declval<Stream&>() << std::declval<Tp const&>())> 16*58b9f456SAndroid Build Coastguard Worker std::true_type IsStreamableImp(int); 17*58b9f456SAndroid Build Coastguard Worker template <class Stream, class Tp> std::false_type IsStreamableImp(long); 18*58b9f456SAndroid Build Coastguard Worker 19*58b9f456SAndroid Build Coastguard Worker template <class Stream, class Tp> 20*58b9f456SAndroid Build Coastguard Worker struct IsStreamable : decltype(IsStreamableImp<Stream, Tp>(0)) {}; 21*58b9f456SAndroid Build Coastguard Worker 22*58b9f456SAndroid Build Coastguard Worker template <class Tp, int ST = (IsStreamable<decltype(std::cerr), Tp>::value ? 1 23*58b9f456SAndroid Build Coastguard Worker : (IsStreamable<decltype(std::wcerr), Tp>::value ? 2 : -1))> 24*58b9f456SAndroid Build Coastguard Worker struct SelectStream { 25*58b9f456SAndroid Build Coastguard Worker static_assert(ST == -1, "specialization required for ST != -1"); PrintSelectStream26*58b9f456SAndroid Build Coastguard Worker static void Print(Tp const&) { std::clog << "Value Not Streamable!\n"; } 27*58b9f456SAndroid Build Coastguard Worker }; 28*58b9f456SAndroid Build Coastguard Worker 29*58b9f456SAndroid Build Coastguard Worker template <class Tp> 30*58b9f456SAndroid Build Coastguard Worker struct SelectStream<Tp, 1> { 31*58b9f456SAndroid Build Coastguard Worker static void Print(Tp const& val) { std::cerr << val; } 32*58b9f456SAndroid Build Coastguard Worker }; 33*58b9f456SAndroid Build Coastguard Worker 34*58b9f456SAndroid Build Coastguard Worker template <class Tp> 35*58b9f456SAndroid Build Coastguard Worker struct SelectStream<Tp, 2> { 36*58b9f456SAndroid Build Coastguard Worker static void Print(Tp const& val) { std::wcerr << val; } 37*58b9f456SAndroid Build Coastguard Worker }; 38*58b9f456SAndroid Build Coastguard Worker 39*58b9f456SAndroid Build Coastguard Worker struct AssertData { 40*58b9f456SAndroid Build Coastguard Worker AssertData(const char* xcheck, const char* xfile, const char* xfunc, 41*58b9f456SAndroid Build Coastguard Worker unsigned long xline, bool xpassed = true) 42*58b9f456SAndroid Build Coastguard Worker : passed(xpassed), check(xcheck), file(xfile), func(xfunc), line(xline), 43*58b9f456SAndroid Build Coastguard Worker msg() {} 44*58b9f456SAndroid Build Coastguard Worker 45*58b9f456SAndroid Build Coastguard Worker AssertData& SetFailed(std::string xmsg = std::string()) { 46*58b9f456SAndroid Build Coastguard Worker msg = xmsg; 47*58b9f456SAndroid Build Coastguard Worker passed = false; 48*58b9f456SAndroid Build Coastguard Worker return *this; 49*58b9f456SAndroid Build Coastguard Worker } 50*58b9f456SAndroid Build Coastguard Worker 51*58b9f456SAndroid Build Coastguard Worker void PrintFailed() const { 52*58b9f456SAndroid Build Coastguard Worker std::fprintf(stderr, "%s:%lu %s: Assertion '%s' failed.\n", file, line, 53*58b9f456SAndroid Build Coastguard Worker func, check); 54*58b9f456SAndroid Build Coastguard Worker if (!msg.empty()) 55*58b9f456SAndroid Build Coastguard Worker std::fprintf(stderr, "%s\n", msg.data()); 56*58b9f456SAndroid Build Coastguard Worker } 57*58b9f456SAndroid Build Coastguard Worker 58*58b9f456SAndroid Build Coastguard Worker bool passed; 59*58b9f456SAndroid Build Coastguard Worker const char* check; 60*58b9f456SAndroid Build Coastguard Worker const char* file; 61*58b9f456SAndroid Build Coastguard Worker const char* func; 62*58b9f456SAndroid Build Coastguard Worker unsigned long line; 63*58b9f456SAndroid Build Coastguard Worker std::string msg; 64*58b9f456SAndroid Build Coastguard Worker }; 65*58b9f456SAndroid Build Coastguard Worker 66*58b9f456SAndroid Build Coastguard Worker // AssertHandler is the class constructed by failing CHECK macros. AssertHandler 67*58b9f456SAndroid Build Coastguard Worker // will log information about the failures and abort when it is destructed. 68*58b9f456SAndroid Build Coastguard Worker class AssertHandler { 69*58b9f456SAndroid Build Coastguard Worker public: 70*58b9f456SAndroid Build Coastguard Worker AssertHandler(AssertData const& Data) 71*58b9f456SAndroid Build Coastguard Worker : passed(Data.passed) { 72*58b9f456SAndroid Build Coastguard Worker if (!passed) 73*58b9f456SAndroid Build Coastguard Worker Data.PrintFailed(); 74*58b9f456SAndroid Build Coastguard Worker } 75*58b9f456SAndroid Build Coastguard Worker 76*58b9f456SAndroid Build Coastguard Worker ~AssertHandler() TEST_NOEXCEPT_FALSE { 77*58b9f456SAndroid Build Coastguard Worker if (!passed) { 78*58b9f456SAndroid Build Coastguard Worker error_log << std::endl; 79*58b9f456SAndroid Build Coastguard Worker std::abort(); 80*58b9f456SAndroid Build Coastguard Worker } 81*58b9f456SAndroid Build Coastguard Worker } 82*58b9f456SAndroid Build Coastguard Worker 83*58b9f456SAndroid Build Coastguard Worker class LogType { 84*58b9f456SAndroid Build Coastguard Worker friend class AssertHandler; 85*58b9f456SAndroid Build Coastguard Worker 86*58b9f456SAndroid Build Coastguard Worker template <class Tp> 87*58b9f456SAndroid Build Coastguard Worker friend LogType& operator<<(LogType& log, Tp const& value) { 88*58b9f456SAndroid Build Coastguard Worker if (!log.is_disabled) { 89*58b9f456SAndroid Build Coastguard Worker SelectStream<Tp>::Print(value); 90*58b9f456SAndroid Build Coastguard Worker } 91*58b9f456SAndroid Build Coastguard Worker return log; 92*58b9f456SAndroid Build Coastguard Worker } 93*58b9f456SAndroid Build Coastguard Worker 94*58b9f456SAndroid Build Coastguard Worker friend LogType& operator<<(LogType& log, EndLType* m) { 95*58b9f456SAndroid Build Coastguard Worker if (!log.is_disabled) { 96*58b9f456SAndroid Build Coastguard Worker SelectStream<EndLType*>::Print(m); 97*58b9f456SAndroid Build Coastguard Worker } 98*58b9f456SAndroid Build Coastguard Worker return log; 99*58b9f456SAndroid Build Coastguard Worker } 100*58b9f456SAndroid Build Coastguard Worker 101*58b9f456SAndroid Build Coastguard Worker private: 102*58b9f456SAndroid Build Coastguard Worker LogType(bool disable) : is_disabled(disable) {} 103*58b9f456SAndroid Build Coastguard Worker bool is_disabled; 104*58b9f456SAndroid Build Coastguard Worker 105*58b9f456SAndroid Build Coastguard Worker LogType(LogType const&); 106*58b9f456SAndroid Build Coastguard Worker LogType& operator=(LogType const&); 107*58b9f456SAndroid Build Coastguard Worker }; 108*58b9f456SAndroid Build Coastguard Worker 109*58b9f456SAndroid Build Coastguard Worker LogType& GetLog() { 110*58b9f456SAndroid Build Coastguard Worker if (passed) 111*58b9f456SAndroid Build Coastguard Worker return null_log; 112*58b9f456SAndroid Build Coastguard Worker return error_log; 113*58b9f456SAndroid Build Coastguard Worker } 114*58b9f456SAndroid Build Coastguard Worker 115*58b9f456SAndroid Build Coastguard Worker private: 116*58b9f456SAndroid Build Coastguard Worker static LogType null_log; 117*58b9f456SAndroid Build Coastguard Worker static LogType error_log; 118*58b9f456SAndroid Build Coastguard Worker 119*58b9f456SAndroid Build Coastguard Worker AssertHandler& operator=(const AssertHandler&) = delete; 120*58b9f456SAndroid Build Coastguard Worker AssertHandler(const AssertHandler&) = delete; 121*58b9f456SAndroid Build Coastguard Worker AssertHandler() = delete; 122*58b9f456SAndroid Build Coastguard Worker 123*58b9f456SAndroid Build Coastguard Worker private: 124*58b9f456SAndroid Build Coastguard Worker bool passed; 125*58b9f456SAndroid Build Coastguard Worker }; 126*58b9f456SAndroid Build Coastguard Worker 127*58b9f456SAndroid Build Coastguard Worker AssertHandler::LogType AssertHandler::null_log(true); 128*58b9f456SAndroid Build Coastguard Worker AssertHandler::LogType AssertHandler::error_log(false); 129*58b9f456SAndroid Build Coastguard Worker 130*58b9f456SAndroid Build Coastguard Worker template <class It1> 131*58b9f456SAndroid Build Coastguard Worker std::string PrintRange(const char* Name, It1 F, It1 E) { 132*58b9f456SAndroid Build Coastguard Worker std::stringstream ss; 133*58b9f456SAndroid Build Coastguard Worker ss << " " << Name << " = ["; 134*58b9f456SAndroid Build Coastguard Worker while (F != E) { 135*58b9f456SAndroid Build Coastguard Worker ss << *F; 136*58b9f456SAndroid Build Coastguard Worker ++F; 137*58b9f456SAndroid Build Coastguard Worker if (F != E) 138*58b9f456SAndroid Build Coastguard Worker ss << ", "; 139*58b9f456SAndroid Build Coastguard Worker } 140*58b9f456SAndroid Build Coastguard Worker ss << "]\n"; 141*58b9f456SAndroid Build Coastguard Worker return ss.str(); 142*58b9f456SAndroid Build Coastguard Worker } 143*58b9f456SAndroid Build Coastguard Worker 144*58b9f456SAndroid Build Coastguard Worker template <class Tp, class Up> 145*58b9f456SAndroid Build Coastguard Worker std::string PrintMismatch(Tp const& LHS, Up const& RHS, int Elem) { 146*58b9f456SAndroid Build Coastguard Worker std::stringstream ss; 147*58b9f456SAndroid Build Coastguard Worker ss << " Element " << Elem << " mismatched: `" << LHS << "` != `" << RHS 148*58b9f456SAndroid Build Coastguard Worker << "`!\n"; 149*58b9f456SAndroid Build Coastguard Worker return ss.str(); 150*58b9f456SAndroid Build Coastguard Worker }; 151*58b9f456SAndroid Build Coastguard Worker 152*58b9f456SAndroid Build Coastguard Worker struct EqualToComp { 153*58b9f456SAndroid Build Coastguard Worker template <class Tp, class Up> 154*58b9f456SAndroid Build Coastguard Worker bool operator()(Tp const& LHS, Up const& RHS) const { 155*58b9f456SAndroid Build Coastguard Worker return LHS == RHS; 156*58b9f456SAndroid Build Coastguard Worker } 157*58b9f456SAndroid Build Coastguard Worker }; 158*58b9f456SAndroid Build Coastguard Worker 159*58b9f456SAndroid Build Coastguard Worker template <class It1, class It2, class Comp> 160*58b9f456SAndroid Build Coastguard Worker AssertData CheckCollectionsEqual(It1 F1, It1 E1, It2 F2, It2 E2, 161*58b9f456SAndroid Build Coastguard Worker AssertData Data, Comp C = EqualToComp()) { 162*58b9f456SAndroid Build Coastguard Worker const It1 F1Orig = F1; 163*58b9f456SAndroid Build Coastguard Worker const It2 F2Orig = F2; 164*58b9f456SAndroid Build Coastguard Worker bool Failed = false; 165*58b9f456SAndroid Build Coastguard Worker std::string ErrorMsg; 166*58b9f456SAndroid Build Coastguard Worker int Idx = 0; 167*58b9f456SAndroid Build Coastguard Worker while (F1 != E1 && F2 != E2) { 168*58b9f456SAndroid Build Coastguard Worker if (!(C(*F1, *F2))) { 169*58b9f456SAndroid Build Coastguard Worker ErrorMsg += PrintMismatch(*F1, *F2, Idx); 170*58b9f456SAndroid Build Coastguard Worker Failed = true; 171*58b9f456SAndroid Build Coastguard Worker break; 172*58b9f456SAndroid Build Coastguard Worker } 173*58b9f456SAndroid Build Coastguard Worker ++Idx; 174*58b9f456SAndroid Build Coastguard Worker ++F1; 175*58b9f456SAndroid Build Coastguard Worker ++F2; 176*58b9f456SAndroid Build Coastguard Worker } 177*58b9f456SAndroid Build Coastguard Worker if (!Failed && (F1 != E1 || F2 != E2)) { 178*58b9f456SAndroid Build Coastguard Worker ErrorMsg += " Ranges have different sizes!\n"; 179*58b9f456SAndroid Build Coastguard Worker Failed = true; 180*58b9f456SAndroid Build Coastguard Worker } 181*58b9f456SAndroid Build Coastguard Worker if (Failed) { 182*58b9f456SAndroid Build Coastguard Worker ErrorMsg += PrintRange("LHS", F1Orig, E1); 183*58b9f456SAndroid Build Coastguard Worker ErrorMsg += PrintRange("RHS", F2Orig, E2); 184*58b9f456SAndroid Build Coastguard Worker Data.SetFailed(ErrorMsg); 185*58b9f456SAndroid Build Coastguard Worker } 186*58b9f456SAndroid Build Coastguard Worker return Data; 187*58b9f456SAndroid Build Coastguard Worker } 188*58b9f456SAndroid Build Coastguard Worker } // namespace verbose_assert 189*58b9f456SAndroid Build Coastguard Worker 190*58b9f456SAndroid Build Coastguard Worker #ifdef __GNUC__ 191*58b9f456SAndroid Build Coastguard Worker #define ASSERT_FN_NAME() __PRETTY_FUNCTION__ 192*58b9f456SAndroid Build Coastguard Worker #else 193*58b9f456SAndroid Build Coastguard Worker #define ASSERT_FN_NAME() __func__ 194*58b9f456SAndroid Build Coastguard Worker #endif 195*58b9f456SAndroid Build Coastguard Worker 196*58b9f456SAndroid Build Coastguard Worker #define DISPLAY(...) " " #__VA_ARGS__ " = " << (__VA_ARGS__) << "\n" 197*58b9f456SAndroid Build Coastguard Worker 198*58b9f456SAndroid Build Coastguard Worker #define ASSERT(...) \ 199*58b9f456SAndroid Build Coastguard Worker ::verbose_assert::AssertHandler(::verbose_assert::AssertData( \ 200*58b9f456SAndroid Build Coastguard Worker #__VA_ARGS__, __FILE__, ASSERT_FN_NAME(), __LINE__,(__VA_ARGS__))).GetLog() 201*58b9f456SAndroid Build Coastguard Worker 202*58b9f456SAndroid Build Coastguard Worker #define ASSERT_EQ(LHS, RHS) \ 203*58b9f456SAndroid Build Coastguard Worker ASSERT(LHS == RHS) << DISPLAY(LHS) << DISPLAY(RHS) 204*58b9f456SAndroid Build Coastguard Worker #define ASSERT_NEQ(LHS, RHS) \ 205*58b9f456SAndroid Build Coastguard Worker ASSERT(LHS != RHS) << DISPLAY(LHS) << DISPLAY(RHS) 206*58b9f456SAndroid Build Coastguard Worker #define ASSERT_PRED(PRED, LHS, RHS) \ 207*58b9f456SAndroid Build Coastguard Worker ASSERT(PRED(LHS, RHS)) << DISPLAY(LHS) << DISPLAY(RHS) 208*58b9f456SAndroid Build Coastguard Worker 209*58b9f456SAndroid Build Coastguard Worker #define ASSERT_COLLECTION_EQ_COMP(F1, E1, F2, E2, Comp) \ 210*58b9f456SAndroid Build Coastguard Worker (::verbose_assert::AssertHandler( \ 211*58b9f456SAndroid Build Coastguard Worker ::verbose_assert::CheckCollectionsEqual( \ 212*58b9f456SAndroid Build Coastguard Worker F1, E1, F2, E2, \ 213*58b9f456SAndroid Build Coastguard Worker ::verbose_assert::AssertData("CheckCollectionsEqual(" #F1 ", " #E1 \ 214*58b9f456SAndroid Build Coastguard Worker ", " #F2 ", " #E2 ")", \ 215*58b9f456SAndroid Build Coastguard Worker __FILE__, ASSERT_FN_NAME(), __LINE__), \ 216*58b9f456SAndroid Build Coastguard Worker Comp)) \ 217*58b9f456SAndroid Build Coastguard Worker .GetLog()) 218*58b9f456SAndroid Build Coastguard Worker 219*58b9f456SAndroid Build Coastguard Worker #define ASSERT_COLLECTION_EQ(F1, E1, F2, E2) \ 220*58b9f456SAndroid Build Coastguard Worker ASSERT_COLLECTION_EQ_COMP(F1, E1, F2, E2, ::verbose_assert::EqualToComp()) 221*58b9f456SAndroid Build Coastguard Worker 222*58b9f456SAndroid Build Coastguard Worker #endif 223