1 //
2 // Tests for
3 //  template <typename T, typename U, typename P>
4 //  bool operator<(T* a, bounded_ptr<U, P> const& b);
5 //
6 //  template <typename T, typename U, typename P>
7 //  bool operator<(bounded_ptr<T, P> const& a, U* b);
8 //
9 //  template <typename T, typename U, typename P>
10 //  bool operator<=(T* a, bounded_ptr<U, P> const& b);
11 //
12 //  template <typename T, typename U, typename P>
13 //  bool operator<=(bounded_ptr<T, P> const& a, U* b);
14 //
15 //  template <typename T, typename U, typename P>
16 //  bool operator>(T* a, bounded_ptr<U, P> const& b);
17 //
18 //  template <typename T, typename U, typename P>
19 //  bool operator>(bounded_ptr<T, P> const& a, U* b);
20 //
21 //  template <typename T, typename U, typename P>
22 //  bool operator>=(T* a, bounded_ptr<U, P> const& b);
23 //
24 //  template <typename T, typename U, typename P>
25 //  bool operator>=(bounded_ptr<T, P> const& a, U* b);
26 //
27 
28 #include <libkern/c++/bounded_ptr.h>
29 #include <array>
30 #include <darwintest.h>
31 #include <darwintest_utils.h>
32 #include "test_utils.h"
33 
34 #define _assert(...) T_ASSERT_TRUE((__VA_ARGS__), # __VA_ARGS__)
35 
36 template <typename T, typename U>
37 static void
38 check_lt(T t, U u)
39 {
40 	_assert(t < u);
41 	_assert(t <= u);
42 	_assert(!(t >= u));
43 	_assert(!(t > u));
44 
45 	_assert(!(u < t));
46 	_assert(!(u <= t));
47 	_assert(u > t);
48 	_assert(u >= t);
49 }
50 
51 template <typename T, typename U>
52 static void
53 check_eq(T t, U u)
54 {
55 	_assert(!(t < u));
56 	_assert(t <= u);
57 	_assert(t >= u);
58 	_assert(!(t > u));
59 
60 	_assert(!(u < t));
61 	_assert(u <= t);
62 	_assert(!(u > t));
63 	_assert(u >= t);
64 }
65 
66 template <typename T, typename TQual>
67 static void
68 tests()
69 {
70 	std::array<T, 5> array = {T{0}, T{1}, T{2}, T{3}, T{4}};
71 
72 	// Compare pointers within the bounds
73 	{
74 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
75 		//   ^                                                ^
76 		//   |                                                |
77 		// begin,a,b                                         end
78 		test_bounded_ptr<TQual> const a(array.begin(), array.begin(), array.end());
79 		TQual* b = array.begin();
80 		check_eq(a, b);
81 	}
82 	{
83 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
84 		//   ^        ^                                       ^
85 		//   |        |                                       |
86 		// begin     a,b                                     end
87 		test_bounded_ptr<TQual> const a(array.begin() + 1, array.begin(), array.end());
88 		TQual* b = array.begin() + 1;
89 		check_eq(a, b);
90 	}
91 	{
92 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
93 		//   ^                 ^                              ^
94 		//   |                 |                              |
95 		// begin,a             b                             end
96 		test_bounded_ptr<TQual> const a(array.begin(), array.begin(), array.end());
97 		TQual* b = array.begin() + 2;
98 		check_lt(a, b);
99 	}
100 	{
101 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
102 		//   ^                                                ^
103 		//   |                                                |
104 		// begin                                           end,a,b
105 		test_bounded_ptr<TQual> const a(array.end(), array.begin(), array.end());
106 		TQual* b = array.end();
107 		check_eq(a, b);
108 	}
109 	{
110 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
111 		//   ^                 ^        ^        ^
112 		//   |                 |        |        |
113 		// begin               a       end       b
114 		test_bounded_ptr<TQual> const a(array.begin() + 2, array.begin(), array.begin() + 3);
115 		TQual* b = array.begin() + 4;
116 		check_lt(a, b);
117 	}
118 
119 	// Check when the bounded_ptr is outside of its bounds
120 	{
121 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
122 		//   ^                 ^                              ^
123 		//   |                 |                              |
124 		//  a,b              begin                           end
125 		test_bounded_ptr<TQual> const a(array.begin(), array.begin() + 2, array.end());
126 		TQual* b = array.begin();
127 		check_eq(a, b);
128 	}
129 	{
130 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
131 		//   ^                          ^        ^
132 		//   |                          |        |
133 		// begin                       end      a,b
134 		test_bounded_ptr<TQual> const a(array.end() - 1, array.begin(), array.end() - 2);
135 		TQual* b = array.end() - 1;
136 		check_eq(a, b);
137 	}
138 	{
139 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
140 		//   ^                                   ^            ^
141 		//   |                                   |            |
142 		// begin                                end          a,b
143 		test_bounded_ptr<TQual> const a(array.end(), array.begin(), array.end() - 1);
144 		TQual* b = array.end();
145 		check_eq(a, b);
146 	}
147 	{
148 		// T{0}     T{1}     T{2}     T{3}     T{4}     <one-past-last>
149 		//   ^                          ^        ^            ^
150 		//   |                          |        |            |
151 		// begin                       end       a            b
152 		test_bounded_ptr<TQual> const a(array.end() - 1, array.begin(), array.end() - 2);
153 		TQual* b = array.end();
154 		check_lt(a, b);
155 	}
156 
157 	// Test comparing against a null pointer
158 	{
159 		test_bounded_ptr<TQual> a = nullptr;
160 		TQual* b = nullptr;
161 		check_eq(a, b);
162 	}
163 	{
164 		test_bounded_ptr<TQual> a(array.end() - 1, array.begin(), array.end() - 2);
165 		TQual* b = nullptr;
166 		check_lt(b, a);
167 	}
168 	{
169 		test_bounded_ptr<TQual> a = nullptr;
170 		TQual* b = array.begin();
171 		check_lt(a, b);
172 	}
173 }
174 
175 struct Base { int i; };
176 struct Derived : Base { };
177 
178 template <typename Related>
179 static void
180 tests_convert()
181 {
182 	std::array<Derived, 5> array = {Derived{0}, Derived{1}, Derived{2}, Derived{3}, Derived{4}};
183 
184 	{
185 		test_bounded_ptr<Derived> const a(array.begin() + 1, array.begin(), array.end() - 1);
186 		Related* b = array.begin();
187 		check_lt(b, a);
188 	}
189 	{
190 		test_bounded_ptr<Related> const a(array.begin(), array.begin(), array.end() - 1);
191 		Derived* b = array.begin() + 1;
192 		check_lt(a, b);
193 	}
194 
195 	// Test comparisons against cv-void*
196 	{
197 		test_bounded_ptr<Related> const a(array.begin(), array.begin(), array.end() - 1);
198 		void* b = array.begin() + 1;
199 		check_lt(a, b);
200 	}
201 }
202 
203 T_DECL(compare_order_raw, "bounded_ptr.compare.order.raw") {
204 	tests<Derived, Derived>();
205 	tests<Derived, Derived const>();
206 	tests<Derived, Derived volatile>();
207 	tests<Derived, Derived const volatile>();
208 	tests_convert<Base>();
209 	tests_convert<Base const>();
210 	tests_convert<Base volatile>();
211 	tests_convert<Base const volatile>();
212 }
213