summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/range/test/join.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/range/test/join.cpp
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/range/test/join.cpp')
-rw-r--r--src/boost/libs/range/test/join.cpp397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/boost/libs/range/test/join.cpp b/src/boost/libs/range/test/join.cpp
new file mode 100644
index 00000000..300028b3
--- /dev/null
+++ b/src/boost/libs/range/test/join.cpp
@@ -0,0 +1,397 @@
+// 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));
+ boost::push_back(joined, join(v2, v1));
+ }
+
+ 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;
+}