blob: d0f9e20db9228c68df3a8d0614058784d1b36b1d [file]
/*
* 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 "paimon/common/utils/range_helper.h"
#include <optional>
#include "gtest/gtest.h"
#include "paimon/status.h"
#include "paimon/testing/utils/testharness.h"
namespace paimon::test {
class RangeHelperTest : public ::testing::Test {
public:
void SetUp() override {
start_func_ = [](const Range& range) -> Result<int64_t> {
if (range.start) {
return range.start.value();
}
return Status::Invalid("start is null");
};
end_func_ = [](const Range& range) -> Result<int64_t> {
if (range.end) {
return range.end.value();
}
return Status::Invalid("end is null");
};
}
void TearDown() override {}
struct Range {
Range(const std::optional<int64_t>& _start, const std::optional<int64_t>& _end)
: start(_start), end(_end) {}
Range(Range&& other) : start(other.start), end(other.end) {}
Range(const Range& other) = default;
Range& operator=(Range&& other) noexcept {
if (&other == this) {
return *this;
}
start = other.start;
end = other.end;
return *this;
}
Range& operator=(const Range& other) noexcept {
if (&other == this) {
return *this;
}
start = other.start;
end = other.end;
return *this;
}
bool operator==(const Range& other) const {
return start == other.start && end == other.end;
}
std::optional<int64_t> start;
std::optional<int64_t> end;
};
private:
std::function<Result<int64_t>(const Range&)> start_func_;
std::function<Result<int64_t>(const Range&)> end_func_;
};
TEST_F(RangeHelperTest, TestAreAllRangesSame) {
{
std::vector<Range> ranges = {Range(0l, 100l), Range(0l, 100l), Range(1l, 100l)};
ASSERT_OK_AND_ASSIGN(bool same,
RangeHelper(start_func_, end_func_).AreAllRangesSame(ranges));
ASSERT_FALSE(same);
}
{
std::vector<Range> ranges = {Range(0l, 100l), Range(0l, 100l), Range(0l, 300l)};
ASSERT_OK_AND_ASSIGN(bool same,
RangeHelper(start_func_, end_func_).AreAllRangesSame(ranges));
ASSERT_FALSE(same);
}
{
std::vector<Range> ranges = {Range(0l, 100l), Range(0l, 100l), Range(0l, 100l)};
ASSERT_OK_AND_ASSIGN(bool same,
RangeHelper(start_func_, end_func_).AreAllRangesSame(ranges));
ASSERT_TRUE(same);
}
{
ASSERT_OK_AND_ASSIGN(bool same, RangeHelper(start_func_, end_func_).AreAllRangesSame({}));
ASSERT_TRUE(same);
}
{
std::vector<Range> ranges = {Range(0l, 100l)};
ASSERT_OK_AND_ASSIGN(bool same,
RangeHelper(start_func_, end_func_).AreAllRangesSame(ranges));
ASSERT_TRUE(same);
}
{
std::vector<Range> ranges = {Range(0l, std::nullopt)};
ASSERT_NOK_WITH_MSG(RangeHelper(start_func_, end_func_).AreAllRangesSame(ranges),
"end is null");
}
}
TEST_F(RangeHelperTest, TestMergeOverlappingRanges) {
{
std::vector<Range> ranges = {Range(200, 299), Range(0, 99), Range(110, 199),
Range(100, 109), Range(100, 199), Range(0, 49),
Range(50, 99)};
ASSERT_OK_AND_ASSIGN(
auto merged_ranges,
RangeHelper(start_func_, end_func_).MergeOverlappingRanges(std::move(ranges)));
std::vector<std::vector<Range>> expected = {
{Range(0, 99), Range(0, 49), Range(50, 99)},
{Range(110, 199), Range(100, 109), Range(100, 199)},
{Range(200, 299)},
};
ASSERT_EQ(expected, merged_ranges);
}
{
ASSERT_OK_AND_ASSIGN(auto merged_ranges,
RangeHelper(start_func_, end_func_).MergeOverlappingRanges({}));
ASSERT_TRUE(merged_ranges.empty());
}
{
std::vector<Range> ranges = {Range(0, 99)};
ASSERT_OK_AND_ASSIGN(
auto merged_ranges,
RangeHelper(start_func_, end_func_).MergeOverlappingRanges(std::move(ranges)));
std::vector<std::vector<Range>> expected = {{Range(0, 99)}};
ASSERT_EQ(expected, merged_ranges);
}
{
std::vector<Range> ranges = {Range(200, 299), Range(std::nullopt, 299)};
ASSERT_NOK_WITH_MSG(
RangeHelper(start_func_, end_func_).MergeOverlappingRanges(std::move(ranges)),
"start is null");
}
}
} // namespace paimon::test