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