#pragma once #ifndef _MSC_VER #include #else #include #endif #include #include #include #include #define ExpectEqual(t, a, b) ExpectEqualFun(a, b, #a, #b, __FILE__, __LINE__) #define ExpectTrue(a) ExpectTrueFun(a, #a, __FILE__, __LINE__) #define ExpectException(expr, excp) \ do \ { \ bool success = false; \ try \ { \ expr; \ } \ catch (const excp &) \ { \ success = true; \ } \ catch (const std::exception& ex) \ { \ std::stringstream ss; \ ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__); \ ss << " ExpectException failed: unexpected exception '" << typeid(ex).name(); \ ss << "' thrown." << std::endl; \ throw std::runtime_error(ss.str()); \ } \ \ if (!success) \ { \ std::stringstream ss; \ ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__); \ ss << " ExpectException failed: expected exception '" << #excp << "' not thrown."; \ ss << std::endl; \ throw std::runtime_error(ss.str()); \ } \ } \ while (0) #define ExpectExceptionMsg(expr, excp, msg) \ do \ { \ bool success = false; \ try \ { \ expr; \ } \ catch (const excp& ex) \ { \ if (std::string(ex.what()) == msg) \ { \ success = true; \ } \ else \ { \ std::stringstream ss; \ ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__); \ ss << " ExpectExceptionMsg failed: unexpected exception message '" << ex.what(); \ ss << "'." << std::endl; \ throw std::runtime_error(ss.str()); \ } \ } \ catch (const std::exception& ex) \ { \ std::stringstream ss; \ ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__); \ ss << " ExpectExceptionMsg failed: unexpected exception '" << typeid(ex).name(); \ ss << "' thrown." << std::endl; \ throw std::runtime_error(ss.str()); \ } \ \ if (!success) \ { \ std::stringstream ss; \ ss << unittest::detail::FileName(__FILE__) << ":" << std::to_string(__LINE__); \ ss << " ExpectException failed: expected exception '" << #excp << "' not thrown."; \ ss << std::endl; \ throw std::runtime_error(ss.str()); \ } \ } \ while (0) namespace unittest { namespace detail { inline std::string FileName(const std::string& pPath) { const std::size_t slash = pPath.rfind("/"); std::string name = (slash != std::string::npos) ? pPath.substr(slash + 1) : pPath; return name; } } inline std::string TempPath() { char name[] = "rapidcsvtest.XX" "XX" "XX"; #ifndef _MSC_VER int fd = mkstemp(name); close(fd); #else _mktemp_s(name, strlen(name) + 1); #endif return std::string(name); } inline void WriteFile(const std::string& pPath, const std::string& pData) { std::ofstream outfile; outfile.open(pPath, std::ifstream::out | std::ifstream::binary); outfile << pData; outfile.close(); } inline std::string ReadFile(const std::string& pPath) { std::ifstream infile; infile.open(pPath, std::ifstream::in | std::ifstream::binary); std::string data((std::istreambuf_iterator(infile)), std::istreambuf_iterator()); infile.close(); return data; } inline void DeleteFile(const std::string& pPath) { std::remove(pPath.c_str()); } template inline void ExpectEqualFun(T pTest, T pRef, const std::string& testName, const std::string& refName, const std::string& filePath, int lineNo) { if (pTest != pRef) { std::stringstream ss; ss << std::setprecision(std::numeric_limits::digits10 + 1); ss << detail::FileName(filePath) << ":" << std::to_string(lineNo); ss << " ExpectEqual failed: " << testName << " != " << refName << std::endl; ss << testName << " = '" << pTest << "'" << std::endl; ss << refName << " = '" << pRef << "'" << std::endl; throw std::runtime_error(ss.str()); } } inline void ExpectTrueFun(bool pTest, const std::string& testName, const std::string& filePath, int lineNo) { if (!pTest) { std::stringstream ss; ss << detail::FileName(filePath) << ":" << std::to_string(lineNo); ss << " ExpectTrue failed: " << testName << " == false" << std::endl; throw std::runtime_error(ss.str()); } } }