incubator-stdcxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Travis Vitek" <tvi...@quovadx.com>
Subject RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results
Date Tue, 07 Aug 2007 16:28:13 GMT

Looks like my attachment got stripped. This is really annoying. Does
anyone have any idea why ezmlm hates me so?

I'm going to try one more time. I'm attaching the patch file, and I'm
pasting the contents below the patch information. If that fails I'll
stop trying to paste/attach patches and I'll just start opening JIRAs.

Travis

-----Original Message-----

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

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

	* 22.locale.time.put.mt.cpp (MyIos, MyStreambuf, MyTimeData):
      Added structures to simplify testing.
	(run_test): Build table of in/outputs for verification in test
      threads. 
      (thread_func): Assert that data written matches expected.

Index: 22.locale.time.put.mt.cpp
===================================================================
--- 22.locale.time.put.mt.cpp	(revision 562577)
+++ 22.locale.time.put.mt.cpp	(working copy)
@@ -32,7 +32,7 @@
 #include <iterator>   // for ostreambuf_iterator
 #include <locale>     // for locale, time_put
 
-#include <cstring>    // for strlen()
+#include <cstring>    // for strlen ()
 #include <ctime>      // for tm
 
 #include <rw_locale.h>
@@ -60,76 +60,124 @@
 static std::size_t
 nlocales;
 
-/**********************************************************************
****/
+struct MyTimeData
+{
+    enum { BufferSize = 64 };
 
-extern "C" {
+    // name of the locale the data corresponds to
+    const char* locale_name_;
 
-bool test_char;    // exercise time_put<char>
-bool test_wchar;   // exercise time_put<wchar_t>
+    // optinally set to the named locale for threads to share
+    std::locale locale_;
 
+    // the time struct used to generate strings below
+    std::tm time_;
 
-static void*
-thread_func (void*)
+    // the format specifier
+    char format_;
+
+    // narrow representations of time_ given the 
+    // locale_name_ and the format_
+    char ncs_ [BufferSize];
+    std::char_traits<char>::off_type nlen_;
+    
+#ifndef _RWSTD_NO_WCHAR_T
+
+    // wide representations of time_
+    wchar_t wcs_ [BufferSize];
+    std::char_traits<wchar_t>::off_type wlen_;
+
+#endif // _RWSTD_NO_WCHAR_T
+
+} my_time_data [MAX_THREADS];
+
+
+/**********************************************************************
****/
+
+template <class charT, class Traits>
+struct MyIos: std::basic_ios<charT, Traits>
 {
-    std::tm tmb = std::tm ();
+    MyIos () {
+        this->init (0);
+    }
+};
 
-    const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
+template <class charT, class Traits>
+struct MyStreambuf: std::basic_streambuf<charT, Traits>
+{
+    typedef std::basic_streambuf<charT, Traits> Base;
 
-    // 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;
+    MyStreambuf ()
+        : Base () {
+    }
 
-#ifndef _RWSTD_NO_WCHAR_T
+    void pubsetp (charT *pbeg, charT *pend) {
+        this->setp (pbeg, pend);
+    }
 
-    struct WideBuf: std::wstreambuf {
-        int_type overflow (int_type c) { return c; }
-    } wsb;
+    charT* pubpbase () const {
+        return pbase ();
+    }
 
-#endif   // _RWSTD_NO_WCHAR_T
+    charT* pubpptr () const {
+        return pptr ();
+    }
 
-    struct Ios: std::ios {
-        Ios () { this->init (0); }
-    } io;
+    charT* pubepptr () const {
+        return epptr ();
+    }
+};
 
-    int j = 0;
+#define countof(x) (sizeof (x) / sizeof (*x))
 
-    for (int i = 0; i != rw_opt_nloops; ++i, ++j) {
+extern "C" {
 
-        // initialize tm with random but valid values
-        tmb.tm_sec  = ++j % 61;
-        tmb.tm_min  = ++j % 60;
-        tmb.tm_min  = ++j % 60;
-        tmb.tm_wday = ++j % 7;
-        tmb.tm_mon  = ++j % 12;
-        tmb.tm_year = ++j;
+bool test_char;    // exercise time_put<char>
+bool test_wchar;   // exercise time_put<wchar_t>
 
-        // generate a "random" conversion specifier from the set
-        // of valid specifiers recognized by the facet to exercise
-        // all (or most) code paths
-        const char cvt = cvtspecs [i % (sizeof cvtspecs - 1)];
 
+static void*
+thread_func (void*)
+{
+    char                                       ncs
[MyTimeData::BufferSize];
+    MyIos<char, std::char_traits<char> >       nio;
+    MyStreambuf<char, std::char_traits<char> > nsb;
+
+#ifndef _RWSTD_NO_WCHAR_T
+    wchar_t                                          wcs
[MyTimeData::BufferSize];
+    MyIos<wchar_t, std::char_traits<wchar_t> >       wio;
+    MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+#endif // _RWSTD_NO_WCHAR_T
+
+    for (int i = 0; i != rw_opt_nloops; ++i) {
+
         // save the name of the locale
-        const char* const locale_name = locales [i % nlocales];
+        const MyTimeData& data = my_time_data[i % nlocales];
 
         // construct a named locale, get a reference to the time_put
         // facet from it and use it to format a random time value
         // using a random conversion specifier
-        const std::locale loc (locale_name);
+        const std::locale loc (data.locale_name_);
 
         if (test_char) {
             // exercise the narrow char specialization of the facet
 
+            // should this be hoisted out of the loop?
             const std::time_put<char> &tp =
                 std::use_facet<std::time_put<char> >(loc);
 
-            // format a "random" but valid tm value using the random
-            // format specifier
-            tp.put (std::ostreambuf_iterator<char>(&sb),
-                    io, ' ', &tmb, cvt);
+            // assign data buffer to streambuf
+            nsb.pubsetp (ncs, ncs + countof (ncs));
 
+            // format time using provided format specifier
+            tp.put (std::ostreambuf_iterator<char>(&nsb),
+                    nio, ' ', &data.time_, data.format_);
+
+            const std::char_traits<char>::off_type nlen =
+                nsb.pubpptr() - nsb.pubpbase();
+
+            RW_ASSERT (nlen == data.nlen_ &&
+                       !memcmp (data.ncs_, ncs, nlen));
         }
 
         // both specializations may be tested at the same time
@@ -139,14 +187,23 @@
 
 #ifndef _RWSTD_NO_WCHAR_T
 
+            // should this be hoisted out of the loop?
             const std::time_put<wchar_t> &wtp =
                 std::use_facet<std::time_put<wchar_t> >(loc);
 
+            wsb.pubsetp (wcs, wcs + countof (wcs));
+
             wtp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
-                     io, L' ', &tmb, cvt);
+                     wio, L' ', &data.time_, data.format_);
 
-#endif   // _RWSTD_NO_WCHAR_T
+            const std::char_traits<wchar_t>::off_type wlen =
+                wsb.pubpptr() - wsb.pubpbase();
 
+            RW_ASSERT (wlen == data.wlen_ &&
+                       !memcmp (data.wcs_, wcs, wlen));
+
+#endif // _RWSTD_NO_WCHAR_T
+
         }
     }
 
@@ -160,19 +217,91 @@
 static int
 run_test (int, char**)
 {
-    // find all installed locales for which setlocale(LC_ALL) succeeds
+    MyIos<char, std::char_traits<char> >       nio;
+    MyStreambuf<char, std::char_traits<char> > nsb;
+
+#ifndef _RWSTD_NO_WCHAR_T
+    MyIos<wchar_t, std::char_traits<wchar_t> >       wio;
+    MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb;
+#endif // _RWSTD_NO_WCHAR_T
+
+    // find all installed locales for which setlocale (LC_ALL) succeeds
     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 char cvtspecs [] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
 
+    int j = 0;
+    for (const char const *name = locale_list;
+         *name;
+         name += std::strlen (name) + 1) {
+
+        const std::size_t inx = nlocales;
+        locales [inx] = name;
+
+        // fill in the time and results for this locale
+        MyTimeData& data = my_time_data[nlocales];
+        data.locale_name_ = name;
+
+        try {
+            const std::locale loc (name);
+
+            // initialize tm with random but valid values
+            data.time_.tm_sec  = ++j % 61;
+            data.time_.tm_min  = ++j % 60;
+            data.time_.tm_hour = ++j % 12;
+            data.time_.tm_wday = ++j % 7;
+            data.time_.tm_mon  = ++j % 12;
+            data.time_.tm_mday = ++j % 31;
+            data.time_.tm_yday = ++j % 366;
+            data.time_.tm_year = ++j;
+
+            // get the "random" conversion specifier used to generate
+            // the result string
+            data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)];
+
+            const std::time_put<char> &np =
+                std::use_facet<std::time_put<char> >(loc);
+
+            nsb.pubsetp (data.ncs_, data.ncs_ + countof (data.ncs_));
+            
+            np.put (std::ostreambuf_iterator<char>(&nsb),
+                    nio, ' ', &data.time_, data.format_);
+
+            data.nlen_ = nsb.pubpptr() - nsb.pubpbase();
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+            const std::time_put<wchar_t> &wp =
+                std::use_facet<std::time_put<wchar_t> >(loc);
+
+            wsb.pubsetp (data.wcs_, data.wcs_ + countof (data.wcs_));
+            
+            wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
+                    wio, L' ', &data.time_, data.format_);
+
+            data.wlen_ = wsb.pubpptr() - wsb.pubpbase();
+
+#endif // _RWSTD_NO_WCHAR_T
+
+        } catch (...) {
+            // skip over bad locale
+        }
+
+        nlocales += 1;
+
         if (nlocales == maxinx)
             break;
     }
 
+    // avoid divide by zero in thread if there are no locales to test
+    if (nlocales < 1) {
+        rw_fatal(nlocales != 0, 0, __LINE__,
+                 "failed to create one or more usable locales");
+    }
+
     rw_info (0, 0, 0,
              "testing std::time_put<charT> with %d thread%{?}s%{;}, "
              "%zu iteration%{?}s%{;} each, in locales { %{ .*A@} }",

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