stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From far...@apache.org
Subject svn commit: r511015 - in /incubator/stdcxx/trunk/tests: include/21.strings.h include/23.containers.h src/23.containers.cpp
Date Fri, 23 Feb 2007 16:57:55 GMT
Author: faridz
Date: Fri Feb 23 08:57:54 2007
New Revision: 511015

URL: http://svn.apache.org/viewvc?view=rev&rev=511015
Log:
2007-02-23 Farid Zaripov <faridz@kyiv.vdiweb.com>

	ChangeLog:
	* 21.strings.h: #included 23.containers.h;
	struct StringIds inherited from struct ContainerIds;
	removed definitions of the AllocId and IteratorId.
	* 23.containers.h: New file with definitions of helpers used
	in clause 23 tests.
	* 23.containers.cpp: Ditto.

Added:
    incubator/stdcxx/trunk/tests/include/23.containers.h   (with props)
    incubator/stdcxx/trunk/tests/src/23.containers.cpp   (with props)
Modified:
    incubator/stdcxx/trunk/tests/include/21.strings.h

Modified: incubator/stdcxx/trunk/tests/include/21.strings.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/21.strings.h?view=diff&rev=511015&r1=511014&r2=511015
==============================================================================
--- incubator/stdcxx/trunk/tests/include/21.strings.h (original)
+++ incubator/stdcxx/trunk/tests/include/21.strings.h Fri Feb 23 08:57:54 2007
@@ -29,32 +29,20 @@
 
 #include <rw_char.h>        // for rw_expand()
 #include <testdefs.h>
+#include <23.containers.h>  // for ContainerIds
 
 /**************************************************************************/
 
 // defines enumerations identifying basic_string template arguments,
 // sets of overloaded functions, member types used in the declarations
 // of their signatures, and specific overloads of such member functions
-struct StringIds {
+struct StringIds: ContainerIds {
 
     // identifiers for the charT template argument
     enum CharId { Char, WChar, UChar };
 
     // identifiers for the Traits template argument
     enum TraitsId { DefaultTraits, UserTraits };
-
-    // identifiers for the Allocator template argument
-    enum AllocId { DefaultAlloc, UserAlloc };
-
-    // identifiers for the Iterator template argument
-    // used with meber templates
-    enum IteratorId {
-        None,
-        Input, Forward, Bidir, Random,
-        Pointer, ConstPointer,
-        Iterator, ConstIterator,
-        ReverseIterator, ConstReverseIterator
-    };
 
     // identifies a set of overloaded member or non-member
     // string functions

Added: incubator/stdcxx/trunk/tests/include/23.containers.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/23.containers.h?view=auto&rev=511015
==============================================================================
--- incubator/stdcxx/trunk/tests/include/23.containers.h (added)
+++ incubator/stdcxx/trunk/tests/include/23.containers.h Fri Feb 23 08:57:54 2007
@@ -0,0 +1,406 @@
+/************************************************************************
+*
+* 23.containers.h - definitions of helpers used in clause 23 tests
+*
+* $Id: 23.containers.h
+*
+***************************************************************************
+*
+* Licensed to the Apache Software  Foundation (ASF) under one or more
+* contributor  license agreements.  See  the NOTICE  file distributed
+* with  this  work  for  additional information  regarding  copyright
+* ownership.   The ASF  licenses this  file to  you under  the Apache
+* License, Version  2.0 (the  "License"); you may  not use  this file
+* except in  compliance with the License.   You may obtain  a copy of
+* the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the  License is distributed on an  "AS IS" BASIS,
+* WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+* implied.   See  the License  for  the  specific language  governing
+* permissions and limitations under the License.
+* 
+**************************************************************************/
+
+#ifndef RW_23_CONTAINERS_H_INCLUDED
+#define RW_23_CONTAINERS_H_INCLUDED
+
+#include <testdefs.h>
+#include <rw_value.h>       // for UserClass, UserPOD
+#include <rw_char.h>        // for rw_expand ()
+#include <driver.h>         // for rw_assert ()
+
+/**************************************************************************/
+
+// defines enumerations identifying the general template arguments,
+// sets of overloaded functions, member types used in the declarations
+// of their signatures, and specific overloads of such member functions
+struct ContainerIds {
+
+    // identifiers for the T template argument
+    enum ElemId { UserPOD, UserClass };
+
+    // identifiers for the Allocator template argument
+    enum AllocId { DefaultAlloc, UserAlloc };
+
+    // identifiers for the Iterator template argument
+    // used with member templates
+    enum IteratorId {
+        None,
+        Input, Forward, Bidir, Random,
+        Pointer, ConstPointer,
+        Iterator, ConstIterator,
+        ReverseIterator, ConstReverseIterator
+    };
+
+    enum ContainerId {
+        List, Vector, Deque, Queue, Stack
+    };
+
+    // identifies a set of overloaded member or non-member
+    // container functions
+    enum FuncId {
+        // 6 bits, 64 functions max
+        // common
+        /*  0 */ fid_ctor,
+        /*  1 */ fid_op_set,
+        /*  2 */ fid_assign,
+        /*  3 */ fid_get_allocator,
+        /*  4 */ fid_begin,
+        /*    */ fid_begin_const = fid_begin,
+        /*  5 */ fid_end,
+        /*    */ fid_end_const = fid_end,
+        /*  6 */ fid_rbegin,
+        /*    */ fid_rbegin_const = fid_rbegin,
+        /*  7 */ fid_rend,
+        /*    */ fid_rend_const = fid_rend,
+        /*  8 */ fid_empty,
+        /*  9 */ fid_size,
+        /* 10 */ fid_max_size,
+        /* 11 */ fid_resize,
+        /* 12 */ fid_insert,
+        /* 13 */ fid_erase,
+        /* 14 */ fid_swap,
+        /* 15 */ fid_clear,
+        /* 16 */ fid_op_equal,
+        /* 17 */ fid_op_less,
+        /* 18 */ fid_op_not_equal,
+        /* 19 */ fid_op_greater,
+        /* 20 */ fid_op_greater_equal,
+        /* 21 */ fid_op_less_equal,
+        /* 22 */ fid_push_back,
+
+        // list, deque, vector
+        /* 23 */ fid_front,
+        /*    */ fid_front_const = fid_front,
+        /* 24 */ fid_back,
+        /*    */ fid_back_const = fid_back,
+        /* 25 */ fid_pop_back,
+
+        // list, deque
+        /* 26 */ fid_push_front,
+        /* 27 */ fid_pop_front,
+
+        // list
+        /* 28 */ fid_splice,
+        /* 29 */ fid_remove,
+        /* 30 */ fid_remove_if,
+        /* 31 */ fid_unique,
+        /* 32 */ fid_merge,
+        /* 33 */ fid_sort,
+        /* 34 */ fid_reverse,
+
+        // vector, string, deque
+        /* 35 */ fid_op_index,
+        /*    */ fid_op_index_const = fid_op_index,
+        /* 36 */ fid_at,
+        /*    */ fid_at_const = fid_at,
+
+        // vector, string
+        /* 37 */ fid_capacity,
+        /* 38 */ fid_reserve,
+
+        // vector<bool>
+        /* 39 */ fid_flip,
+
+        /* -- */ fid_bits = 6,
+        /* -- */ fid_mask = 63
+    };
+
+    // identifies the type of a function argument, including
+    // the implicit this
+    enum ArgId {
+        // 4 bits, 16 types max
+        /*  0 */ arg_void,    // void
+        /*  1 */ arg_size,    // size_type
+        /*  2 */ arg_val,     // value_type
+        /*  3 */ arg_ref,     // reference
+        /*  4 */ arg_cref,    // const_reference
+        /*  5 */ arg_iter,    // iterator
+        /*  6 */ arg_citer,   // const_iterator
+        /*  7 */ arg_range,   // Iterator, Iterator
+        /*  8 */ arg_cont,    // container& (or this for member functions)
+        /*  9 */ arg_ccont,   // const container& (or const this for members)
+        /* 10 */ arg_alloc,   // const allocator&
+        /* 11 */ arg_pred,    // Predicate
+        /* 12 */ arg_bpred,   // BinaryPredicate
+        /* 13 */ arg_comp,    // Compare
+        /* -- */ arg_bits = 4,
+        /* -- */ arg_mask = 15
+    };
+
+    enum {
+        // bit designating a member function
+        bit_member = 1 << (fid_bits + 6 * arg_bits)
+    };
+
+    static ArgId arg_type (_RWSTD_SIZE_T id, int argno) {
+        return ArgId (((id >> fid_bits) >> argno * arg_bits) & arg_mask);
+    }
+};
+
+/**************************************************************************/
+
+struct ContainerFunc
+{
+    ContainerIds::ElemId      elem_id_;
+    ContainerIds::AllocId     alloc_id_;
+    ContainerIds::IteratorId  iter_id_;
+    ContainerIds::ContainerId cont_id_;
+    _RWSTD_SIZE_T             which_;
+};
+
+
+// describes a single test case for any overload of any container
+// function (the same test case can be used to exercise more
+// than one overload of the same function)
+struct ContainerTestCase
+{
+    int            line;      // test case line number
+
+    int            off;       // offset (position argument)
+    int            size;      // size (count argument)
+
+    int            off2;      // offset 2 (position argument)
+    int            size2;     // size 2 (count argument)
+
+    int            val;       // value (single character to append)
+
+    const char*    str;       // controlled sequence
+    _RWSTD_SIZE_T  str_len;   // length of sequence
+
+    const char*    arg;       // sequence to insert
+    _RWSTD_SIZE_T  arg_len;   // length of sequence
+
+    const char*    res;       // resulting sequence
+    _RWSTD_SIZE_T  nres;      // length of sequence or expected result value
+
+    int            bthrow;    // exception expected
+};
+
+
+// describes a set of test cases for a single overload of a function
+struct ContainerTest
+{
+    // container function overload to exercise
+    _RWSTD_SIZE_T which;
+
+    // test cases to exercise overload with
+    const ContainerTestCase *cases;
+
+    // number of test cases
+    _RWSTD_SIZE_T case_count;
+};
+
+
+typedef void ContainerTestFunc (const ContainerFunc&, const ContainerTestCase&);
+
+_TEST_EXPORT int
+rw_run_cont_test (int, char**, const char*, const char*,
+                  ContainerIds::ContainerId, ContainerTestFunc*,
+                  const ContainerTest*, _RWSTD_SIZE_T);
+
+typedef void VoidFunc ();
+
+_TEST_EXPORT int
+rw_run_cont_test (int, char**, const char*, const char*,
+                  ContainerIds::ContainerId, VoidFunc* const*,
+                  const ContainerTest*, _RWSTD_SIZE_T);
+
+/**************************************************************************/
+
+template <class T>
+class ContainerTestCaseData
+{
+private:
+
+    // not defined, not copyable, not assignable
+    ContainerTestCaseData (const ContainerTestCaseData&);
+    void operator= (const ContainerTestCaseData&);
+
+    // for convenience
+    typedef _RWSTD_SIZE_T SizeType;
+
+public:
+
+    SizeType strlen_;   // the length of the expanded string
+    SizeType arglen_;   // the length of the expanded argument
+    SizeType reslen_;   // the length of the expanded result
+
+    // the offset and extent (the number of elements) of
+    // the first range into the container object being modified
+    SizeType off1_;
+    SizeType ext1_;
+
+    // the offset and extent (the number of elements) of
+    // the argument of the function call
+    SizeType off2_;
+    SizeType ext2_;
+
+    const T* str_;   // pointer to the expanded string
+    const T* arg_;   // pointer to the expanded argument
+    const T* res_;   // pointer to the expanded result
+
+    const ContainerFunc     &func_;
+    const ContainerTestCase &tcase_;
+
+    // converts the narrow (and possibly) condensed strings to fully
+    // expanded wide character arrays that can be used to construct
+    // container objects
+    ContainerTestCaseData (const ContainerFunc &func,
+                           const ContainerTestCase &tcase)
+        : func_ (func), tcase_ (tcase) {
+
+        char buf [256];
+
+        strlen_ = sizeof (buf);
+        char* str = rw_expand (buf, tcase.str, tcase.str_len, &strlen_);
+        str_ = T::from_char (str, strlen_);
+        if (str != buf)
+            delete[] str;
+
+        arglen_ = sizeof (buf);
+        str = rw_expand (buf, tcase.arg, tcase.arg_len, &arglen_);
+        arg_ = T::from_char (str, arglen_);
+        if (str != buf)
+            delete[] str;
+
+        reslen_ = sizeof (buf);
+        str = rw_expand (buf, tcase.res, tcase.nres, &reslen_);
+        res_ = T::from_char (str, reslen_);
+        if (str != buf)
+            delete[] str;
+
+        // compute the offset and extent of the container object
+        // representing the controlled sequence and the offset
+        // and extent of the argument of the function call
+        const SizeType argl = tcase_.arg ? arglen_ : strlen_;
+
+        off1_ = SizeType (tcase_.off) < strlen_ ?
+            SizeType (tcase_.off) : strlen_;
+
+        ext1_ = off1_ + tcase_.size < strlen_ ?
+            SizeType (tcase_.size) : strlen_ - off1_;
+
+        off2_ = SizeType (tcase_.off2) < argl ?
+            SizeType (tcase_.off2) : argl;
+
+        ext2_ = off2_ + tcase_.size2 < argl ?
+            SizeType (tcase_.size2) : argl - off2_;
+    }
+
+    ~ContainerTestCaseData () {
+        // clean up dynamically allocated memory
+        delete[] str_;
+        delete[] arg_;
+        delete[] res_;
+    }
+};
+
+/**************************************************************************/
+
+// base class-functor for the range template overloads testing
+template <class Cont>
+struct ContRangeBase {
+
+    typedef typename Cont::value_type                 ContVal;
+    typedef typename Cont::iterator                   ContIter;
+    typedef typename Cont::const_iterator             ContConstIter;
+    typedef typename Cont::reverse_iterator           ContRevIter;
+    typedef typename Cont::const_reverse_iterator     ContConstRevIter;
+
+    ContRangeBase () { }
+
+    virtual ~ContRangeBase () { /* silence warnings */ }
+
+    static ContIter
+    begin (Cont &cont, ContIter*) {
+        return cont.begin ();
+    }
+
+    static ContConstIter
+    begin (const Cont &cont, ContConstIter*) {
+        return cont.begin ();
+    }
+
+    static ContRevIter
+    begin (Cont &cont, ContRevIter*) {
+        return cont.rbegin ();
+    }
+
+    static ContConstRevIter
+    begin (const Cont &cont, ContConstRevIter*) {
+        return cont.rbegin ();
+    }
+
+    virtual Cont&
+    operator() (Cont &cont, const ContainerTestCaseData<ContVal>&) const {
+        RW_ASSERT (!"logic error: should be never called");
+        return cont;
+    }
+};
+
+/**************************************************************************/
+
+#  define CONTAINER_TEST_DISPATCH(Alloc, fname, func, tcase)    \
+    if (ContainerIds::UserPOD == func.elem_id_)                 \
+        fname (UserPOD (), (Alloc<UserPOD>*)0, func, tcase);    \
+    else                                                        \
+        fname (UserClass (), (Alloc<UserClass>*)0, func, tcase)
+
+
+#define DEFINE_CONTAINER_TEST_DISPATCH(fname)                             \
+    static void                                                           \
+    fname (const ContainerFunc     &func,                                 \
+           const ContainerTestCase &tcase) {                              \
+        if (ContainerIds::DefaultAlloc == func.alloc_id_) {               \
+            CONTAINER_TEST_DISPATCH (std::allocator, fname, func, tcase); \
+        }                                                                 \
+        else if (ContainerIds::UserAlloc == func.alloc_id_) {             \
+            CONTAINER_TEST_DISPATCH (UserAlloc, fname, func, tcase);      \
+        }                                                                 \
+        else                                                              \
+            RW_ASSERT (!"logic error: bad allocator");                    \
+    } typedef void rw_unused_typedef
+
+
+#define CONTAINER_TFUNC(T, Allocator)         \
+    void (*)(T*, Allocator<T>*,               \
+             const ContainerTestCaseData<T>&)
+
+#define CONTAINER_TFUNC_ADDR(fname, T, Allocator) \
+    (VoidFunc*)(CONTAINER_TFUNC (T, Allocator))   \
+        &fname<T, Allocator<T> >
+
+#define DEFINE_CONTAINER_TEST_FUNCTIONS(fname)                 \
+    static VoidFunc* const fname ## _func_array [] = {         \
+      CONTAINER_TFUNC_ADDR (fname, UserPOD, std::allocator),   \
+      CONTAINER_TFUNC_ADDR (fname, UserPOD, UserAlloc),        \
+                                                               \
+      CONTAINER_TFUNC_ADDR (fname, UserClass, std::allocator), \
+      CONTAINER_TFUNC_ADDR (fname, UserClass, UserAlloc)       \
+    }
+
+#endif   // RW_23_CONTAINERS_H_INCLUDED

Propchange: incubator/stdcxx/trunk/tests/include/23.containers.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/include/23.containers.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: incubator/stdcxx/trunk/tests/src/23.containers.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/23.containers.cpp?view=auto&rev=511015
==============================================================================
--- incubator/stdcxx/trunk/tests/src/23.containers.cpp (added)
+++ incubator/stdcxx/trunk/tests/src/23.containers.cpp Fri Feb 23 08:57:54 2007
@@ -0,0 +1,1180 @@
+/************************************************************************
+*
+* 23.containers.cpp - definitions of helpers used in clause 23 tests
+*
+* $Id: 23.containers.cpp
+*
+***************************************************************************
+*
+* Licensed to the Apache Software  Foundation (ASF) under one or more
+* contributor  license agreements.  See  the NOTICE  file distributed
+* with  this  work  for  additional information  regarding  copyright
+* ownership.   The ASF  licenses this  file to  you under  the Apache
+* License, Version  2.0 (the  "License"); you may  not use  this file
+* except in  compliance with the License.   You may obtain  a copy of
+* the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the  License is distributed on an  "AS IS" BASIS,
+* WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+* implied.   See  the License  for  the  specific language  governing
+* permissions and limitations under the License.
+* 
+**************************************************************************/
+
+// expand _TEST_EXPORT macros
+#define _RWSTD_TEST_SRC
+
+#include <memory>           // for allocator
+
+#include <23.containers.h>
+
+#include <cmdopt.h>         // for rw_enabled()
+#include <rw_allocator.h>   // for UserAlloc
+#include <rw_printf.h>      // for rw_asnprintf()
+
+#include <ctype.h>          // for isdigit()
+#include <stdarg.h>         // for va_arg, ...
+#include <stddef.h>         // for size_t
+#include <stdlib.h>         // for free()
+#include <string.h>         // for strcpy()
+
+/**************************************************************************/
+
+static const char
+_rw_this_file[] = __FILE__;
+
+
+static const char* const
+_rw_elem_names[] = {
+    "UserPOD", "UserClass"
+};
+
+
+static const char* const
+_rw_alloc_names[] = {
+    "allocator", "UserAlloc"
+};
+
+
+static const char* const
+_rw_iter_names[] = {
+    "",
+    "InputIterator", "ForwardIterator", "BidirectionalIterator",
+    "RandomAccessIterator",
+    "pointer", "const_pointer",
+    "iterator", "const_iterator",
+    "reverse_iterator", "const_reverse_iterator"
+};
+
+
+static const char* const
+_rw_cont_names[] = {
+    "list", "vector", "deque", "queue", "stack"
+};
+
+
+// order of elements depends on the values of ContainerIds::FuncId
+static const char* const
+_rw_func_names[] = {
+    0 /* special handling for the ctor */, "operator=", "assign",
+    "get_allocator", "begin", "end", "rbegin", "rend", "empty",
+    "size", "max_size", "resize", "insert", "erase", "swap",
+    "clear", "operator==", "operator<", "operator!=", "operator>",
+    "operator>=", "operator<=", "push_back", "front", "back",
+    "pop_back", "push_front", "pop_front", "splice", "remove",
+    "remove_if", "unique", "merge", "sort", "reverse", "operator[]",
+    "at", "capacity", "reserve", "flip"
+};
+
+/**************************************************************************/
+
+const size_t MAX_OVERLOADS = 32;
+
+// disabled (-1) or explicitly enabled (+1) for each overload
+// of the cont function being tested
+static int
+_rw_opt_func [MAX_OVERLOADS];
+
+// array of tests each exercising a single cont function
+static const ContainerTest*
+_rw_cont_tests;
+
+// size of the array above
+static size_t
+_rw_cont_test_count;
+
+static int
+_rw_opt_elem_types [sizeof _rw_elem_names / sizeof *_rw_elem_names];
+
+static int
+_rw_opt_alloc_types [sizeof _rw_alloc_names / sizeof *_rw_alloc_names];
+
+static int
+_rw_opt_iter_types [sizeof _rw_iter_names / sizeof *_rw_iter_names];
+
+static int
+_rw_opt_no_exceptions;
+
+static int
+_rw_opt_no_exception_safety;
+
+static int
+_rw_opt_self_ref;
+
+/**************************************************************************/
+
+static size_t
+_rw_get_func_inx (size_t fid)
+{
+    size_t inx = _RWSTD_SIZE_MAX;
+
+    for (size_t i = 0; _rw_cont_test_count; ++i) {
+        if (fid == _rw_cont_tests [i].which) {
+            inx = i;
+            break;
+        }
+    }
+
+    RW_ASSERT (inx < _RWSTD_SIZE_MAX);
+
+    return inx;
+}
+
+/**************************************************************************/
+
+static const char*
+_rw_class_name (const ContainerFunc & func)
+{
+    return _rw_cont_names [func.cont_id_];
+}
+
+/**************************************************************************/
+
+// appends the signature of the function specified by which
+// to the provided buffer; when the second argument is null,
+// appends the mnemonic representing the signature, including
+// the name of the function, as specified by the third argument
+static void
+_rw_sigcat (char **pbuf, size_t *pbufsize,
+            const ContainerFunc *func,
+            size_t               which = 0)
+{
+    // for convenience
+    typedef ContainerIds Ids;
+
+    if (func)
+        which = func->which_;
+
+    // determine whether the function is a member function
+    const bool is_member = 0 != (Ids::bit_member & which);
+
+    // get the bitmap describing the function's argument types
+    int argmap = (which & ~Ids::bit_member) >> Ids::fid_bits;
+
+    // determine whether the function is a const member function
+    bool is_const_member =
+        is_member && Ids::arg_ccont == (argmap & Ids::arg_mask);
+
+    // remove the *this argument if the function is a member
+    if (is_member)
+        argmap >>= Ids::arg_bits;
+
+    const char* funcname = 0;
+
+    if (0 == func) {
+        const Ids::FuncId fid = Ids::FuncId (which & ContainerIds::fid_mask);
+
+        switch (fid) {
+            // translate names with funky characters to mnemonics
+        case Ids::fid_ctor:          funcname = "ctor"; break;
+        case Ids::fid_op_index:      funcname = "op_index"; break;
+        case Ids::fid_op_set:        funcname = "op_assign"; break;
+        case Ids::fid_op_equal:      funcname = "op_equal"; break;
+        case Ids::fid_op_less:       funcname = "op_less"; break;
+        case Ids::fid_op_not_equal:  funcname = "op_not_equal"; break;
+        case Ids::fid_op_greater:    funcname = "op_greater"; break;
+        case Ids::fid_op_greater_equal: funcname = "op_greater_equal"; break;
+        case Ids::fid_op_less_equal: funcname = "op_less_equal"; break;
+
+        case Ids::fid_get_allocator:
+        case Ids::fid_empty:
+        case Ids::fid_size:
+        case Ids::fid_max_size:
+            // prevent appending the "_const" bit to the mnemonics
+            // of member functions not overloaded on const
+            is_const_member = false;
+
+            // fall through
+
+        default: {
+            // determine the cont function name (for brief output)
+            const size_t nfuncs =
+                sizeof _rw_func_names / sizeof *_rw_func_names;
+
+            RW_ASSERT (size_t (fid) < nfuncs);
+
+            funcname = _rw_func_names [fid];
+            RW_ASSERT (0 != funcname);
+            break;
+        }
+        }
+    }
+
+    // iterator name for member templates, empty cont for other functions
+    const char* const iname = func ? _rw_iter_names [func->iter_id_] : "";
+
+    rw_asnprintf (pbuf, pbufsize,
+        "%{+}%{?}%s%{?}_const%{;}%{:}%{?}<%s>%{;}(%{;}",
+        0 == func, funcname, is_const_member, 0 != *iname, iname);
+
+    char iname_buf [80];
+    *iname_buf = '\0';
+
+    // iterate through the map of argument types one field at a time
+    // determining and formatting the type of each argument until
+    // void is reached
+    for (size_t argno = 0; argmap; ++argno, argmap >>= Ids::arg_bits) {
+
+        const char* pfx = "";
+        const char* sfx = "";
+
+        const int argtype = argmap & Ids::arg_mask;
+
+        const char* tname = 0;
+
+        if (func) {
+            switch (argtype) {
+            case Ids::arg_size:  tname = "size_type"; break;
+            case Ids::arg_val:   tname = "value_type"; break;
+            case Ids::arg_ref:   tname = "reference"; break;
+            case Ids::arg_cref:  tname = "const_reference"; break;
+            case Ids::arg_iter:  tname = "iterator"; break;
+            case Ids::arg_citer: tname = "const_iterator"; break;
+            case Ids::arg_range:
+                if ('\0' == *iname_buf) {
+                    strcpy (iname_buf, iname);
+                    strcat (iname_buf, ", ");
+                    strcat (iname_buf, iname);
+                }
+                tname = iname_buf;
+                break;
+
+            case Ids::arg_ccont:
+                pfx   = "const ";
+                // fall through
+            case Ids::arg_cont:
+                tname = _rw_class_name (*func);
+                sfx   = "&";
+                break;
+
+            case Ids::arg_alloc: tname = "const allocator_type&"; break;
+            case Ids::arg_pred:  tname = "Predicate"; break;
+            case Ids::arg_bpred: tname = "BinaryPredicate"; break;
+            case Ids::arg_comp:  tname = "Compare"; break;
+            }
+        }
+        else {
+            switch (argtype) {
+            case Ids::arg_size:  tname = "size"; break;
+            case Ids::arg_val:   tname = "val"; break;
+            case Ids::arg_ref:   tname = "ref"; break;
+            case Ids::arg_cref:  tname = "cref"; break;
+            case Ids::arg_iter:  tname = "iter"; break;
+            case Ids::arg_citer: tname = "citer"; break;
+            case Ids::arg_range: tname = "range"; break;
+            case Ids::arg_cont:  tname = "cont"; break;
+            case Ids::arg_ccont: tname = "ccont"; break;
+            case Ids::arg_alloc: tname = "alloc"; break;
+            case Ids::arg_pred:  tname = "pred"; break;
+            case Ids::arg_bpred: tname = "bpred"; break;
+            case Ids::arg_comp:  tname = "comp"; break;
+            }
+        }
+
+        RW_ASSERT (0 != tname);
+
+        if (   0 == func || is_member
+            || Ids::arg_cont != argtype && Ids::arg_ccont != argtype) {
+                // append the name or mnemonic of the argument type
+                rw_asnprintf (pbuf, pbufsize, "%{+}%{?}_%{:}%{?}, %{;}%{;}%s%s%s",
+                    0 == func, 0 < argno, pfx, tname, sfx);
+            }
+        else {
+            // in non-member functions use ${CLASS} to format
+            // the cont argument in order to expand
+            // its template argument cont
+            rw_asnprintf (pbuf, pbufsize,
+                "%{+}%{?}, %{;}%{?}const %{;}%{$CLASS}&",
+                0 < argno, Ids::arg_ccont == argtype);
+
+        }
+    }
+
+    if (func)
+        rw_asnprintf (pbuf, pbufsize, "%{+})%{?} const%{;}", is_const_member);
+}
+
+/**************************************************************************/
+
+// returns the zero-based index of the argument type specified
+// by arg in the function signature given by which
+static int
+_rw_argno (size_t which, int arg)
+{
+    // get the bitmap describing the function's argument types
+    int argmap = (which & ~ContainerIds::bit_member) >> ContainerIds::fid_bits;
+
+    int argno = 0;
+
+    // iterate over argument types looking for the first one
+    // that equals arg
+    for (; argmap; argmap >>= ContainerIds::arg_bits, ++argno) {
+        if ((argmap & ContainerIds::arg_mask) == arg) {
+            return argno;
+        }
+    }
+
+    // return -1 when the function doesn't take an argument
+    // of the specified type
+    return -1;
+}
+
+/**************************************************************************/
+
+// temporary, shuld be defined in 23.list.h
+struct ListIds : ContainerIds
+{
+    enum OverloadId {};
+};
+
+static void
+_rw_list_sigcat (char** pbuf, size_t * pbufsize, ListIds::OverloadId which,
+                 bool self, const char* str, size_t str_len,
+                 const char* arg, size_t arg_len,
+                 const ContainerTestCase &tcase)
+{
+    // temporary empty
+}
+
+/**************************************************************************/
+
+// temporary, should be defined in 23.deque.h
+struct VectorIds : ContainerIds
+{
+    enum OverloadId {};
+};
+
+static void
+_rw_vector_sigcat (char** pbuf, size_t * pbufsize, VectorIds::OverloadId which,
+                   bool self, const char* str, size_t str_len,
+                   const char* arg, size_t arg_len,
+                   const ContainerTestCase &tcase)
+{
+    // temporary empty
+}
+
+/**************************************************************************/
+
+// temporary, should be defined in 23.deque.h
+struct DequeIds : ContainerIds
+{
+    enum OverloadId {};
+};
+
+static void
+_rw_deque_sigcat (char** pbuf, size_t * pbufsize, DequeIds::OverloadId which,
+                  bool self, const char* str, size_t str_len,
+                  const char* arg, size_t arg_len,
+                  const ContainerTestCase &tcase)
+{
+    // temporary empty
+}
+
+/**************************************************************************/
+
+// temporary, should be defined in 23.queue.h
+struct QueueIds : ContainerIds
+{
+    enum OverloadId {};
+};
+
+static void
+_rw_queue_sigcat (char** pbuf, size_t * pbufsize, QueueIds::OverloadId which,
+                  bool self, const char* str, size_t str_len,
+                  const char* arg, size_t arg_len,
+                  const ContainerTestCase &tcase)
+{
+    // temporary empty
+}
+
+/**************************************************************************/
+
+// temporary, should be defined in 23.stack.h
+struct StackIds : ContainerIds
+{
+    enum OverloadId {};
+};
+
+static void
+_rw_stack_sigcat (char** pbuf, size_t * pbufsize, StackIds::OverloadId which,
+                  bool self, const char* str, size_t str_len,
+                  const char* arg, size_t arg_len,
+                  const ContainerTestCase &tcase)
+{
+    // temporary empty
+}
+
+/**************************************************************************/
+
+// sets the {CLASS}, {FUNC}, {FUNCSIG}, and optionally {FUNCALL}
+// environment variables as follows:
+// CLASS:   the name of cont specialization
+// FUNC:    the name of the cont function
+// FUNCSIG: the name and signature of a specific overload
+//          of the cont function
+// FUNCALL: a cont describing the call to the cont function
+//          with function with function arguments expanded (as specified
+//          by the TestCase argument)
+static void
+_rw_setvars (const ContainerFunc     &func,
+             const ContainerTestCase *pcase = 0)
+{
+    char*  buf     = 0;
+    size_t bufsize = 0;
+
+    const char* const class_name = _rw_class_name (func);
+
+    if (0 == pcase) {
+        // set the {Elem}, {Allocator}, {Iterator} and {Container}
+        // environment variables to the name of the element type
+        // and the Allocator and Iterator and Container specializations
+        rw_fprintf (0, "%{$Elem!:*}", _rw_elem_names [func.elem_id_]);
+
+        rw_fprintf (0, "%{$Allocator!:*}", _rw_alloc_names [func.alloc_id_]);
+
+        rw_fprintf (0, "%{$Iterator!:*}", _rw_iter_names [func.iter_id_]);
+
+        rw_fprintf (0, "%{$Container!:*}", class_name);
+
+        // set the {CLASS}, {FUNC}, and {FUNCSIG} environment variables
+        // to the name of the specialization of the template, the name
+        // of the container function, and the name of the overload of the
+        // container function, respectively, when no test case is given
+
+        // format container specializations, leaving out the name
+        // of the default allocator for brevity
+        rw_asnprintf (&buf, &bufsize,
+                      "std::%s<%s%{?}, %s<%2$s>%{;}>",
+                      class_name,
+                      _rw_elem_names [func.elem_id_],
+                      ContainerIds::DefaultAlloc != func.alloc_id_,
+                      _rw_alloc_names [func.alloc_id_]);
+
+        // set the {CLASS} variable to the name of the specialization
+        // of container
+        rw_fprintf (0, "%{$CLASS!:*}", buf);
+        free (buf);
+        buf     = 0;
+        bufsize = 0;
+
+        // determine the container function name
+        const size_t funcinx = func.which_ & ContainerIds::fid_mask;
+        const size_t nfuncs =  sizeof _rw_func_names / sizeof *_rw_func_names;
+
+        RW_ASSERT (funcinx < nfuncs);
+
+        // get the undecorated function name; ctors are treated
+        // specially so that we can have string, wstring, or
+        // cont, depending on the template arguments
+        const char* const funcname = _rw_func_names [funcinx] ?
+            _rw_func_names [funcinx] : class_name;
+
+        // determine whether the function is a member function
+        const bool is_member = 0 != (func.which_ & ContainerIds::bit_member);
+
+        // set the {FUNC} variable to the unqualified/undecorated
+        // name of the container function (member or otherwise)
+        rw_asnprintf (&buf, &bufsize, "%{?}std::%{;}%s",
+            !is_member, funcname);
+
+        rw_fprintf (0, "%{$FUNC!:*}", buf);
+
+        // append the function signature
+        _rw_sigcat (&buf, &bufsize, &func);
+
+        rw_fprintf (0, "%{$FUNCSIG!:*}", buf);
+        free (buf);
+
+        return;
+    }
+
+    // do the function call arguments reference *this?
+    const bool self = 0 == pcase->arg;
+
+    char str_buf [256];
+    char arg_buf [256];
+
+    char *str;
+    char *arg;
+
+    size_t str_len = sizeof str_buf;
+    size_t arg_len = sizeof arg_buf;
+
+    if (pcase->str)
+        str = rw_expand (str_buf, pcase->str, pcase->str_len, &str_len);
+    else
+        str = 0;
+
+    if (pcase->arg)
+        arg = rw_expand (arg_buf, pcase->arg, pcase->arg_len, &arg_len);
+    else
+        arg = 0;
+
+    // determine whether the function is a member function
+    const bool is_member = 0 != (func.which_ & ContainerIds::bit_member);
+
+    // determine whether the function is a ctor
+    bool is_ctor = ContainerIds::fid_ctor == (func.which_ & ContainerIds::fid_mask);
+
+    if (is_ctor) {
+        // for ctors append just the class name here
+        // the class name will inserted below during argument
+        // formatting
+        rw_asnprintf (&buf, &bufsize, "%{$CLASS}::%s", class_name);
+    }
+    else if (is_member) {
+        // for other members append the ctor argument(s) followed
+        // by the cont member function name
+        rw_asnprintf (&buf, &bufsize,
+                      "%{$CLASS} (%{?}%{#*s}%{;}).%{$FUNC}",
+                      str != 0, int (str_len), str);
+    }
+    else {
+        // for non-members append just the function name here
+        // the class name will inserted below during argument
+        // formatting
+        rw_asnprintf (&buf, &bufsize, "%{$FUNC}");
+    }
+
+    // format and append container function arguments abbreviating complex
+    // expressions as much as possible to make them easy to understand
+    switch (func.cont_id_) {
+
+    case ContainerIds::List:
+        _rw_list_sigcat (&buf, &bufsize,
+            _RWSTD_STATIC_CAST (ListIds::OverloadId, func.which_),
+            self, str, str_len, arg, arg_len, *pcase);
+        break;
+
+    case ContainerIds::Vector:
+        _rw_vector_sigcat (&buf, &bufsize,
+            _RWSTD_STATIC_CAST (VectorIds::OverloadId, func.which_),
+            self, str, str_len, arg, arg_len, *pcase);
+        break;
+
+    case ContainerIds::Deque:
+        _rw_deque_sigcat (&buf, &bufsize,
+            _RWSTD_STATIC_CAST (DequeIds::OverloadId, func.which_),
+            self, str, str_len, arg, arg_len, *pcase);
+        break;
+
+    case ContainerIds::Queue:
+        _rw_queue_sigcat (&buf, &bufsize,
+            _RWSTD_STATIC_CAST (QueueIds::OverloadId, func.which_),
+            self, str, str_len, arg, arg_len, *pcase);
+        break;
+
+    case ContainerIds::Stack:
+        _rw_stack_sigcat (&buf, &bufsize,
+            _RWSTD_STATIC_CAST (StackIds::OverloadId, func.which_),
+            self, str, str_len, arg, arg_len, *pcase);
+        break;
+
+    default:
+        RW_ASSERT (!"unknown container id");
+    }
+
+    rw_fprintf (0, "%{$FUNCALL!:*}", buf);
+    free (buf);
+
+    if (str != str_buf)
+        delete[] str;
+
+    if (arg != arg_buf)
+        delete[] arg;
+}
+
+/**************************************************************************/
+
+// helper function to reverse substring in the resulting sequence
+_RWSTD_INTERNAL ContainerTestCase
+_rw_reverse_results (const ContainerTestCase &tsrc,
+                     size_t off, size_t ext)
+{
+    // expand expected results
+    size_t res_len = 0;
+    char* const new_res = rw_expand ((char*)0, tsrc.res, tsrc.nres, &res_len);
+
+    // reverse them
+    const size_t res_off = off;
+    const size_t res_ext = (ext < res_len ? ext : res_len) - 1;
+
+    char* beg = new_res + res_off;
+    char* end = beg + res_ext;
+
+    for (; beg < end; ++beg, --end) {
+        const char tmp = *beg;
+        *beg = *end;
+        *end = tmp;
+    }
+
+    // form new test case
+    const ContainerTestCase new_case = {
+        tsrc.line, tsrc.off, tsrc.size, tsrc.off2,
+        tsrc.size2, tsrc.val, tsrc.str, tsrc.str_len,
+        tsrc.arg, tsrc.arg_len, new_res, res_len, tsrc.bthrow
+    };
+
+    return new_case;
+}
+
+
+template <class T, class Allocator>
+void
+_rw_dispatch (T*, Allocator*,
+              VoidFunc* const    *farray,
+              const ContainerFunc     &func,
+              const ContainerTestCase &tcase)
+{
+    typedef ContainerTestCaseData<T> Data;
+    typedef void TestFunc (T*, Allocator*, const Data&);
+
+    const size_t inx = func.elem_id_ * 2 + func.alloc_id_;
+
+    TestFunc* const tfunc = _RWSTD_REINTERPRET_CAST (TestFunc*, farray [inx]);
+
+    if (0 == tfunc) {
+        rw_error (0, __FILE__, __LINE__,
+                  "logic error: null test function for %{$FUNCSIG}");
+        return;
+    }
+
+    const bool reverse_iter =
+           ContainerIds::ReverseIterator      == func.iter_id_ 
+        || ContainerIds::ConstReverseIterator == func.iter_id_;
+
+    const Data tdata (func, tcase);
+
+    if (reverse_iter) {
+        // special processing for reverse iterators
+
+        const size_t func_id = tdata.func_.which_ & ContainerIds::fid_mask;
+
+        const bool like_ctor =
+               ContainerIds::fid_ctor   == func_id 
+            || ContainerIds::fid_assign == func_id;
+
+        // ctor and assignment operator require the full container reverse
+        const size_t off = like_ctor ? 0 : tdata.off1_;
+        const size_t ext = like_ctor ? tdata.reslen_ : tdata.ext2_;
+
+        const ContainerTestCase rev_tcase =
+            _rw_reverse_results (tcase, off, ext);
+
+        const Data rev_tdata (func, rev_tcase);
+
+        tfunc ((T*)0, (Allocator*)0, rev_tdata);
+
+        // clean up allocated memory, if any
+        delete[] rev_tcase.res;
+    }
+    else
+        tfunc ((T*)0, (Allocator*)0, tdata);
+}
+
+
+template <class T>
+void
+_rw_dispatch (T*,
+              VoidFunc* const    *farray,
+              const ContainerFunc     &func,
+              const ContainerTestCase &tcase)
+{
+    if (ContainerIds::DefaultAlloc == func.alloc_id_) {
+        typedef std::allocator<T> Alloc;
+        _rw_dispatch ((T*)0, (Alloc*)0, farray, func, tcase);
+    }
+    else if (ContainerIds::UserAlloc == func.alloc_id_) {
+        typedef UserAlloc<T> Alloc;
+        _rw_dispatch ((T*)0, (Alloc*)0, farray, func, tcase);
+    }
+    else {
+        RW_ASSERT (!"logic error: unknown Allocator argument");
+    }
+}
+
+
+static void
+_rw_dispatch (VoidFunc* const    *farray,
+              const ContainerFunc     &func,
+              const ContainerTestCase &tcase)
+{
+    if (ContainerIds::UserPOD == func.elem_id_) {
+        _rw_dispatch ((UserPOD*)0, farray, func, tcase);
+    }
+    else if (ContainerIds::UserClass == func.elem_id_) {
+        _rw_dispatch ((UserClass*)0, farray, func, tcase);
+    }
+    else {
+        RW_ASSERT (!"logic error: unknown T argument");
+    }
+}
+
+/**************************************************************************/
+
+// exercise a single test case for the given function
+static void
+_rw_test_case (const ContainerFunc     &func,
+               const ContainerTestCase &tcase,
+               ContainerTestFunc       *test_callback,
+               VoidFunc* const         *farray)
+{
+    // check to see if this is an exception safety test case
+    // and avoid running it when exception safety has been
+    // disabled via a command line option
+    if (-1 == tcase.bthrow && _rw_opt_no_exception_safety) {
+
+        // issue only the first note
+        rw_note (1 < _rw_opt_no_exception_safety++, _rw_this_file, __LINE__,
+            "exception safety tests disabled");
+        return;
+    }
+
+    // check to see if this is a test case that involves the throwing
+    // of an exception and avoid running it when exceptions have been
+    // disabled
+    if (tcase.bthrow && _rw_opt_no_exceptions) {
+
+        // issue only the first note
+        rw_note (1 < _rw_opt_no_exceptions++, _rw_this_file, __LINE__,
+                 "exception tests disabled");
+        return;
+    }
+
+    const bool self_ref = 0 == tcase.arg;
+
+    // check for tests exercising self-referential modifications
+    // (e.g., insert(1, *this))
+    if (_rw_opt_self_ref < 0 && self_ref) {
+        // issue only the first note
+        rw_note (0, _rw_this_file, tcase.line,
+                 "self-referential test disabled");
+        return;
+    }
+    else if (0 < _rw_opt_self_ref && !self_ref) {
+        // issue only the first note
+        rw_note (0, _rw_this_file, tcase.line,
+                 "non-self-referential test disabled");
+        return;
+    }
+
+    // check to see if the test case is enabled
+    if (rw_enabled (tcase.line)) {
+
+        // set the {FUNCALL} environment variable to describe
+        // the function call specified by this test case
+        _rw_setvars (func, &tcase);
+
+        if (test_callback) {
+            // invoke the test callback function
+            test_callback (func, tcase);
+        }
+        else {
+            _rw_dispatch (farray, func, tcase);
+        }
+    }
+    else
+        rw_note (0, _rw_this_file, tcase.line,
+                 "test on line %d disabled", tcase.line);
+}
+
+/**************************************************************************/
+
+static ContainerIds::ContainerId
+_rw_container_id;
+
+static ContainerTestFunc*
+_rw_test_callback;
+
+
+static VoidFunc* const*
+_rw_func_array;
+
+
+// exercise all test cases defined for the given function
+static void
+_rw_run_cases (const ContainerFunc &func,
+               const ContainerTest &test)
+{
+    // set the {CLASS}, {FUNC}, and {FUNCSIG} environment
+    // variable to the name of the container specialization
+    // and the container function being exercised
+    _rw_setvars (func);
+
+    // determine whether the function is a member function
+    const bool is_member = 0 != (ContainerIds::bit_member & test.which);
+
+    // compute the function overload's 0-based index
+    const size_t siginx = _rw_get_func_inx (test.which);
+
+    // check if tests of the function overload
+    // have been disabled
+    if (0 == rw_note (0 <= _rw_opt_func [siginx], _rw_this_file, __LINE__,
+                      "%{?}%{$CLASS}::%{;}%{$FUNCSIG} tests disabled",
+                      is_member))
+        return;
+
+    rw_info (0, 0, 0, "%{?}%{$CLASS}::%{;}%{$FUNCSIG}", is_member);
+
+    const size_t case_count = test.case_count;
+
+    // iterate over all test cases for this function
+    // overload invoking the test case handler for each
+    // in turn
+    for (size_t n = 0; n != case_count; ++n) {
+
+        const ContainerTestCase& tcase = test.cases [n];
+
+        _rw_test_case (func, tcase, _rw_test_callback, _rw_func_array);
+    }
+}
+
+/**************************************************************************/
+
+void
+_rw_toggle_options (int *opts, size_t count)
+{
+    for (size_t i = 0; i != count; ++i) {
+        if (0 < opts [i]) {
+            // if one or more options has been explicitly enabled
+            // treat all those that haven't been as if they had
+            // been disabled
+            for (i = 0; i != count; ++i) {
+                if (0 == opts [i])
+                    opts [i] = -1;
+            }
+            break;
+        }
+    }
+}
+
+
+static int
+_rw_run_test (int, char*[])
+{
+#ifdef _RWSTD_NO_EXCEPTIONS
+
+    rw_note (0, 0, 0, "exception tests disabled (macro "
+        "_RWSTD_NO_EXCEPTIONS #defined)");
+
+    // disable all exception tests and avoid further notes
+    _rw_no_exceptions       = 2;
+    _rw_no_exception_safety = 2;
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+    // see if any option controlling a container function has been
+    // explicitly enabled and if so disable all those that haven't
+    // been (i.e., so that --enable-foo-size will have the effect
+    // of specifying --disable-foo-val and --disable-foo-range,
+    // given the three overloads of foo)
+    const size_t nopts = sizeof _rw_opt_func / sizeof *_rw_opt_func;
+    _rw_toggle_options (_rw_opt_func, nopts);
+
+    static const ContainerIds::ElemId elem_types[] = {
+        ContainerIds::UserPOD, ContainerIds::UserClass
+    };
+
+    static const ContainerIds::AllocId alloc_types[] = {
+        ContainerIds::DefaultAlloc, ContainerIds::UserAlloc
+    };
+
+    static const ContainerIds::IteratorId iter_types[] = {
+        ContainerIds::Input, ContainerIds::Forward,
+        ContainerIds::Bidir, ContainerIds::Random,
+        ContainerIds::Pointer, ContainerIds::ConstPointer,
+        ContainerIds::Iterator, ContainerIds::ConstIterator,
+        ContainerIds::ReverseIterator, ContainerIds::ConstReverseIterator
+    };
+
+    const size_t n_elem_types   = sizeof elem_types / sizeof *elem_types;
+    const size_t n_alloc_types  = sizeof alloc_types / sizeof *alloc_types;
+    const size_t n_iter_types   = sizeof iter_types / sizeof *iter_types;
+
+    // see if any option controlling the container template arguments
+    // explicitly enabled and if so disable all those that haven't been
+    _rw_toggle_options (_rw_opt_elem_types, n_elem_types);
+    _rw_toggle_options (_rw_opt_alloc_types, n_alloc_types);
+    _rw_toggle_options (_rw_opt_iter_types, n_iter_types);
+
+    // exercise different T specializations last
+    for (size_t i = 0; i != n_elem_types; ++i) {
+
+        if (_rw_opt_elem_types [i] < 0) {
+            // issue only the first note
+            rw_note (-1 > _rw_opt_elem_types [i]--,
+                     _rw_this_file, __LINE__,
+                     "%s tests disabled", _rw_elem_names [i]);
+            continue;
+        }
+
+        for (size_t k = 0; k != n_alloc_types; ++k) {
+
+            if (_rw_opt_alloc_types [k] < 0) {
+                // issue only the first note
+                rw_note (-1 > _rw_opt_alloc_types [k]--,
+                         _rw_this_file, __LINE__,
+                         "%s tests disabled", _rw_alloc_names [k]);
+                continue;
+            }
+
+            for (size_t m = 0; m != _rw_cont_test_count; ++m) {
+
+                const ContainerTest& test = _rw_cont_tests [m];
+
+                // create an object uniquely identifying the overload
+                // of the container function exercised by the set of test
+                // cases defined to exercise it
+                ContainerFunc func = {
+                    elem_types [i],
+                    alloc_types [k],
+                    ContainerIds::None,
+                    _rw_container_id,
+                    test.which
+                };
+
+                // determine whether the function is a template
+                if (-1 < _rw_argno (test.which, ContainerIds::arg_range)) {
+
+                    // iterate over the standard iterator categories
+                    // and iterator types the template might perhaps
+                    // be specialized on
+                    for (size_t l = 0; l != n_iter_types; ++l) {
+
+                        if (_rw_opt_iter_types [l] < 0) {
+                            // issue only the first note
+                            rw_note (-1 > _rw_opt_iter_types [l]--,
+                                     _rw_this_file, __LINE__,
+                                     "%s tests disabled",
+                                     _rw_iter_names [l]);
+                            continue;
+                        }
+
+                        func.iter_id_ = iter_types [l];
+
+                        // exercise all test cases defined for
+                        // the function template
+                        _rw_run_cases (func, test);
+                    }
+                }
+                else {
+                    // exercise all test cases defined for the ordinary
+                    // (i.e., non-template) function
+                    _rw_run_cases (func, test);
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+/**************************************************************************/
+
+// add a bunch of toggle-type command line options based on the names array
+static void
+_rw_add_toggles (char **pbuf, size_t *pbufsize,
+                 const char* const names[], size_t count)
+{
+    for (size_t i = 0; i != count; ++i) {
+        rw_asnprintf (pbuf, pbufsize, "%{+}|-%s~ ", names [i]);
+    }
+}
+
+static void
+_rw_add_container_toggles (char **pbuf, size_t *pbufsize)
+{
+    _rw_add_toggles (pbuf, pbufsize, _rw_alloc_names,
+                     sizeof _rw_alloc_names / sizeof *_rw_alloc_names);
+    _rw_add_toggles (pbuf, pbufsize, _rw_iter_names + 1,
+                     sizeof _rw_iter_names / sizeof *_rw_iter_names - 1);
+}
+
+
+static int
+_rw_run_test  (int                       argc,
+               char                     *argv [],
+               const char               *file,
+               const char               *clause,
+               ContainerIds::ContainerId container,
+               ContainerTestFunc        *test_callback,
+               VoidFunc* const          *func_array,
+               const ContainerTest      *tests,
+               size_t                    test_count)
+{
+    // set the global variables accessed in _rw_run_test
+    _rw_container_id      = container;
+    _rw_test_callback     = test_callback;
+    _rw_func_array        = func_array,
+    _rw_cont_tests        = tests;
+    _rw_cont_test_count   = test_count;
+
+    // put together a command line option specification with options
+    // to enable and disable tests exercising functions for all known
+    // specializations of the functions specified by the test array
+    char   *optbuf     = 0;
+    size_t  optbufsize = 0;
+
+    rw_asnprintf (&optbuf, &optbufsize,
+                  "|-no-exceptions# "
+                  "|-no-exception-safety# "
+                  "|-self-ref~ ");
+
+    const size_t n_elems  = sizeof _rw_elem_names / sizeof *_rw_elem_names;
+
+    // see if any option has been explicitly enabled and if so,
+    // unconditionally disable all those that have not been
+    _rw_add_toggles (&optbuf, &optbufsize, _rw_elem_names, n_elems);
+    _rw_add_container_toggles (&optbuf, &optbufsize);
+
+    for (size_t i = 0; i != test_count; ++i) {
+
+        // for each function append a command line option specification
+        // to allow to enable or disable it
+        rw_asnprintf (&optbuf, &optbufsize, "%{+}|-");
+        _rw_sigcat (&optbuf, &optbufsize, 0, tests [i].which);
+        rw_asnprintf (&optbuf, &optbufsize, "%{+}~ ");
+    }
+
+    RW_ASSERT (test_count <= 32);
+    RW_ASSERT (test_count <= MAX_OVERLOADS);
+
+    // process command line arguments run tests
+    const int status =
+        rw_test (argc, argv, file, clause,
+        0,              // comment
+        _rw_run_test,   // test callback
+        optbuf,         // option specification
+
+        // handlers controlling exceptions
+        &_rw_opt_no_exceptions,
+        &_rw_opt_no_exception_safety,
+
+        // handler controlling self-referential modifiers
+        &_rw_opt_self_ref,
+
+        // handlers controlling specializations of the template
+        // ...on the T template parameter
+        _rw_opt_elem_types + 0,
+        _rw_opt_elem_types + 1,
+
+        // ...on the Allocator template parameter
+        _rw_opt_alloc_types + 0,
+        _rw_opt_alloc_types + 1,
+
+        // FIXME: add handlers (and options) only for tests
+        // that exercise member templates
+
+        // handlers controlling specializations of the member
+        // template (if this is one) on the InputIterator
+        // template parameter
+        _rw_opt_iter_types + 0,
+        _rw_opt_iter_types + 1,
+        _rw_opt_iter_types + 2,
+        _rw_opt_iter_types + 3,
+        _rw_opt_iter_types + 4,
+        _rw_opt_iter_types + 5,
+        _rw_opt_iter_types + 6,
+        _rw_opt_iter_types + 7,
+        _rw_opt_iter_types + 8,
+        _rw_opt_iter_types + 9,
+
+        // FIXME: install exactly as many handlers (and options)
+        // as there are distinct functions being exercised
+
+        // handlers for up to 32 overloads
+        _rw_opt_func +  0,
+        _rw_opt_func +  1,
+        _rw_opt_func +  2,
+        _rw_opt_func +  3,
+        _rw_opt_func +  4,
+        _rw_opt_func +  5,
+        _rw_opt_func +  6,
+        _rw_opt_func +  7,
+        _rw_opt_func +  8,
+        _rw_opt_func +  9,
+        _rw_opt_func + 10,
+        _rw_opt_func + 11,
+        _rw_opt_func + 12,
+        _rw_opt_func + 13,
+        _rw_opt_func + 14,
+        _rw_opt_func + 15,
+        _rw_opt_func + 16,
+        _rw_opt_func + 17,
+        _rw_opt_func + 18,
+        _rw_opt_func + 19,
+        _rw_opt_func + 20,
+        _rw_opt_func + 21,
+        _rw_opt_func + 22,
+        _rw_opt_func + 23,
+        _rw_opt_func + 24,
+        _rw_opt_func + 25,
+        _rw_opt_func + 26,
+        _rw_opt_func + 27,
+        _rw_opt_func + 28,
+        _rw_opt_func + 29,
+        _rw_opt_func + 30,
+        _rw_opt_func + 31,
+
+        // sentinel
+        (void*)0);
+
+    // free storage allocated for the option specification
+    free (optbuf);
+
+    return status;
+}   
+
+
+
+_TEST_EXPORT int
+rw_run_cont_test (int                        argc,
+                  char                      *argv [],
+                  const char                *file,
+                  const char                *clause,
+                  ContainerIds::ContainerId  container,
+                  ContainerTestFunc         *callback,
+                  const ContainerTest       *tests,
+                  size_t                     count)
+{
+    return _rw_run_test (argc, argv, file, clause, container,
+                         callback, 0, tests, count);
+}
+
+
+_TEST_EXPORT int
+rw_run_cont_test (int                        argc,
+                  char                      *argv [],
+                  const char                *file,
+                  const char                *clause,
+                  ContainerIds::ContainerId  container,
+                  VoidFunc* const           *farray,
+                  const ContainerTest       *tests,
+                  size_t                     count)
+{
+    return _rw_run_test (argc, argv, file, clause, container,
+                         0, farray, tests, count);
+}

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

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



Mime
View raw message