blob: 28f4a4849549a5a5f7201c0156b6990f62f23ad7 [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 <memory>
#include <string>
#include <gtest/gtest.h>
#include "iceberg/test/matchers.h"
#include "iceberg/transform.h"
namespace iceberg {
struct HumanStringTestParam {
std::string test_name;
std::shared_ptr<Type> source_type;
Literal literal;
std::vector<std::string> expecteds;
};
class IdentityHumanStringTest : public ::testing::TestWithParam<HumanStringTestParam> {
protected:
std::vector<std::shared_ptr<Transform>> transforms_{{Transform::Identity()}};
};
TEST_P(IdentityHumanStringTest, ToHumanString) {
const auto& param = GetParam();
for (int32_t i = 0; i < transforms_.size(); ++i) {
EXPECT_THAT(transforms_[i]->ToHumanString(param.literal),
HasValue(::testing::Eq(param.expecteds[i])));
}
}
INSTANTIATE_TEST_SUITE_P(
IdentityHumanStringTestCases, IdentityHumanStringTest,
::testing::Values(
HumanStringTestParam{.test_name = "Null",
.literal = Literal::Null(std::make_shared<IntType>()),
.expecteds{"null"}},
HumanStringTestParam{.test_name = "Binary",
.literal = Literal::Binary(std::vector<uint8_t>{1, 2, 3}),
.expecteds{"AQID"}},
HumanStringTestParam{.test_name = "Fixed",
.literal = Literal::Fixed(std::vector<uint8_t>{1, 2, 3}),
.expecteds{"AQID"}},
HumanStringTestParam{.test_name = "Date",
.literal = Literal::Date(17501),
.expecteds{"2017-12-01"}},
HumanStringTestParam{.test_name = "Time",
.literal = Literal::Time(36775038194),
.expecteds{"10:12:55.038194"}},
HumanStringTestParam{.test_name = "TimestampWithZone",
.literal = Literal::TimestampTz(1512151975038194),
.expecteds{"2017-12-01T18:12:55.038194+00:00"}},
HumanStringTestParam{.test_name = "TimestampWithoutZone",
.literal = Literal::Timestamp(1512123175038194),
.expecteds{"2017-12-01T10:12:55.038194"}},
HumanStringTestParam{.test_name = "Long",
.literal = Literal::Long(-1234567890000L),
.expecteds{"-1234567890000"}},
HumanStringTestParam{.test_name = "String",
.literal = Literal::String("a/b/c=d"),
.expecteds{"a/b/c=d"}}),
[](const ::testing::TestParamInfo<HumanStringTestParam>& info) {
return info.param.test_name;
});
class DateHumanStringTest : public ::testing::TestWithParam<HumanStringTestParam> {
protected:
std::vector<std::shared_ptr<Transform>> transforms_{
Transform::Year(), Transform::Month(), Transform::Day()};
};
TEST_P(DateHumanStringTest, ToHumanString) {
const auto& param = GetParam();
for (uint32_t i = 0; i < transforms_.size(); i++) {
ICEBERG_UNWRAP_OR_FAIL(auto trans_func,
transforms_[i]->Bind(std::make_shared<DateType>()));
ICEBERG_UNWRAP_OR_FAIL(auto literal, trans_func->Transform(param.literal));
EXPECT_THAT(transforms_[i]->ToHumanString(literal),
HasValue(::testing::Eq(param.expecteds[i])));
}
}
INSTANTIATE_TEST_SUITE_P(
DateHumanStringTestCases, DateHumanStringTest,
::testing::Values(
HumanStringTestParam{.test_name = "Date",
.literal = Literal::Date(17501),
.expecteds = {"2017", "2017-12", "2017-12-01"}},
HumanStringTestParam{.test_name = "NegativeDate",
.literal = Literal::Date(-2),
.expecteds = {"1969", "1969-12", "1969-12-30"}},
HumanStringTestParam{.test_name = "DateLowerBound",
.literal = Literal::Date(0),
.expecteds = {"1970", "1970-01", "1970-01-01"}},
HumanStringTestParam{.test_name = "NegativeDateLowerBound",
.literal = Literal::Date(-365),
.expecteds = {"1969", "1969-01", "1969-01-01"}},
HumanStringTestParam{.test_name = "NegativeDateUpperBound",
.literal = Literal::Date(-1),
.expecteds = {"1969", "1969-12", "1969-12-31"}},
HumanStringTestParam{.test_name = "Null",
.literal = Literal::Null(std::make_shared<DateType>()),
.expecteds = {"null", "null", "null"}}),
[](const ::testing::TestParamInfo<HumanStringTestParam>& info) {
return info.param.test_name;
});
class TimestampHumanStringTest : public ::testing::TestWithParam<HumanStringTestParam> {
protected:
std::vector<std::shared_ptr<Transform>> transforms_{
Transform::Year(), Transform::Month(), Transform::Day(), Transform::Hour()};
};
TEST_F(TimestampHumanStringTest, InvalidType) {
ICEBERG_UNWRAP_OR_FAIL(auto above_max,
Literal::Long(std::numeric_limits<int64_t>::max())
.CastTo(std::make_shared<IntType>()));
ICEBERG_UNWRAP_OR_FAIL(auto below_min,
Literal::Long(std::numeric_limits<int64_t>::min())
.CastTo(std::make_shared<IntType>()));
auto unmatch_type_literal = Literal::Long(std::numeric_limits<int64_t>::max());
for (const auto& transform : transforms_) {
auto result = transform->ToHumanString(above_max);
EXPECT_THAT(result, IsError(ErrorKind::kNotSupported));
EXPECT_THAT(result,
HasErrorMessage("Cannot transfrom human string for value: aboveMax"));
result = transform->ToHumanString(below_min);
EXPECT_THAT(result, IsError(ErrorKind::kNotSupported));
EXPECT_THAT(result,
HasErrorMessage("Cannot transfrom human string for value: belowMin"));
result = transform->ToHumanString(unmatch_type_literal);
EXPECT_THAT(result, IsError(ErrorKind::kNotSupported));
EXPECT_THAT(result, HasErrorMessage(std::format(
"Transfrom human {} from type {} is not supported",
TransformTypeToString(transform->transform_type()),
unmatch_type_literal.type()->ToString())));
}
}
TEST_P(TimestampHumanStringTest, ToHumanString) {
const auto& param = GetParam();
for (uint32_t i = 0; i < transforms_.size(); i++) {
ICEBERG_UNWRAP_OR_FAIL(auto trans_func, transforms_[i]->Bind(param.source_type));
ICEBERG_UNWRAP_OR_FAIL(auto literal, trans_func->Transform(param.literal));
EXPECT_THAT(transforms_[i]->ToHumanString(literal),
HasValue(::testing::Eq(param.expecteds[i])));
}
}
INSTANTIATE_TEST_SUITE_P(
TimestampHumanStringTestCases, TimestampHumanStringTest,
::testing::Values(
HumanStringTestParam{
.test_name = "Timestamp",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Timestamp(1512123175038194),
.expecteds = {"2017", "2017-12", "2017-12-01", "2017-12-01-10"}},
HumanStringTestParam{
.test_name = "NegativeTimestamp",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Timestamp(-136024961806),
.expecteds = {"1969", "1969-12", "1969-12-30", "1969-12-30-10"}},
HumanStringTestParam{
.test_name = "TimestampLowerBound",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Timestamp(0),
.expecteds = {"1970", "1970-01", "1970-01-01", "1970-01-01-00"}},
HumanStringTestParam{
.test_name = "NegativeTimestampLowerBound",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Timestamp(-172800000000),
.expecteds = {"1969", "1969-12", "1969-12-30", "1969-12-30-00"},
},
HumanStringTestParam{
.test_name = "NegativeTimestampUpperBound",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Timestamp(-1),
.expecteds = {"1969", "1969-12", "1969-12-31", "1969-12-31-23"}},
HumanStringTestParam{
.test_name = "TimestampTz",
.source_type = std::make_shared<TimestampTzType>(),
.literal = Literal::TimestampTz(1512151975038194),
.expecteds = {"2017", "2017-12", "2017-12-01", "2017-12-01-18"}},
HumanStringTestParam{.test_name = "Null",
.source_type = std::make_shared<TimestampType>(),
.literal = Literal::Null(std::make_shared<TimestampType>()),
.expecteds = {"null", "null", "null", "null"}}),
[](const ::testing::TestParamInfo<HumanStringTestParam>& info) {
return info.param.test_name;
});
} // namespace iceberg