mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-16 19:32:07 +00:00
215 lines
6.3 KiB
C++
215 lines
6.3 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <Common/DateLUT.h>
|
|
#include <IO/WriteHelpers.h>
|
|
#include <IO/WriteBufferFromString.h>
|
|
|
|
namespace
|
|
{
|
|
using namespace DB;
|
|
|
|
struct DateTime64WithScale
|
|
{
|
|
DateTime64 value;
|
|
UInt32 scale;
|
|
};
|
|
|
|
template <typename ValueType>
|
|
auto getTypeName(const ValueType &)
|
|
{
|
|
if constexpr (std::is_same_v<ValueType, DayNum>)
|
|
{
|
|
return "DayNum";
|
|
}
|
|
else if constexpr (std::is_same_v<ValueType, time_t>)
|
|
{
|
|
return "time_t";
|
|
}
|
|
else if constexpr (std::is_same_v<ValueType, DateTime64WithScale>)
|
|
{
|
|
return "DateTime64WithScale";
|
|
}
|
|
}
|
|
|
|
std::ostream & dump_datetime(std::ostream & ostr, const DayNum & d)
|
|
{
|
|
return ostr << getTypeName(d) << "{" << d.toUnderType() << "}";
|
|
}
|
|
|
|
std::ostream & dump_datetime(std::ostream & ostr, const time_t & dt)
|
|
{
|
|
return ostr << getTypeName(dt) << "{" << dt << "}";
|
|
}
|
|
|
|
std::ostream & dump_datetime(std::ostream & ostr, const DateTime64WithScale & dt64)
|
|
{
|
|
return ostr << getTypeName(dt64) << "{" << dt64.value.value << ", scale: " << dt64.scale << "}";
|
|
}
|
|
|
|
template <typename ValueType>
|
|
struct DateTimeToStringParamTestCase
|
|
{
|
|
const char * description;
|
|
const ValueType input;
|
|
const char * expected;
|
|
const char * timezone = "UTC";
|
|
};
|
|
|
|
template <typename T>
|
|
std::ostream & operator << (std::ostream & ostr, const DateTimeToStringParamTestCase<T> & test_case)
|
|
{
|
|
ostr << "DateTimeToStringParamTestCase<" << getTypeName(test_case.input) << ">{"
|
|
<< "\n\t\"" << test_case.description << "\""
|
|
<< "\n\tinput : ";
|
|
dump_datetime(ostr, test_case.input)
|
|
<< "\n\texpected : " << test_case.expected
|
|
<< "\n\ttimezone : " << test_case.timezone
|
|
<< "\n}";
|
|
return ostr;
|
|
}
|
|
|
|
}
|
|
|
|
TEST(DateTimeToStringTest, RFC1123)
|
|
{
|
|
using namespace DB;
|
|
WriteBufferFromOwnString out;
|
|
writeDateTimeTextRFC1123(1111111111, out, DateLUT::instance("UTC"));
|
|
ASSERT_EQ(out.str(), "Fri, 18 Mar 2005 01:58:31 GMT");
|
|
}
|
|
|
|
template <typename ValueType>
|
|
class DateTimeToStringParamTestBase : public ::testing::TestWithParam<DateTimeToStringParamTestCase<ValueType>>
|
|
{
|
|
public:
|
|
void test(const DateTimeToStringParamTestCase<ValueType> & param)
|
|
{
|
|
[[maybe_unused]] const auto & [description, input, expected, timezone_name] = param;
|
|
|
|
using namespace DB;
|
|
WriteBufferFromOwnString out;
|
|
|
|
if constexpr (std::is_same_v<ValueType, DayNum>)
|
|
{
|
|
writeDateText(input, out);
|
|
}
|
|
else if constexpr (std::is_same_v<ValueType, time_t>)
|
|
{
|
|
writeDateTimeText(input, out, DateLUT::instance(timezone_name));
|
|
}
|
|
else if constexpr (std::is_same_v<ValueType, DateTime64WithScale>)
|
|
{
|
|
writeDateTimeText(input.value, input.scale, out, DateLUT::instance(timezone_name));
|
|
}
|
|
|
|
ASSERT_EQ(expected, out.str());
|
|
}
|
|
};
|
|
|
|
class DateTimeToStringParamTestDayNum : public DateTimeToStringParamTestBase<DayNum>
|
|
{};
|
|
|
|
TEST_P(DateTimeToStringParamTestDayNum, writeDateText)
|
|
{
|
|
ASSERT_NO_FATAL_FAILURE(test(GetParam()));
|
|
}
|
|
|
|
class DateTimeToStringParamTestTimeT : public DateTimeToStringParamTestBase<time_t>
|
|
{};
|
|
|
|
TEST_P(DateTimeToStringParamTestTimeT, writeDateText)
|
|
{
|
|
ASSERT_NO_FATAL_FAILURE(test(GetParam()));
|
|
}
|
|
|
|
class DateTimeToStringParamTestDateTime64 : public DateTimeToStringParamTestBase<DateTime64WithScale>
|
|
{};
|
|
|
|
TEST_P(DateTimeToStringParamTestDateTime64, writeDateText)
|
|
{
|
|
ASSERT_NO_FATAL_FAILURE(test(GetParam()));
|
|
}
|
|
|
|
static const Int32 NON_ZERO_TIME_T = 10 * 365 * 3600 * 24 + 123456; /// NOTE This arithmetic is obviously wrong but it's ok for test.
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DateTimeToString, DateTimeToStringParamTestDayNum,
|
|
::testing::ValuesIn(std::initializer_list<DateTimeToStringParamTestCase<DayNum>>
|
|
{
|
|
{
|
|
"Zero DayNum pointing to 1970-01-01",
|
|
DayNum(0),
|
|
"1970-01-01"
|
|
},
|
|
{
|
|
"Non-Zero DayNum",
|
|
DayNum(1),
|
|
"1970-01-02"
|
|
},
|
|
{
|
|
"Non-Zero DayNum",
|
|
DayNum(10 * 365),
|
|
"1979-12-30"
|
|
},
|
|
{
|
|
"Negative DayNum value wraps as if it was UInt16 due to LUT limitations and to maintain compatibility with existing code.",
|
|
DayNum(-10 * 365),
|
|
"2139-06-10"
|
|
},
|
|
})
|
|
);
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DateTimeToString, DateTimeToStringParamTestTimeT,
|
|
::testing::ValuesIn(std::initializer_list<DateTimeToStringParamTestCase<time_t>>
|
|
{
|
|
{
|
|
"Zero time_t pointing to 1970-01-01 00:00:00 in UTC",
|
|
time_t(0),
|
|
"1970-01-01 00:00:00"
|
|
},
|
|
{
|
|
"Non-Zero time_t is a valid date/time",
|
|
time_t{NON_ZERO_TIME_T},
|
|
"1979-12-31 10:17:36"
|
|
},
|
|
// { // Negative time_t value produces (expectedly) bogus results,
|
|
// // and there is no reliable way to verify output values on all platforms and configurations
|
|
// // (since part of stacktrace is printed), so this test case is disabled.
|
|
// "Negative time_t value wraps as if it was UInt32 due to LUT limitations.",
|
|
// time_t(-1LL * 365 * 3600 * 24),
|
|
// "2006-03-03 06:28:16"
|
|
// },
|
|
})
|
|
);
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DateTimeToString, DateTimeToStringParamTestDateTime64,
|
|
::testing::ValuesIn(std::initializer_list<DateTimeToStringParamTestCase<DateTime64WithScale>>
|
|
{
|
|
/// Inside basic LUT boundaries
|
|
{
|
|
"Zero DateTime64 with scale 0 string representation matches one of zero time_t",
|
|
DateTime64WithScale{0, 0},
|
|
"1970-01-01 00:00:00"
|
|
},
|
|
{
|
|
"Zero DateTime64 with scale 3 string representation matches one of zero time_t with subsecond part",
|
|
DateTime64WithScale{0, 3},
|
|
"1970-01-01 00:00:00.000"
|
|
},
|
|
{
|
|
"Non-Zero DateTime64 with scale 0",
|
|
DateTime64WithScale{NON_ZERO_TIME_T, 0},
|
|
"1979-12-31 10:17:36"
|
|
},
|
|
{
|
|
"Non-Zero DateTime64 with scale 3",
|
|
DateTime64WithScale{NON_ZERO_TIME_T * 1000LL + 123, 3},
|
|
"1979-12-31 10:17:36.123"
|
|
},
|
|
// {
|
|
// "Negative time_t value wraps around as if it was UInt32 due to LUT limitations and to maintain compatibility with existing code",
|
|
// time_t(-10 * 365 * 3600 * 24),
|
|
// "1979-12-30 08:00:00"
|
|
// },
|
|
})
|
|
);
|