stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r372607 - in /incubator/stdcxx/trunk/tests/containers: ./ 23.deque.modifiers.cpp 23.deque.special.cpp
Date Thu, 26 Jan 2006 20:56:20 GMT
Author: sebor
Date: Thu Jan 26 12:56:15 2006
New Revision: 372607

URL: http://svn.apache.org/viewcvs?rev=372607&view=rev
Log:
2006-01-26  Liviu Nicoara  <nicoara@roguewave.com>
	    Martin Sebor  <sebor@roguewave.com>

	STDCXX-4
	* 23.deque.modifiers.cpp: New test exercising lib.deque.modifiers.
	* 23.deque.special.cpp: New test exercising lib.deque.special.

Added:
    incubator/stdcxx/trunk/tests/containers/
    incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp   (with props)
    incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp   (with props)

Added: incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp?rev=372607&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp (added)
+++ incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp Thu Jan 26 12:56:15 2006
@@ -0,0 +1,1406 @@
+/***************************************************************************
+ *
+ * 23.deque.modifiers.cpp - test exercising [lib.deque.modifiers]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. 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.
+ * 
+ **************************************************************************/
+
+#ifdef _MSC_VER
+   // silence warning C4244: 'argument' : conversion from 'T' to
+   // 'const std::allocator<_TypeT>::value_type', possible loss of data
+   // issued for deque::assign(InputIterator a, InputIterator b) and
+   // deque::insert(iterator, InputIterator a, InputIterator b) due
+   // the implicit conversion of a to size_type and b to value_type
+   // required by DR 438:
+   // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#438
+#  pragma warning (disable: 4244)
+#endif
+
+#include <deque>     // for deque
+
+#include <cstdlib>   // for free()
+
+#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
+   // disabled for MSVC since it can't reliably replace the operators
+#  include <rw_new.h>
+#endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
+
+#include <alg_test.h>    // for X
+#include <driver.h>      // for rw_test(), ...
+#include <snprintfa.h>   // for rw_asnprintf
+
+/**************************************************************************/
+
+// Runtime options
+/* extern */ int rw_opt_no_assign = 0;
+/* extern */ int rw_opt_no_erase  = 0;
+/* extern */ int rw_opt_no_insert = 0;
+/* extern */ int rw_opt_no_dr438  = 0;
+/* extern */ int rw_opt_no_input_iterator = 0;
+/* extern */ int rw_opt_no_forward_iterator = 0;
+/* extern */ int rw_opt_no_bidirectional_iterator = 0;
+/* extern */ int rw_opt_no_random_iterator = 0;
+/* extern */ int rw_opt_no_right_thing = 0;
+
+/**************************************************************************/
+
+// For konvenience
+typedef unsigned char UChar;
+
+/**************************************************************************/
+
+typedef std::deque<X, std::allocator<X> > Deque;
+
+Deque::size_type new_capacity;
+
+namespace __rw {
+
+_RWSTD_SPECIALIZED_FUNCTION
+inline Deque::size_type
+__rw_new_capacity<Deque>(Deque::size_type n, const Deque*)
+{
+    if (n) {
+        // non-zero size argument indicates a request for an increase
+        // in the capacity of a deque object's dynamically sizable
+        // vector of nodes
+        return n * 2;
+    }
+
+    // zero size argument is a request for the initial size of a deque
+    // object's dynamically sizable vector of nodes or for the size of
+    // the objects's fixed-size buffer for elements
+    return new_capacity;
+}
+
+}
+
+/**************************************************************************/
+
+enum {
+    NewThrows = 0x1          /* cause operator new to throw */,
+    CopyCtorThrows = 0x2     /* cause element's copy ctor to throw */,
+    AssignmentThrows = 0x4   /* cause element's assignment to throw */
+};
+
+enum MemberFunction {
+    Assign_n    /* deque::assign (size_type, const_reference) */,
+    AssignRange /* deque::assign (InputIterator, InputIterator) */,
+
+    Erase_1     /* deque::erase (iterator) */,
+    EraseRange  /* deque::erase (iterator, iterator) */,
+
+    Insert_1    /* deque::insert (iterator, const_reference) */,
+    Insert_n    /* deque::insert (iterator, size_type, const_reference) */,
+    InsertRange /* deque::insert (iterator, InputIterator, InputIterator) */
+};
+
+
+// causes operator new, deque element's copy ctor, or assignment operator
+// to throw an exception and iterates as long as the member function exits
+// by throwing an exception; verifies that the exception had no effects
+// on the container
+template <class Iterator>
+void exception_loop (int             line /* line number in caller*/,
+                     MemberFunction  mfun /* deque member function */,
+                     const char     *fcall /* function call string */,
+                     int             exceptions /* enabled exceptions */,
+                     Deque          &deq /* container to call function on */,
+                     const Deque::iterator &it /* iterator into container */,
+                     int             n /* number of elements or offset */,
+                     const X        *x /* pointer to an element or 0 */,
+                     const Iterator &first /* beginning of range */,
+                     const Iterator &last /* end of range to insert */,
+                     int            *n_copy /* number of copy ctors */,
+                     int            *n_asgn /* number of assignments */)
+{
+    std::size_t throw_after = 0;
+
+    // get the initial size of the container and its begin() iterator
+    // to detect illegal changes after an exception (i.e., violations
+    // if the strong exception guarantee)
+    const std::size_t           size  = deq.size ();
+    const Deque::const_iterator begin = deq.begin ();
+    const Deque::const_iterator end   = deq.end ();
+
+#ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+    rwt_free_store* const pst = rwt_get_free_store (0);
+
+#endif   // DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+    // repeatedly call the specified member function until it returns
+    // without throwing an exception
+    for ( ; ; ) {
+
+        // detect objects constructed but not destroyed after an exception
+        std::size_t x_count = X::count_;
+
+        _RWSTD_ASSERT (n_copy);
+        _RWSTD_ASSERT (n_asgn);
+
+        *n_copy = X::n_total_copy_ctor_;
+        *n_asgn = X::n_total_op_assign_;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+        // 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)
+
+#  ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+        if (exceptions & NewThrows) {
+            *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_after + 1;
+        }
+
+#  endif   // DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+        if (exceptions & CopyCtorThrows) {
+            X::copy_ctor_throw_count_ = X::n_total_copy_ctor_ + throw_after;
+        }
+
+        if (exceptions & AssignmentThrows) {
+            X::op_assign_throw_count_ = X::n_total_op_assign_ + throw_after;
+        }
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        _TRY {
+
+            switch (mfun) {
+            case Assign_n:
+                _RWSTD_ASSERT (x);
+                deq.assign (n, *x);
+                break;
+            case AssignRange:
+                deq.assign (first, last);
+                break;
+
+            case Erase_1:
+                deq.erase (it);
+                break;
+            case EraseRange: {
+                const Deque::iterator erase_end (it + n);
+                deq.erase (it, erase_end);
+                break;
+            }
+
+            case Insert_1:
+                _RWSTD_ASSERT (x);
+                deq.insert (it, *x);
+                break;
+            case Insert_n:
+                _RWSTD_ASSERT (x);
+                deq.insert (it, n, *x);
+                break;
+            case InsertRange:
+                deq.insert (it, first, last);
+                break;
+            }
+        }
+        _CATCH (...) {
+
+            // verify that an exception thrown from the member function
+            // didn't cause a change in the state of the container
+
+            rw_assert (deq.size () == size, 0, line,
+                       "line %d: %s: size unexpectedly changed "
+                       "from %zu to %zu after an exception",
+                       __LINE__, fcall, size, deq.size ());
+            
+            rw_assert (deq.begin () == begin, 0, line,
+                       "line %d: %s: begin() unexpectedly "
+                       "changed after an exception by %td",
+                       __LINE__, fcall, deq.begin () - begin);
+
+            rw_assert (deq.end () == end, 0, line,
+                       "line %d: %s: end() unexpectedly "
+                       "changed after an exception by %td",
+                       __LINE__, fcall, deq.end () - end);
+            
+
+            // count the number of objects to detect leaks
+            x_count = X::count_ - x_count;
+            rw_assert (x_count == deq.size () - size, 0, line,
+                       "line %d: %s: leaked %zu objects after an exception",
+                       __LINE__, fcall, x_count - (deq.size () - size));
+            
+            if (exceptions) {
+
+                // increment to allow this call to operator new to succeed
+                // and force the next one to fail, and try to insert again
+                ++throw_after;
+            }
+            else
+                break;
+
+            continue;
+        }
+
+        // count the number of objects to detect leaks
+        x_count = X::count_ - x_count;
+        rw_assert (x_count == deq.size () - size, 0, line,
+                   "line %d: %s: leaked %zu objects "
+                   "after a successful insertion",
+                   __LINE__, fcall, x_count - (deq.size () - size));
+
+        break;
+    }
+
+#ifdef DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+    // disable exceptions from replacement operator new
+    *pst->throw_at_calls_ [0] = _RWSTD_SIZE_MAX;
+
+#endif   // DEFINE_REPLACEMENT_NEW_AND_DELETE
+
+    X::copy_ctor_throw_count_ = 0;
+    X::op_assign_throw_count_ = 0;
+
+    // compute the number of calls to X copy ctor and assignment operator
+    // and set `n_copy' and `n_assgn' to the value of the result
+    *n_copy = X::n_total_copy_ctor_ - *n_copy;
+    *n_asgn = X::n_total_op_assign_ - *n_asgn;
+}
+
+
+// used to determine whether insert() can or cannot use
+// an algorithm optimized for BidirectionalIterators
+bool is_bidirectional (std::input_iterator_tag) { return false; }
+bool is_bidirectional (std::bidirectional_iterator_tag) { return true; }
+
+// returns the number of invocations of the assignment operators
+// for a call to deque::insert(iterator, InputIterator, InputIterator)
+// (the value depends on the iterator category)
+template <class Iterator>
+std::size_t insert_assignments (Iterator it,
+                                int nelems,
+                                std::size_t off,
+                                std::size_t seqlen,
+                                std::size_t inslen)
+{
+    if (is_bidirectional (_RWSTD_ITERATOR_CATEGORY (Iterator, it)))
+        return 0 == nelems ? 0 : off < seqlen - off ? off : seqlen - off;
+
+    if (0 < nelems)
+        --nelems;
+
+    if (0 == nelems || 0 == inslen)
+        return 0;
+
+    // compute the number of assignments done
+    // to insert the first element in the sequence
+    const std::size_t first = off < seqlen - off ? off : seqlen - off;
+
+    // recursively compute the numner of assignments
+    // for the rest of the elements in the sequence
+    const std::size_t rest =
+        insert_assignments (it, nelems, off + 1, seqlen + 1, inslen - 1);
+
+    return first + rest;
+}
+
+
+template <class Iterator>
+void test_insert (int line, int exceptions,
+                  const Iterator &dummy, int nelems,
+                  const char *seq, std::size_t seqlen, std::size_t off, 
+                  const char *ins, std::size_t inslen, 
+                  const char *res, std::size_t reslen)
+{
+    // Ensure that xsrc, xins are always dereferenceable
+    const X* const xseq = X::from_char (seq, seqlen + 1);
+          X* const xins = X::from_char (ins, inslen + 1);
+
+    Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque ();
+
+    // offset must be valid
+    _RWSTD_ASSERT (off <= deq.size ());
+    const Deque::iterator iter = deq.begin () + off;
+
+    // only insert() at either end of the container is exception safe
+    // insertions into the middle of the container are not (i.e., the
+    // container may grow or may even become inconsistent)
+    if (off && off < deq.size ())
+        exceptions = 0;
+
+    // format a string describing the function call being exercised
+    // (used in diagnostic output below)
+    char* funcall = 0;
+    std::size_t len = 0;
+
+    rw_asnprintf (&funcall, &len, "deque(\"%{X=*.*}\").insert("
+                  "%{?}begin(), %{:}%{?}end (), %{:}begin () + %zu%{;}%{;}"
+                  "%{?}%d)%{:}%{?}\"%{X=*.*}\")%{:}%d, %d)%{;}%{;}",
+                  int (seqlen), -1, xseq, 0 == off, seqlen == off, off,
+                  nelems == -2, *ins, nelems == -1, 
+                  int (inslen), -1, xins, nelems, *ins);
+
+    int n_copy = X::n_total_copy_ctor_;
+    int n_asgn = X::n_total_op_assign_;
+
+    if (-2 == nelems) {   // insert(iterator, const_reference)
+
+        exception_loop (line, Insert_1, funcall, exceptions,
+                        deq, iter, nelems, xins, dummy, dummy,
+                        &n_copy, &n_asgn);
+
+    }
+    else if (-1 == nelems) {   // insert(iterator, Iterator, Iterator)
+
+        if (inslen > 1)
+            exceptions = 0;
+
+        const Iterator first =
+            make_iter (xins, xins, xins + inslen, dummy);
+
+        const Iterator last =
+            make_iter (xins + inslen, xins, xins + inslen, dummy);
+
+        exception_loop (line, InsertRange, funcall, exceptions,
+                        deq, iter, nelems, 0, first, last,
+                        &n_copy, &n_asgn);
+
+    }
+    else {   // insert(iterator, size_type, const_reference)
+
+        if (nelems > 1)
+            exceptions = 0;
+
+        exception_loop (line, Insert_n, funcall, exceptions,
+                        deq, iter, nelems, xins, dummy, dummy,
+                        &n_copy, &n_asgn);
+
+    }
+
+    // verify the expected size of the deque after insertion
+    rw_assert (deq.size () == reslen, __FILE__, line,
+               "line %d: %s: size == %zu, got %zu\n",
+               __LINE__, funcall, reslen, deq.size ());
+
+    // verify the expected contents of the deque after insertion
+    const Deque::const_iterator resbeg = deq.begin ();
+    const Deque::const_iterator resend = deq.end ();
+
+    for (Deque::const_iterator it = resbeg; it != resend; ++it) {
+        if ((*it).val_ != UChar (res [it - resbeg])) {
+
+            char* const got = new char [deq.size () + 1];
+
+            for (Deque::const_iterator i = resbeg; i != resend; ++i) {
+                got [i - resbeg] = char ((*i).val_);
+            }
+
+            got [deq.size ()] = '\0';
+
+            rw_assert (false, __FILE__, line,
+                       "line %d: %s: expected %s, got %s\n",
+                       __LINE__, funcall, res, got);
+
+            delete[] got;
+            break;
+        }
+    }
+
+    // verify the complexity of the operation in terms of the number
+    // of calls to the copy ctor and assignment operator on value_type
+    const std::size_t expect_copy = nelems < 0 ? inslen : nelems;
+
+    rw_assert (n_copy == int (expect_copy),
+               __FILE__, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::X(const X&), got %d\n",
+               __LINE__, funcall, expect_copy, n_copy);
+
+    // compute the number of calls to the assignment operator
+    const std::size_t expect_asgn =
+        insert_assignments (dummy, nelems, off, seqlen, inslen);
+
+    rw_assert (n_asgn == int (expect_asgn), 
+               __FILE__, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::operator=(const X&), got %d\n",
+               __LINE__, funcall, expect_asgn, n_asgn);
+
+    // Free funcall storage
+    std::free (funcall);
+
+    delete[] xins;
+    delete[] xseq;
+}
+
+/**************************************************************************/
+
+template <class Iterator>
+void test_insert_range (const Iterator &it, const char* itname)
+{
+    rw_info (0, 0 ,0, 
+             "std::deque<X>::insert(iterator, %s, %s)", itname, itname);
+
+#undef TEST
+#define TEST(seq, off, ins, res)                        \
+    test_insert (__LINE__, -1,                          \
+                            it, -1,                     \
+                            seq, sizeof seq - 1,        \
+                            std::size_t (off),          \
+                            ins, sizeof ins - 1,        \
+                            res, sizeof res - 1)
+
+    //    +---------------------------------------- seq
+    //    |      +--------------------------------- off
+    //    |      |   +----------------------------- ins
+    //    |      |   |      +---------------------- res
+    //    |      |   |      |
+    //    v      v   v      v
+    TEST ("",    +0, "",    "");
+    TEST ("",    +0, "a",   "a");
+    TEST ("",    +0, "ab",  "ab");
+    TEST ("",    +0, "abc", "abc");
+    TEST ("a",   +0, "",    "a");
+    TEST ("b",   +0, "a",   "ab");
+    TEST ("c",   +0, "ab",  "abc");
+    TEST ("cd",  +0, "ab",  "abcd");
+    TEST ("def", +0, "abc", "abcdef");
+
+    TEST ("a",   +1, "",    "a");
+    TEST ("a",   +1, "b",   "ab");
+    TEST ("a",   +1, "bc",  "abc");
+    TEST ("a",   +1, "bcd", "abcd");
+
+    TEST ("ab",  +1, "",    "ab");
+    TEST ("ac",  +1, "b",   "abc");
+    TEST ("acd", +1, "b",   "abcd");
+
+    TEST ("ab",  +2, "",    "ab");
+    TEST ("ab",  +2, "c",   "abc");
+    TEST ("ab",  +2, "cd",  "abcd");
+
+    TEST ("abc", +2, "",    "abc");
+    TEST ("abd", +2, "c",   "abcd");
+    TEST ("abe", +2, "cd",  "abcde");
+    TEST ("abf", +2, "cde", "abcdef");
+
+    TEST ("abc", +3, "",    "abc");
+    TEST ("abc", +3, "d",   "abcd");
+    TEST ("abc", +3, "de",  "abcde");
+    TEST ("abc", +3, "def", "abcdef");
+    
+
+#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define LOWER "abcdefghijklmnopqrstuvwxyz"
+
+    TEST (UPPER,  +0, LOWER, "" LOWER "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +1, LOWER, "A" LOWER "BCDEFGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +2, LOWER, "AB" LOWER "CDEFGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +3, LOWER, "ABC" LOWER "DEFGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +4, LOWER, "ABCD" LOWER "EFGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +5, LOWER, "ABCDE" LOWER "FGHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +6, LOWER, "ABCDEF" LOWER "GHIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +7, LOWER, "ABCDEFG" LOWER "HIJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +8, LOWER, "ABCDEFGH" LOWER "IJKLMNOPQRSTUVWXYZ");
+    TEST (UPPER,  +9, LOWER, "ABCDEFGHI" LOWER "JKLMNOPQRSTUVWXYZ");
+    TEST (UPPER, +10, LOWER, "ABCDEFGHIJ" LOWER "KLMNOPQRSTUVWXYZ");
+    TEST (UPPER, +11, LOWER, "ABCDEFGHIJK" LOWER "LMNOPQRSTUVWXYZ");
+    TEST (UPPER, +12, LOWER, "ABCDEFGHIJKL" LOWER "MNOPQRSTUVWXYZ");
+    TEST (UPPER, +13, LOWER, "ABCDEFGHIJKLM" LOWER "NOPQRSTUVWXYZ");
+    TEST (UPPER, +14, LOWER, "ABCDEFGHIJKLMN" LOWER "OPQRSTUVWXYZ");
+    TEST (UPPER, +15, LOWER, "ABCDEFGHIJKLMNO" LOWER "PQRSTUVWXYZ");
+    TEST (UPPER, +16, LOWER, "ABCDEFGHIJKLMNOP" LOWER "QRSTUVWXYZ");
+    TEST (UPPER, +17, LOWER, "ABCDEFGHIJKLMNOPQ" LOWER "RSTUVWXYZ");
+    TEST (UPPER, +18, LOWER, "ABCDEFGHIJKLMNOPQR" LOWER "STUVWXYZ");
+    TEST (UPPER, +19, LOWER, "ABCDEFGHIJKLMNOPQRS" LOWER "TUVWXYZ");
+    TEST (UPPER, +20, LOWER, "ABCDEFGHIJKLMNOPQRST" LOWER "UVWXYZ");
+    TEST (UPPER, +21, LOWER, "ABCDEFGHIJKLMNOPQRSTU" LOWER "VWXYZ");
+    TEST (UPPER, +22, LOWER, "ABCDEFGHIJKLMNOPQRSTUV" LOWER "WXYZ");
+    TEST (UPPER, +23, LOWER, "ABCDEFGHIJKLMNOPQRSTUVW" LOWER "XYZ");
+    TEST (UPPER, +24, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWX" LOWER "YZ");
+    TEST (UPPER, +25, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXY" LOWER "Z");
+    TEST (UPPER, +26, LOWER, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" LOWER "");
+}
+
+/**************************************************************************/
+
+template <class T, class IntType>
+void test_insert_int_range (const T&, const IntType&,
+                            const char* t_name, const char* int_name)
+{
+    rw_info (0, 0, 0, 
+             "std::deque<%s>::insert(iterator, %s, %s)", 
+             t_name, int_name, int_name);
+
+    std::deque<T> d;
+
+    typename std::deque<T>::iterator it = d.begin ();
+
+    // deque<T>::insert(iterator, size_type, const_reference)
+
+    d.insert (it, IntType (1), IntType (0));
+
+    rw_assert (1 == d.size (), 0, __LINE__,
+               "deque<%s>::insert(begin(), %s = 1, %s = 0); size() == 1,"
+               " got %zu", t_name, int_name, int_name, d.size ());
+
+    it = d.begin ();
+    ++it;
+
+    d.insert (it, IntType (3), IntType (2));
+
+    rw_assert (4 == d.size (), 0, __LINE__,
+               "deque<%s>::insert(begin() + 1, %s = 3, %s = 2); size() == 4,"
+               " got %zu", t_name, int_name, int_name, d.size ());
+
+    it = d.begin ();
+    ++it;
+
+    d.insert (it, IntType (2), IntType (1));
+
+    rw_assert (6 == d.size (), 0, __LINE__,
+               "deque<%s>::insert(begin() + 1, %s = 2, %s = 1); size() == 6,"
+               " got %zu", t_name, int_name, int_name, d.size ());
+}
+
+
+template <class T>
+void test_insert_int_range (const T &dummy, const char* tname)
+{
+    test_insert_int_range (dummy, (signed char)0, tname, "signed char");
+    test_insert_int_range (dummy, (unsigned char)0, tname, "unsigned char");
+    test_insert_int_range (dummy, short (), tname, "short");
+    test_insert_int_range (dummy, (unsigned short)0, tname, "unsigned short");
+    test_insert_int_range (dummy, int (), tname, "int");
+    test_insert_int_range (dummy, (unsigned int)0, tname, "unsigned int");
+    test_insert_int_range (dummy, long (), tname, "long");
+    test_insert_int_range (dummy, (unsigned long)0, tname, "unsigned long");
+
+#ifdef _RWSTD_LONG_LONG
+
+    test_insert_int_range (dummy, (_RWSTD_LONG_LONG)0, 
+                           tname, "long long");
+    test_insert_int_range (dummy, (unsigned _RWSTD_LONG_LONG)0, 
+                           tname, "unsigned long long");
+
+#endif   // _RWSTD_LONG_LONG
+
+}
+
+/**************************************************************************/
+
+void test_insert ()
+{
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::insert(iterator, const_reference)
+
+    rw_info (0, 0, 0, "std::deque<X>::insert(iterator, const_reference)");
+
+#undef TEST
+#define TEST(seq, off, ins, res) do {                   \
+      const char insseq [] = { ins, '\0' };             \
+      test_insert (__LINE__, -1,                        \
+                              (X*)0, -2,                \
+                              seq, sizeof seq - 1,      \
+                              std::size_t (off),        \
+                              insseq, 1,                \
+                              res, sizeof res - 1);     \
+    } while (0)
+
+    //    +------------------- original sequence
+    //    |       +----------- insertion offset
+    //    |       |    +------ element to insert
+    //    |       |    |   +-- resulting sequence
+    //    |       |    |   |
+    //    V       V    V   V
+    TEST ("",     +0, 'a', "a");
+    TEST ("b",    +0, 'a', "ab");
+    TEST ("bc",   +0, 'a', "abc");
+    TEST ("bcd",  +0, 'a', "abcd");
+    TEST ("bcde", +0, 'a', "abcde");
+
+    TEST ("a",    +1, 'b', "ab");
+    TEST ("ac",   +1, 'b', "abc");
+    TEST ("acd",  +1, 'b', "abcd");
+    TEST ("acde", +1, 'b', "abcde");
+
+    TEST ("ab",   +2, 'c', "abc");
+    TEST ("abd",  +2, 'c', "abcd");
+    TEST ("abde", +2, 'c', "abcde");
+
+    TEST ("abc",  +3, 'd', "abcd");
+    TEST ("abce", +3, 'd', "abcde");
+
+    TEST ("abcd", +4, 'e', "abcde");
+
+#define A_to_B "AB"
+#define A_to_C "ABC"
+#define A_to_D "ABCD"
+#define A_to_E "ABCDE"
+#define A_to_F "ABCDEF"
+#define A_to_G "ABCDEFG"
+#define A_to_H "ABCDEFGH"
+#define A_to_I "ABCDEFGHI"
+#define A_to_J "ABCDEFGHIJ"
+#define A_to_K "ABCDEFGHIJK"
+#define A_to_L "ABCDEFGHIJKL"
+#define A_to_M "ABCDEFGHIJKLM"
+#define A_to_N "ABCDEFGHIJKLMN"
+#define A_to_O "ABCDEFGHIJKLMNO"
+#define A_to_P "ABCDEFGHIJKLMNOP"
+#define A_to_Q "ABCDEFGHIJKLMNOPQ"
+#define A_to_R "ABCDEFGHIJKLMNOPQR"
+#define A_to_S "ABCDEFGHIJKLMNOPQRS"
+#define A_to_T "ABCDEFGHIJKLMNOPQRST"
+#define A_to_U "ABCDEFGHIJKLMNOPQRSTU"
+#define A_to_V "ABCDEFGHIJKLMNOPQRSTUV"
+#define A_to_W "ABCDEFGHIJKLMNOPQRSTUVW"
+#define A_to_X "ABCDEFGHIJKLMNOPQRSTUVWX"
+#define A_to_Y "ABCDEFGHIJKLMNOPQRSTUVWXY"
+#define A_to_Z "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define B_to_Z "BCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define C_to_Z "CDEFGHIJKLMNOPQRSTUVWXYZ"
+#define D_to_Z "DEFGHIJKLMNOPQRSTUVWXYZ"
+#define E_to_Z "EFGHIJKLMNOPQRSTUVWXYZ"
+#define F_to_Z "FGHIJKLMNOPQRSTUVWXYZ"
+#define G_to_Z "GHIJKLMNOPQRSTUVWXYZ"
+#define H_to_Z "HIJKLMNOPQRSTUVWXYZ"
+#define I_to_Z "IJKLMNOPQRSTUVWXYZ"
+#define J_to_Z "JKLMNOPQRSTUVWXYZ"
+#define K_to_Z "KLMNOPQRSTUVWXYZ"
+#define L_to_Z "LMNOPQRSTUVWXYZ"
+#define M_to_Z "MNOPQRSTUVWXYZ"
+#define N_to_Z "NOPQRSTUVWXYZ"
+#define O_to_Z "OPQRSTUVWXYZ"
+#define P_to_Z "PQRSTUVWXYZ"
+#define Q_to_Z "QRSTUVWXYZ"
+#define R_to_Z "RSTUVWXYZ"
+#define S_to_Z "STUVWXYZ"
+#define T_to_Z "TUVWXYZ"
+#define U_to_Z "UVWXYZ"
+#define V_to_Z "VWXYZ"
+#define W_to_Z "WXYZ"
+#define X_to_Z "XYZ"
+#define Y_to_Z "YZ"
+
+    TEST (A_to_Z, + 0, '^', ""     "^" A_to_Z);
+    TEST (A_to_Z, + 1, '^', "A"    "^" B_to_Z);
+    TEST (A_to_Z, + 2, '^', A_to_B "^" C_to_Z);
+    TEST (A_to_Z, + 3, '^', A_to_C "^" D_to_Z);
+    TEST (A_to_Z, + 4, '^', A_to_D "^" E_to_Z);
+    TEST (A_to_Z, + 5, '^', A_to_E "^" F_to_Z);
+    TEST (A_to_Z, + 6, '^', A_to_F "^" G_to_Z);
+    TEST (A_to_Z, + 7, '^', A_to_G "^" H_to_Z);
+    TEST (A_to_Z, + 8, '^', A_to_H "^" I_to_Z);
+    TEST (A_to_Z, + 9, '^', A_to_I "^" J_to_Z);
+    TEST (A_to_Z, +10, '^', A_to_J "^" K_to_Z);
+    TEST (A_to_Z, +11, '^', A_to_K "^" L_to_Z);
+    TEST (A_to_Z, +12, '^', A_to_L "^" M_to_Z);
+    TEST (A_to_Z, +13, '^', A_to_M "^" N_to_Z);
+    TEST (A_to_Z, +14, '^', A_to_N "^" O_to_Z);
+    TEST (A_to_Z, +15, '^', A_to_O "^" P_to_Z);
+    TEST (A_to_Z, +16, '^', A_to_P "^" Q_to_Z);
+    TEST (A_to_Z, +17, '^', A_to_Q "^" R_to_Z);
+    TEST (A_to_Z, +18, '^', A_to_R "^" S_to_Z);
+    TEST (A_to_Z, +19, '^', A_to_S "^" T_to_Z);
+    TEST (A_to_Z, +20, '^', A_to_T "^" U_to_Z);
+    TEST (A_to_Z, +21, '^', A_to_U "^" V_to_Z);
+    TEST (A_to_Z, +22, '^', A_to_V "^" W_to_Z);
+    TEST (A_to_Z, +23, '^', A_to_W "^" X_to_Z);
+    TEST (A_to_Z, +24, '^', A_to_X "^" Y_to_Z);
+    TEST (A_to_Z, +25, '^', A_to_Y "^" "Z");
+    TEST (A_to_Z, +26, '^', A_to_Z "^" "");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::insert(iterator, size_type, const_reference)
+
+    rw_info (0, 0, 0, 
+             "std::deque<X>::insert(iterator, size_type, "
+             "const_reference)");
+
+#undef TEST
+#define TEST(seq, off, n, ins, res) do {                \
+      const char insseq [] = { ins, '\0' };             \
+      test_insert (__LINE__, -1,                        \
+                              (X*)0, n,                 \
+                              seq, sizeof seq - 1,      \
+                              std::size_t (off),        \
+                              insseq, 1,                \
+                              res, sizeof res - 1);     \
+    } while (0)
+    
+    TEST ("",     +0, 0, 'a', "");
+    TEST ("",     +0, 1, 'a', "a");
+    TEST ("",     +0, 2, 'b', "bb");
+    TEST ("",     +0, 3, 'c', "ccc");
+
+    TEST ("a",    +0, 0, 'a', "a");
+    TEST ("b",    +0, 1, 'a', "ab");
+    TEST ("b",    +0, 2, 'a', "aab");
+    TEST ("b",    +0, 3, 'a', "aaab");
+
+    TEST ("ab",   +1, 0, 'b', "ab");
+    TEST ("ac",   +1, 1, 'b', "abc");
+    TEST ("ac",   +1, 2, 'b', "abbc");
+    TEST ("ac",   +1, 3, 'b', "abbbc");
+
+    TEST ("abcd", +2, 0, 'c', "abcd");
+    TEST ("abde", +2, 1, 'c', "abcde");
+    TEST ("abde", +2, 2, 'c', "abccde");
+    TEST ("abde", +2, 3, 'c', "abcccde");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::insert(iterator, InputIterator, InputIterator)
+
+    rw_info (0, 0, 0, 
+             "template <class InputIterator> std::deque<X>::"
+             "insert(iterator, InputIterator, InputIterator)");
+
+    if (0 == rw_opt_no_input_iterator)
+        test_insert_range (InputIter<X>(0, 0, 0), "InputIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::insert(iterator, T, T) "
+                 "[with T = InputIterator] test disabled.");
+
+    if (0 == rw_opt_no_forward_iterator)
+        test_insert_range (FwdIter<X>(), "FwdIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::insert(iterator, T, T) "
+                 "[with T = ForwardIterator] test disabled.");
+
+    if (0 == rw_opt_no_bidirectional_iterator)
+        test_insert_range (BidirIter<X>(), "BidirIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::insert(iterator, T, T) "
+                 "[with T = BidirectionalIterator] test disabled.");
+
+    if (0 == rw_opt_no_random_iterator)
+        test_insert_range (RandomAccessIter<X>(), "RandomAccessIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::insert(iterator, T, T) "
+                 "[with T = RandomAccessIterator] test disabled."); 
+
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::insert(iterator, int, int)
+
+    rw_info (0, 0, 0, 
+             "template <class IntType> "
+             "std::deque<IntType>::"
+             "insert(iterator, IntType, IntType)");
+
+    if (0 == rw_opt_no_right_thing) {
+        test_insert_int_range ((signed char)0, "signed char");
+        test_insert_int_range ((unsigned char)0, "unsigned char");
+        test_insert_int_range (short (), "short");
+        test_insert_int_range ((unsigned short)0, "unsigned short");
+        test_insert_int_range (int (), "int");
+        test_insert_int_range ((unsigned int)0, "unsigned int");
+        test_insert_int_range (long (), "long");
+        test_insert_int_range ((unsigned long)0, "unsigned long");
+
+#ifdef _RWSTD_LONG_LONG
+
+        test_insert_int_range ((_RWSTD_LONG_LONG)0, 
+                               "long long");
+        test_insert_int_range ((unsigned _RWSTD_LONG_LONG)0, 
+                               "unsigned long long");
+
+#endif   // _RWSTD_LONG_LONG
+    }
+    else
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::insert(iterator, T, T) "
+                 "[with T = IntegralType] tests disabled."); 
+
+}
+
+/**************************************************************************/
+
+template <class Iterator>
+void test_assign (int line, int exceptions,
+                  const Iterator &dummy, int nelems,
+                  const char *seq, std::size_t seqlen,
+                  const char *asn, std::size_t asnlen,
+                  const char *res, std::size_t reslen)
+{
+    const X* const xseq = X::from_char (seq, seqlen + 1);
+          X* const xasn = X::from_char (asn, asnlen + 1);
+
+    Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque ();
+
+    // format a string describing the function call being exercised
+    // (used in diagnostic output below)
+    char* funcall = 0;
+    std::size_t len = 0;
+
+    rw_asnprintf (&funcall, &len, 
+                  "deque(\"%{X=*.*}\").assign("
+                  "%{?}\"%{X=*.*}\")%{:}%d, %d)%{;}", 
+                  seqlen, -1, xseq, 
+                  nelems < 0, 
+                  asnlen, -1, xasn, 
+                  nelems, *asn);
+
+    int n_copy = X::n_total_copy_ctor_;
+    int n_asgn = X::n_total_op_assign_;
+
+    // create a dummy deque iterator to pass to exception_loop
+    // (the object will not be used by the functiuon)
+    const Deque::iterator dummy_it = deq.begin ();
+
+    if (nelems < 0) {   // assign(Iterator, Iterator)
+
+        if (asnlen > 1)
+            exceptions = 0;
+
+        const Iterator first =
+            make_iter (xasn, xasn, xasn + asnlen, dummy);
+
+        const Iterator last =
+            make_iter (xasn + asnlen, xasn, xasn + asnlen, dummy);
+
+        exception_loop (line, AssignRange, funcall, exceptions,
+                        deq, dummy_it, nelems, 0, first, last,
+                        &n_copy, &n_asgn);
+    }
+    else {   // assign(size_type, const_reference)
+        if (nelems > 1)
+            exceptions = 0;
+
+        exception_loop (line, Assign_n, funcall, exceptions,
+                        deq, dummy_it, nelems, xasn, dummy, dummy,
+                        &n_copy, &n_asgn);
+    }
+
+    // verify the expected size of the deque after assignment
+    rw_assert (deq.size () == reslen, 0, line,
+               "line %d: %s: size == %zu, got %zu\n",
+               __LINE__, funcall, reslen, deq.size ());
+
+    // verify the expected contents of the deque after assignment
+    const Deque::const_iterator resbeg = deq.begin ();
+    const Deque::const_iterator resend = deq.end ();
+
+    for (Deque::const_iterator it = resbeg; it != resend; ++it) {
+
+        const Deque::size_type inx = it - resbeg;
+
+        _RWSTD_ASSERT (inx < deq.size ());
+
+        if ((*it).val_ != UChar (res [inx])) {
+
+            char* const got = new char [deq.size () + 1];
+
+            for (Deque::const_iterator i = resbeg; i != resend; ++i) {
+
+                const Deque::size_type inx_2 = i - resbeg;
+
+                _RWSTD_ASSERT (inx_2 < deq.size ());
+
+                got [inx_2] = char ((*i).val_);
+            }
+
+            got [deq.size ()] = '\0';
+
+            rw_assert (false, 0, line,
+                       "line %d: %s: expected %s, got %s\n",
+                       __LINE__, funcall, res, got);
+
+            delete[] got;
+            break;
+        }
+    }
+
+    // set asnlen to the number of elements assigned to the container
+    if (0 <= nelems)
+        asnlen = std::size_t (nelems);
+
+    // verify the complexity of the operation in terms of the number
+    // of calls to the copy ctor and assignment operator on value_type
+
+    // the number of invocations of the copy ctor and the assignment
+    // operator depends on whether the implementation of assign()
+    // strictly follows the requirements in 23.2.1.1, p7 or p8 and
+    // destroys the existing elements before inserting the new ones,
+    // or whether it assigns the new elements over the existing ones
+
+#ifndef _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE
+    const std::size_t expect_copy = seqlen < asnlen ? asnlen - seqlen : 0;
+    const std::size_t expect_asgn = asnlen < seqlen ? asnlen : seqlen;
+#else   // if defined (_RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE)
+    const std::size_t expect_copy = asnlen;
+    const std::size_t expect_asgn = 0;
+#endif   // _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE
+
+    rw_assert (n_copy == int (expect_copy), 0, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::X(const X&), got %d\n",
+               __LINE__, funcall, expect_copy, n_copy);
+
+    rw_assert (n_asgn == int (expect_asgn), 0, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::operator=(const X&), got %d\n",
+               __LINE__, funcall, expect_asgn, n_asgn);
+
+    // Free funcall storage
+    std::free (funcall);
+
+    delete[] xasn;
+    delete[] xseq;
+}
+
+
+template <class Iterator>
+void test_assign_range (const Iterator &it, const char* itname)
+{
+    rw_info (0, 0, 0, "std::deque<X>::assign(%s, %s)", itname, itname);
+
+    static const char seq[] = "abcdefghijklmnopqrstuvwxyz";
+    static const char asn[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    for (std::size_t i = 0; i != sizeof seq - 1; ++i) {
+        for (std::size_t j = 0; j != sizeof asn - 1; ++j) {
+
+            test_assign (__LINE__, 0, it, -1, seq, i, asn, j, asn, j);
+        }
+    }
+}
+
+
+void test_assign ()
+{
+    //////////////////////////////////////////////////////////////////
+    // exercise
+    //   deque::assign(size_type, const_reference)
+
+    rw_info (0, 0, 0, "std::deque<X>::assign(size_type, const_reference)");
+
+    static const char seq[] = "abcdefghijklmnopqrstuvwxyz";
+    static const char res[] = "AAAAAAAAAAAAAAAAAAAAAAAAAA";
+
+    for (std::size_t i = 0; i != sizeof seq - 1; ++i) {
+        for (std::size_t j = 0; j != sizeof seq - 1; ++j) {
+
+            test_assign (__LINE__, -1, (X*)0, int (j), seq, i, res, 1U, res, j);
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // exercise
+    //   template <class InputIterator>
+    //   deque::assign(InputIterator, InputIterator)
+
+    rw_info (0, 0, 0, 
+             "template <class InputIterator> "
+             "std::deque<X>::assign(InputIterator, InputIterator)");
+
+    if (0 == rw_opt_no_input_iterator)
+        test_assign_range (InputIter<X>(0, 0, 0), "InputIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::assign(T, T) [with T = InputIterator]"
+                 "test disabled.");
+
+    if (0 == rw_opt_no_forward_iterator)
+        test_assign_range (FwdIter<X>(), "FwdIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::assign(T, T) [with T = ForwardIterator]"
+                 "test disabled.");
+
+    if (0 == rw_opt_no_bidirectional_iterator)
+        test_assign_range (BidirIter<X>(), "BidirIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::assign(T, T) [with T = BidirectionalIterator]"
+                 "test disabled.");
+
+    if (0 == rw_opt_no_random_iterator)
+        test_assign_range (RandomAccessIter<X>(), "RandomAccessIter<X>");
+    else 
+        rw_note (0, 0, __LINE__, 
+                 "template <class T> "
+                 "std::deque<X>::assign(T, T) [with T = RandomAccessIterator]"
+                 "test disabled.");
+}
+
+/**************************************************************************/
+
+void test_erase (int line,
+                 const char *seq, std::size_t seqlen,
+                 std::size_t begoff, std::size_t len,
+                 const char *res, std::size_t reslen)
+{
+    const X* const xseq = X::from_char (seq, seqlen + 1);
+
+    Deque deq = seqlen ? Deque (xseq, xseq + seqlen) : Deque ();
+    const Deque::iterator start = deq.begin () + begoff;
+ 
+    int n_copy = X::n_total_copy_ctor_;
+    int n_asgn = X::n_total_op_assign_;
+
+    char* funcall = 0;
+    std::size_t buflen = 0;
+
+    if (std::size_t (-1) == len) {   // erase(iterator)
+
+        rw_asnprintf (&funcall, &buflen,
+                      "deque(\"%{X=*.*}\").erase(%{?}end()%{:}"
+                      "%{?}begin () + %zu%{:}begin ()%{;}%{;}",
+                      seqlen, -1, xseq,
+                      begoff == deq.size (), begoff, begoff);
+        
+        exception_loop (line, Erase_1, funcall, 0,
+                        deq, start, 1, 0, (X*)0, (X*)0,
+                        &n_copy, &n_asgn);
+    }
+    else {   // assign(size_type, const_reference)
+
+        const Deque::iterator end = start + len;
+
+        rw_asnprintf (&funcall, &buflen,
+                      "deque(\"%{X=*.*}\").erase(%{?}end()%{:}"
+                      "%{?}begin () + %zu%{:}begin ()%{;}%{;}"
+                      "%{?})%{:}%{?}, end ())%{:}%{?}, begin ())"
+                      "%{:}begin () + %zu%{;}%{;}%{;}",
+                      seqlen, -1, xseq,
+                      begoff == deq.size (), begoff, begoff,
+                      std::size_t (-1) == len,
+                      end == deq.end (),
+                      end == deq.begin (),
+                      end - deq.begin ());
+        
+        exception_loop (line, EraseRange, funcall, 0,
+                        deq, start, len, 0, (X*)0, (X*)0,
+                        &n_copy, &n_asgn);
+
+    }
+
+    // verify the expected size of the deque after erasure
+    rw_assert (deq.size () == reslen, 0, line,
+               "line %d: %s: size == %zu, got %zu\n",
+               __LINE__, funcall, reslen, deq.size ());
+
+    // verify the expected contents of the deque after assignment
+    const Deque::const_iterator resbeg = deq.begin ();
+    const Deque::const_iterator resend = deq.end ();
+
+    for (Deque::const_iterator it = resbeg; it != resend; ++it) {
+        if ((*it).val_ != UChar (res [it - resbeg])) {
+
+            char* const got = new char [deq.size () + 1];
+
+            for (Deque::const_iterator i = resbeg; i != resend; ++i) {
+                got [i - resbeg] = char ((*i).val_);
+            }
+
+            got [deq.size ()] = '\0';
+
+            rw_assert (false, 0, line,
+                       "line %d: %s: expected %s, got %s\n",
+                       __LINE__, funcall, res, got);
+
+            delete[] got;
+            break;
+        }
+    }
+
+#if 0
+    // set asnlen to the number of elements assigned to the container
+    if (0 <= nelems)
+        asnlen = std::size_t (nelems);
+
+    // verify the complexity of the operation in terms of the number
+    // of calls to the copy ctor and assignment operator on value_type
+
+    // the number of invocations of the copy ctor and the assignment
+    // operator depends on whether the implementation of assign()
+    // strictly follows the requirements in 23.2.1.1, p7 or p8 and
+    // destroys the existing elements before inserting the new ones,
+    // or whether it assigns the new elements over the existing ones
+
+#ifndef _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE
+    const std::size_t expect_copy = seqlen < asnlen ? asnlen - seqlen : 0;
+    const std::size_t expect_asgn = asnlen < seqlen ? asnlen : seqlen;
+#else   // if defined (_RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE)
+    const std::size_t expect_copy = asnlen;
+    const std::size_t expect_asgn = 0;
+#endif   // _RWSTD_NO_EXT_DEQUE_ASSIGN_IN_PLACE
+
+    rw_assert (n_copy == int (expect_copy), 0, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::X(const X&), got %d\n",
+               __LINE__, funcall, expect_copy, n_copy);
+
+    rw_assert (n_asgn == int (expect_asgn), 0, line,
+               "line %d: %s: expected %zu invocations "
+               "of X::operator=(const X&), got %d\n",
+               __LINE__, funcall, expect_asgn, n_asgn);
+#endif
+
+    std::free (funcall);
+
+    delete[] xseq;
+}
+
+void test_erase ()
+{
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::erase(iterator)
+
+    rw_info (0, 0, 0, "std::deque<X>::erase(iterator)");
+
+#undef TEST
+#define TEST(seq, off, res) do {                        \
+      test_erase (__LINE__,                             \
+                             seq, sizeof seq - 1,       \
+                             std::size_t (off),         \
+                             std::size_t (-1),          \
+                             res, sizeof res - 1);      \
+    } while (0)
+
+    TEST ("a", 0, "");
+
+    TEST ("ab", 0, "b");
+    TEST ("ab", 1, "a");
+
+    TEST ("abc", 0, "bc");
+    TEST ("abc", 1, "ac");
+    TEST ("abc", 2, "ab");
+
+    TEST ("abcd", 0, "bcd");
+    TEST ("abcd", 1, "acd");
+    TEST ("abcd", 2, "abd");
+    TEST ("abcd", 3, "abc");
+
+    TEST ("abcde", 0, "bcde");
+    TEST ("abcde", 1, "acde");
+    TEST ("abcde", 2, "abde");
+    TEST ("abcde", 3, "abce");
+    TEST ("abcde", 4, "abcd");
+
+    TEST ("abcdef", 0, "bcdef");
+    TEST ("abcdef", 1, "acdef");
+    TEST ("abcdef", 2, "abdef");
+    TEST ("abcdef", 3, "abcef");
+    TEST ("abcdef", 4, "abcdf");
+    TEST ("abcdef", 5, "abcde");
+
+    TEST ("abcdefg", 0, "bcdefg");
+    TEST ("abcdefg", 1, "acdefg");
+    TEST ("abcdefg", 2, "abdefg");
+    TEST ("abcdefg", 3, "abcefg");
+    TEST ("abcdefg", 4, "abcdfg");
+    TEST ("abcdefg", 5, "abcdeg");
+    TEST ("abcdefg", 6, "abcdef");
+
+    TEST ("abcdefgh", 0, "bcdefgh");
+    TEST ("abcdefgh", 1, "acdefgh");
+    TEST ("abcdefgh", 2, "abdefgh");
+    TEST ("abcdefgh", 3, "abcefgh");
+    TEST ("abcdefgh", 4, "abcdfgh");
+    TEST ("abcdefgh", 5, "abcdegh");
+    TEST ("abcdefgh", 6, "abcdefh");
+    TEST ("abcdefgh", 7, "abcdefg");
+
+    //////////////////////////////////////////////////////////////////
+    // exercise deque::erase(iterator, iterator)
+
+    rw_info (0, 0, 0, "std::deque<X>::erase(iterator, iterator)");
+}
+
+/**************************************************************************/
+
+#ifndef _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+#  ifndef _RWSTD_NO_EXPLICIT
+#    if !defined (_MSC_VER) || _MSC_VER > 1200
+
+struct DR_438
+{
+    static bool cast_used;
+
+    DR_438 () { }
+
+    explicit DR_438 (std::size_t) { cast_used = true; }
+
+    template <class T> DR_438 (T) { }
+};
+
+bool DR_438::cast_used;
+
+#    else   // if MSVC <= 6.0
+       // avoid an MSVC 6.0 ICE on this code
+#      define NO_DR_438_TEST "this version of MSVC is too broken"
+#    endif   // !MSVC || MSVC > 6.0
+#  else
+#    define NO_DR_438_TEST "_RWSTD_NO_EXPLICIT #defined"
+#  endif   // _RWSTD_NO_EXPLICIT
+#  else
+#    define NO_DR_438_TEST   "_RWSTD_NO_INLINE_MEMBER_TEMPLATES #defined"
+#endif   // _RWSTD_NO_INLINE_MEMBER_TEMPLATES
+
+
+void test_dr_438 ()
+{
+    //////////////////////////////////////////////////////////////////
+    // exercise the resolution of DR 438:
+    //////////////////////////////////////////////////////////////////
+    //
+    // For every sequence defined in clause [lib.containers]
+    // and in clause [lib.strings]:
+
+    // *  If the constructor
+    //
+    //    template <class InputIterator>
+    //    X (InputIterator f, InputIterator l,
+    //       const allocator_type& a = allocator_type())
+    //
+    //    is called with a type InputIterator that does not qualify
+    //    as an input iterator, then the constructor will behave
+    //    as if the overloaded constructor:
+    //
+    //    X (size_type, const value_type& = value_type(),
+    //       const allocator_type& = allocator_type())
+    //
+    //    were called instead, with the arguments static_cast<size_type>(f),
+    //    l and a, respectively.
+    //
+    // *  If the member functions of the forms:
+    //
+    //    template <class InputIterator>       // such as insert()
+    //    rt fx1(iterator p, InputIterator f, InputIterator l);
+    //
+    //    template <class InputIterator>       // such as append(), assign()
+    //    rt fx2(InputIterator f, InputIterator l);
+    //
+    //    template <class InputIterator>        // such as replace()
+    //    rt fx3(iterator i1, iterator i2, InputIterator f, InputIterator l);
+    //
+    //    are called with a type InputIterator that does not qualify
+    //    as an input iterator, then these functions will behave
+    //    as if the overloaded member functions:
+    //
+    //    rt fx1(iterator, size_type, const value_type&);
+    //
+    //    rt fx2(size_type, const value_type&);
+    //
+    //    rt fx3(iterator, iterator, size_type, const value_type&);
+    //
+    //    were called instead, with the same arguments.
+    //
+    // In the previous paragraph the alternative binding will fail
+    // if f is not implicitly convertible to X::size_type or
+    // if l is not implicitly convertible to X::value_type.
+    //
+    // The extent to which an implementation determines that a type
+    // cannot be an input iterator is unspecified, except that
+    // as a minimum integral types shall not qualify as input iterators.
+    //////////////////////////////////////////////////////////////////
+
+    rw_info (0, 0, 0, "resolution of DR 438");
+
+#ifndef NO_DR_438_TEST
+
+    std::deque<DR_438, std::allocator<DR_438> > dq;
+
+    dq.assign (1, 2);
+
+    rw_assert (!DR_438::cast_used, 0, __LINE__,
+               "deque::assign(InputIterator, InputIterator)"
+               "[ with InputIterator = <integral type> ] unexpectedly "
+               "used explicit argument conversion");
+    
+    dq.insert (dq.begin (), 1, 2);
+
+    rw_assert (!DR_438::cast_used, 0, __LINE__,
+               "deque::insert(iterator, InputIterator, InputIterator) "
+               "[ with InputIterator = <integral type> ] unexpectedly "
+               "used explicit argument conversion");
+#else   // if defined (NO_DR_438_TEST)
+
+    rw_warning (0, 0, __LINE__, "%s; skipping test", NO_DR_438_TEST);
+
+#endif   // NO_DR_438_TEST
+
+}
+
+/**************************************************************************/
+
+int run_test (int, char**)
+{
+    if (0 == rw_opt_no_dr438)
+        test_dr_438 ();
+
+    static const std::size_t caps[] = {
+        2, 3, 4, 5, 16, 32
+    };
+
+    for (std::size_t i = 0; i != sizeof caps / sizeof *caps; ++i) {
+
+        new_capacity = caps [i];
+
+        rw_info (0, 0, 0, 
+                 "__rw::__rw_new_capacity<std::deque<X> >(0) = %zu",
+                 _RW::__rw_new_capacity (0, (Deque*)0));
+
+        if (0 == rw_opt_no_assign)
+            test_assign ();
+        
+        if (0 == rw_opt_no_erase)
+            test_erase ();
+        
+        if (0 == rw_opt_no_insert)
+            test_insert ();
+    }
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char** argv)
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.deque.modifiers",
+                    0 /* no comment */, run_test,
+                    "|-no-dr438#"
+                    "|-no-assign#"
+                    "|-no-erase#"
+                    "|-no-insert#"
+                    "|-no-InputIterator#"
+                    "|-no-ForwardIterator#"
+                    "|-no-BidirectionalIterator#"
+                    "|-no-RandomIterator#"
+                    "|-no-right-thing#",
+                    &rw_opt_no_dr438,
+                    &rw_opt_no_assign,
+                    &rw_opt_no_erase,
+                    &rw_opt_no_insert,
+                    &rw_opt_no_input_iterator,
+                    &rw_opt_no_forward_iterator,
+                    &rw_opt_no_bidirectional_iterator,
+                    &rw_opt_no_random_iterator,
+                    &rw_opt_no_right_thing);
+}

Propchange: incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/containers/23.deque.modifiers.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp?rev=372607&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp (added)
+++ incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp Thu Jan 26 12:56:15 2006
@@ -0,0 +1,271 @@
+/***************************************************************************
+ *
+ * 23.deque.special.cpp - test exercising [lib.deque.special]
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. 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 <deque>        // for deque
+
+#include <cstddef>      // for size_t
+
+#include <alg_test.h>   // for X
+#include <driver.h>     // for rw_test(), ...
+
+/**************************************************************************/
+
+struct DequeValueType { };
+
+typedef std::allocator<DequeValueType>             DequeAllocator;
+typedef std::deque<DequeValueType, DequeAllocator> DequeType;
+
+
+int deque_swap_called;
+
+_RWSTD_NAMESPACE (std) {
+
+// define an explicit specialization of the deque::swap() member
+// to verify tha the non-member swap function calls the member
+
+_RWSTD_SPECIALIZED_FUNCTION
+void DequeType::swap (DequeType&)
+{
+    ++deque_swap_called;
+}
+
+}   // namespace std
+
+/**************************************************************************/
+
+void test_std_swap ()
+{
+    rw_info (0, 0, 0, 
+             "Testing std::swap (std::deque&, std::deque&) "
+             "calls std::deque::swap");
+
+    // verify the signature of the function specialization
+    void (*pswap)(DequeType&, DequeType&) =
+        &std::swap<DequeValueType, DequeAllocator>;
+
+    _RWSTD_UNUSED (pswap);
+
+    // verify that std::swap() calls std::deque::swap()
+    DequeType d;
+
+    std::swap (d, d);
+
+    rw_assert (1 == deque_swap_called, 0, __LINE__,
+               "std::swap (std::deque<T, A>&, std::deque<T, A>&) called "
+               "std::deque<T, A>::swap (std::deque<T, A>&) exactly once; "
+               "got %d times", deque_swap_called);
+}
+
+/**************************************************************************/
+
+typedef std::deque<X, std::allocator<X> > Deque;
+
+Deque::size_type new_capacity;
+
+namespace __rw {
+
+_RWSTD_SPECIALIZED_FUNCTION
+inline Deque::size_type
+__rw_new_capacity<Deque>(Deque::size_type n, const Deque*)
+{
+    if (n) {
+        // non-zero size argument indicates a request for an increase
+        // in the capacity of a deque object's dynamically sizable
+        // vector of nodes
+        return n * 2;
+    }
+
+    // zero size argument is a request for the initial size of a deque
+    // object's dynamically sizable vector of nodes or for the size of
+    // the objects's fixed-size buffer for elements
+    return new_capacity;
+}
+
+}
+
+/**************************************************************************/
+
+template <class T, class Allocator>
+void test_swap (const T *lhs_seq, std::size_t lhs_seq_len,
+                const T *rhs_seq, std::size_t rhs_seq_len,
+                std::deque<T, Allocator>*,
+                const char *tname)
+{
+    typedef std::deque<T, Allocator>  Deque;
+    typedef typename Deque::iterator  Iterator;
+    typedef typename Deque::size_type SizeType;
+
+    // create two containers from the provided sequences
+    Deque lhs (lhs_seq, lhs_seq + lhs_seq_len);
+    Deque rhs (rhs_seq, rhs_seq + rhs_seq_len);
+
+    // save the begin and and iterators and the size
+    // of each container before swapping the objects
+    const Iterator lhs_begin_0 = lhs.begin ();
+    const Iterator lhs_end_0   = lhs.end ();
+    const SizeType lhs_size_0  = lhs.size ();
+
+    const Iterator rhs_begin_0 = rhs.begin ();
+    const Iterator rhs_end_0   = rhs.end ();
+    const SizeType rhs_size_0  = rhs.size ();
+
+    // swap the two containers
+    lhs.swap (rhs);
+
+    // compute the begin and and iterators and the size
+    // of each container after swapping the objects
+    const Iterator lhs_begin_1 = lhs.begin ();
+    const Iterator lhs_end_1   = lhs.end ();
+    const SizeType lhs_size_1  = lhs.size ();
+
+    const Iterator rhs_begin_1 = rhs.begin ();
+    const Iterator rhs_end_1   = rhs.end ();
+    const SizeType rhs_size_1  = rhs.size ();
+
+    // verify that the iterators and sizes
+    // of the two objects were swapped
+    rw_assert (lhs_begin_0 == rhs_begin_1 && lhs_begin_1 == rhs_begin_0, 
+               0, __LINE__,
+               "begin() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"",
+               int (lhs_seq_len), -1, lhs_seq,
+               int (rhs_seq_len), -1, rhs_seq);
+
+    rw_assert (lhs_end_0 == rhs_end_1 && lhs_end_1 == rhs_end_0, 
+               0, __LINE__,
+               "end() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"",
+               int (lhs_seq_len), -1, lhs_seq,
+               int (rhs_seq_len), -1, rhs_seq);
+
+    rw_assert (lhs_size_0 == rhs_size_1 && lhs_size_1 == rhs_size_0, 
+               0, __LINE__,
+               "size() not swapped for \"%{X=*.*}\" and \"%{X=*.*}\"",
+               int (lhs_seq_len), -1, lhs_seq,
+               int (rhs_seq_len), -1, rhs_seq);
+
+    // swap one of the containers with an empty unnamed temporary
+    // container and verify that the object is empty
+    { Deque ().swap (lhs); }
+
+    const Iterator lhs_begin_2 = lhs.begin ();
+    const Iterator lhs_end_2   = lhs.end ();
+    const SizeType lhs_size_2  = lhs.size ();
+
+    rw_assert (lhs_begin_2 == lhs_end_2, 0, __LINE__,
+               "deque<%s>().begin() not swapped for \"%{X=*.*}\"",
+               tname, int (rhs_seq_len), -1, rhs_seq);
+
+    rw_assert (0 == lhs_size_2, 0, __LINE__,
+               "deque<%s>().size() not swapped for \"%{X=*.*}\"",
+               tname, int (rhs_seq_len), -1, rhs_seq);
+}
+
+
+template <class T>
+void test_swap (const T*, const char* tname)
+{
+    rw_info (0, 0, 0, 
+             "std::deque<%s>::swap(deque<%1$s>&)", tname);
+
+    typedef std::deque<T, std::allocator<T> > MyDeque;
+    typedef typename MyDeque::iterator        Iterator;
+
+    // create two empty deque objects
+    MyDeque empty [2];
+
+    // save their begin and end iterators before calling swap
+    const Iterator before [2][2] = {
+        { empty [0].begin (), empty [0].end () },
+        { empty [1].begin (), empty [1].end () }
+    };
+
+    // swap the two containers
+    empty [0].swap (empty [1]);
+
+    // get the new begin and end iterators
+    const Iterator after [2][2] = {
+        { empty [0].begin (), empty [0].end () },
+        { empty [1].begin (), empty [1].end () }
+    };
+
+    // verify that the iterators have not been invalidated
+    rw_assert (   before [0][0] == after [1][0] 
+               && before [1][0] == after [0][0], 0, __LINE__, 
+               "deque<%s>().begin() not swapped", tname);
+    
+    rw_assert (   before [0][1] == after [1][1] 
+               && before [1][1] == after [0][1], 0, __LINE__, 
+               "deque<%s>().end() not swapped", tname);
+
+    // static to zero-initialize if T is a POD type
+    static T seq [32];
+
+    const std::size_t seq_len = sizeof seq / sizeof *seq;
+
+    for (std::size_t i = 0; i != seq_len; ++i) {
+        for (std::size_t j = 0; j != seq_len; ++j) {
+            test_swap (seq, i, seq, j, (MyDeque*)0, tname);
+        }
+    }
+}
+
+/**************************************************************************/
+
+void test_swap ()
+{
+    test_swap ((int*)0, "int");
+    test_swap ((X*)0, "X");
+}
+
+/**************************************************************************/
+
+int run_test (int, char**)
+{
+    // Test std::swap calling std::deque::swap
+    test_std_swap ();
+
+    static const Deque::size_type caps[] = {
+        2, 3, 4, 5, 16, 32
+    };
+
+    for (std::size_t i = 0; i != sizeof caps / sizeof *caps; ++i) {
+
+        new_capacity = caps [i];
+
+        rw_info (0, 0, 0, 
+                 "__rw::__rw_new_capacity<std::deque<X> >(0) = %u",
+                 _RW::__rw_new_capacity (0, (Deque*)0));
+
+        test_swap ();
+    }
+
+    return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char** argv)
+{
+    return rw_test (argc, argv, __FILE__,
+                    "lib.deque.special",
+                    0 /* no comment */,
+                    run_test,
+                    0 /* co command line options */);
+}

Propchange: incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/containers/23.deque.special.cpp
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message