stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Travis Vitek" <tvi...@quovadx.com>
Subject [PATCH] Update test 22.locale.num.put.mt.cpp to validate results
Date Mon, 06 Aug 2007 21:52:06 GMT

Attached is a patch to enhance the num_put facet mt test. Threads
verify that the values they put compare equal to those put in the
primary thread.

2007-08-06	Travis Vitek	<vitek@roguewave.com>

	* 22.locale.num.put.mt.cpp: Added structure for MyIos,
MyStreambuf
	and CnumData types to simplify testing.
	(thread_func): Verify that data written matches expected.
	(run_test): Build table of inputs and outputs for verification
by
	test threads.

Index: 22.locale.num.put.mt.cpp
===================================================================
--- 22.locale.num.put.mt.cpp	(revision 562577)
+++ 22.locale.num.put.mt.cpp	(working copy)
@@ -36,6 +36,8 @@
 #include <rw_thread.h>   // for rw_get_processors (), rw_thread_pool()
 #include <driver.h>
 
+// helper gets the number of elements in an array
+#define countof(x) (sizeof(x) / sizeof(*x))
 
 // maximum number of threads allowed by the command line interface
 #define MAX_THREADS   32
@@ -58,8 +60,98 @@
 static std::size_t
 nlocales;
 
+struct CnumData
+{
+    enum { BufferSize = 32 };
+
+    // name of the locale the data corresponds to
+    const char* locale_name_;
+
+    // optinally set to the named locale for threads to share
+    std::locale locale_;
+
+    // holder for original value and character representation
+    template <typename T>
+    struct result
+    {
+        result()
+            : flags_(std::ios::dec)
+        {
+            memset(nrep_, 0, sizeof nrep_);
+            memset(wrep_, 0, sizeof wrep_);
+        }
+
+        T value_; // the original value
+        std::ios::fmtflags flags_; // flags used
+
+        // holds the narrow/wide character representation of value_
+        char    nrep_[BufferSize]; 
+        wchar_t wrep_[BufferSize];
+    };
+
+    int width_;
+
+    result<bool> bool_;
+    result<long> long_;
+    result<unsigned long> ulong_;
+
+#ifndef _RWSTD_NO_LONG_LONG
+
+    result<_RWSTD_LONG_LONG> llong_;
+    result<unsigned _RWSTD_LONG_LONG> ullong_;
+
+#endif // _RWSTD_NO_LONG_LONG
+
+    result<double> dbl_;
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+    result<long double> ldbl_;
+
+#endif // _RWSTD_NO_LONG_DOUBLE
+
+    result<void*> ptr_;
+
+} num_put_data[MAX_THREADS];
+
+const std::ios::fmtflags baseflags[] = {
+    std::ios::oct,
+    std::ios::dec,
+    std::ios::hex
+};
+
+const std::ios::fmtflags fmtflags[] = {
+    std::ios::showpos,
+    std::ios::showpoint,
+    std::ios::fixed,
+    std::ios::scientific
+};
+
+const std::ios::fmtflags adjustflags[] = {
+    std::ios::internal,
+    std::ios::left,
+    std::ios::right
+};
+
 
/***********************************************************************
***/
 
+template <class charT, class Traits>
+struct MyIos: std::basic_ios<charT, Traits>
+{
+    MyIos () { this->init (0); }
+};
+
+template <class charT, class Traits>
+struct MyStreambuf: std::basic_streambuf<charT, Traits>
+{
+    typedef std::basic_streambuf<charT, Traits> Base;
+
+    MyStreambuf (charT *pbeg, charT *pend)
+        : Base () {
+        this->setp (pbeg, pend);
+    }
+};
+
 extern "C" {
 
 bool test_char;    // exercise num_put<char>
@@ -69,54 +161,43 @@
 static void*
 thread_func (void*)
 {
-    // dummy streambuf-derived object the doesn't do anything
-    // but allows ostreambuf_iterator to "think" it can write
-    // to it
-    struct NarrowBuf: std::streambuf {
-        int_type overflow (int_type c) { return c; }
-    } sb;
 
-#ifndef _RWSTD_NO_WCHAR_T
+// these macros should probably assert goodbit
 
-    struct WideBuf: std::wstreambuf {
-        int_type overflow (int_type c) { return c; }
-    } wb;
+#define TEST_PUT(cType, vType, field, value, fill, flag)            \
+    {                                                               \
+        MyIos<cType, std::char_traits<cType> > io;                  \
+        io.imbue(loc); io.flags(flag); io.width(data->width_);      \
+                                                                    \
+        cType chars[CnumData::BufferSize];                          \
+        memset(chars, 0, sizeof chars);                             \
+                                                                    \
+        MyStreambuf<cType, std::char_traits<cType> > sb             \
+           (chars, chars + CnumData::BufferSize);                   \
+                                                                    \
+        const std::ostreambuf_iterator<cType> iter (&sb);           \
+                                                                    \
+        np.put(iter, io, fill, value);                              \
+        rw_assert(0 == memcmp(field, chars, sizeof chars),          \
+            __FILE__, __LINE__,                                     \
+            "%s '%s' != '%s'", #vType, field, chars);               \
+    }
 
-#endif   // _RWSTD_NO_WCHAR_T
+#define TEST_PUT_NARROW(type, it)                                   \
+    TEST_PUT(char, type, it.nrep_, it.value_, ' ', it.flags_)
 
-    struct Ios: std::ios {
-        Ios () { this->init (0); }
-    } io;
+#define TEST_PUT_WIDE(type, it)                                     \
+    TEST_PUT(wchar_t, type, it.wrep_, it.value_, L' ', it.flags_)
 
-    const std::ios::fmtflags baseflags[] = {
-        std::ios::oct,
-        std::ios::dec,
-        std::ios::hex
-    };
-
-    const std::ios::fmtflags fmtflags[] = {
-        std::ios::showpos,
-        std::ios::showpoint,
-        std::ios::fixed,
-        std::ios::scientific
-    };
-
-    const std::ios::fmtflags adjustflags[] = {
-        std::ios::internal,
-        std::ios::left,
-        std::ios::right
-    };
-
     for (int i = 0; i != rw_opt_nloops; ++i) {
 
-        // save the name of the locale
-        const char* const locale_name = locales [i % nlocales];
+        // fill in the value and results for this locale
+        const CnumData* data = num_put_data + (i % nlocales);
 
         // construct a named locale and imbue it in the ios object
         // so that the locale is used not only by the num_put facet
         // but also by the numpunct facet
-        const std::locale loc (locale_name);
-        io.imbue (loc);
+        const std::locale loc (data->locale_name_);
 
         enum PutId {
             put_bool,
@@ -131,75 +212,62 @@
 #endif   // _RWSTD_NO_LONG_LONG
 
             put_dbl,
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
             put_ldbl,
+
+#endif // _RWSTD_NO_LONG_DOUBLE
+
             put_ptr,
             put_max
         };
 
-        const std::ios::fmtflags base =
-            baseflags [i % (sizeof baseflags / sizeof *baseflags)];
-
-        const std::ios::fmtflags fmt =
-            fmtflags [i % (sizeof baseflags / sizeof *baseflags)];
-
-        const std::ios::fmtflags adjust =
-            adjustflags [i % (sizeof baseflags / sizeof *baseflags)];
-
-        io.flags (base | fmt | adjust);
-
-        io.width (i % 16);
-
-        // exercise postive and negative values
-        const int ival = i & 1 ? -i : i;
-
         if (test_char) {
             // exercise the narrow char specialization of the facet
 
             const std::num_put<char> &np =
                 std::use_facet<std::num_put<char> >(loc);
 
-            const std::ostreambuf_iterator<char> iter (&sb);
-
             switch (i % put_max) {
             case put_bool:
-                if (i & 2)
-                    io.setf (std::ios::boolalpha);
-                else
-                    io.unsetf (std::ios::boolalpha);
-                        
-                np.put (iter, io, ' ', bool (ival));
+                TEST_PUT_NARROW(bool, data->bool_);
                 break;
 
             case put_long:
-                np.put (iter, io, ' ', long (ival));
+                TEST_PUT_NARROW(long, data->long_);
                 break;
 
             case put_ulong:
-                np.put (iter, io, ' ', (unsigned long)ival);
+                TEST_PUT_NARROW(unsigned long, data->ulong_);
                 break;
 
 #ifndef _RWSTD_NO_LONG_LONG
 
             case put_llong:
-                np.put (iter, io, ' ', (_RWSTD_LONG_LONG)ival);
+                TEST_PUT_NARROW(long long, data->llong_);
                 break;
 
-#endif   // _RWSTD_NO_LONG_LONG
-
             case put_ullong:
-                np.put (iter, io, ' ', (unsigned
_RWSTD_LONG_LONG)ival);
+                TEST_PUT_NARROW(unsigned long long, data->ullong_);
                 break;
 
+#endif   // _RWSTD_NO_LONG_LONG
+
             case put_dbl:
-                np.put (iter, io, ' ', double (ival));
+                TEST_PUT_NARROW(double, data->dbl_);
                 break;
 
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
             case put_ldbl:
-                np.put (iter, io, ' ', (long double)ival);
+                TEST_PUT_NARROW(long double, data->ldbl_);
                 break;
 
+#endif // _RWSTD_NO_LONG_DOUBLE
+
             case put_ptr:
-                np.put (iter, io, ' ', (void*)ival);
+                TEST_PUT_NARROW(void*, data->ptr_);
                 break;
             }
         }
@@ -214,43 +282,45 @@
             const std::num_put<wchar_t> &np =
                 std::use_facet<std::num_put<wchar_t> >(loc);
 
-            const std::ostreambuf_iterator<wchar_t> iter (&wb);
-
             switch (i % put_max) {
             case put_bool:
-                np.put (iter, io, L' ', bool (ival));
+                TEST_PUT_WIDE(bool, data->bool_);
                 break;
 
             case put_long:
-                np.put (iter, io, L' ', long (ival));
+                TEST_PUT_WIDE(long, data->long_);
                 break;
 
             case put_ulong:
-                np.put (iter, io, L' ', (unsigned long)ival);
+                TEST_PUT_WIDE(unsigned long, data->ulong_);
                 break;
 
 #ifndef _RWSTD_NO_LONG_LONG
 
             case put_llong:
-                np.put (iter, io, L' ', (_RWSTD_LONG_LONG)ival);
+                TEST_PUT_WIDE(long, data->llong_);
                 break;
 
             case put_ullong:
-                np.put (iter, io, L' ', (unsigned
_RWSTD_LONG_LONG)ival);
+                TEST_PUT_WIDE(unsigned long long, data->ullong_);
                 break;
 
 #endif   // _RWSTD_NO_LONG_LONG
 
             case put_dbl:
-                np.put (iter, io, L' ', double (ival));
+                TEST_PUT_WIDE(double, data->dbl_);
                 break;
 
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
             case put_ldbl:
-                np.put (iter, io, L' ', (long double)ival);
+                TEST_PUT_WIDE(long double, data->ldbl_);
                 break;
 
+#endif // _RWSTD_NO_LONG_DOUBLE
+
             case put_ptr:
-                np.put (iter, io, L' ', (void*)ival);
+                TEST_PUT_WIDE(void*, data->ptr_);
                 break;
             }
 
@@ -273,12 +343,124 @@
     const char* const locale_list =
         rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
 
-    const std::size_t maxinx = sizeof locales / sizeof *locales;
+    const std::size_t maxinx = countof(locales);
 
     for (const char *name = locale_list; *name; name += std::strlen
(name) +1) {
 
-        locales [nlocales++] = name;
+        const std::size_t inx = nlocales;
+        locales [inx] = name;
 
+        // fill in the value and results for this locale
+        CnumData* data = num_put_data + nlocales;
+        data->locale_name_ = name;
+
+        try {
+            const std::locale loc(name);
+
+            std::ios::fmtflags base =
+                baseflags [nlocales % countof(baseflags)];
+
+            std::ios::fmtflags fmt =
+                fmtflags [nlocales % countof(baseflags)];
+
+            std::ios::fmtflags adjust =
+                adjustflags [nlocales % countof(baseflags)];
+
+            data->width_ = nlocales % 16;
+
+            // exercise postive and negative values
+            const int ival = nlocales & 1 ? -1 * nlocales : nlocales;
+
+            // format data into buffers
+            const std::num_put<char> &np =
+                std::use_facet<std::num_put<char> >(loc);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+            const std::num_put<wchar_t> &wp =
+                std::use_facet<std::num_put<wchar_t> >(loc);
+
+#endif // _RWSTD_NO_WCHAR_T
+
+#define PUT(charT, field, value, fill, flag, putter)               \
+    {                                                              \
+        flag = base | fmt | adjust;                                \
+                                                                   \
+        MyIos<charT, std::char_traits<charT> > io;                 \
+        io.imbue(loc); io.flags(flag); io.width(data->width_);     \
+                                                                   \
+        MyStreambuf<charT, std::char_traits<charT> > sb(           \
+            field, field + CnumData::BufferSize);                  \
+        const std::ostreambuf_iterator<charT> iter (&sb);          \
+                                                                   \
+        putter.put(iter, io, fill, value);                         \
+    }
+
+#if 1
+#  define PUT_NARROW(it)                                           \
+    PUT(char, it.nrep_, it.value_, ' ', it.flags_, np)
+#else
+#  define PUT_NARROW(thing)
+#endif // 1
+
+#ifndef _RWSTD_NO_WCHAR_T
+#  define PUT_WIDE(it)                                             \
+    PUT(wchar_t, it.wrep_, it.value_, L' ', it.flags_, wp)
+#else
+#  define PUT_WIDE(thing)
+#endif // _RWSTD_NO_WCHAR_T
+
+            data->long_.value_   = (long)ival;
+            PUT_NARROW(data->long_);
+            PUT_WIDE  (data->long_);
+
+            data->ulong_.value_  = (unsigned long)ival;
+            PUT_NARROW(data->ulong_);
+            PUT_WIDE  (data->ulong_);
+
+#ifndef _RWSTD_NO_LONG_LONG
+
+            data->llong_.value_  = (_RWSTD_LONG_LONG)ival;
+            PUT_NARROW(data->llong_);
+            PUT_WIDE  (data->llong_);
+
+            data->ullong_.value_ =
+                (unsigned _RWSTD_LONG_LONG)ival;
+            PUT_NARROW(data->ullong_);
+            PUT_WIDE  (data->ullong_);
+
+#endif // _RWSTD_NO_LONG_LONG
+
+            data->dbl_.value_    = (double)ival;
+            PUT_NARROW(data->dbl_);
+            PUT_WIDE  (data->dbl_);
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+
+            data->ldbl_.value_   = (long double)ival;
+            PUT_NARROW(data->ldbl_);
+            PUT_WIDE  (data->ldbl_);
+
+#endif // _RWSTD_NO_LONG_DOUBLE
+
+            data->ptr_.value_    = (void*)ival;
+            PUT_NARROW(data->ptr_);
+            PUT_WIDE  (data->ptr_);
+
+            // test boolapha flag
+            if (ival & 1) fmt |= std::ios_base::boolalpha;
+
+            data->bool_.value_   = ival & 2 ? true : false;
+            PUT_NARROW(data->bool_);
+            PUT_WIDE  (data->bool_);
+
+            ++nlocales;
+        }
+        catch(...) {
+            // skip over bad locale
+            //rw_warn(0, 0, 0, "unable to create locale '%s'", name);
+        }
+
         if (nlocales == maxinx)
             break;
     }
@@ -290,6 +472,13 @@
              rw_opt_nloops, 1 != rw_opt_nloops,
              int (nlocales), "%#s", locales);
 
+    // avoid divide by zero in thread if there are no locales to test
+    if (nlocales < 1)
+    {
+        rw_fatal(nlocales != 0, __FILE__, __LINE__,
+            "failed to create one or more usable locales");
+    }
+
     rw_info (0, 0, 0, "exercising std::num_put<char>");
 
     test_char  = true;

Mime
  • Unnamed multipart/mixed (inline, None, 0 bytes)
View raw message