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