mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-12 10:34:21 +00:00
148 lines
4.2 KiB
C++
148 lines
4.2 KiB
C++
#pragma once
|
||
|
||
#include <stdexcept>
|
||
#include <sstream>
|
||
#include <iostream>
|
||
|
||
/// Часть функциональности - только для сборки из репозитория Метрики.
|
||
#ifndef NO_METRIKA
|
||
#include <ssqls/IDbObject.h>
|
||
#else
|
||
struct IDbObject {};
|
||
#endif
|
||
|
||
#include <regex>
|
||
#include <iostream>
|
||
|
||
#include <DB/Common/StackTrace.h>
|
||
#include <DB/IO/WriteBufferFromString.h>
|
||
#include <daemon/OwnPatternFormatter.h>
|
||
|
||
#include <Poco/ConsoleChannel.h>
|
||
#include <Poco/FormattingChannel.h>
|
||
#include <Poco/Logger.h>
|
||
#include <Poco/AutoPtr.h>
|
||
|
||
|
||
namespace Test
|
||
{
|
||
template <class Result, class Reference, class Enable = void>
|
||
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 <class Result, class Reference, class Enable = void, class ... Args>
|
||
void compare(const Result & result, const Reference & reference, Args && ... args)
|
||
{
|
||
Comparator<Result, Reference> comp;
|
||
comp.check(result, reference, std::forward<Args>(args)...);
|
||
}
|
||
|
||
template <class ContainerA, class ContainerB>
|
||
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 <class Result, class Reference>
|
||
struct Comparator<Result, Reference, typename std::enable_if<
|
||
std::is_base_of<IDbObject, Result>::value &&
|
||
std::is_base_of<IDbObject, Reference>::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<OwnPatternFormatter> pattern_formatter = new OwnPatternFormatter(nullptr);
|
||
pattern_formatter->setProperty("times", "local");
|
||
Poco::AutoPtr<Poco::FormattingChannel> formatting_channel = new Poco::FormattingChannel(pattern_formatter);
|
||
Poco::AutoPtr<Poco::ConsoleChannel> console_channel = new Poco::ConsoleChannel(std::cerr);
|
||
formatting_channel->setChannel(console_channel);
|
||
|
||
Poco::Logger::root().setChannel(formatting_channel);
|
||
Poco::Logger::root().setLevel("trace");
|
||
}
|
||
};
|
||
|
||
/// использование в boost_unit_test:
|
||
/// BOOST_GLOBAL_FIXTURE(TestLogInitializer);
|
||
///
|
||
/// без namespace, т.к. BOOST_GLOBAL_FIXTURE некорректно работает с namespace
|
||
struct TestLogInitializer
|
||
{
|
||
TestLogInitializer()
|
||
{
|
||
Test::initLogger();
|
||
}
|
||
};
|