Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
run: sudo apt-get update

- name: Do install
run: sudo apt-get install -y ${{ matrix.compiler.pkg }} cmake ninja-build libgtest-dev libgmock-dev
run: sudo apt-get install -y ${{ matrix.compiler.pkg }} cmake ninja-build

- name: Checkout
uses: actions/checkout@v2
Expand All @@ -64,7 +64,7 @@ jobs:
uses: actions/checkout@v2

- name: Setup MSVC
uses: microsoft/setup-msbuild@v1.0.2
uses: ilammy/msvc-dev-cmd@v1

- name: Install vcpkg and gtest
run: |
Expand All @@ -76,12 +76,12 @@ jobs:
VCPKG_DEFAULT_TRIPLET: x64-windows

- name: CMake Configure
run: cmake -B ${{github.workspace}}/build -G"Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_STANDARD=20 -DINT_TREE_USE_OPTIONAL_POLYFILL=on -DINT_TREE_BUILD_EXAMPLES=on -DINT_TREE_ENABLE_TESTS=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
run: cmake -B ${{github.workspace}}/build -G"Ninja" -DCMAKE_TOOLCHAIN_FILE=${{github.workspace}}/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_CXX_STANDARD=20 -DINT_TREE_USE_OPTIONAL_POLYFILL=on -DINT_TREE_BUILD_EXAMPLES=on -DINT_TREE_ENABLE_TESTS=on -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}

- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
run: .\tests\Release\tree-tests.exe
run: .\tests\tree-tests.exe
shell: cmd
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,15 @@ int main()
```

## Compile & Run Testing
Having googletest (find here on github) installed / built is a requirement to run the tests.
Create a build folder, navigate there, run cmake and build the tree-tests target.
You might have to adapt the linker line for gtest, if you built it yourself and didn't install it into your system.

```bash
mkdir build
cd build
cmake --build .
./tests/tree-tests
```

If you want to generate the pretty drawings, install cairo, pull the submodule and pass INT_TREE_DRAW_EXAMPLES=on to the cmake command line to generate a drawings/make_drawings executeable.

Some features of this library require the presence of an optional type.
Expand Down
36 changes: 20 additions & 16 deletions include/interval-tree/interval_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <algorithm>
#include <utility>
#include <type_traits>
#include <limits>

namespace lib_interval_tree
{
Expand Down Expand Up @@ -220,7 +221,8 @@ namespace lib_interval_tree
#endif
overlaps(numerical_type l1, numerical_type h1, numerical_type l2, numerical_type h2)
{
return (l1 <= (h2 + 1)) && (l2 <= (h1 + 1));
return (h2 == std::numeric_limits<numerical_type>::max() || l1 <= (h2 + 1)) &&
(h1 == std::numeric_limits<numerical_type>::max() || l2 <= (h1 + 1));
}

template <typename numerical_type>
Expand Down Expand Up @@ -412,23 +414,25 @@ namespace lib_interval_tree

auto closedOverlap =
closed::overlaps(closedEquiv1.low(), closedEquiv1.high(), closedEquiv2.low(), closedEquiv2.high());
if (!closedOverlap)
if (closedOverlap)
{
if (closedEquiv1.high() + 1 == closedEquiv2.low() &&
(ival1.right_border() == interval_border::closed_adjacent ||
ival2.left_border() == interval_border::closed_adjacent))
{
return true;
}
if (closedEquiv2.high() + 1 == closedEquiv1.low() &&
(ival2.right_border() == interval_border::closed_adjacent ||
ival1.left_border() == interval_border::closed_adjacent))
{
return true;
}
return false;
return true;
}
return true;
if (closedEquiv2.low() > closedEquiv1.high() &&
closedEquiv2.low() - closedEquiv1.high() == 1 &&
(ival1.right_border() == interval_border::closed_adjacent ||
ival2.left_border() == interval_border::closed_adjacent))
{
return true;
}
if (closedEquiv1.low() > closedEquiv2.high() &&
closedEquiv1.low() - closedEquiv2.high() == 1 &&
(ival2.right_border() == interval_border::closed_adjacent ||
ival1.left_border() == interval_border::closed_adjacent))
{
return true;
}
return false;
}

template <typename interval_type>
Expand Down
14 changes: 13 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ file(GLOB sources "*.cpp")
# Add Executable
add_executable(tree-tests ${sources})

find_package(GTest REQUIRED)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.15.2
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

target_link_libraries(tree-tests PRIVATE interval-tree GTest::gtest GTest::gmock GTest::gmock_main)

Expand Down Expand Up @@ -47,4 +54,9 @@ if (DEFINED ENV{MSYSTEM})
COMMAND bash -c "ldd $<TARGET_FILE:tree-tests>" | "grep" "clang" | awk "NF == 4 { system(\"${CMAKE_COMMAND} -E copy \" \$3 \" $<TARGET_FILE_DIR:tree-tests>\") }"
VERBATIM
)
endif()

if(CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
target_compile_options(tree-tests PRIVATE -fsanitize=signed-integer-overflow)
target_link_options(tree-tests PRIVATE -fsanitize=signed-integer-overflow)
endif()
64 changes: 64 additions & 0 deletions tests/interval_tests.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,70 @@ TEST_F(OverlapTests, DynamicBorderTests)
// one side open or closed follows from other tests
}

TEST_F(OverlapTests, DynamicBorderTestsLimits)
{
const auto MIN = std::numeric_limits<int>::min();
const auto MAX = std::numeric_limits<int>::max();

constexpr auto c = interval_border::closed;
constexpr auto o = interval_border::open;
constexpr auto ca = interval_border::closed_adjacent;

// one min
EXPECT_TRUE(i<dynamic>(MIN, 5, c, c).overlaps({3, 16, c, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, o, c).overlaps({3, 16, c, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, ca, c).overlaps({3, 16, c, c}));

// one max
EXPECT_TRUE(i<dynamic>(0, 5, c, c).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, 5, c, c).overlaps({3, MAX, c, o}));
EXPECT_TRUE(i<dynamic>(0, 5, c, c).overlaps({3, MAX, c, ca}));

// both min
EXPECT_TRUE(i<dynamic>(MIN, 5, c, c).overlaps({MIN, 16, c, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, o, c).overlaps({MIN, 16, c, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, ca, c).overlaps({MIN, 16, c, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, c, c).overlaps({MIN, 16, o, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, o, c).overlaps({MIN, 16, o, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, ca, c).overlaps({MIN, 16, o, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, c, c).overlaps({MIN, 16, ca, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, o, c).overlaps({MIN, 16, ca, c}));
EXPECT_TRUE(i<dynamic>(MIN, 5, ca, c).overlaps({MIN, 16, ca, c}));

// both max
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, o).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({3, MAX, c, o}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({3, MAX, c, ca}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({3, MAX, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({3, MAX, c, o}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({3, MAX, c, ca}));

// min-max overlap
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({MIN, 3, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, o).overlaps({MIN, 3, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({MIN, 3, c, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({MIN, 3, o, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, o).overlaps({MIN, 3, o, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({MIN, 3, o, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, c).overlaps({MIN, 3, ca, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, o).overlaps({MIN, 3, ca, c}));
EXPECT_TRUE(i<dynamic>(0, MAX, c, ca).overlaps({MIN, 3, ca, c}));

// min-max not overlap
EXPECT_FALSE(i<dynamic>(1, MAX, c, c).overlaps({MIN, 0, c, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, o).overlaps({MIN, 0, c, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, ca).overlaps({MIN, 0, c, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, c).overlaps({MIN, 0, o, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, o).overlaps({MIN, 0, o, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, ca).overlaps({MIN, 0, o, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, c).overlaps({MIN, 0, ca, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, o).overlaps({MIN, 0, ca, c}));
EXPECT_FALSE(i<dynamic>(1, MAX, c, ca).overlaps({MIN, 0, ca, c}));
}

TEST_F(IntervalTests, DynamicWithinTest)
{
auto base = i<dynamic>(-100, 100, interval_border::closed, interval_border::closed);
Expand Down