mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 01:50:30 -04:00 
			
		
		
		
	
		
			
	
	
		
			397 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			397 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
|  | // Boost.Range library
 | ||
|  | //
 | ||
|  | //  Copyright Neil Groves 2010. Use, modification and
 | ||
|  | //  distribution is subject to the Boost Software License, Version
 | ||
|  | //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
 | ||
|  | //  http://www.boost.org/LICENSE_1_0.txt)
 | ||
|  | //
 | ||
|  | //
 | ||
|  | // For more information, see http://www.boost.org/libs/range/
 | ||
|  | //
 | ||
|  | // Credits:
 | ||
|  | // Trac 7376 - was raised by Leonid Gershanovich and his sample was used to
 | ||
|  | // make the test case to cover this condition.
 | ||
|  | //
 | ||
|  | #include <boost/range/join.hpp>
 | ||
|  | #include <boost/range/adaptor/transformed.hpp>
 | ||
|  | 
 | ||
|  | #include <boost/foreach.hpp>
 | ||
|  | #include <boost/test/test_tools.hpp>
 | ||
|  | #include <boost/test/unit_test.hpp>
 | ||
|  | 
 | ||
|  | #include <boost/assign.hpp>
 | ||
|  | #include <boost/range/algorithm_ext.hpp>
 | ||
|  | #include <boost/range/irange.hpp>
 | ||
|  | 
 | ||
|  | #include <boost/iterator/iterator_facade.hpp>
 | ||
|  | 
 | ||
|  | #include <algorithm>
 | ||
|  | #include <deque>
 | ||
|  | #include <list>
 | ||
|  | #include <vector>
 | ||
|  | 
 | ||
|  | namespace boost | ||
|  | { | ||
|  |     namespace | ||
|  |     { | ||
|  |         // This function is a helper function that writes integers
 | ||
|  |         // of increasing value into a range. It is used to test
 | ||
|  |         // that joined ranged may be written to.
 | ||
|  |         //
 | ||
|  |         // Requires:
 | ||
|  |         // - Range uses shallow copy semantics.
 | ||
|  |         template< typename Range > | ||
|  |         void fill_with_ints(Range rng) | ||
|  |         { | ||
|  |             typedef typename range_iterator<Range>::type iterator; | ||
|  |             iterator target = boost::begin(rng); | ||
|  |             const int count = boost::distance(rng); | ||
|  |             for (int i = 0; i < count; ++i) | ||
|  |             { | ||
|  |                 *target = i; | ||
|  |                 ++target; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // The test_join_traversal function is used to provide additional
 | ||
|  |         // tests based upon the underlying join iterator traversal.
 | ||
|  |         // The join iterator takes care of the appropriate demotion, and
 | ||
|  |         // this demotion.
 | ||
|  | 
 | ||
|  |         // test_join_traversal - additional tests for input and forward
 | ||
|  |         // traversal iterators. This is of course a no-op.
 | ||
|  |         template< typename Range1, typename Range2, typename TraversalTag > | ||
|  |         void test_join_traversal(Range1& rng1, Range2& rng2, TraversalTag) | ||
|  |         { | ||
|  |         } | ||
|  | 
 | ||
|  |         // test_join_traversal - additional tests for bidirectional
 | ||
|  |         // traversal iterators.
 | ||
|  |         template< typename Range1, typename Range2 > | ||
|  |         void test_join_traversal(Range1& rng1, Range2& rng2, boost::bidirectional_traversal_tag) | ||
|  |         { | ||
|  |             typedef typename range_value<Range1>::type value_type; | ||
|  |             std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1)); | ||
|  |             boost::push_back(reference, rng2); | ||
|  |             std::reverse(reference.begin(), reference.end()); | ||
|  | 
 | ||
|  |             std::vector<value_type> test_result; | ||
|  |             BOOST_REVERSE_FOREACH( value_type x, join(rng1, rng2) ) | ||
|  |             { | ||
|  |                 test_result.push_back(x); | ||
|  |             } | ||
|  | 
 | ||
|  |             BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), | ||
|  |                                            test_result.begin(), test_result.end() ); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Test helper function to implement the additional tests for random
 | ||
|  |         // access traversal iterators. This is used by the test_join_traversal
 | ||
|  |         // function for random access iterators. The reason that the test
 | ||
|  |         // implementation is put into this function is to utilise
 | ||
|  |         // template parameter type deduction for the joined range type.
 | ||
|  |         template< typename Range1, typename Range2, typename JoinedRange > | ||
|  |         void test_random_access_join(Range1& rng1, Range2& rng2, JoinedRange joined) | ||
|  |         { | ||
|  |             BOOST_CHECK_EQUAL( boost::end(joined) - boost::begin(joined), boost::distance(joined) ); | ||
|  |             BOOST_CHECK( boost::end(joined) <= boost::begin(joined) ); | ||
|  |             BOOST_CHECK( boost::begin(joined) >= boost::end(joined) ); | ||
|  |             if (boost::empty(joined)) | ||
|  |             { | ||
|  |                 BOOST_CHECK(!(boost::begin(joined) < boost::end(joined))); | ||
|  |                 BOOST_CHECK(!(boost::end(joined) > boost::begin(joined))); | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  |                 BOOST_CHECK(boost::begin(joined) < boost::end(joined)); | ||
|  |                 BOOST_CHECK(boost::end(joined) < boost::begin(joined)); | ||
|  |             } | ||
|  | 
 | ||
|  |             typedef typename boost::range_difference<JoinedRange>::type difference_t; | ||
|  |             const difference_t count = boost::distance(joined); | ||
|  |             BOOST_CHECK( boost::begin(joined) + count == boost::end(joined) ); | ||
|  |             BOOST_CHECK( boost::end(joined) - count == boost::begin(joined) ); | ||
|  | 
 | ||
|  |             typedef typename boost::range_iterator<JoinedRange>::type iterator_t; | ||
|  |             iterator_t it = boost::begin(joined); | ||
|  |             it += count; | ||
|  |             BOOST_CHECK( it == boost::end(joined) ); | ||
|  | 
 | ||
|  |             it = boost::end(joined); | ||
|  |             it -= count; | ||
|  |             BOOST_CHECK( it == boost::begin(joined) ); | ||
|  |         } | ||
|  | 
 | ||
|  |         // test_join_traversal function for random access traversal joined
 | ||
|  |         // ranges.
 | ||
|  |         template< typename Range1, typename Range2 > | ||
|  |         void test_join_traversal(Range1& rng1, Range2& rng2, boost::random_access_traversal_tag) | ||
|  |         { | ||
|  |             test_join_traversal(rng1, rng2, boost::bidirectional_traversal_tag()); | ||
|  |             test_random_access_join(rng1, rng2, join(rng1, rng2)); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Test the ability to write values into a joined range. This is
 | ||
|  |         // achieved by copying the constant collections, altering them
 | ||
|  |         // and then checking the result. Hence this relies upon both
 | ||
|  |         // rng1 and rng2 having value copy semantics.
 | ||
|  |         template< typename Collection1, typename Collection2 > | ||
|  |         void test_write_to_joined_range(const Collection1& rng1, const Collection2& rng2) | ||
|  |         { | ||
|  |             Collection1 c1(rng1); | ||
|  |             Collection2 c2(rng2); | ||
|  |              | ||
|  |             typedef BOOST_DEDUCED_TYPENAME boost::range_value< | ||
|  |                 Collection1 | ||
|  |             >::type value_t BOOST_RANGE_UNUSED; | ||
|  |              | ||
|  |             fill_with_ints(boost::join(c1,c2)); | ||
|  | 
 | ||
|  |             // Ensure that the size of the written range has not been
 | ||
|  |             // altered.
 | ||
|  |             BOOST_CHECK_EQUAL( boost::distance(c1), boost::distance(rng1) ); | ||
|  |             BOOST_CHECK_EQUAL( boost::distance(c2), boost::distance(rng2) ); | ||
|  | 
 | ||
|  |             // For each element x, in c1 ensure that it has been written to
 | ||
|  |             // with incrementing integers
 | ||
|  |             int x = 0; | ||
|  |             typedef typename range_iterator<Collection1>::type iterator1; | ||
|  |             iterator1 it1 = boost::begin(c1); | ||
|  |             for (; it1 != boost::end(c1); ++it1) | ||
|  |             { | ||
|  |                 BOOST_CHECK_EQUAL( x, *it1 ); | ||
|  |                 ++x; | ||
|  |             } | ||
|  | 
 | ||
|  |             // For each element y, in c2 ensure that it has been written to
 | ||
|  |             // with incrementing integers
 | ||
|  |             typedef typename range_iterator<Collection2>::type iterator2; | ||
|  |             iterator2 it2 = boost::begin(c2); | ||
|  |             for (; it2 != boost::end(c2); ++it2) | ||
|  |             { | ||
|  |                 BOOST_CHECK_EQUAL( x, *it2 ); | ||
|  |                 ++x; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // Perform a unit test of a Boost.Range join() comparing
 | ||
|  |         // it to a reference that is populated by appending
 | ||
|  |         // elements from both source ranges into a vector.
 | ||
|  |         template< typename Collection1, typename Collection2 > | ||
|  |         void test_join_impl(Collection1& rng1, Collection2& rng2) | ||
|  |         { | ||
|  |             typedef typename range_value<Collection1>::type value_type; | ||
|  |             std::vector<value_type> reference(boost::begin(rng1), boost::end(rng1)); | ||
|  |             boost::push_back(reference, rng2); | ||
|  | 
 | ||
|  |             std::vector<value_type> test_result; | ||
|  |             boost::push_back(test_result, join(rng1, rng2)); | ||
|  | 
 | ||
|  |             BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), | ||
|  |                                            test_result.begin(), test_result.end() ); | ||
|  | 
 | ||
|  |             typedef boost::range_detail::join_iterator< | ||
|  |                 typename boost::range_iterator<Collection1>::type, | ||
|  |                 typename boost::range_iterator<Collection2>::type | ||
|  |                 > join_iterator_t; | ||
|  | 
 | ||
|  |             typedef boost::iterator_traversal< join_iterator_t > tag_t; | ||
|  | 
 | ||
|  |            test_join_traversal(rng1, rng2, tag_t()); | ||
|  | 
 | ||
|  |            test_write_to_joined_range(rng1, rng2); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Make a collection filling it with items from the source
 | ||
|  |         // range. This is used to build collections of various
 | ||
|  |         // sizes populated with various values designed to optimize
 | ||
|  |         // the code coverage exercised by the core test function
 | ||
|  |         // test_join_impl.
 | ||
|  |         template<typename Collection, typename Range> | ||
|  |         boost::shared_ptr<Collection> makeCollection(const Range& source) | ||
|  |         { | ||
|  |             boost::shared_ptr<Collection> c(new Collection); | ||
|  |             c->insert(c->end(), boost::begin(source), boost::end(source)); | ||
|  |             return c; | ||
|  |         } | ||
|  | 
 | ||
|  |         // This templatised version of the test_join_impl function
 | ||
|  |         // generates and populates collections which are later
 | ||
|  |         // used as input to the core test function.
 | ||
|  |         // The caller of this function explicitly provides the
 | ||
|  |         // template parameters. This supports the generation
 | ||
|  |         // of testing a large combination of range types to be
 | ||
|  |         // joined. It is of particular importance to remember
 | ||
|  |         // to combine a random_access range with a bidirectional
 | ||
|  |         // range to determine that the correct demotion of
 | ||
|  |         // types occurs in the join_iterator.
 | ||
|  |         template< typename Collection1, typename Collection2 > | ||
|  |         void test_join_impl() | ||
|  |         { | ||
|  |             typedef boost::shared_ptr<Collection1> collection1_ptr; | ||
|  |             typedef boost::shared_ptr<Collection2> collection2_ptr; | ||
|  |             typedef boost::shared_ptr<const Collection1> collection1_cptr; | ||
|  |             typedef boost::shared_ptr<const Collection2> collection2_cptr; | ||
|  |             std::vector< collection1_cptr > left_containers; | ||
|  |             std::vector< collection2_cptr > right_containers; | ||
|  | 
 | ||
|  |             left_containers.push_back(collection1_ptr(new Collection1)); | ||
|  |             left_containers.push_back(makeCollection<Collection1>(irange(0,1))); | ||
|  |             left_containers.push_back(makeCollection<Collection1>(irange(0,100))); | ||
|  | 
 | ||
|  |             right_containers.push_back(collection2_ptr(new Collection2)); | ||
|  |             right_containers.push_back(makeCollection<Collection2>(irange(0,1))); | ||
|  |             right_containers.push_back(makeCollection<Collection2>(irange(0,100))); | ||
|  | 
 | ||
|  |             BOOST_FOREACH( collection1_cptr left_container, left_containers ) | ||
|  |             { | ||
|  |                 BOOST_FOREACH( collection2_cptr right_container, right_containers ) | ||
|  |                 { | ||
|  |                     test_join_impl(*left_container, *right_container); | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // entry-point into the unit test for the join() function
 | ||
|  |         // this tests a representative sample of combinations of
 | ||
|  |         // source range type.
 | ||
|  |         void join_test() | ||
|  |         { | ||
|  |             test_join_impl< std::vector<int>, std::vector<int> >(); | ||
|  |             test_join_impl< std::list<int>,   std::list<int>   >(); | ||
|  |             test_join_impl< std::deque<int>,  std::deque<int>  >(); | ||
|  | 
 | ||
|  |             test_join_impl< std::vector<int>, std::list<int>   >(); | ||
|  |             test_join_impl< std::list<int>,   std::vector<int> >(); | ||
|  |             test_join_impl< std::vector<int>, std::deque<int>  >(); | ||
|  |             test_join_impl< std::deque<int>,  std::vector<int> >(); | ||
|  |         } | ||
|  |          | ||
|  |         void test_join_iterator_reference_type_constness_ticket8483() | ||
|  |         { | ||
|  |             // Just test that this compiles.
 | ||
|  |             // Before the fix for bug 8483, the reference type of the joined
 | ||
|  |             // range's iterator was incorrect ('int&' instead of 'const int&'),
 | ||
|  |             // causing compiler errors.
 | ||
|  |             const std::vector<int> v1; | ||
|  |             std::vector<int> v2; | ||
|  |             std::vector<int> joined; | ||
|  |             boost::push_back(joined, join(v1, v2)); | ||
|  |         } | ||
|  | 
 | ||
|  |         namespace trac7376 | ||
|  |         { | ||
|  |             struct base_type | ||
|  |             { | ||
|  |                 explicit base_type(boost::int32_t value) | ||
|  |                     : value(value) | ||
|  |                 { | ||
|  |                 } | ||
|  | 
 | ||
|  |                 virtual boost::int32_t get() const = 0; | ||
|  | 
 | ||
|  |                 boost::int32_t value; | ||
|  |             }; | ||
|  | 
 | ||
|  |             struct derived_type1 | ||
|  |                 : base_type | ||
|  |             { | ||
|  |                 derived_type1(boost::int32_t value) | ||
|  |                     : base_type(value) | ||
|  |                 { | ||
|  |                 } | ||
|  | 
 | ||
|  |                 virtual boost::int32_t get() const | ||
|  |                 { | ||
|  |                     return value * 2; | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             struct derived_type2 | ||
|  |                 : base_type | ||
|  |             { | ||
|  |                 derived_type2(boost::int32_t value) | ||
|  |                     : base_type(value) | ||
|  |                 { | ||
|  |                 } | ||
|  | 
 | ||
|  |                 virtual boost::int32_t get() const | ||
|  |                 { | ||
|  |                     return value * 4; | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             struct apply_get | ||
|  |             { | ||
|  |                 typedef boost::int32_t result_type; | ||
|  |                 result_type operator()(const base_type& arg) const | ||
|  |                 { | ||
|  |                     return arg.get(); | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             void test_reference_types() | ||
|  |             { | ||
|  |                 using namespace boost::adaptors; | ||
|  | 
 | ||
|  |                 typedef boost::range_detail::join_iterator< | ||
|  |                         std::vector<derived_type1>::iterator, | ||
|  |                         std::vector<derived_type2>::iterator, | ||
|  |                         const base_type&, | ||
|  |                         const base_type& | ||
|  |                 > join_iterator_t; | ||
|  | 
 | ||
|  |                 std::vector<boost::int32_t> reference_output; | ||
|  | 
 | ||
|  |                 std::vector<derived_type1> x; | ||
|  |                 for (boost::int32_t i = 0; i < 10; ++i) | ||
|  |                 { | ||
|  |                     x.push_back(derived_type1(i)); | ||
|  |                     reference_output.push_back(i * 2); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 std::vector<derived_type2> y; | ||
|  |                 for (boost::int32_t i = 0; i < 10; ++i) | ||
|  |                 { | ||
|  |                     y.push_back(derived_type2(i)); | ||
|  |                     reference_output.push_back(i * 4); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 join_iterator_t it( | ||
|  |                     x, | ||
|  |                     y, | ||
|  |                     boost::range_detail::join_iterator_begin_tag()); | ||
|  | 
 | ||
|  |                 std::vector<boost::int32_t> output; | ||
|  |                 boost::push_back( | ||
|  |                     output, | ||
|  |                     boost::make_iterator_range( | ||
|  |                         join_iterator_t( | ||
|  |                             x, y, | ||
|  |                             boost::range_detail::join_iterator_begin_tag()), | ||
|  |                         join_iterator_t( | ||
|  |                             x, y, | ||
|  |                             boost::range_detail::join_iterator_end_tag())) | ||
|  |                         | transformed(apply_get())); | ||
|  | 
 | ||
|  |                 BOOST_CHECK_EQUAL_COLLECTIONS( | ||
|  |                             output.begin(), output.end(), | ||
|  |                             reference_output.begin(), reference_output.end()); | ||
|  |             } | ||
|  |         } // namespace trac7376
 | ||
|  |     } | ||
|  | } | ||
|  | 
 | ||
|  | boost::unit_test::test_suite* | ||
|  | init_unit_test_suite(int argc, char* argv[]) | ||
|  | { | ||
|  |     boost::unit_test::test_suite* test | ||
|  |         = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.joined" ); | ||
|  | 
 | ||
|  |     test->add( BOOST_TEST_CASE( &boost::join_test ) ); | ||
|  |     test->add( BOOST_TEST_CASE( &boost::test_join_iterator_reference_type_constness_ticket8483 ) ); | ||
|  |     test->add( BOOST_TEST_CASE( &boost::trac7376::test_reference_types ) ); | ||
|  | 
 | ||
|  |     return test; | ||
|  | } |