blob: 343d8eefd4d1327060decb7264faa3246ba669d2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "kudu/common/types.h"
#include <cmath>
#include <cstdint>
#include <limits>
#include <string>
#include <tuple> // IWYU pragma: keep
#include <utility>
#include <vector>
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include "kudu/common/common.pb.h"
#include "kudu/gutil/mathlimits.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/util/slice.h"
#include "kudu/util/test_util.h"
using std::get;
using std::make_tuple;
using std::nextafter;
using std::string;
using std::tuple;
using std::vector;
namespace kudu {
class TestTypes : public KuduTest {
protected:
static void TestDateToString(const string& expected, int32_t date) {
const TypeInfo* info = GetTypeInfo(DATE);
string result;
info->AppendDebugStringForValue(&date, &result);
ASSERT_EQ(expected, result);
}
};
TEST_F(TestTypes, TestDatePrinting) {
#if defined(__APPLE__)
// On MacOS the `%F` date format pads the year with zeros.
TestDateToString("0001-01-01", *DataTypeTraits<DATE>::min_value());
#else
TestDateToString("1-01-01", *DataTypeTraits<DATE>::min_value());
#endif
TestDateToString("9999-12-31", *DataTypeTraits<DATE>::max_value());
TestDateToString("1970-01-01", 0);
TestDateToString("1942-08-16", -10000);
TestDateToString("1997-05-19", 10000);
TestDateToString("value -2147483648 out of range for DATE type",
std::numeric_limits<int32_t>::min());
TestDateToString("value 2147483647 out of range for DATE type",
std::numeric_limits<int32_t>::max());
TestDateToString("value -719163 out of range for DATE type",
*DataTypeTraits<DATE>::min_value() - 1);
TestDateToString("value 2932897 out of range for DATE type",
*DataTypeTraits<DATE>::max_value() + 1);
}
TEST_F(TestTypes, TestTimestampPrinting) {
const TypeInfo* info = GetTypeInfo(UNIXTIME_MICROS);
// Test the minimum value
int64_t time;
info->CopyMinValue(&time);
string result;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("-290308-12-21T19:59:05.224192Z", result);
result = "";
// Test a regular negative timestamp.
time = -1454368523123456;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("1923-12-01T00:44:36.876544Z", result);
result = "";
// Test that passing 0 microseconds returns the correct time (0 msecs after the epoch).
// This is a test for a bug where printing a timestamp with the value 0 would return the
// current time instead.
time = 0;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("1970-01-01T00:00:00.000000Z", result);
result = "";
// Test a regular positive timestamp.
time = 1454368523123456;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("2016-02-01T23:15:23.123456Z", result);
result = "";
// Test the maximum value.
time = MathLimits<int64_t>::kMax;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("294247-01-10T04:00:54.775807Z", result);
result = "";
{
// Check that row values are redacted when --redact is set with 'log'.
google::FlagSaver flag_saver;
ASSERT_NE("", gflags::SetCommandLineOption("redact", "log"));
time = 0;
info->AppendDebugStringForValue(&time, &result);
ASSERT_EQ("<redacted>", result);
result = "";
}
}
namespace {
template <typename T>
void TestAreConsecutive(DataType type, vector<tuple<T, T, bool>> test_cases) {
const TypeInfo* info = GetTypeInfo(type);
for (auto test_case : test_cases) {
string lower, upper;
info->AppendDebugStringForValue(&get<0>(test_case), &lower);
info->AppendDebugStringForValue(&get<1>(test_case), &upper);
SCOPED_TRACE(strings::Substitute("lower: $0, upper: $1, expected: $2",
lower, upper, get<2>(test_case)));
ASSERT_EQ(get<2>(test_case), info->AreConsecutive(&get<0>(test_case), &get<1>(test_case)));
}
}
} // anonymous namespace
TEST_F(TestTypes, TestAreConsecutiveInteger) {
vector<tuple<int64_t, int64_t, bool>> test_cases {
make_tuple(0, 0, false),
make_tuple(0, 1, true),
make_tuple(-1, 0, true),
make_tuple(INT64_MAX, 0, false),
make_tuple(0, INT64_MAX, false),
make_tuple(INT64_MAX - 1, INT64_MAX, true),
make_tuple(INT64_MIN, 0, false),
make_tuple(INT64_MIN, INT64_MIN + 1, true),
make_tuple(INT64_MIN, 0, false),
make_tuple(-32, -31, true),
make_tuple(42, 43, true),
make_tuple(99, -98, false),
};
TestAreConsecutive(INT64, test_cases);
}
TEST_F(TestTypes, TestAreConsecutiveDouble) {
vector<tuple<double, double, bool>> test_cases {
make_tuple(0.0, 1.0, false),
make_tuple(0.0, 0.1, false),
make_tuple(0, nextafter(0, INFINITY), true),
make_tuple(123.45, nextafter(123.45, INFINITY), true),
make_tuple(-123.45, nextafter(-123.45, INFINITY), true),
make_tuple(123.45, 88.0, false),
};
TestAreConsecutive(DOUBLE, test_cases);
}
TEST_F(TestTypes, TestAreConsecutiveString) {
vector<tuple<Slice, Slice, bool>> test_cases {
make_tuple("abc", "abc", false),
make_tuple("abc", Slice("abc\0", 4), true),
make_tuple("", Slice("\0", 1), true),
make_tuple("", Slice("\1", 1), false),
make_tuple("", "", false),
make_tuple("", "a", false),
make_tuple("abacadaba", Slice("abacadaba\0", 10), true),
};
TestAreConsecutive(STRING, test_cases);
}
} // namespace kudu