diff --git a/libs/libcommon/include/common/Test.h b/libs/libcommon/include/common/Test.h new file mode 100644 index 00000000000..35e2ad8363c --- /dev/null +++ b/libs/libcommon/include/common/Test.h @@ -0,0 +1,125 @@ +#pragma once + +#include +#include + +/// Часть функциональности - только для сборки из репозитория Метрики. +#ifndef NO_METRIKA + #include +#else + struct IDbObject {}; +#endif + +#include +#include +#include + +#include +#include +#include + + +namespace Test +{ + template + struct Comparator + { + void check(const Result & result, const Reference & reference, const std::string & check_name = "") + { + if (result != reference) + { + std::stringstream ss; + if (check_name.size()) + ss << "Check name: " << check_name << ". "; + + StackTrace stacktrace; + ss << "Result "; + if (check_name.size()) + ss << "for \"" << check_name << "\" "; + + ss << "differs from reference" << + ". Result: " << result << ", reference: " << reference << "\n. Stacktrace: " << stacktrace.toString(); + throw std::logic_error(ss.str()); + } + } + }; + + template + void compare(const Result & result, const Reference & reference, Args && ... args) + { + Comparator comp; + comp.check(result, reference, std::forward(args)...); + } + + template + void compareContainers(const ContainerA & result, const ContainerB & reference) + { + if (result != reference) + { + std::stringstream ss; + ss << "Result differs from reference. Result: {"; + for (auto a : result) + ss << " " << a; + ss << " }, reference {"; + for (auto b : reference) + ss << " " << b; + ss << " }"; + + StackTrace stacktrace; + ss << "\n. Stacktrace: " << stacktrace.toString(); + + throw std::logic_error(ss.str()); + } + } + + template + struct Comparator::value && + std::is_base_of::value>::type> + { + void check(const Result & result, const Reference & reference, const std::string field_name_regexp_str = ".*") + { + std::string res_s; + { + DB::WriteBufferFromString res_b(res_s); + result.writeTSKV(res_b, "", "", ""); + } + + std::string ref_s; + { + DB::WriteBufferFromString ref_b(ref_s); + reference.writeTSKV(ref_b, "", "", ""); + } + + size_t ref_pos = 0; + size_t res_pos = 0; + + while (ref_pos != std::string::npos && res_pos != std::string::npos) + { + size_t new_ref_pos = ref_s.find('\t', ref_pos); + size_t new_res_pos = res_s.find('\t', res_pos); + + auto ref_field = ref_s.substr(ref_pos, + new_ref_pos != std::string::npos ? new_ref_pos - ref_pos : new_ref_pos); + + if (std::regex_match(ref_field, std::regex(field_name_regexp_str + "=.*"))) + { + auto res_field = res_s.substr(res_pos, new_res_pos != std::string::npos ? new_res_pos - res_pos : new_res_pos); + compare(res_field, ref_field); + } + + res_pos = new_res_pos != res_s.size() && new_res_pos != std::string::npos ? + new_res_pos + 1 : std::string::npos; + ref_pos = new_ref_pos != ref_s.size() && new_ref_pos != std::string::npos ? + new_ref_pos + 1 : std::string::npos; + } + } + }; + + inline void initLogger() + { + Poco::AutoPtr channel = new Poco::ConsoleChannel(std::cerr); + Poco::Logger::root().setChannel(channel); + Poco::Logger::root().setLevel("trace"); + } +}; diff --git a/libs/libcommon/src/tests/CMakeLists.txt b/libs/libcommon/src/tests/CMakeLists.txt index 3f20a5f2698..11056819424 100644 --- a/libs/libcommon/src/tests/CMakeLists.txt +++ b/libs/libcommon/src/tests/CMakeLists.txt @@ -12,6 +12,6 @@ target_link_libraries (date_lut2 common libicui18n.a libicuuc.a libicudata.a dl) target_link_libraries (date_lut3 common libicui18n.a libicuuc.a libicudata.a dl) target_link_libraries (date_lut4 common libicui18n.a libicuuc.a libicudata.a dl) target_link_libraries (multi_version common libboost_thread.a libboost_system.a rt) -target_link_libraries (json_test statdaemons common libboost_thread.a libboost_system.a rt) +target_link_libraries (json_test dbms libboost_thread.a libboost_system.a rt) add_check (json_test) diff --git a/libs/libcommon/src/tests/json_test.cpp b/libs/libcommon/src/tests/json_test.cpp index a507fc5ad33..4d5c6a91ece 100644 --- a/libs/libcommon/src/tests/json_test.cpp +++ b/libs/libcommon/src/tests/json_test.cpp @@ -1,4 +1,5 @@ -#include +#define NO_METRIKA +#include #include #include #include