1+ #pragma once
2+
3+ #include " test_utility.hpp"
4+ #include " multi_join_interval.hpp"
5+
6+ #include < ctime>
7+ #include < random>
8+ #include < cmath>
9+ #include < functional>
10+
11+ class CustomIntervalTests : public ::testing::Test
12+ {};
13+
14+ template <typename numerical_type, typename interval_kind_ = lib_interval_tree::closed>
15+ struct custom_interval : public lib_interval_tree ::interval<numerical_type, interval_kind_>
16+ {
17+ public:
18+ using value_type = numerical_type;
19+ using interval_kind = interval_kind_;
20+
21+ using lib_interval_tree::interval<numerical_type, interval_kind_>::low_;
22+ using lib_interval_tree::interval<numerical_type, interval_kind_>::high_;
23+
24+ /* *
25+ * Constructs an custom_interval. low MUST be smaller than high.
26+ */
27+ custom_interval (value_type low, value_type high)
28+ : lib_interval_tree::interval<numerical_type, interval_kind_>{low, high}
29+ {}
30+
31+ std::function<bool (value_type, value_type)> on_overlaps;
32+ bool overlaps (custom_interval const & other) const
33+ {
34+ if (on_overlaps)
35+ return on_overlaps (other.low_ , other.high_ );
36+ return interval_kind::overlaps (low_, high_, other.low_ , other.high_ );
37+ }
38+
39+ std::function<bool (custom_interval const & other)> on_overlaps_exclusive_ival;
40+ bool overlaps_exclusive (custom_interval const & other) const
41+ {
42+ if (on_overlaps_exclusive_ival)
43+ return on_overlaps_exclusive_ival (other);
44+ return low_ < other.high_ && other.low_ < high_;
45+ }
46+
47+ std::function<custom_interval(custom_interval const & other)> on_join;
48+ custom_interval join (custom_interval const & other) const
49+ {
50+ if (on_join)
51+ return on_join (other);
52+ return {std::min (low_, other.low_ ), std::max (high_, other.high_ )};
53+ }
54+ };
55+
56+ TEST_F (CustomIntervalTests, CanInsertCustomIntervalJoined)
57+ {
58+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
59+ tree.insert ({0 , 5 });
60+ tree.insert_overlap ({4 , 10 });
61+
62+ ASSERT_EQ (tree.size (), 1 );
63+ EXPECT_EQ (tree.begin ()->low (), 0 );
64+ EXPECT_EQ (tree.begin ()->high (), 10 );
65+ }
66+
67+ TEST_F (CustomIntervalTests, CustomJoinIsCalled)
68+ {
69+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
70+ auto ival1 = custom_interval<int >{0 , 5 };
71+ auto ival2 = custom_interval<int >{4 , 10 };
72+
73+ bool join_called = false ;
74+ ival1.on_join = [&](custom_interval<int > const & other) -> custom_interval<int > {
75+ join_called = true ;
76+ return {std::min (ival1.low_ , other.low_ ), std::max (ival1.high_ , other.high_ )};
77+ };
78+
79+ tree.insert (ival1);
80+ tree.insert_overlap (ival2);
81+
82+ EXPECT_TRUE (join_called);
83+ }
84+
85+ TEST_F (CustomIntervalTests, CustomOverlapsIsCalled)
86+ {
87+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
88+ auto ival1 = custom_interval<int >{0 , 5 };
89+ auto ival2 = custom_interval<int >{4 , 10 };
90+
91+ bool overlaps_called = false ;
92+ ival1.on_overlaps = [&](int l, int h) -> bool {
93+ overlaps_called = true ;
94+ return custom_interval<int >::interval_kind::overlaps (ival1.low_ , ival1.high_ , l, h);
95+ };
96+
97+ tree.insert (ival1);
98+ tree.insert_overlap (ival2);
99+
100+ EXPECT_TRUE (overlaps_called);
101+ }
102+
103+ TEST_F (CustomIntervalTests, CustomOverlapsExclusiveIvalIsCalled)
104+ {
105+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
106+ auto ival1 = custom_interval<int >{0 , 5 };
107+ auto ival2 = custom_interval<int >{4 , 10 };
108+
109+ bool overlaps_exclusive_ival_called = false ;
110+ ival1.on_overlaps_exclusive_ival = [&](custom_interval<int > const & other) -> bool {
111+ overlaps_exclusive_ival_called = true ;
112+ return ival1.low_ < other.high_ && other.low_ < ival1.high_ ;
113+ };
114+
115+ tree.insert (ival1);
116+ tree.insert_overlap (ival2, true );
117+
118+ EXPECT_TRUE (overlaps_exclusive_ival_called);
119+ }
0 commit comments