]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/test/tools/collection_comparison_op.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / test / tools / collection_comparison_op.hpp
1 // (C) Copyright Gennadiy Rozental 2001.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5
6 // See http://www.boost.org/libs/test for the library home page.
7 //
8 //!@file
9 //!@brief Collection comparison with enhanced reporting
10 // ***************************************************************************
11
12 #ifndef BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER
13 #define BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER
14
15 // Boost.Test
16 #include <boost/test/tools/assertion.hpp>
17
18 #include <boost/test/utils/is_forward_iterable.hpp>
19 #include <boost/test/utils/is_cstring.hpp>
20
21 // Boost
22 #include <boost/mpl/bool.hpp>
23 #include <boost/utility/enable_if.hpp>
24 #include <boost/type_traits/decay.hpp>
25
26 #include <boost/test/detail/suppress_warnings.hpp>
27
28 //____________________________________________________________________________//
29
30 namespace boost {
31 namespace test_tools {
32 namespace assertion {
33
34 // ************************************************************************** //
35 // ************* selectors for specialized comparizon routines ************** //
36 // ************************************************************************** //
37
38 template<typename T>
39 struct specialized_compare : public mpl::false_ {};
40
41 template <typename T>
42 struct is_c_array : public mpl::false_ {};
43
44 template<typename T, std::size_t N>
45 struct is_c_array<T [N]> : public mpl::true_ {};
46
47 template<typename T, std::size_t N>
48 struct is_c_array<T (&)[N]> : public mpl::true_ {};
49
50 #define BOOST_TEST_SPECIALIZED_COLLECTION_COMPARE(Col) \
51 namespace boost { namespace test_tools { namespace assertion { \
52 template<> \
53 struct specialized_compare<Col> : public mpl::true_ {}; \
54 }}} \
55 /**/
56
57 // ************************************************************************** //
58 // ************** lexicographic_compare ************** //
59 // ************************************************************************** //
60
61 namespace op {
62
63 template <typename OP, bool can_be_equal, bool prefer_shorter,
64 typename Lhs, typename Rhs>
65 inline
66 typename boost::enable_if_c<
67 unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
68 && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
69 assertion_result>::type
70 lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
71 {
72 assertion_result ar( true );
73
74 typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
75 typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
76
77 typename t_Lhs_iterator::const_iterator first1 = t_Lhs_iterator::begin(lhs);
78 typename t_Rhs_iterator::const_iterator first2 = t_Rhs_iterator::begin(rhs);
79 typename t_Lhs_iterator::const_iterator last1 = t_Lhs_iterator::end(lhs);
80 typename t_Rhs_iterator::const_iterator last2 = t_Rhs_iterator::end(rhs);
81 std::size_t pos = 0;
82
83 for( ; (first1 != last1) && (first2 != last2); ++first1, ++first2, ++pos ) {
84 assertion_result const& element_ar = OP::eval(*first1, *first2);
85 if( !can_be_equal && element_ar )
86 return ar; // a < b
87
88 assertion_result const& reverse_ar = OP::eval(*first2, *first1);
89 if( element_ar && !reverse_ar )
90 return ar; // a<=b and !(b<=a) => a < b => return true
91
92 if( element_ar || !reverse_ar )
93 continue; // (a<=b and b<=a) or (!(a<b) and !(b<a)) => a == b => keep looking
94
95 // !(a<=b) and b<=a => b < a => return false
96 ar = false;
97 ar.message() << "\nFailure at position " << pos << ": "
98 << tt_detail::print_helper(*first1)
99 << OP::revert()
100 << tt_detail::print_helper(*first2)
101 << ". " << element_ar.message();
102 return ar;
103 }
104
105 if( first1 != last1 ) {
106 if( prefer_shorter ) {
107 ar = false;
108 ar.message() << "\nFirst collection has extra trailing elements.";
109 }
110 }
111 else if( first2 != last2 ) {
112 if( !prefer_shorter ) {
113 ar = false;
114 ar.message() << "\nSecond collection has extra trailing elements.";
115 }
116 }
117 else if( !can_be_equal ) {
118 ar = false;
119 ar.message() << "\nCollections appear to be equal.";
120 }
121
122 return ar;
123 }
124
125 template <typename OP, bool can_be_equal, bool prefer_shorter,
126 typename Lhs, typename Rhs>
127 inline
128 typename boost::enable_if_c<
129 (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
130 assertion_result>::type
131 lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
132 {
133 typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type;
134 typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
135
136 return lexicographic_compare<OP, can_be_equal, prefer_shorter>(
137 lhs_char_type(lhs),
138 rhs_char_type(rhs));
139 }
140
141 //____________________________________________________________________________//
142
143 // ************************************************************************** //
144 // ************** equality_compare ************** //
145 // ************************************************************************** //
146
147 template <typename OP, typename Lhs, typename Rhs>
148 inline
149 typename boost::enable_if_c<
150 unit_test::is_forward_iterable<Lhs>::value && !unit_test::is_cstring<Lhs>::value
151 && unit_test::is_forward_iterable<Rhs>::value && !unit_test::is_cstring<Rhs>::value,
152 assertion_result>::type
153 element_compare( Lhs const& lhs, Rhs const& rhs )
154 {
155 typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
156 typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
157
158 assertion_result ar( true );
159
160 if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) ) {
161 ar = false;
162 ar.message() << "\nCollections size mismatch: " << t_Lhs_iterator::size(lhs) << " != " << t_Rhs_iterator::size(rhs);
163 return ar;
164 }
165
166 typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
167 typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
168 std::size_t pos = 0;
169
170 for( ; pos < t_Lhs_iterator::size(lhs); ++left, ++right, ++pos ) {
171 assertion_result const element_ar = OP::eval( *left, *right );
172 if( element_ar )
173 continue;
174
175 ar = false;
176 ar.message() << "\nMismatch at position " << pos << ": "
177 << tt_detail::print_helper(*left)
178 << OP::revert()
179 << tt_detail::print_helper(*right)
180 << ". " << element_ar.message();
181 }
182
183 return ar;
184 }
185
186 // In case string comparison is branching here
187 template <typename OP, typename Lhs, typename Rhs>
188 inline
189 typename boost::enable_if_c<
190 (unit_test::is_cstring<Lhs>::value || unit_test::is_cstring<Rhs>::value),
191 assertion_result>::type
192 element_compare( Lhs const& lhs, Rhs const& rhs )
193 {
194 typedef typename unit_test::deduce_cstring<Lhs>::type lhs_char_type;
195 typedef typename unit_test::deduce_cstring<Rhs>::type rhs_char_type;
196
197 return element_compare<OP>(lhs_char_type(lhs),
198 rhs_char_type(rhs));
199 }
200
201 //____________________________________________________________________________//
202
203 // ************************************************************************** //
204 // ************** non_equality_compare ************** //
205 // ************************************************************************** //
206
207 template <typename OP, typename Lhs, typename Rhs>
208 inline assertion_result
209 non_equality_compare( Lhs const& lhs, Rhs const& rhs )
210 {
211 typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator;
212 typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator;
213
214 assertion_result ar( true );
215
216 if( t_Lhs_iterator::size(lhs) != t_Rhs_iterator::size(rhs) )
217 return ar;
218
219 typename t_Lhs_iterator::const_iterator left = t_Lhs_iterator::begin(lhs);
220 typename t_Rhs_iterator::const_iterator right = t_Rhs_iterator::begin(rhs);
221 typename t_Lhs_iterator::const_iterator end = t_Lhs_iterator::end(lhs);
222
223 for( ; left != end; ++left, ++right ) {
224 if( OP::eval( *left, *right ) )
225 return ar;
226 }
227
228 ar = false;
229 ar.message() << "\nCollections appear to be equal";
230
231 return ar;
232 }
233
234 //____________________________________________________________________________//
235
236 // ************************************************************************** //
237 // ************** cctraits ************** //
238 // ************************************************************************** //
239 // set of collection comparison traits per comparison OP
240
241 template<typename OP>
242 struct cctraits;
243
244 template<typename Lhs, typename Rhs>
245 struct cctraits<op::EQ<Lhs, Rhs> > {
246 typedef specialized_compare<Lhs> is_specialized;
247 };
248
249 template<typename Lhs, typename Rhs>
250 struct cctraits<op::NE<Lhs, Rhs> > {
251 typedef specialized_compare<Lhs> is_specialized;
252 };
253
254 template<typename Lhs, typename Rhs>
255 struct cctraits<op::LT<Lhs, Rhs> > {
256 static const bool can_be_equal = false;
257 static const bool prefer_short = true;
258
259 typedef specialized_compare<Lhs> is_specialized;
260 };
261
262 template<typename Lhs, typename Rhs>
263 struct cctraits<op::LE<Lhs, Rhs> > {
264 static const bool can_be_equal = true;
265 static const bool prefer_short = true;
266
267 typedef specialized_compare<Lhs> is_specialized;
268 };
269
270 template<typename Lhs, typename Rhs>
271 struct cctraits<op::GT<Lhs, Rhs> > {
272 static const bool can_be_equal = false;
273 static const bool prefer_short = false;
274
275 typedef specialized_compare<Lhs> is_specialized;
276 };
277
278 template<typename Lhs, typename Rhs>
279 struct cctraits<op::GE<Lhs, Rhs> > {
280 static const bool can_be_equal = true;
281 static const bool prefer_short = false;
282
283 typedef specialized_compare<Lhs> is_specialized;
284 };
285
286 // ************************************************************************** //
287 // ************** compare_collections ************** //
288 // ************************************************************************** //
289 // Overloaded set of functions dispatching to specific implementation of comparison
290
291 template <typename Lhs, typename Rhs, typename L, typename R>
292 inline assertion_result
293 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::EQ<L, R> >*, mpl::true_ )
294 {
295 return assertion::op::element_compare<op::EQ<L, R> >( lhs, rhs );
296 }
297
298 //____________________________________________________________________________//
299
300 template <typename Lhs, typename Rhs, typename L, typename R>
301 inline assertion_result
302 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::EQ<L, R> >*, mpl::false_ )
303 {
304 return lhs == rhs;
305 }
306
307 //____________________________________________________________________________//
308
309 template <typename Lhs, typename Rhs, typename L, typename R>
310 inline assertion_result
311 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::NE<L, R> >*, mpl::true_ )
312 {
313 return assertion::op::non_equality_compare<op::NE<L, R> >( lhs, rhs );
314 }
315
316 //____________________________________________________________________________//
317
318 template <typename Lhs, typename Rhs, typename L, typename R>
319 inline assertion_result
320 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::NE<L, R> >*, mpl::false_ )
321 {
322 return lhs != rhs;
323 }
324
325 //____________________________________________________________________________//
326
327 template <typename OP, typename Lhs, typename Rhs>
328 inline assertion_result
329 lexicographic_compare( Lhs const& lhs, Rhs const& rhs )
330 {
331 return assertion::op::lexicographic_compare<OP, cctraits<OP>::can_be_equal, cctraits<OP>::prefer_short>( lhs, rhs );
332 }
333
334 //____________________________________________________________________________//
335
336 template <typename Lhs, typename Rhs, typename OP>
337 inline assertion_result
338 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<OP>*, mpl::true_ )
339 {
340 return lexicographic_compare<OP>( lhs, rhs );
341 }
342
343 //____________________________________________________________________________//
344
345 template <typename Lhs, typename Rhs, typename L, typename R>
346 inline assertion_result
347 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LT<L, R> >*, mpl::false_ )
348 {
349 return lhs < rhs;
350 }
351
352 //____________________________________________________________________________//
353
354 template <typename Lhs, typename Rhs, typename L, typename R>
355 inline assertion_result
356 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::LE<L, R> >*, mpl::false_ )
357 {
358 return lhs <= rhs;
359 }
360
361 //____________________________________________________________________________//
362
363 template <typename Lhs, typename Rhs, typename L, typename R>
364 inline assertion_result
365 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GT<L, R> >*, mpl::false_ )
366 {
367 return lhs > rhs;
368 }
369
370 //____________________________________________________________________________//
371
372 template <typename Lhs, typename Rhs, typename L, typename R>
373 inline assertion_result
374 compare_collections( Lhs const& lhs, Rhs const& rhs, boost::type<op::GE<L, R> >*, mpl::false_ )
375 {
376 return lhs >= rhs;
377 }
378
379 //____________________________________________________________________________//
380
381 // ************************************************************************** //
382 // ********* specialization of comparison operators for collections ********* //
383 // ************************************************************************** //
384
385 #define DEFINE_COLLECTION_COMPARISON( oper, name, rev ) \
386 template<typename Lhs,typename Rhs> \
387 struct name<Lhs,Rhs,typename boost::enable_if_c< \
388 unit_test::is_forward_iterable<Lhs>::value \
389 && !unit_test::is_cstring_comparable<Lhs>::value \
390 && unit_test::is_forward_iterable<Rhs>::value \
391 && !unit_test::is_cstring_comparable<Rhs>::value>::type> { \
392 public: \
393 typedef assertion_result result_type; \
394 typedef unit_test::bt_iterator_traits<Lhs> t_Lhs_iterator_helper; \
395 typedef unit_test::bt_iterator_traits<Rhs> t_Rhs_iterator_helper; \
396 \
397 typedef name<Lhs, Rhs> OP; \
398 \
399 typedef typename \
400 mpl::if_c< \
401 mpl::or_< \
402 typename is_c_array<Lhs>::type, \
403 typename is_c_array<Rhs>::type \
404 >::value, \
405 mpl::true_, \
406 typename \
407 mpl::if_c<is_same<typename decay<Lhs>::type, \
408 typename decay<Rhs>::type>::value, \
409 typename cctraits<OP>::is_specialized, \
410 mpl::false_>::type \
411 >::type is_specialized; \
412 \
413 typedef name<typename t_Lhs_iterator_helper::value_type, \
414 typename t_Rhs_iterator_helper::value_type \
415 > elem_op; \
416 \
417 static assertion_result \
418 eval( Lhs const& lhs, Rhs const& rhs) \
419 { \
420 return assertion::op::compare_collections( lhs, rhs, \
421 (boost::type<elem_op>*)0, \
422 is_specialized() ); \
423 } \
424 \
425 template<typename PrevExprType> \
426 static void \
427 report( std::ostream&, \
428 PrevExprType const&, \
429 Rhs const& ) {} \
430 \
431 static char const* revert() \
432 { return " " #rev " "; } \
433 \
434 }; \
435 /**/
436
437 BOOST_TEST_FOR_EACH_COMP_OP( DEFINE_COLLECTION_COMPARISON )
438 #undef DEFINE_COLLECTION_COMPARISON
439
440 //____________________________________________________________________________//
441
442 } // namespace op
443 } // namespace assertion
444 } // namespace test_tools
445 } // namespace boost
446
447 #include <boost/test/detail/enable_warnings.hpp>
448
449 #endif // BOOST_TEST_TOOLS_COLLECTION_COMPARISON_OP_HPP_050815GER