You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Travis Vitek <tv...@quovadx.com> on 2007/08/07 18:15:37 UTC

[PATCH] Update test 22.locale.time.put.mt.cpp to validate results

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	<vi...@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.


Re: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
[...]
> Exactly. I'm okay with a warning. I'm considering adding a
> warning for each locale that couldn't be loaded. If no usable
> locale is available, I will issue another warning that the 'C'
> locale will be used.

You mean only when --locales= is used, right? I.e., not when
the test itself finds one that's bad. That sounds like useful
enhancement.

> 
>> The API is the same. The machinery is enabled automatically by
>> pointing the RWSTD_LOCALE_ROOT environment variable at the root
>> of the stdcxx locale database tree and referencing locales
>> installed under it by name (or pathname). Most of the locale
>> tests, including 22.locale.time.put.cpp, exercise both
>> implementations.
> 
> I'll add this to my todo list. Right now I think it is best if
> I get some commitable tests written. :)

Sounds good!
Martin

RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin Sebor wrote:
>
>You mean when the user specifies --locales="foo bar" and one or
>more of them isn't available the test should give an error? Hmm,
>I agree that we should give some indication that one (or more)
>of the locales are unavailable in this case but think I would
>still prefer a warning to a hard error, simply because I see no
>harm in being robust (not every locale that /usr/bin/locale -a
>spits out is valid, so having the test weed out the bad ones
>can be useful when scripting things). Do you have a reason for
>wanting it to be an error?
>

Exactly. I'm okay with a warning. I'm considering adding a
warning for each locale that couldn't be loaded. If no usable
locale is available, I will issue another warning that the 'C'
locale will be used.

>
>The API is the same. The machinery is enabled automatically by
>pointing the RWSTD_LOCALE_ROOT environment variable at the root
>of the stdcxx locale database tree and referencing locales
>installed under it by name (or pathname). Most of the locale
>tests, including 22.locale.time.put.cpp, exercise both
>implementations.

I'll add this to my todo list. Right now I think it is best if
I get some commitable tests written. :)

>
>Martin
>

Re: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
>  
> 
> Martin Sebor wrote:
>> A test failure should indicate that there is a problem with 
>> the library,
>> not that the environment system is not equipped to exercise it.
> 
> Agreed.
> 
>> When
>> there's only one locale installed on a system (the "C" locale must
>> always be present) that's not a problem we can do much about. All it
>> means is that we can't tell if the library would work correctly if
>> there were more than one locale. So I think in this case the test
>> should just run all threads in the "C" locale. It won't be a very
>> useful test but it'll be better than nothing, don't you agree?
>>
> 
> The only issue I would have is when the test is run manually. There
> is a command line argument to explicitly specify the locales to use,
> and if none of them are available I think I'd expect the test to exit
> immediately with an error.

You mean when the user specifies --locales="foo bar" and one or
more of them isn't available the test should give an error? Hmm,
I agree that we should give some indication that one (or more)
of the locales are unavailable in this case but think I would
still prefer a warning to a hard error, simply because I see no
harm in being robust (not every locale that /usr/bin/locale -a
spits out is valid, so having the test weed out the bad ones
can be useful when scripting things). Do you have a reason for
wanting it to be an error?

> 
> I can live with defaulting to the C locale as long as there is a
> warning, which is already provided.
> 
>> Btw., the locale thread safety tests currently only exercise the
>> implementation when using the native (libc) locales. There's a big
>> chunk of code that deals with our own locales that's not being
>> tested. At some point we'll need to enhance the tests to exercise
>> this functionality as well.
>>
> 
> I'm not sure what needs to be added for this enhancement. Could you
> name a test or two that does this, or point me to the APIs I need
> to be using?

The API is the same. The machinery is enabled automatically by
pointing the RWSTD_LOCALE_ROOT environment variable at the root
of the stdcxx locale database tree and referencing locales
installed under it by name (or pathname). Most of the locale
tests, including 22.locale.time.put.cpp, exercise both
implementations.

Martin

RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Travis Vitek <tv...@quovadx.com>.
 

Martin Sebor wrote:
>
>A test failure should indicate that there is a problem with 
>the library,
>not that the environment system is not equipped to exercise it.

Agreed.

>When
>there's only one locale installed on a system (the "C" locale must
>always be present) that's not a problem we can do much about. All it
>means is that we can't tell if the library would work correctly if
>there were more than one locale. So I think in this case the test
>should just run all threads in the "C" locale. It won't be a very
>useful test but it'll be better than nothing, don't you agree?
>

The only issue I would have is when the test is run manually. There
is a command line argument to explicitly specify the locales to use,
and if none of them are available I think I'd expect the test to exit
immediately with an error.

I can live with defaulting to the C locale as long as there is a
warning, which is already provided.

>Btw., the locale thread safety tests currently only exercise the
>implementation when using the native (libc) locales. There's a big
>chunk of code that deals with our own locales that's not being
>tested. At some point we'll need to enhance the tests to exercise
>this functionality as well.
>

I'm not sure what needs to be added for this enhancement. Could you
name a test or two that does this, or point me to the APIs I need
to be using?

>Martin
>

Re: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
> 
[...]
>> [...]
>>> +    // 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");
>> There are systems with no locales installed. I think we just want
>> rw_warn() here, not something as severe as rw_fatal(). (And we
>> want a space before the open paren :)
>>
> 
> Not exactly sure what you want here. I can put an rw_warn() followed
> immediately by a return, or I can have each thread test the number of
> locales again and bail early. If the threads are allowed to run, they
> will all fail with a div-by-zero when they try to mod by 'nlocales'.

A test failure should indicate that there is a problem with the library,
not that the environment system is not equipped to exercise it. When
there's only one locale installed on a system (the "C" locale must
always be present) that's not a problem we can do much about. All it
means is that we can't tell if the library would work correctly if
there were more than one locale. So I think in this case the test
should just run all threads in the "C" locale. It won't be a very
useful test but it'll be better than nothing, don't you agree?

Btw., the locale thread safety tests currently only exercise the
implementation when using the native (libc) locales. There's a big
chunk of code that deals with our own locales that's not being
tested. At some point we'll need to enhance the tests to exercise
this functionality as well.

Martin

RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Travis Vitek <tv...@quovadx.com>.

>Martin Sebor wrote:
>
>It looks like Outlook is even more braindead than I thought. It
>encoded the plain text attachment in base64, so there's no easy
>way to comment on it. Sigh. I had to copy the patch to an email
>and send it to myself to get the ticks ('>') so that my comments
>wouldn't get mixed up with the patch. Travis, you need to get
>yourself a decent mailer :) Anything but Outlook.
>

I'll apply the suggested changes, verify on gcc, and submit the patch
again using a mailer on the unix side.

>[...]
> > +    // 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");
>
>There are systems with no locales installed. I think we just want
>rw_warn() here, not something as severe as rw_fatal(). (And we
>want a space before the open paren :)
>

Not exactly sure what you want here. I can put an rw_warn() followed
immediately by a return, or I can have each thread test the number of
locales again and bail early. If the threads are allowed to run, they
will all fail with a div-by-zero when they try to mod by 'nlocales'.

>Martin
>

Re: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
> 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.

It looks like Outlook is even more braindead than I thought. It
encoded the plain text attachment in base64, so there's no easy
way to comment on it. Sigh. I had to copy the patch to an email
and send it to myself to get the ticks ('>') so that my comments
wouldn't get mixed up with the patch. Travis, you need to get
yourself a decent mailer :) Anything but Outlook.

> 
> 2007-08-07	Travis Vitek	<vi...@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_;

If nlen_ is the length of ncs_ and can't be negative its type
should be size_t, not off_type (off_type is for file offsets).

[...]
 > +    charT* pubpptr () const {
 > +        return pptr ();

It's hard for me to tell but if the called function is defined
in a context that depends on a template parameter it needs to
be qualified with this-> (the compiler isn't allowed to look
in dependent bases when parsing unqualified calls). If you're
using MSVC to test your changes you might want to run them by
a recent version of gcc as well to catch more problems.

[...]
 > +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];

Please make sure not to exceed 78 characters per line :)

[...]
 >          // save the name of the locale
 > -        const char* const locale_name = locales [i % nlocales];
 > +        const MyTimeData& data = my_time_data[i % nlocales];

Missing space before the open bracket.

 >
 >          // 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);

I think it probably should. In fact, creating the locale in the
thread function exercises (much) more than the tests are designed
to exercise. That's not without value but there should be a way
to reduce the scope of the test so as to avoid constructing the
same named locales in the thread function. 22.locale.ctype.mt.cpp
makes it possible under the --shared-locale command line option.

 >
[...]
 > +
 > +            const std::char_traits<char>::off_type nlen =
 > +                nsb.pubpptr() - nsb.pubpbase();

I understand why you declared nlen to have off_type but since
pbase() is required/guaranteed to be less than or equal to pptr()
the type of nlen should be size_t. That way there's no need to
worry about it being negative somewhere else.

 > +
 > +            RW_ASSERT (nlen == data.nlen_ &&
 > +                       !memcmp (data.ncs_, ncs, nlen));

memcmp() needs to be qualified with std:: here and operator&&
should be on the same line, like so:

+            RW_ASSERT (   nlen == data.nlen_
+                       && !memcmp (data.ncs_, ncs, nlen));

[...]
 > +        // fill in the time and results for this locale
 > +        MyTimeData& data = my_time_data[nlocales];

Missing space before the open bracket.

[...]
 > +#endif // _RWSTD_NO_WCHAR_T
 > +
 > +        } catch (...) {

No code should follow the closing brace.

[...]
 > +    // 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");

There are systems with no locales installed. I think we just want
rw_warn() here, not something as severe as rw_fatal(). (And we
want a space before the open paren :)

Martin

RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Travis Vitek <tv...@quovadx.com>.
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	<vi...@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.


Re: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Martin Sebor <se...@roguewave.com>.
Travis Vitek wrote:
> Looks like my attachment got stripped. This is really annoying. Does
> anyone have any idea why ezmlm hates me so?

I suspect it hates Outlook users more than the rest of us ;-)
Check to see the MIME type of the attachment in your outgoing
email and cross-reference it with the list in INFRA-1194 to
see if it's forbidden. If it is, you'll either need to figure
out how to change it to a type that's not forbidden or get
the Apache infrastructure team to allow that type. You might
also want to try sending it from a different mailer, such
as Mozilla or Thunderbird. They both work for me (for plain
text attachments.)

> 
> 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.

That might be what we need to do in the meantime, until you
get one of the approaches above to work. It would be a huge
hassle to have to open a new Jira for every patch.

Martin

> 
> 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	<vi...@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@} }",


RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Farid Zaripov <Fa...@epam.com>.
> -----Original Message-----
> From: Travis Vitek [mailto:tvitek@quovadx.com] 
> Sent: Tuesday, August 07, 2007 7:28 PM
> To: stdcxx-dev@incubator.apache.org
> Subject: RE: [PATCH] Update test 22.locale.time.put.mt.cpp to 
> validate results
> 
> 
> 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.

  Ezmlm strips any attachment from letters, produced by MS Outlook.
I don't know the reason, but it's a fact :( Personally, I'm using
the Mozilla Thunderbird to send letters with attachments, and
MS Outlook for any other letters.

Farid.

RE: [PATCH] Update test 22.locale.time.put.mt.cpp to validate results

Posted by Travis Vitek <tv...@quovadx.com>.
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	<vi...@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@} }",