|
| 1 | +/* |
| 2 | + * Copyright (c) Facebook, Inc. and its affiliates. |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | +#include "velox/functions/iceberg/BucketFunction.h" |
| 17 | +#include "velox/common/base/tests/GTestUtils.h" |
| 18 | +#include "velox/functions/iceberg/tests/IcebergFunctionBaseTest.h" |
| 19 | + |
| 20 | +#include <gtest/gtest.h> |
| 21 | + |
| 22 | +using namespace facebook::velox; |
| 23 | +using namespace facebook::velox::exec; |
| 24 | + |
| 25 | +namespace facebook::velox::functions::iceberg { |
| 26 | +namespace { |
| 27 | + |
| 28 | +class BucketFunctionTest |
| 29 | + : public functions::iceberg::test::IcebergFunctionBaseTest { |
| 30 | + public: |
| 31 | + BucketFunctionTest() { |
| 32 | + options_.parseDecimalAsDouble = false; |
| 33 | + } |
| 34 | + |
| 35 | + protected: |
| 36 | + template <typename T> |
| 37 | + std::optional<int32_t> bucket( |
| 38 | + std::optional<int32_t> numBuckets, |
| 39 | + std::optional<T> value) { |
| 40 | + return evaluateOnce<int32_t>("bucket(c0, c1)", numBuckets, value); |
| 41 | + } |
| 42 | + |
| 43 | + template <typename T> |
| 44 | + std::optional<int32_t> bucket( |
| 45 | + const TypePtr& type, |
| 46 | + std::optional<int32_t> numBuckets, |
| 47 | + std::optional<T> value) { |
| 48 | + return evaluateOnce<int32_t>( |
| 49 | + "bucket(c0, c1)", {INTEGER(), type}, numBuckets, value); |
| 50 | + } |
| 51 | +}; |
| 52 | + |
| 53 | +TEST_F(BucketFunctionTest, integerTypes) { |
| 54 | + EXPECT_EQ(bucket<int32_t>(10, 8), 3); |
| 55 | + EXPECT_EQ(bucket<int32_t>(10, 42), 6); |
| 56 | + EXPECT_EQ(bucket<int32_t>(100, 34), 79); |
| 57 | + EXPECT_EQ(bucket<int32_t>(1000, INT_MAX), 606); |
| 58 | + EXPECT_EQ(bucket<int32_t>(1000, INT_MIN), 856); |
| 59 | + EXPECT_EQ(bucket<int64_t>(10, 8), 3); |
| 60 | + EXPECT_EQ(bucket<int64_t>(10, 42), 6); |
| 61 | + EXPECT_EQ(bucket<int64_t>(100, -34), 97); |
| 62 | + EXPECT_EQ(bucket<int64_t>(2, -1), 0); |
| 63 | + VELOX_ASSERT_THROW( |
| 64 | + bucket<int64_t>(0, 34), |
| 65 | + "Reason: (0 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 66 | + VELOX_ASSERT_THROW( |
| 67 | + bucket<int64_t>(-3, 34), |
| 68 | + "Reason: (-3 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 69 | +} |
| 70 | + |
| 71 | +TEST_F(BucketFunctionTest, string) { |
| 72 | + EXPECT_EQ(bucket<std::string>(5, "abcdefg"), 4); |
| 73 | + EXPECT_EQ(bucket<std::string>(128, "abc"), 122); |
| 74 | + EXPECT_EQ(bucket<std::string>(128, "abcd"), 106); |
| 75 | + EXPECT_EQ(bucket<std::string>(64, "abcde"), 54); |
| 76 | + EXPECT_EQ(bucket<std::string>(12, "测试"), 8); |
| 77 | + EXPECT_EQ(bucket<std::string>(16, "测试raul试测"), 1); |
| 78 | + EXPECT_EQ(bucket<std::string>(16, ""), 0); |
| 79 | + EXPECT_EQ(bucket<std::string>(16, "Товары"), 10); |
| 80 | + EXPECT_EQ(bucket<std::string>(120, "😀"), 58); |
| 81 | + VELOX_ASSERT_THROW( |
| 82 | + bucket<std::string>(0, "abc"), |
| 83 | + "Reason: (0 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 84 | + VELOX_ASSERT_THROW( |
| 85 | + bucket<std::string>(-3, "abc"), |
| 86 | + "Reason: (-3 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 87 | +} |
| 88 | + |
| 89 | +TEST_F(BucketFunctionTest, binary) { |
| 90 | + EXPECT_EQ(bucket<StringView>(VARBINARY(), 128, "abc"), 122); |
| 91 | + EXPECT_EQ(bucket<StringView>(VARBINARY(), 5, "abcdefg"), 4); |
| 92 | +} |
| 93 | + |
| 94 | +TEST_F(BucketFunctionTest, timestamp) { |
| 95 | + EXPECT_EQ(bucket<Timestamp>(20, Timestamp(1633046400, 0)), 17); |
| 96 | + EXPECT_EQ(bucket<Timestamp>(20, Timestamp(0, 123456789)), 0); |
| 97 | + EXPECT_EQ(bucket<Timestamp>(20, Timestamp(-62167219200, 0)), 5); |
| 98 | + VELOX_ASSERT_THROW( |
| 99 | + bucket<Timestamp>(0, Timestamp(-62167219200, 0)), |
| 100 | + "Reason: (0 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 101 | + VELOX_ASSERT_THROW( |
| 102 | + bucket<Timestamp>(-3, Timestamp(-62167219200, 0)), |
| 103 | + "Reason: (-3 vs. 0) Invalid number of buckets.\nExpression: numBuckets <= 0\n"); |
| 104 | +} |
| 105 | + |
| 106 | +TEST_F(BucketFunctionTest, date) { |
| 107 | + EXPECT_EQ(bucket<int32_t>(DATE(), 10, 8), 3); |
| 108 | + EXPECT_EQ(bucket<int32_t>(DATE(), 10, 42), 6); |
| 109 | +} |
| 110 | + |
| 111 | +TEST_F(BucketFunctionTest, decimal) { |
| 112 | + EXPECT_EQ(bucket<int64_t>(DECIMAL(9, 2), 64, 1234), 56); |
| 113 | + EXPECT_EQ(bucket<int64_t>(DECIMAL(9, 2), 18, 1230), 13); |
| 114 | + EXPECT_EQ(bucket<int64_t>(DECIMAL(9, 2), 16, 12999), 2); |
| 115 | + EXPECT_EQ(bucket<int64_t>(DECIMAL(9, 2), 128, 5), 85); |
| 116 | + EXPECT_EQ(bucket<int64_t>(DECIMAL(9, 2), 18, 5), 3); |
| 117 | + |
| 118 | + EXPECT_EQ(bucket<int128_t>(DECIMAL(38, 2), 10, 12), 7); |
| 119 | + EXPECT_EQ(bucket<int128_t>(DECIMAL(38, 2), 10, 0), 7); |
| 120 | + EXPECT_EQ(bucket<int128_t>(DECIMAL(38, 2), 10, 234), 6); |
| 121 | + EXPECT_EQ( |
| 122 | + bucket<int128_t>(DECIMAL(38, 2), 10, DecimalUtil::kLongDecimalMax), 4); |
| 123 | +} |
| 124 | + |
| 125 | +} // namespace |
| 126 | +} // namespace facebook::velox::functions::iceberg |
0 commit comments