You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/03/04 03:12:59 UTC
svn commit: r383002 -
/incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp
Author: sebor
Date: Fri Mar 3 18:12:57 2006
New Revision: 383002
URL: http://svn.apache.org/viewcvs?rev=383002&view=rev
Log:
2006-03-03 Liviu Nicoara <nicoare@roguewave.com
Martin Sebor <se...@roguewave.com>
STDCXX-4
* 23.vector.modifiers.cpp: New test exercising lib.vector.modifiers.
Added:
incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp (with props)
Added: incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp?rev=383002&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp (added)
+++ incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp Fri Mar 3 18:12:57 2006
@@ -0,0 +1,1196 @@
+/***************************************************************************
+ *
+ * 23.vector.modifiers.cpp - test exercising [lib.vector.modifiers]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright 2006 The Apache Software Foundation or its licensors,
+ * as applicable.
+ *
+ * Copyright 2006 Rogue Wave Software.
+ *
+ * Licensed 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 <memory> // for placement operator new()
+#include <vector> // for vector
+
+#include <cstddef> // for size_t
+
+#include <rw_printf.h>
+#include <alg_test.h>
+#include <driver.h>
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+ // disabled for compilers such as IBM VAC++ or MSVC
+ // that can't reliably replace the operators
+# include <rw_new.h>
+#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+/**************************************************************************/
+
+static unsigned rw_opt_nloops;
+static int rw_opt_no_input_iter;
+static int rw_opt_no_forward_iter;
+static int rw_opt_no_bidir_iter;
+static int rw_opt_no_random_iter;
+static int rw_opt_no_insert;
+static int rw_opt_no_insert_range;
+static int rw_opt_no_insert_at_end;
+static int rw_opt_no_complexity;
+static int rw_opt_no_push_back;
+
+/**************************************************************************/
+
+typedef std::vector<X, std::allocator<X> > Vector;
+
+Vector::size_type new_capacity;
+
+namespace __rw {
+
+_RWSTD_SPECIALIZED_FUNCTION
+inline Vector::size_type
+__rw_new_capacity<Vector>(Vector::size_type n, const Vector*)
+{
+ if (n)
+ return n * 2;
+
+ return new_capacity;
+}
+
+}
+
+/**************************************************************************/
+
+// used to determine whether insert() can or cannot use
+// an algorithm optimized for ForwardIterators
+bool is_forward_category (std::input_iterator_tag) { return false; }
+bool is_forward_category (std::forward_iterator_tag) { return true; }
+
+template <class Iterator>
+bool is_forward (const Iterator &it)
+{
+ _RWSTD_UNUSED (it);
+
+ return is_forward_category (_RWSTD_ITERATOR_CATEGORY (Iterator, it));
+
+}
+
+// exercises the exception safety of each tested function by successively
+// forcing operator new to thow a bad_alloc exception at each iteration
+// of the loop until the call succeeds (i.e., until no exception is
+// thrown)
+template <class Iterator>
+void exception_loop (int line, const char *fcall, bool capchg,
+ Vector &vec, const Vector::iterator &it,
+ int n, const X *x,
+ const Iterator &first, const Iterator &last,
+ std::size_t *n_copy, std::size_t *n_asgn)
+{
+ std::size_t throw_after = 0;
+
+ const std::size_t size = vec.size ();
+ const std::size_t capacity = vec.capacity ();
+ const Vector::const_iterator begin = vec.begin ();
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ rwt_free_store* const pst = rwt_get_free_store (0);
+
+#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // iterate for`n=throw_after' starting at the next call to operator
+ // new, forcing each call to throw an exception, until the insertion
+ // finally succeeds (i.e, no exception is thrown)
+ for ( ; ; ) {
+
+ *n_copy = X::n_total_copy_ctor_;
+ *n_asgn = X::n_total_op_assign_;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ // detect objects constructed but not destroyed after an exception
+ const std::size_t count = X::count_;
+
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // disable out of memory exceptions before copying iterators
+ // (InputIter ctors may dynamically allocate memory)
+ *pst->throw_at_calls_ [0] = std::size_t (-1);
+# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ // create "deep" copies of the iterators to thwart
+ // InpuIter's multi-pass detection
+ const Iterator beg = copy_iter (first, (X*)0);
+ const Iterator end = copy_iter (last, (X*)0);
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
+
+# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ _TRY {
+ if (-2 == n) {
+ vec.insert (it, *x);
+ }
+ else if (-1 == n) {
+
+#ifndef _RWSTD_NO_EXT_VECTOR_INSERT_IN_PLACE
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+ // disable exceptions if Iterator is not at least
+ // a ForwardIterator since the extension doesn't
+ // provide the strong exception safety guarantee
+ // required in 23.2.4.3, p1
+ if (!is_forward (beg)) {
+ *pst->throw_at_calls_ [0] = std::size_t (-1);
+ }
+# endif //_RWSTD_NO_REPLACEABLE_NEW_DELETE
+#endif // _RWSTD_NO_EXT_VECTOR_INSERT_IN_PLACE
+
+ vec.insert (it, beg, end);
+ }
+ else {
+ vec.insert (it, n, *x);
+ }
+ break;
+ }
+ _CATCH (...) {
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+ // verify that an exception thrown during allocation
+ // doesn't cause a change in the state of the vector
+
+ rw_assert (vec.size () == size, 0, line,
+ "line %d: %s: size unexpectedly changed "
+ "from %zu to %zu after an exception",
+ __LINE__, fcall, size, vec.size ());
+
+ rw_assert (vec.capacity () == capacity, 0, line,
+ "line %d: %s: capacity unexpectedly "
+ "changed from %zu to %zu after an exception",
+ __LINE__, fcall, capacity, vec.capacity ());
+
+
+ rw_assert (vec.begin () == begin, 0, line,
+ "line %d: %s: begin() unexpectedly "
+ "changed from after an exception by %d",
+ __LINE__, fcall, vec.begin () - begin);
+
+
+ rw_assert (count == X::count_, 0, line,
+ "line %d: %s: leaked %d objects "
+ "after an exception",
+ __LINE__, fcall, X::count_ - count);
+
+ // increment to allow this call to operator new to succeed
+ // and force the next one to fail, and try to insert again
+ ++throw_after;
+
+#endif // _RWSTD_NO_EXCEPTIONS
+
+ } // catch
+ } // for
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+# ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // verify that if exceptions are enabled and when capacity changes
+ // at least one exception is thrown
+ rw_assert ( *pst->throw_at_calls_ [0] == std::size_t (-1)
+ || !capchg
+ || throw_after,
+ 0, line,
+ "line %d: %s: failed to throw an expected exception",
+ __LINE__, fcall);
+
+ // commented out: just because capacity doesn't change doesn't mean
+ // that no exception is thrown (e.g., if the function dynamically
+ // allocates temporary storage)
+ //
+ // rw_assert (capchg || !throw_after,
+ // 0, line,
+ // "line %d: %s: unexpectedly threw an exception",
+ // __LINE__, fcall);
+
+# endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+#else // if defined (_RWSTD_NO_EXCEPTIONS)
+
+ _RWSTD_UNUSED (t);
+ _RWSTD_UNUSED (line);
+ _RWSTD_UNUSED (fcall);
+ _RWSTD_UNUSED (capchg);
+ _RWSTD_UNUSED (size);
+ _RWSTD_UNUSED (capacity);
+ _RWSTD_UNUSED (throw_after);
+
+#endif // _RWSTD_NO_EXCEPTIONS
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ *pst->throw_at_calls_ [0] = std::size_t (-1);
+
+#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+ // compute the number of calls to X copy ctor and assignment operator
+ *n_copy = X::n_total_copy_ctor_ - *n_copy;
+ *n_asgn = X::n_total_op_assign_ - *n_asgn;
+}
+
+/**************************************************************************/
+
+template <class Iterator>
+void test_insert (int line, // line number of call site
+ const Iterator &dummy, // unused dummy iterator
+ int n, // number of elements to insert
+ // or the special values -1 and -2
+ const char *seq, // initial container contents
+ std::size_t seqlen, // initial container size
+ std::size_t seqcap, // initial container capacity
+ int off, // offset at which to insert
+ const char *ins, // inserted sequence
+ std::size_t inslen, // length of inserted sequence
+ const char *res, // resulting sequence
+ std::size_t reslen /* length of resulting sequence */)
+{
+ // create arrays of `seqlen' and `inslen' elements of type X
+ // initialized from the sequences `seq' and `ins', respectively
+ const X* const xseq = X::from_char (seq, seqlen);
+ X* const xins = X::from_char (ins, inslen);
+
+ // construct a std::vector from the sequence of elements
+ Vector vec = seqlen ? Vector (xseq, xseq + seqlen) : Vector ();
+
+ // set the capacity of the container (if specified)
+ if (std::size_t (-1) == seqcap)
+ seqcap = vec.capacity ();
+ else
+ vec.reserve (seqcap);
+
+ // create an iterator pointing `off' past the beginning of the vector
+ const Vector::iterator it = vec.begin () + off;
+
+ char* fcall = 0;
+ std::size_t len = 0;
+
+ // format a string describing the function call being tested
+ // (used in diagnostic messages, if any, below)
+ rw_asnprintf (&fcall, &len, "vector(\"%{X=*.*}\").insert("
+ "%{?}begin(), %{:}%{?}end (), %{:}begin () + %zu%{;}%{;}"
+ "%{?}%d)%{:}%{?}\"%{X=*.*}\")%{:}%d, %d)%{;}%{;}",
+ int (seqlen), -1, xseq,
+ 0 == off, int (seqlen) == off, off,
+ n == -2, *ins, n == -1,
+ int (inslen), -1, xins, n, *ins);
+
+ // 23.2.4.3, p1
+ // Notes: Causes reallocation if the new size is greater than
+ // the old capacity. If no reallocation happens, all the iterators
+ // and references before the insertion point remain valid.
+ // If an exception is thrown other than by the copy constructor
+ // an assignment operator of T there are no effects.
+
+ // determine whether the insertion must or must not change capacity
+ const bool capchg = seqlen + (n < 0 ? inslen : n) > seqcap;
+
+ std::size_t n_copy = X::n_total_copy_ctor_;
+ std::size_t n_asgn = X::n_total_op_assign_;
+
+ if (-2 == n) {
+
+ exception_loop (line, fcall, capchg,
+ vec, it, n, xins, dummy, dummy,
+ &n_copy, &n_asgn);
+ }
+ else if (-1 == n) {
+
+ const Iterator first =
+ make_iter (xins, xins, xins + inslen, dummy);
+
+ const Iterator last =
+ make_iter (xins + inslen, xins, xins + inslen, dummy);
+
+ exception_loop (line, fcall, capchg,
+ vec, it, n, 0, first, last,
+ &n_copy, &n_asgn);
+ }
+ else /* if (n != -2 && n != -1) */ {
+ // n must be in the range [-2, INT_MAX]
+ _RWSTD_ASSERT (n >= 0);
+
+ exception_loop (line, fcall, capchg,
+ vec, it, n, xins, dummy, dummy,
+ &n_copy, &n_asgn);
+ }
+
+ // verify the expected size of the vector after insertion
+ rw_assert (vec.size () == reslen, 0, line,
+ "line %d: %s: size == %zu, got %zu",
+ __LINE__, fcall, reslen, vec.size ());
+
+ // verify the expected change in capacity of the vactor
+ rw_assert (capchg == (vec.capacity () != seqcap),
+ 0, line, "line %d: %s: capacity %c = %zu, got %zu",
+ __LINE__, fcall, capchg ? '!' : '=', seqcap, vec.capacity ());
+
+ // verify the expected contents of the vector after insertion
+ const Vector::const_pointer resbeg = vec.size () ? &*vec.begin () : 0;
+ const Vector::const_pointer resend = resbeg + vec.size ();
+
+ for (Vector::const_pointer ptr = resbeg; ptr != resend; ++ptr) {
+
+ typedef unsigned char UChar;
+
+ if (ptr->val_ != UChar (res [ptr - resbeg])) {
+
+ char* const got = new char [vec.size () + 1];
+
+ for (Vector::const_pointer p = resbeg; p != resend; ++p) {
+ got [p - resbeg] = char (p->val_);
+ }
+
+ got [vec.size ()] = '\0';
+
+ rw_assert (0, 0, line,
+ "line %d: %s: expected %s, got %s",
+ __LINE__, fcall, res, got);
+
+ delete [] got;
+ break;
+ }
+ }
+
+ // 23.2.4.3, p2
+ // Complexity:
+ // -- If first and last are forward iterators, bidirectional iterators,
+ // or random access iterators, the complexity is linear in the number
+ // of elements in the range [first, last) plus the distance to
+ // the end of the vector.
+ // -- If they are input iterators, the complexity is proportional
+ // to the number of elements in the range [first, last) times
+ // the distance to the end of the vector.
+
+ // verify the complexity of the operation in terms of the number
+ // of calls to the copy ctor and assignment operator on value_type
+ // note that the complexity requirement imposes an upper bound on
+ // the number of operations and implementations are allowed to do
+ // better (see 17.3.1.3, p5)
+
+ std::size_t expect_copy; // expected number of copy ctor calls
+ std::size_t expect_asgn; // expected number of assignments
+
+ if (is_forward (dummy)) {
+ // ForwardIterator or better
+
+ if (capchg) {
+ // when the insertion causes a change in capacity
+ // (i.e., reallocation), the number of copy ctor
+ // invocations is equal to the size of the resulting
+ // sequence; no assignment operators are invoked
+ expect_copy = reslen;
+ expect_asgn = 0;
+ }
+ else {
+ // when no change in capacity occurs the number of copy
+ // ctor invocations is equal to the number of elements
+ // between the end of the inserted range and the end of
+ // the original sequence
+ // the number of assignments is equal to the distance
+ // from the point of insertion to the end of the original
+ // sequence
+ expect_copy = n < 0 ? inslen : n;
+ expect_asgn = n && inslen ? reslen - off : 0;
+ }
+ }
+ else {
+ // InputIterator
+ expect_copy = n_copy;
+ expect_asgn = n_asgn;
+
+ // don't bother testing the complexity of the functions with
+ // InputIterators, the standard's messed up (see issue 247
+ // and the indirectly related issue 406)
+ }
+
+ rw_assert (expect_copy >= n_copy,
+ 0, line,
+ "line %d: %s: expected at most %zu "
+ "invocation(s) of X::X(const X&), got %zu",
+ __LINE__, fcall, expect_copy, n_copy);
+
+ rw_assert (expect_asgn >= n_asgn,
+ 0, line,
+ "line %d: %s: expected at most %zu invocation(s) "
+ "of X::operator=(const X&), got %zu",
+ __LINE__, fcall, expect_asgn, n_asgn);
+
+ delete [] xins;
+ delete [] _RWSTD_CONST_CAST (X*, xseq);
+}
+
+/**************************************************************************/
+
+void test_insert ()
+{
+ //////////////////////////////////////////////////////////////////
+ // exercise vector::insert(iterator, const_reference)
+
+ rw_info (0, 0, 0,
+ "std::vector<X>::insert(iterator, const_reference)");
+
+#undef TEST
+#define TEST(seq, seqcap, off, ins, res) do { \
+ const char insseq [] = { ins, '\0' }; \
+ test_insert (__LINE__, (X*)0, -2, \
+ seq, sizeof seq - 1, \
+ std::size_t (seqcap), off, \
+ insseq, 1, \
+ res, sizeof res - 1); \
+ } while (0)
+
+ // +----------------------- initial container contents
+ // | +--------------- initial container capacity
+ // | | +----------- offset at which to insert
+ // | | | +------ element to insert
+ // | | | | +-- resulting sequence
+ // | | | | |
+ // V V V V V
+ TEST ("", -1, +0, 'a', "a");
+ TEST ("b", -1, +0, 'a', "ab");
+ TEST ("bc", -1, +0, 'a', "abc");
+ TEST ("bcd", -1, +0, 'a', "abcd");
+ TEST ("bcde", -1, +0, 'a', "abcde");
+
+ TEST ("a", -1, +1, 'b', "ab");
+ TEST ("ac", -1, +1, 'b', "abc");
+ TEST ("acd", -1, +1, 'b', "abcd");
+ TEST ("acde", -1, +1, 'b', "abcde");
+
+ TEST ("ab", -1, +2, 'c', "abc");
+ TEST ("abd", -1, +2, 'c', "abcd");
+ TEST ("abde", -1, +2, 'c', "abcde");
+
+ TEST ("abc", -1, +3, 'd', "abcd");
+ TEST ("abce", -1, +3, 'd', "abcde");
+
+ TEST ("abcd", -1, +4, 'e', "abcde");
+
+ //////////////////////////////////////////////////////////////////
+ // exercise vector::insert(iterator, size_type, const_reference)
+
+ rw_info (0, 0, 0,
+ "std::vector<X>::insert(iterator, "
+ "size_type, const_reference)");
+
+#undef TEST
+#define TEST(seq, seqcap, off, n, ins, res) do { \
+ const char insseq [] = { ins, '\0' }; \
+ test_insert (__LINE__, (X*)0, n, \
+ seq, sizeof seq - 1, \
+ std::size_t (seqcap), off, \
+ insseq, 1, \
+ res, sizeof res - 1); \
+ } while (0)
+
+ // +-------------------------- initial container contents
+ // | +------------------ initial container capacity
+ // | | +-------------- offset at which to insert
+ // | | | +---------- number of elements to insert
+ // | | | | +------ element value to insert
+ // | | | | | +-- resulting sequence
+ // | | | | | |
+ // V V V V V V
+ TEST ("", -1, +0, 0, 'a', "");
+ TEST ("", -1, +0, 1, 'a', "a");
+ TEST ("", -1, +0, 2, 'b', "bb");
+ TEST ("", -1, +0, 3, 'c', "ccc");
+
+ TEST ("a", -1, +0, 0, 'a', "a");
+ TEST ("b", -1, +0, 1, 'a', "ab");
+ TEST ("b", -1, +0, 2, 'a', "aab");
+ TEST ("b", -1, +0, 3, 'a', "aaab");
+
+ TEST ("ab", -1, +1, 0, 'b', "ab");
+ TEST ("ac", -1, +1, 1, 'b', "abc");
+ TEST ("ac", -1, +1, 2, 'b', "abbc");
+ TEST ("ac", -1, +1, 3, 'b', "abbbc");
+
+ TEST ("abcd", -1, +2, 0, 'c', "abcd");
+ TEST ("abde", -1, +2, 1, 'c', "abcde");
+ TEST ("abde", -1, +2, 2, 'c', "abccde");
+ TEST ("abde", -1, +2, 3, 'c', "abcccde");
+}
+
+/**************************************************************************/
+
+template <class Iterator>
+void test_insert_range (const Iterator &dummy)
+{
+ static const char* const itname = type_name (dummy, (X*)0);
+
+ rw_info (0, 0, 0,
+ "std::vector<X>::insert(iterator, %s, %s)",
+ itname, itname);
+
+#undef TEST
+#define TEST(seq, seqcap, off, ins, res) \
+ test_insert (__LINE__, dummy, -1, \
+ seq, sizeof seq - 1, \
+ std::size_t (seqcap), off, \
+ ins, sizeof ins - 1, \
+ res, sizeof res - 1)
+
+ // +-------------------------------------------- seq(uence)
+ // | +------------------------------------- seqcap(acity)
+ // | | +--------------------------------- off(set of insertion)
+ // | | | +----------------------------- ins(erted sequence)
+ // | | | | +---------------------- res(ultin sequence)
+ // | | | | |
+ // v v v v v
+ TEST ("", -1, +0, "", "");
+ TEST ("", -1, +0, "a", "a");
+ TEST ("", -1, +0, "ab", "ab");
+ TEST ("", -1, +0, "abc", "abc");
+ TEST ("a", -1, +0, "", "a");
+ TEST ("b", -1, +0, "a", "ab");
+ TEST ("c", -1, +0, "ab", "abc");
+ TEST ("cd", -1, +0, "ab", "abcd");
+ TEST ("def", -1, +0, "abc", "abcdef");
+
+ TEST ("a", -1, +1, "", "a");
+ TEST ("a", -1, +1, "b", "ab");
+ TEST ("a", -1, +1, "bc", "abc");
+ TEST ("a", -1, +1, "bcd", "abcd");
+
+ TEST ("ab", -1, +1, "", "ab");
+ TEST ("ac", -1, +1, "b", "abc");
+ TEST ("acd", -1, +1, "b", "abcd");
+
+ TEST ("ab", -1, +2, "", "ab");
+ TEST ("ab", -1, +2, "c", "abc");
+ TEST ("ab", -1, +2, "cd", "abcd");
+
+ TEST ("abc", -1, +2, "", "abc");
+ TEST ("abd", -1, +2, "c", "abcd");
+ TEST ("abe", -1, +2, "cd", "abcde");
+ TEST ("abf", -1, +2, "cde", "abcdef");
+
+ TEST ("abc", -1, +3, "", "abc");
+ TEST ("abc", -1, +3, "d", "abcd");
+ TEST ("abc", -1, +3, "de", "abcde");
+ TEST ("abc", -1, +3, "def", "abcdef");
+
+
+#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define LOWER "abcdefghijklmnopqrstuvwxyz"
+
+ TEST (UPPER, -1, +0, LOWER, "" LOWER "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +1, LOWER, "A" LOWER "BCDEFGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +2, LOWER, "AB" LOWER "CDEFGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +3, LOWER, "ABC" LOWER "DEFGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +4, LOWER, "ABCD" LOWER "EFGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +5, LOWER, "ABCDE" LOWER "FGHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +6, LOWER, "ABCDEF" LOWER "GHIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +7, LOWER, "ABCDEFG" LOWER "HIJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +8, LOWER, "ABCDEFGH" LOWER "IJKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +9, LOWER, "ABCDEFGHI" LOWER "JKLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +10, LOWER, "ABCDEFGHIJ" LOWER "KLMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +11, LOWER, "ABCDEFGHIJK" LOWER "LMNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +12, LOWER, "ABCDEFGHIJKL" LOWER "MNOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +13, LOWER, "ABCDEFGHIJKLM" LOWER "NOPQRSTUVWXYZ");
+ TEST (UPPER, -1, +14, LOWER, "ABCDEFGHIJKLMN" LOWER "OPQRSTUVWXYZ");
+ TEST (UPPER, -1, +15, LOWER, "ABCDEFGHIJKLMNO" LOWER "PQRSTUVWXYZ");
+ TEST (UPPER, -1, +16, LOWER, "ABCDEFGHIJKLMNOP" LOWER "QRSTUVWXYZ");
+ TEST (UPPER, -1, +17, LOWER, "ABCDEFGHIJKLMNOPQ" LOWER "RSTUVWXYZ");
+ TEST (UPPER, -1, +18, LOWER, "ABCDEFGHIJKLMNOPQR" LOWER "STUVWXYZ");
+ TEST (UPPER, -1, +19, LOWER, "ABCDEFGHIJKLMNOPQRS" LOWER "TUVWXYZ");
+ TEST (UPPER, -1, +20, LOWER, "ABCDEFGHIJKLMNOPQRST" LOWER "UVWXYZ");
+ TEST (UPPER, -1, +21, LOWER, "ABCDEFGHIJKLMNOPQRSTU" LOWER "VWXYZ");
+ TEST (UPPER, -1, +22, LOWER, "ABCDEFGHIJKLMNOPQRSTUV" LOWER "WXYZ");
+ TEST (UPPER, -1, +23, LOWER, "ABCDEFGHIJKLMNOPQRSTUVW" LOWER "XYZ");
+ TEST (UPPER, -1, +24, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWX" LOWER "YZ");
+ TEST (UPPER, -1, +25, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXY" LOWER "Z");
+ TEST (UPPER, -1, +26, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" LOWER "");
+}
+
+/**************************************************************************/
+
+void test_insert_at_end ()
+{
+ //////////////////////////////////////////////////////////////////
+ // exercise vector::insert() at the end of the container and
+ // verify that the functions perform in amortized constant time
+ // (see also PR #30615)
+
+ rw_info (0, 0, 0,
+ "std::vector<X>::insert (end(), const_reference)");
+
+ typedef Vector::size_type size_type;
+
+ Vector v;
+
+ size_type nextcap = 0;
+
+ // iterate to grow vector excactly 8 times
+ for (int i = 0; i != 8; ++i) {
+
+ // count the number of copy ctor and assignment operator invocations
+ std::size_t n_copy;
+ std::size_t n_asgn;
+
+ // compute the next (non-zero) capacity of the container
+ nextcap = _RW::__rw_new_capacity (nextcap + 1, (Vector*)0);
+
+ // insert elements at the end of the container until its size
+ // reaches its capacity, verifying that each of the insertions
+ // performed in (amortized) constant time
+ while (v.size () < nextcap) {
+
+ n_copy = X::n_total_copy_ctor_;
+ n_asgn = X::n_total_op_assign_;
+
+ v.insert (v.end (), Vector::value_type ());
+
+ rw_assert (nextcap >= v.capacity (), 0, __LINE__,
+ "vector<X>::insert (end(), value_type()); "
+ "capacity == %zu, got %zu after %zu insertions",
+ nextcap, v.capacity (), v.size ());
+
+ if (nextcap < v.capacity ()) break;
+
+ // compute the number of copy ctor and assignment operator calls
+ n_copy = X::n_total_copy_ctor_ - n_copy;
+ n_asgn = X::n_total_op_assign_ - n_asgn;
+
+ // verify that the copy ctor was invoked exactly once
+ rw_assert (1U == n_copy, 0, __LINE__,
+ "vector<X>::insert (end(), value_type()); "
+ "expected 1 invocation of the copy ctor, got %zu",
+ n_copy);
+
+ // verify that the assignment operator was not invoked
+ rw_assert (n_asgn == 0, 0, __LINE__,
+ "vector<X>::insert (end(), value_type()); "
+ "expected 0 invocations of the assignment "
+ "operator, got %zu", n_asgn);
+ }
+
+ // inserting the next element must reallocate
+ v.insert (v.end (), Vector::value_type ());
+
+ rw_assert (v.capacity () > nextcap, 0, __LINE__,
+ "vector<X>::insert (end(), value_type()); "
+ "capacity > %zu, got %zu after %zu insertions",
+ nextcap, v.capacity (), v.size ());
+ }
+}
+
+/**************************************************************************/
+
+// exercise vector<>::insert() and vector::erase()
+// focus on the complexity of the function
+
+void test_complexity ()
+{
+ rw_info (0, 0, 0, "std::vector<X>::insert(iterator, const_reference)");
+ rw_info (0, 0, 0, "std::ector<X>::insert(iterator, size_type, "
+ "const_reference)");
+ rw_info (0, 0, 0, "template <class InputIterator> std::vector<X>::insert"
+ "(iterator, InputIterator, InputIterator)");
+ rw_info (0, 0, 0, "std::vector<X>::erase(iterator)");
+ rw_info (0, 0, 0, "std::vector<X>::erase(iterator, iterator)");
+
+ typedef std::vector<X, std::allocator<X> > Vector;
+
+ bool success = true;
+
+ Vector v0;
+ Vector v1;
+ Vector v2;
+
+ Vector::iterator it = v0.begin ();
+ Vector::iterator it1 = v1.begin ();
+ Vector::iterator it2 = v2.begin ();
+
+ Vector::size_type i;
+
+ for (i = 0; i < rw_opt_nloops; i++) {
+ // initialize the current size, capacity and begin iterator variables
+ Vector::size_type v0_size = v0.size ();
+ Vector::size_type v0_cap = v0.capacity ();
+ Vector::iterator v0_beg = v0.begin ();
+
+ X val;
+
+ // reset the X totals
+ X::reset_totals ();
+
+ // inseert val into the vector
+ it = v0.insert (it, val);
+
+ // 23.2.4.3, p1: causes reallocation if the new size
+ // is greater than the old capacity
+ rw_assert (v0_cap <= v0.size () || v0_beg == v0.begin (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) "
+ "invalidated iterators w/o reallocation");
+
+ // make sure that the vector is now one element larger
+ rw_assert (v0.size () == v0_size + 1,
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference); "
+ "new size = %zu, expected %zu", v0.size (), v0_size + 1);
+
+ // make sure that the returned iterator points to the new value
+ rw_assert (*it == val,
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference); "
+ "returned iterator doesn't point at inserted value");
+
+ // 23.2.4.3, p2: the complexity is linear in the number of elements
+ // in the range [first, last) plus the distance to the
+ // end of the vector.
+ if(v0.begin () != v0_beg) {
+ rw_assert ((Vector::size_type)X::n_total_copy_ctor_ == v0.size (),
+ 0, __LINE__,
+ "vector<X>::insert() - fails complexity "
+ "copy_ctor called %zu; size = %zu",
+ X::n_total_copy_ctor_, v0.size ());
+ }
+ else {
+ rw_assert ( (X::n_total_copy_ctor_ + X::n_total_op_assign_)
+ == std::size_t (v0.end() - it),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) - "
+ "fails complexity copy_ctor and assign called "
+ "%zu correct = %zu", X::n_total_copy_ctor_ +
+ X::n_total_op_assign_, (v0.end() - it));
+ }
+
+ // every 5 loops erase 'it'
+ if (i % 5) {
+ it1 = it;
+ Vector::value_type next_val;
+
+ // if we are not at the end of the vector then increment it1 and
+ // if we are still not at the end then set next_val = *it1
+ // because when we erase it, that will be the value it should
+ // point to
+ if (it != v0.end () && ++it1 != v0.end())
+ next_val = *it1;
+
+ Vector::size_type num_left = v0.end () - it - 1;
+ Vector::size_type X_count = X::count_;
+
+ v0_size = v0.size ();
+
+ // reset the totals for the complexity test
+ X::reset_totals ();
+ it = v0.erase (it);
+
+ // make sure only one element was erased
+ rw_assert (v0.size () != v0_size - 1, 0, __LINE__,
+ "vector<X>::erase(iterator); new size = %zu, "
+ "expected %zu", v0.size (), v0_size - 1);
+
+ // if we were not at the end of the vector then *it should be
+ // next_val
+ rw_assert (it == v0.end () || *it == next_val, 0, __LINE__,
+ "vector<X>::erase(iterator); "
+ "returned iterator doesn't point at next value ");
+
+ // 23.2.4.2, p4: The assignment operator of X should be called the
+ // number of times equal to the number of elements
+ // in the vector after the erased elements.
+ rw_assert ((Vector::size_type)X::n_total_op_assign_ != num_left,
+ 0, __LINE__,
+ "vector<X>::erase(iterator) - fails "
+ "complexity assign called %zu correct = %zu",
+ X::n_total_op_assign_, num_left);
+
+
+ // 23.2.4.2, p4: The destructor of X should be called the number
+ // of times equal to the number of elements erased
+ rw_assert ((Vector::size_type)X_count - X::count_ == 1,
+ 0, __LINE__,
+ "vector<X>::erase(iterator) - "
+ "fails complexity destructor called %zu "
+ "correct = %zu", X_count - X::count_ , 1);
+ }
+
+ // Don't always insert at the beginning
+ if (i % 2 && it != v0.end ())
+ it++;
+ }
+
+ // now lets test nultiple insert and erase functions
+ for (i = 0; i < rw_opt_nloops; i++) {
+ Vector::size_type v1_size = v1.size ();
+ Vector::size_type v1_cap = v1.capacity ();
+ Vector::iterator v1_beg = v1.begin ();
+
+ X val;
+ X::reset_totals ();
+
+ // insert `i' copies of `val' in the middle
+ Vector::size_type offset = (v1.size () ? (i / 2) % v1.size () : 0);
+ it1 = v1.begin () + offset;
+ v1.insert (it1, i, val);
+
+ // since insert doesn't return the next position after the
+ //inserted elements we will calculate this ourself
+ it1 = v1.begin () + offset + i;
+
+ // 23.2.4.3, p1: causes reallocation if the new size
+ // is greater than the old capacity
+ rw_assert (v1_cap <= v1.size () || v1_beg == v1.begin (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) "
+ "invalidated iterators w/o reallocation");
+
+ // make sure that the vector increased in size by the correct number
+ rw_assert (v1.size () == v1_size + i,
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference); "
+ "new size = %zu, expected %zu", v1.size (), v1_size + i);
+
+ // 23.2.4.3, p2: the complexity is linear in the number of elements
+ // in the range [first, last) plus the distance to the
+ // end of the vector.
+ if (v1.begin () != v1_beg) {
+ rw_assert ((Vector::size_type)X::n_total_copy_ctor_ == v1.size (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) - "
+ "fails complexity copy_ctor called %zu size =%zu",
+ X::n_total_copy_ctor_, v1.size());
+ }
+ else {
+ rw_assert ( i + (v1.end() - it1)
+ == (Vector::size_type)(X::n_total_copy_ctor_ +
+ X::n_total_op_assign_),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) - "
+ "fails complexity copy_ctor and assign "
+ "called %zu correct = %zu",
+ X::n_total_copy_ctor_ + X::n_total_op_assign_,
+ (v1.end() - it1));
+ }
+
+ Vector::size_type old_size = v1.size();
+
+ X new_val;
+
+ Vector::value_type expected_val =
+ v1.size () ? *(v1.begin () + (v1.size () / 2)) : new_val;
+
+ X::reset_totals ();
+ // set up some variable that will keep track of how many we are going
+ // to erase, how many are left after the last element we are erasing
+ // and what the current number of Xs are in existance.
+ Vector::size_type num_destroy = v1.size () / 2;
+
+ Vector::size_type num_left =
+ v1.end () - (v1.begin () + (v1.size () / 2));
+
+ Vector::size_type X_count = X::count_;
+
+ it1 = v1.erase(v1.begin (), v1.begin () + (v1.size () / 2));
+
+ // make sure the correct number of elements were erased
+ rw_assert (v1.size () == old_size - (old_size / 2),
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator); "
+ "new size = %zu, expected %zu", v1.size (),
+ old_size - (old_size / 2));
+
+ // if there is at least one element left then make sure that it1 now
+ // points to the expected next element in the vector.
+ rw_assert (v1.size () == 0 || *it1 == expected_val,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator); "
+ "returned iterator doesn't point at next value ");
+
+ // 23.2.4.2, p4: The assignment operator of X should be called the
+ // number of times equal to the number of elements
+ // in the vector after the erased elements.
+ rw_assert ((Vector::size_type)X::n_total_op_assign_ == num_left,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator) - fails "
+ "complexity assign called %zu correct = %zu",
+ X::n_total_op_assign_, num_left);
+
+ // 23.2.4.2, p4: The destructor of X should be called the number
+ // of times equal to the number of elements erased
+ rw_assert (X_count - X::count_ == num_destroy,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator) - fails "
+ "complexity destructor called %zu correct = %zu",
+ X_count - X::count_ , num_destroy);
+
+
+ }
+
+#if !defined (_RWSTD_NO_INLINE_MEMBER_TEMPLATES) \
+ && (!defined (_MSC_VER) || _MSC_VER >= 1300)
+
+ v0.clear ();
+ for (i = 0; i < rw_opt_nloops; i++) {
+ Vector::size_type v2_size = v2.size ();
+ Vector::size_type v2_cap = v2.capacity ();
+ Vector::iterator v2_beg = v2.begin ();
+
+ X val;
+ v0.insert (v0.begin(), val);
+
+ // 23.2.4.3, p1: causes reallocation if the new size
+ // is greater than the old capacity
+ rw_assert (v2_cap <= v2.size () || v2_beg == v2.begin (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) "
+ "invalidated iterators w/o reallocation");
+
+ X::reset_totals ();
+ v2.insert(v2.begin(), v0.begin(), v0.end());
+
+ if (v2.begin () != v2_beg)
+ rw_assert ((Vector::size_type)X::n_total_copy_ctor_ == v2.size (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) - "
+ "fails complexity copy_ctor called %zu size =%zu",
+ X::n_total_copy_ctor_, v2.size());
+ else {
+ rw_assert ( (Vector::size_type)(X::n_total_copy_ctor_
+ + X::n_total_op_assign_)
+ == v0.size () + (v2.end() - (v2.begin() + v0.size())),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference) - "
+ "fails complexity copy_ctor and assign called "
+ "%zu correct = %zu",
+ X::n_total_copy_ctor_ + X::n_total_op_assign_,
+ v0.size() + (v2.end() - (v2.begin() + v0.size())));
+ }
+
+
+ rw_assert (v2.size () == v2_size + v0.size (),
+ 0, __LINE__,
+ "vector<X>::insert(iterator, const_reference); "
+ "new size = %zu, expected %zu", v2.size (),
+ v2_size + v0.size ());
+
+ Vector::size_type old_size = v2.size();
+
+ Vector::iterator expected_it = v2.begin () + (v2.size () / 2) ;
+
+ Vector::value_type expected_val = *expected_it;
+
+ X::reset_totals ();
+
+ Vector::size_type num_destroy = v2.size () / 2;
+
+ Vector::size_type num_left =
+ v2.end () - (v2.begin () + (v2.size () / 2));
+
+ Vector::size_type X_count = X::count_;
+
+ it2 = v2.erase(v2.begin (), v2.begin () + (v2.size () / 2));
+
+
+ rw_assert (v2.size () == v2_size + v0.size() - (old_size / 2),
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator); "
+ "new size = %zu, expected %zu",
+ v2.size (), v2_size + i - (old_size / 2));
+
+ rw_assert (v2.size () == 0 || *it2 == expected_val,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator); "
+ "returned iterator doesn't point at next value ");
+
+ rw_assert ((Vector::size_type)X::n_total_op_assign_ == num_left,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator) - "
+ "fails complexity assign called %zu correct = %zu",
+ X::n_total_op_assign_, num_left);
+
+ rw_assert (X_count - X::count_ == num_destroy,
+ 0, __LINE__,
+ "vector<X>::erase(iterator, iterator) - "
+ "fails complexity destructor called %zu correct = %zu",
+ X_count - X::count_ , num_destroy);
+
+ }
+#endif // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+
+ rw_assert (success, 0, __LINE__, "vector<X>::insert()");
+ rw_assert (success, 0, __LINE__, "vector<X>::erase()");
+}
+
+/**************************************************************************/
+
+template <class T, class Allocator>
+void test_push_back (const std::vector<T, Allocator>*)
+{
+ rw_info (0, 0, 0, "std::vector<X>::push_back(const_reference)");
+
+ typedef std::vector<T, Allocator> MyVector;
+ typedef typename MyVector::value_type ValueType;
+ typedef typename MyVector::size_type SizeType;
+ typedef typename MyVector::pointer Pointer;
+ typedef typename MyVector::const_pointer ConstPointer;
+ typedef typename MyVector::iterator Iterator;
+
+ MyVector v1;
+ MyVector v2;
+
+ const ValueType val = ValueType ();
+
+ for (SizeType i = 0; i != SizeType (4096); ++i) {
+
+ // perform the two operations from Table 68
+ v1.push_back (val);
+
+ v2.insert (v2.end (), val);
+
+ // verify that effects on both sequences
+ // are identical as required by Table 68
+ rw_assert (v1.size () == v2.size (),
+ 0, __LINE__,
+ "Expected std::vector::size to "
+ "compare equal; got %zu and %zu",
+ v1.size (), v2.size ());
+
+ rw_assert (v1.capacity () == v2.capacity (),
+ 0, __LINE__,
+ "Expected std::vector::capacity to "
+ "compare equal; got %zu and %zu",
+ v1.capacity (), v2.capacity ());
+
+ rw_assert (v1.end () - v1.begin () == v2.end () - v2.begin (),
+ 0, __LINE__,
+ "Expected std::vector::end() - std::vector::begin() "
+ "to compare equal; got %zu and %zu",
+ v1.end () - v1.begin (), v2.end () - v2.begin ());
+ }
+}
+
+/**************************************************************************/
+
+static int
+run_test (int /* argc */, char** /* argv */)
+{
+ if (rw_opt_no_complexity) {
+ rw_note (0, 0, __LINE__, "complexity test disabled");
+ }
+ else {
+ test_complexity ();
+ }
+
+ if (rw_opt_no_push_back) {
+ rw_note (0, 0, __LINE__, "push_back test disabled");
+ }
+ else {
+ test_push_back ((std::vector<X, std::allocator<X> >*)0);
+ }
+
+ if (rw_opt_no_insert) {
+ rw_note (0, 0, __LINE__, "insert test disabled");
+ }
+ else {
+ test_insert ();
+ }
+
+ if (rw_opt_no_insert_range) {
+ rw_note (0, 0, __LINE__, "insert range test disabled");
+ }
+ else {
+ if (rw_opt_no_input_iter) {
+ rw_note (0, 0, __LINE__,
+ "InputIterator test disabled");
+ }
+ else {
+ test_insert_range (InputIter<X>(0, 0, 0));
+ }
+
+ if (rw_opt_no_forward_iter) {
+ rw_note (0, 0, __LINE__,
+ "ForwardIterator test disabled");
+ }
+ else {
+ test_insert_range (ConstFwdIter<X>());
+ }
+
+ if (rw_opt_no_bidir_iter) {
+ rw_note (0, 0, __LINE__,
+ "BidirectionalIterator test disabled");
+ }
+ else {
+ test_insert_range (ConstBidirIter<X>());
+ }
+
+ if (rw_opt_no_random_iter) {
+ rw_note (0, 0, __LINE__,
+ "RandomAccessIterator test disabled");
+ }
+ else {
+ test_insert_range (ConstRandomAccessIter<X>());
+ }
+
+ }
+
+ if (rw_opt_no_insert_at_end) {
+ rw_note (0, 0, __LINE__, "insert at end test disabled");
+ }
+ else {
+ test_insert_at_end ();
+ }
+
+ return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char** argv)
+{
+ return rw_test (argc, argv, __FILE__,
+ "lib.vector.modifiers",
+ 0 /* no comment */,
+ run_test,
+ "|-nloops#1 "
+ "|-no-insert# "
+ "|-no-insert_range# "
+ "|-no-insert_at_end# "
+ "|-no-complexity# "
+ "|-no-input_iter# "
+ "|-no-input_iter# "
+ "|-no-forward_iter# "
+ "|-no-bidir_iter# "
+ "|-no-random_iter# "
+ "|-no-push_back#",
+ &rw_opt_nloops,
+ &rw_opt_no_insert,
+ &rw_opt_no_insert_range,
+ &rw_opt_no_insert_at_end,
+ &rw_opt_no_complexity,
+ &rw_opt_no_input_iter,
+ &rw_opt_no_forward_iter,
+ &rw_opt_no_bidir_iter,
+ &rw_opt_no_random_iter,
+ &rw_opt_no_push_back);
+}
Propchange: incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/containers/23.vector.modifiers.cpp
------------------------------------------------------------------------------
svn:keywords = Id