| //===- llvm/unittest/Support/IntegerInclusiveIntervalTest.cpp -------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Support/IntegerInclusiveInterval.h" |
| #include "llvm/Testing/Support/Error.h" |
| #include "gtest/gtest.h" |
| |
| using namespace llvm; |
| |
| TEST(IntegerInclusiveIntervalTest, BasicInterval) { |
| IntegerInclusiveInterval I(5, 10); |
| EXPECT_EQ(I.getBegin(), 5); |
| EXPECT_EQ(I.getEnd(), 10); |
| EXPECT_TRUE(I.contains(5)); |
| EXPECT_TRUE(I.contains(7)); |
| EXPECT_TRUE(I.contains(10)); |
| EXPECT_FALSE(I.contains(4)); |
| EXPECT_FALSE(I.contains(11)); |
| } |
| |
| TEST(IntegerInclusiveIntervalTest, SingleValueInterval) { |
| IntegerInclusiveInterval I(42); |
| EXPECT_EQ(I.getBegin(), 42); |
| EXPECT_EQ(I.getEnd(), 42); |
| EXPECT_TRUE(I.contains(42)); |
| EXPECT_FALSE(I.contains(41)); |
| EXPECT_FALSE(I.contains(43)); |
| } |
| |
| TEST(IntegerInclusiveIntervalTest, IntervalOverlaps) { |
| IntegerInclusiveInterval I1(1, 5); |
| IntegerInclusiveInterval I2(3, 8); |
| IntegerInclusiveInterval I3(6, 10); |
| IntegerInclusiveInterval I4(11, 15); |
| |
| EXPECT_TRUE(I1.overlaps(I2)); |
| EXPECT_TRUE(I2.overlaps(I1)); |
| EXPECT_TRUE(I2.overlaps(I3)); |
| EXPECT_FALSE(I1.overlaps(I3)); |
| EXPECT_FALSE(I1.overlaps(I4)); |
| EXPECT_FALSE(I3.overlaps(I4)); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseSingleNumber) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("42"); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_EQ(Intervals.size(), 1U); |
| EXPECT_EQ(Intervals[0].getBegin(), 42); |
| EXPECT_EQ(Intervals[0].getEnd(), 42); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseSingleInterval) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("10-20"); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_EQ(Intervals.size(), 1U); |
| EXPECT_EQ(Intervals[0].getBegin(), 10); |
| EXPECT_EQ(Intervals[0].getEnd(), 20); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseMultipleIntervals) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("1-5,10,15-20"); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_EQ(Intervals.size(), 3U); |
| |
| // Intervals are in input order (DebugCounter style). |
| EXPECT_EQ(Intervals[0].getBegin(), 1); |
| EXPECT_EQ(Intervals[0].getEnd(), 5); |
| EXPECT_EQ(Intervals[1].getBegin(), 10); |
| EXPECT_EQ(Intervals[1].getEnd(), 10); |
| EXPECT_EQ(Intervals[2].getBegin(), 15); |
| EXPECT_EQ(Intervals[2].getEnd(), 20); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseColonSeparatedIntervals) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("1-5:10:15-20", ':'); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_EQ(Intervals.size(), 3U); |
| EXPECT_EQ(Intervals[0].getBegin(), 1); |
| EXPECT_EQ(Intervals[0].getEnd(), 5); |
| EXPECT_EQ(Intervals[1].getBegin(), 10); |
| EXPECT_EQ(Intervals[1].getEnd(), 10); |
| EXPECT_EQ(Intervals[2].getBegin(), 15); |
| EXPECT_EQ(Intervals[2].getEnd(), 20); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseEmptyString) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals(""); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_TRUE(Intervals.empty()); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, ParseInvalidIntervals) { |
| // Invalid number. |
| auto ER1 = IntegerInclusiveIntervalUtils::parseIntervals("abc"); |
| EXPECT_THAT_EXPECTED(ER1, Failed()); |
| consumeError(ER1.takeError()); |
| |
| // Invalid interval (begin > end). |
| auto ER2 = IntegerInclusiveIntervalUtils::parseIntervals("10-5"); |
| EXPECT_THAT_EXPECTED(ER2, Failed()); |
| consumeError(ER2.takeError()); |
| |
| // Out of order intervals (DebugCounter constraint and overlap). |
| auto ER3 = IntegerInclusiveIntervalUtils::parseIntervals("10,5"); |
| EXPECT_THAT_EXPECTED(ER3, Failed()); |
| consumeError(ER3.takeError()); |
| |
| auto ER4 = IntegerInclusiveIntervalUtils::parseIntervals("1-5,3-7"); |
| EXPECT_THAT_EXPECTED(ER4, Failed()); |
| consumeError(ER4.takeError()); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, Contains) { |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("1-5,10,15-20"); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 1)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 3)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 5)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 10)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 15)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 18)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(Intervals, 20)); |
| |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(Intervals, 6)); |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(Intervals, 9)); |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(Intervals, 11)); |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(Intervals, 14)); |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(Intervals, 21)); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, SeparatorParameter) { |
| IntegerInclusiveIntervalUtils::IntervalList ColonIntervals, CommaIntervals; |
| |
| // Test explicit separator parameters. |
| auto ERC = IntegerInclusiveIntervalUtils::parseIntervals("1-5:10:15-20", ':'); |
| ASSERT_THAT_EXPECTED(ERC, Succeeded()); |
| ColonIntervals = std::move(*ERC); |
| |
| auto ERM = IntegerInclusiveIntervalUtils::parseIntervals("1-5,10,15-20", ','); |
| ASSERT_THAT_EXPECTED(ERM, Succeeded()); |
| CommaIntervals = std::move(*ERM); |
| |
| EXPECT_EQ(ColonIntervals.size(), CommaIntervals.size()); |
| for (size_t I = 0; I < ColonIntervals.size(); ++I) { |
| EXPECT_EQ(ColonIntervals[I].getBegin(), CommaIntervals[I].getBegin()); |
| EXPECT_EQ(ColonIntervals[I].getEnd(), CommaIntervals[I].getEnd()); |
| } |
| |
| // Test that both work with contains(). |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(ColonIntervals, 3)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(CommaIntervals, 3)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(ColonIntervals, 10)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(CommaIntervals, 10)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(ColonIntervals, 18)); |
| EXPECT_TRUE(IntegerInclusiveIntervalUtils::contains(CommaIntervals, 18)); |
| |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(ColonIntervals, 8)); |
| EXPECT_FALSE(IntegerInclusiveIntervalUtils::contains(CommaIntervals, 8)); |
| } |
| |
| TEST(IntegerInclusiveIntervalUtilsTest, DefaultCommaSeparator) { |
| // Test that comma is the default separator. |
| auto ER = IntegerInclusiveIntervalUtils::parseIntervals("1-5,10,15-20"); |
| ASSERT_THAT_EXPECTED(ER, Succeeded()); |
| auto Intervals = std::move(*ER); |
| EXPECT_EQ(Intervals.size(), 3U); |
| EXPECT_EQ(Intervals[0].getBegin(), 1); |
| EXPECT_EQ(Intervals[0].getEnd(), 5); |
| EXPECT_EQ(Intervals[1].getBegin(), 10); |
| EXPECT_EQ(Intervals[1].getEnd(), 10); |
| EXPECT_EQ(Intervals[2].getBegin(), 15); |
| EXPECT_EQ(Intervals[2].getEnd(), 20); |
| } |
| |
| TEST(IntegerInclusiveIntervalTest, MergeAdjacentIntervals) { |
| IntegerInclusiveIntervalUtils::IntervalList Input, Expected, Result; |
| |
| // Empty input |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_TRUE(Result.empty()); |
| |
| // Single interval - no change. |
| Input.push_back(IntegerInclusiveInterval(5, 10)); |
| Expected.push_back(IntegerInclusiveInterval(5, 10)); |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_EQ(Expected, Result); |
| |
| // Adjacent intervals should merge. |
| Input.clear(); |
| Expected.clear(); |
| Input.push_back(IntegerInclusiveInterval(1, 3)); |
| Input.push_back(IntegerInclusiveInterval(4, 6)); |
| Input.push_back(IntegerInclusiveInterval(7, 9)); |
| Expected.push_back(IntegerInclusiveInterval(1, 9)); |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_EQ(Expected, Result); |
| |
| // Non-adjacent intervals should not merge. |
| Input.clear(); |
| Expected.clear(); |
| Input.push_back(IntegerInclusiveInterval(1, 3)); |
| Input.push_back(IntegerInclusiveInterval(5, 7)); // Gap between 3 and 5. |
| Input.push_back(IntegerInclusiveInterval(10, 12)); // Gap between 7 and 10. |
| Expected.push_back(IntegerInclusiveInterval(1, 3)); |
| Expected.push_back(IntegerInclusiveInterval(5, 7)); |
| Expected.push_back(IntegerInclusiveInterval(10, 12)); |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_EQ(Expected, Result); |
| |
| // Mixed adjacent and non-adjacent intervals. |
| Input.clear(); |
| Expected.clear(); |
| Input.push_back(IntegerInclusiveInterval(1, 3)); |
| Input.push_back(IntegerInclusiveInterval(4, 6)); // Adjacent to first. |
| Input.push_back(IntegerInclusiveInterval(8, 10)); // Gap. |
| Input.push_back(IntegerInclusiveInterval(11, 13)); // Adjacent to third. |
| Input.push_back(IntegerInclusiveInterval(14, 16)); // Adjacent to fourth. |
| Expected.push_back(IntegerInclusiveInterval(1, 6)); // Merged 1-3 and 4-6. |
| Expected.push_back( |
| IntegerInclusiveInterval(8, 16)); // Merged 8-10, 11-13, 14-16. |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_EQ(Expected, Result); |
| |
| // Single numbers that are adjacent. |
| Input.clear(); |
| Expected.clear(); |
| Input.push_back(IntegerInclusiveInterval(5)); |
| Input.push_back(IntegerInclusiveInterval(6)); |
| Input.push_back(IntegerInclusiveInterval(7)); |
| Expected.push_back(IntegerInclusiveInterval(5, 7)); |
| Result = IntegerInclusiveIntervalUtils::mergeAdjacentIntervals(Input); |
| EXPECT_EQ(Expected, Result); |
| } |