/*************************************************************************** * * 23.list.iterators.cpp - test exercising [lib.list.iterators] * * $Id: 23.list.iterators.cpp 523692 2007-03-29 13:01:55Z faridz $ * *************************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * **************************************************************************/ #include // for list #include // for out_of_range, length_error #include // for size_t #include <23.list.h> // for ListMembers #include // for rw_test() #include // for UserAlloc #include // for bad_alloc, replacement operator new /**************************************************************************/ static const char* const exceptions[] = { "unknown exception", "bad_alloc", "exception" }; /**************************************************************************/ // used to exercise // begin () and rend () and front () static const ContainerTestCase begin_void_test_cases [] = { #undef TEST #define TEST(lst, res) { \ __LINE__, -1, -1, -1, -1, -1, \ lst, sizeof (lst) - 1, \ 0, 0, 0, res, 0 \ } // +--------------------------------- controlled sequence // | +---------------- expected result // | | // V V TEST ("", _RWSTD_SIZE_MAX), TEST ("a", 'a' ), TEST ("", '\0'), TEST ("abc", 'a' ), TEST ("ab@2c", '\0'), TEST ("ab@2c", 'a' ), TEST ("abc@2", 'a' ), TEST ("x@4096", 'x' ), TEST ("last", 'l' ) }; /**************************************************************************/ // used to exercise // end () and rbegin () and back () static const ContainerTestCase end_void_test_cases [] = { #undef TEST #define TEST(lst, res) { \ __LINE__, -1, -1, -1, -1, -1, \ lst, sizeof (lst) - 1, \ 0, 0, 0, res, 0 \ } // +--------------------------------- controlled sequence // | +---------------- expected result // | | // V V TEST ("", _RWSTD_SIZE_MAX), TEST ("a", 'a' ), TEST ("", '\0'), TEST ("abc", 'c' ), TEST ("ab@2c", 'c' ), TEST ("ab@2c", 'c' ), TEST ("abc@2", '\0'), TEST ("x@4096", 'x' ), TEST ("last", 't' ) }; /**************************************************************************/ // exercises: // get_allocator () static const ContainerTestCase get_allocator_void_test_cases [] = { #undef TEST #define TEST(lst) { \ __LINE__, -1, -1, -1, -1, -1, \ lst, sizeof (lst) - 1, \ 0, 0, 0, 0, 0 \ } // +------------------------------------------ controlled sequence // | // | // | // | // | // | // | // V TEST ("" ), TEST ("ab" ), TEST ("" ), TEST ("x@4096" ), TEST ("ab" ), TEST ("a@2048cb@2047" ), TEST ("last" ) }; /**************************************************************************/ template void test_iterators (T*, Allocator*, const ContainerTestCaseData &tdata) { typedef std::list List; typedef typename List::iterator ListIter; typedef typename List::const_iterator ListCIter; typedef typename List::reverse_iterator ListRIter; typedef typename List::const_reverse_iterator ListCRIter; typedef ListState ListState; const ContainerFunc &func = tdata.func_; const ContainerTestCase &tcase = tdata.tcase_; const bool test_iters = func.which_ == ListIds::begin_void || func.which_ == ListIds::begin_const_void || func.which_ == ListIds::end_void || func.which_ == ListIds::end_const_void || func.which_ == ListIds::rbegin_void || func.which_ == ListIds::rbegin_const_void || func.which_ == ListIds::rend_void || func.which_ == ListIds::rend_const_void || func.which_ == ListIds::front_void || func.which_ == ListIds::front_const_void || func.which_ == ListIds::back_void || func.which_ == ListIds::back_const_void; const bool test_const_list = func.which_ == ListIds::begin_const_void || func.which_ == ListIds::end_const_void || func.which_ == ListIds::rbegin_const_void || func.which_ == ListIds::rend_const_void || func.which_ == ListIds::front_const_void || func.which_ == ListIds::back_const_void; const bool test_end_iters = func.which_ == ListIds::end_void || func.which_ == ListIds::end_const_void || func.which_ == ListIds::rend_void || func.which_ == ListIds::rend_const_void; // allocator object for test get_allocator Allocator alloc; // construct the list object List lst (tdata.str_, tdata.str_ + tdata.strlen_, alloc); // construct the constant list object const List clst (tdata.str_, tdata.str_ + tdata.strlen_, alloc); const std::size_t s_size = test_const_list ? clst.size () : lst.size (); // save the state of the list object before the call // to detect exception safety violations (changes to // the state of the object after an exception) const ListState lst_state (lst); // start checking for memory leaks rw_check_leaks (lst.get_allocator ()); try { // methods result const T* res_ptr = 0; // for begin () and end () ListIter it; // for begin () const and end () const ListCIter cit; // for rbegin () and rend () ListRIter rit; // for rbegin () const and rend () const ListCRIter crit; // for get_allocator () Allocator resalloc; bool it_relations = true; switch (func.which_) { case ListIds::begin_void: it = lst.begin(); it_relations = it == lst.rend ().base (); if (s_size) res_ptr = &*it; break; case ListIds::begin_const_void: cit = clst.begin(); it_relations = cit == clst.rend ().base (); if (s_size) res_ptr = &*cit; break; case ListIds::end_void: it = lst.end(); it_relations = it == lst.rbegin ().base (); if (s_size) res_ptr = &*--it; break; case ListIds::end_const_void: cit = clst.end(); it_relations = cit == clst.rbegin ().base (); if (s_size) res_ptr = &*--cit; break; case ListIds::rbegin_void: rit = lst.rbegin(); it_relations = rit.base () == lst.end (); if (s_size) res_ptr = &*rit; break; case ListIds::rbegin_const_void: crit = clst.rbegin(); it_relations = crit.base () == clst.end (); if (s_size) res_ptr = &*crit; break; case ListIds::rend_void: rit = lst.rend(); it_relations = rit.base () == lst.begin (); if (s_size) res_ptr = &*--rit; break; case ListIds::rend_const_void: crit = clst.rend(); it_relations = crit.base () == clst.begin (); if (s_size) res_ptr = &*--crit; break; case ListIds::front_void: if (s_size) { res_ptr = &lst.front (); it_relations = res_ptr == &*lst.begin (); } break; case ListIds::front_const_void: if (s_size) { res_ptr = &clst.front (); it_relations = res_ptr == &*clst.begin (); } break; case ListIds::back_void: if (s_size) { res_ptr = &lst.back (); it_relations = res_ptr == &*--lst.end (); } break; case ListIds::back_const_void: if (s_size) { res_ptr = &clst.back (); it_relations = res_ptr == &*--clst.end (); } break; case ListIds::get_allocator_void: resalloc = clst.get_allocator (); break; default: RW_ASSERT (!"test logic error: unknown iterators overload"); return; } if (res_ptr) { const char exp_res = (_RWSTD_SIZE_MAX != tcase.nres ? char (tcase.nres) : char ()); const bool success = 0 == T::mismatch (res_ptr, &exp_res, 1); rw_assert (success, 0, tcase.line, "line %d. %{$FUNCALL}%{?} - 1%{;} expected " "%{#c}, got %{#c}", __LINE__, test_end_iters, exp_res, char (res_ptr->data_.val_)); } if (test_iters) { if (0 == s_size) { bool success = true; if ( func.which_ == ListIds::begin_void || func.which_ == ListIds::end_void) success = it == lst.begin () && it == lst.end (); if ( func.which_ == ListIds::begin_const_void || func.which_ == ListIds::end_const_void) success = cit == clst.begin () && cit == clst.end (); if ( func.which_ == ListIds::rbegin_void || func.which_ == ListIds::rend_void) success = rit == lst.rbegin () && rit == lst.rend (); if ( func.which_ == ListIds::rbegin_const_void || func.which_ == ListIds::rend_const_void) success = crit == clst.rbegin () && crit == clst.rend (); // check the begin () == end (), rbegin () == rend () rw_assert(success, 0, tcase.line, "line %d. %{$FUNCALL} returned iterator is not " "equal to begin and end for an empty list", __LINE__); } // check the iterators relationship rw_assert(it_relations, 0, tcase.line, "line %d. %{$FUNCALL} iterators " "relationship is broken", __LINE__); } if (func.which_ == ListIds::get_allocator_void) { // verify that the allocator returned from the function // equal to allocator passed to the ctor const bool success = (alloc == resalloc); rw_assert(success, 0, tcase.line, "line %d. %{$FUNCALL} expected equal to allocator " "passed to the ctor", __LINE__); } } #ifndef _RWSTD_NO_EXCEPTIONS catch (const std::bad_alloc &ex) { rw_assert (0, 0, tcase.line, "line %d. %{$FUNCALL} unexpectedly caught std::%s(%#s)", __LINE__, exceptions [1], ex.what ()); } catch (const std::exception &ex) { rw_assert (0, 0, tcase.line, "line %d. %{$FUNCALL} unexpectedly caught std::%s(%#s)", __LINE__, exceptions [2], ex.what ()); } catch (...) { rw_assert (0, 0, tcase.line, "line %d. %{$FUNCALL} unexpectedly caught %s", __LINE__, exceptions [0]); } #endif // _RWSTD_NO_EXCEPTIONS // FIXME: verify the number of blocks the function call // is expected to allocate and detect any memory leaks rw_check_leaks (lst.get_allocator (), tcase.line, std::size_t (-1), std::size_t (-1)); // verify that state of the object didn't changed lst_state.assert_equal (ListState (lst), __LINE__, tcase.line, "call"); } /**************************************************************************/ DEFINE_CONTAINER_TEST_FUNCTIONS (test_iterators); int main (int argc, char** argv) { static const ContainerTest tests [] = { #undef TEST #define TEST(gsig, sig) { \ gsig, sig ## _test_cases, \ sizeof sig ## _test_cases / sizeof *sig ## _test_cases \ } TEST (ListIds::begin_void, begin_void), TEST (ListIds::begin_const_void, begin_void), TEST (ListIds::end_void, end_void), TEST (ListIds::end_const_void, end_void), TEST (ListIds::rbegin_void, end_void), TEST (ListIds::rbegin_const_void, end_void), TEST (ListIds::rend_void, begin_void), TEST (ListIds::rend_const_void, begin_void), TEST (ListIds::front_void, begin_void), TEST (ListIds::front_const_void, begin_void), TEST (ListIds::back_void, end_void), TEST (ListIds::back_const_void, end_void), TEST (ListIds::get_allocator_void, get_allocator_void) }; const std::size_t test_count = sizeof tests / sizeof *tests; return rw_run_cont_test (argc, argv, __FILE__, "lib.list.iterators", ContainerIds::List, test_iterators_func_array, tests, test_count); }