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+ struct minimal_custom_interval : public lib_interval_tree ::interval<int , lib_interval_tree::closed>
57+ {
58+ using lib_interval_tree::interval<int , lib_interval_tree::closed>::interval;
59+
60+ minimal_custom_interval join (minimal_custom_interval const & other) const
61+ {
62+ return {std::min (low_, other.low_ ), std::max (high_, other.high_ )};
63+ }
64+ };
65+
66+ TEST_F (CustomIntervalTests, CanInsertCustomIntervalJoined)
67+ {
68+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
69+ tree.insert ({0 , 5 });
70+ tree.insert_overlap ({4 , 10 });
71+
72+ ASSERT_EQ (tree.size (), 1 );
73+ EXPECT_EQ (tree.begin ()->low (), 0 );
74+ EXPECT_EQ (tree.begin ()->high (), 10 );
75+ }
76+
77+ TEST_F (CustomIntervalTests, CustomJoinIsCalled)
78+ {
79+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
80+ auto ival1 = custom_interval<int >{0 , 5 };
81+ auto ival2 = custom_interval<int >{4 , 10 };
82+
83+ bool join_called = false ;
84+ ival1.on_join = [&](custom_interval<int > const & other) -> custom_interval<int > {
85+ join_called = true ;
86+ return {std::min (ival1.low_ , other.low_ ), std::max (ival1.high_ , other.high_ )};
87+ };
88+
89+ tree.insert (ival1);
90+ tree.insert_overlap (ival2);
91+
92+ EXPECT_TRUE (join_called);
93+ }
94+
95+ TEST_F (CustomIntervalTests, CustomOverlapsIsCalled)
96+ {
97+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
98+ auto ival1 = custom_interval<int >{0 , 5 };
99+ auto ival2 = custom_interval<int >{4 , 10 };
100+
101+ bool overlaps_called = false ;
102+ ival1.on_overlaps = [&](int l, int h) -> bool {
103+ overlaps_called = true ;
104+ return custom_interval<int >::interval_kind::overlaps (ival1.low_ , ival1.high_ , l, h);
105+ };
106+
107+ tree.insert (ival1);
108+ tree.insert_overlap (ival2);
109+
110+ EXPECT_TRUE (overlaps_called);
111+ }
112+
113+ TEST_F (CustomIntervalTests, CustomOverlapsExclusiveIvalIsCalled)
114+ {
115+ lib_interval_tree::interval_tree<custom_interval<int >> tree;
116+ auto ival1 = custom_interval<int >{0 , 5 };
117+ auto ival2 = custom_interval<int >{4 , 10 };
118+
119+ bool overlaps_exclusive_ival_called = false ;
120+ ival1.on_overlaps_exclusive_ival = [&](custom_interval<int > const & other) -> bool {
121+ overlaps_exclusive_ival_called = true ;
122+ return ival1.low_ < other.high_ && other.low_ < ival1.high_ ;
123+ };
124+
125+ tree.insert (ival1);
126+ tree.insert_overlap (ival2, true );
127+
128+ EXPECT_TRUE (overlaps_exclusive_ival_called);
129+ }
130+
131+ TEST_F (CustomIntervalTests, CanUseMinimalCustomInterval)
132+ {
133+ lib_interval_tree::interval_tree<minimal_custom_interval> tree;
134+ tree.insert ({0 , 5 });
135+ tree.insert_overlap ({4 , 10 });
136+ tree.erase (tree.begin ());
137+
138+ EXPECT_EQ (tree.size (), 0 );
139+
140+ tree.insert ({0 , 5 });
141+ tree.insert ({7 , 10 });
142+ auto iter = tree.find ({0 , 5 });
143+ ASSERT_NE (iter, tree.end ());
144+ EXPECT_EQ (iter->low (), 0 );
145+ EXPECT_EQ (iter->high (), 5 );
146+
147+ tree.deoverlap ();
148+ auto iter2 = tree.overlap_find ({8 , 12 });
149+ ASSERT_NE (iter2, tree.end ());
150+ EXPECT_EQ (iter2->low (), 7 );
151+ EXPECT_EQ (iter2->high (), 10 );
152+ }
0 commit comments