Exemple #1
0
void test_compare (charT, Traits*, Allocator*,
                   const StringFunc     &func,
                   const StringTestCase &tcase)
{
    typedef std::basic_string <charT, Traits, Allocator> String;
    typedef typename UserTraits<charT>::MemFun           UTMemFun;

    static const std::size_t BUFSIZE = 256;

    static charT wstr_buf [BUFSIZE];
    static charT warg_buf [BUFSIZE];

    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;

    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);

    // construct the string object to be modified
    // and the (possibly unused) argument string
    const String str (wstr, str_len);
    const String arg (warg, arg_len);

    if (wstr != wstr_buf)
        delete[] wstr;

    if (warg != warg_buf)
        delete[] warg;

    wstr = 0;
    warg = 0;

    // save the state of the string object before the call
    // to detect wxception safety violations (changes to
    // the state of the object after an exception)
    const StringState str_state (rw_get_string_state (str));

    int res = 0;

    // string function argument
    const charT* const arg_ptr = tcase.arg ? arg.c_str () : str.c_str ();
    const String&      arg_str = tcase.arg ? arg : str;

    std::size_t total_compare_calls = 0;
    std::size_t n_compare_calls = 0;
    std::size_t* const rg_calls =
        rw_get_call_counters ((Traits*)0, (charT*)0);

    if (rg_calls)
        total_compare_calls = rg_calls[UTMemFun::compare];

    // (name of) expected and caught exception
    const char* expected = 0;
    const char* caught   = 0;

#ifndef _RWSTD_NO_EXCEPTIONS

    if (1 == tcase.bthrow)
        expected = exceptions [1];
    else if (   2 == tcase.bthrow
             && Compare (size_size_cstr_size_size) == func.which_)
        expected = exceptions [1];
    else if (3 == tcase.bthrow)
        expected = exceptions [2];

#else   // if defined (_RWSTD_NO_EXCEPTIONS)

    if (tcase.bthrow)
        return;

#endif   // _RWSTD_NO_EXCEPTIONS

    try {
        switch (func.which_) {
            case Compare (cptr):
                res = str.compare (arg_ptr);
                break;

            case Compare (cstr):
                res = str.compare (arg_str);
                if (rg_calls)
                    n_compare_calls = rg_calls[UTMemFun::compare];
                break;

            case Compare (size_size_cptr):
                res = str.compare (tcase.off, tcase.size, arg_ptr);
                break;

            case Compare (size_size_cstr):
                res = str.compare (tcase.off, tcase.size, arg_str);
                break;

            case Compare (size_size_cptr_size):
                res = str.compare (tcase.off, tcase.size,
                                    arg_ptr, tcase.size2);
                break;

            case Compare (size_size_cstr_size_size):
                res = str.compare (tcase.off, tcase.size,
                                    arg_str, tcase.off2, tcase.size2);
                break;

            default:
                RW_ASSERT ("test logic error: unknown compare overload");
                return;
        }

        // verify the returned value
        const bool success =    res < 0 && tcase.nres == NPOS
                             || res > 0 && tcase.nres > 0
                             || res == 0 && tcase.nres == 0;

        rw_assert (success, 0, tcase.line,
                   "line %d. %{$FUNCALL} == %d, got %d",
                   __LINE__, tcase.nres == NPOS ? -1 : int (tcase.nres), res);

        // verify that Traits::length was used
        if (Compare (cstr) == func.which_ && rg_calls) {
            rw_assert (n_compare_calls - total_compare_calls > 0,
                       0, tcase.line, "line %d. %{$FUNCALL} doesn't "
                       "use traits::compare()", __LINE__);
        }
    }

#ifndef _RWSTD_NO_EXCEPTIONS

    catch (const std::out_of_range &ex) {
        caught = exceptions [1];
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (const std::length_error &ex) {
        caught = exceptions [2];
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (const std::exception &ex) {
        caught = exceptions [4];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (...) {
        caught = exceptions [0];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught %s",
                   __LINE__, 0 != expected, expected, caught);
    }

    if (caught) {
        // verify that an exception thrown during allocation
        // didn't cause a change in the state of the object
        str_state.assert_equal (rw_get_string_state (str),
                                __LINE__, tcase.line, caught);
    }

#endif   // _RWSTD_NO_EXCEPTIONS

}
void test_find_first_not_of (charT, Traits*, Allocator*,  
                             const StringFunc     &func,
                             const StringTestCase &tcase)
{
    typedef std::basic_string <charT, Traits, Allocator> String;

    static const std::size_t BUFSIZE = 256;

    static charT wstr_buf [BUFSIZE];
    static charT warg_buf [BUFSIZE];

    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;

    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);

    // construct the string object and the argument string
    const String  s_str (wstr, str_len);
    const String  s_arg (warg, arg_len);

    if (wstr != wstr_buf)
        delete[] wstr;

    if (warg != warg_buf)
        delete[] warg;

    wstr = 0;
    warg = 0;

    // save the state of the string object before the call
    // to detect wxception safety violations (changes to
    // the state of the object after an exception)
    const StringState str_state (rw_get_string_state (s_str));

    const charT* const arg_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
    const String&      arg_str = tcase.arg ? s_arg : s_str;
    const charT        arg_val = make_char (char (tcase.val), (charT*)0);

    std::size_t size = tcase.size >= 0 ? tcase.size : s_arg.max_size () + 1;

#ifndef _RWSTD_NO_EXCEPTIONS

    // is some exception expected ?
    const char* expected = 0;
    if (1 == tcase.bthrow)
        expected = exceptions [2];

    const char* caught = 0;

#else   // if defined (_RWSTD_NO_EXCEPTIONS)

    if (tcase.bthrow)
        return;

#endif   // _RWSTD_NO_EXCEPTIONS

    try {

        std::size_t res = 0;

        switch (func.which_) {
        case FindFirstNotOf (cptr):
            res = s_str.find_first_not_of (arg_ptr);
            break;

        case FindFirstNotOf (cstr):
            res = s_str.find_first_not_of (arg_str);
            break;

        case FindFirstNotOf (cptr_size):
            res = s_str.find_first_not_of (arg_ptr, tcase.off);
            break;

        case FindFirstNotOf (cptr_size_size):
            res = s_str.find_first_not_of (arg_ptr, tcase.off, size);
            break;

        case FindFirstNotOf (cstr_size):
            res = s_str.find_first_not_of (arg_str, tcase.off);
            break;

        case FindFirstNotOf (val):
            res = s_str.find_first_not_of (arg_val);
            break;

        case FindFirstNotOf (val_size):
            res = s_str.find_first_not_of (arg_val, tcase.off);
            break;

        default:
            RW_ASSERT (!"logic error: unknown find_first_not_of overload");
            return;
        }

        const std::size_t exp_res =
            NPOS != tcase.nres ? tcase.nres : String::npos;

        // verify the returned value
        rw_assert (exp_res == res, 0, tcase.line,
                   "line %d. %{$FUNCALL} == %{?}%zu%{;}%{?}npos%{;}, "
                   "got %{?}%zu%{;}%{?}npos%{;}", 
                   __LINE__, NPOS != tcase.nres, exp_res, NPOS == tcase.nres, 
                   String::npos != res, res, String::npos == res);
    }

#ifndef _RWSTD_NO_EXCEPTIONS

    catch (const std::length_error &ex) {
        caught = exceptions [2];
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (const std::exception &ex) {
        caught = exceptions [4];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (...) {
        caught = exceptions [0];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught %s",
                   __LINE__, 0 != expected, expected, caught);
    }

#endif   // _RWSTD_NO_EXCEPTIONS

    if (caught) {
        // verify that an exception thrown during allocation
        // didn't cause a change in the state of the object
        str_state.assert_equal (rw_get_string_state (s_str),
                                __LINE__, tcase.line, caught);
    }
    else if (-1 != tcase.bthrow) {
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
                   "%{:}unexpectedly caught %s%{;}",
                   __LINE__, 0 != expected, expected, caught, caught);
    }
}
Exemple #3
0
void test_op_plus (charT, Traits*, Allocator*,
                   const StringFunc     &func,
                   const StringTestCase &tcase)
{
    typedef std::basic_string <charT, Traits, Allocator> String;
    typedef typename UserTraits<charT>::MemFun           UTMemFun;

    static const std::size_t BUFSIZE = 256;

    static charT wstr_buf [BUFSIZE];
    static charT warg_buf [BUFSIZE];

    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;

    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);

    static charT wres_buf [BUFSIZE];
    std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
    charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);

    // construct the string object to be modified
    // and the (possibly unused) argument string
    /* const */ String  s_str (wstr, str_len);
    const       String  s_arg (warg, arg_len);

    if (wstr != wstr_buf)
        delete[] wstr;

    if (warg != warg_buf)
        delete[] warg;

    wstr = 0;
    warg = 0;

    String s_res;

    // save the state of the string object before the call
    // to detect wxception safety violations (changes to
    // the state of the object after an exception)
    const StringState str_state (rw_get_string_state (s_res));

    const charT* const arg1_ptr = tcase.str ? s_str.c_str () : s_arg.c_str ();
    const String&      arg1_str = tcase.str ? s_str : s_arg;
    const charT* const arg2_ptr = tcase.arg ? s_arg.c_str () : s_str.c_str ();
    const String&      arg2_str = tcase.arg ? s_arg : s_str;
    const charT        arg_val = make_char (char (tcase.val), (charT*)0);

    std::size_t total_length_calls = 0;
    std::size_t n_length_calls = 0;
    std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);

    if (rg_calls)
        total_length_calls = rg_calls [UTMemFun::length];

    rwt_free_store* const pst = rwt_get_free_store (0);
    SharedAlloc*    const pal = SharedAlloc::instance ();

    // iterate for`throw_after' starting at the next call to operator new,
    // forcing each call to throw an exception, until the function finally
    // succeeds (i.e, no exception is thrown)
    std::size_t throw_count;
    for (throw_count = 0; ; ++throw_count) {

        // (name of) expected and caught exception
        const char* expected = 0;
        const char* caught   = 0;

#ifndef _RWSTD_NO_EXCEPTIONS

        if (0 == tcase.bthrow) {
            // by default excercise the exception safety of the function
            // by iteratively inducing an exception at each call to operator
            // new or Allocator::allocate() until the call succeeds
            expected = exceptions [3];      // bad_alloc
            *pst->throw_at_calls_ [0] = pst->new_calls_ [0] + throw_count + 1;
            pal->throw_at_calls_ [pal->m_allocate] =
                pal->throw_at_calls_ [pal->m_allocate] + throw_count + 1;
        }
        else {
            // exceptions disabled for this test case
        }

#else   // if defined (_RWSTD_NO_EXCEPTIONS)

    if (tcase.bthrow) {
        if (wres != wres_buf)
            delete[] wres;

        return;
    }

#endif   // _RWSTD_NO_EXCEPTIONS

        // start checking for memory leaks
        rw_check_leaks (s_res.get_allocator ());

        try {

            switch (func.which_) {
            case OpPlus (cptr_cstr): 
                s_res = arg1_ptr + arg2_str;
                if (rg_calls)
                    n_length_calls = rg_calls [UTMemFun::length];
                break;
            
            case OpPlus (cstr_cstr): 
                s_res = arg1_str + arg2_str;
                break;
            
            case OpPlus (cstr_cptr): 
                s_res = arg1_str + arg2_ptr;
                if (rg_calls)
                    n_length_calls = rg_calls [UTMemFun::length];
                break;
            
            case OpPlus (cstr_val): 
                s_res = arg1_str + arg_val;
                break;
            
            case OpPlus (val_cstr): 
                s_res = arg_val + arg2_str;
                break;

            default:
                RW_ASSERT ("test logic error: unknown operator+ overload");
                return;
            }

            // verfiy that strings length are equal
            rw_assert (res_len == s_res.size (), 0, tcase.line,
                       "line %d. %{$FUNCALL} expected %{#*s} "
                       "with length %zu, got %{/*.*Gs} with length %zu",
                       __LINE__, int (tcase.nres), tcase.res, res_len,
                       int (sizeof (charT)), int (s_res.size ()),
                       s_res.c_str (), s_res.size ());

            if (res_len == s_res.size ()) {
                // if the result length matches the expected length
                // (and only then), also verify that the modified
                // string matches the expected result
                const std::size_t match =
                    rw_match (tcase.res, s_res.c_str(), s_res.size ());

                rw_assert (match == res_len, 0, tcase.line,
                           "line %d. %{$FUNCALL} expected %{#*s}, "
                           "got %{/*.*Gs}, difference at offset %zu",
                           __LINE__, int (tcase.nres), tcase.res,
                           int (sizeof (charT)), int (s_res.size ()),
                           s_res.c_str (), match);
            }

            // verify that Traits::length was used
            if ((OpPlus (cptr_cstr) == func.which_ 
              || OpPlus (cstr_cptr) == func.which_) && rg_calls) {
                    rw_assert (n_length_calls - total_length_calls > 0, 
                               0, tcase.line, "line %d. %{$FUNCALL} doesn't "
                               "use traits::length()", __LINE__);
            }
        }

#ifndef _RWSTD_NO_EXCEPTIONS

        catch (const std::bad_alloc &ex) {
            caught = exceptions [3];
            rw_assert (0 == tcase.bthrow, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught std::%s(%#s)",
                       __LINE__, 0 != expected, expected, caught, ex.what ());
        }
        catch (const std::exception &ex) {
            caught = exceptions [4];
            rw_assert (0, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught std::%s(%#s)",
                       __LINE__, 0 != expected, expected, caught, ex.what ());
        }
        catch (...) {
            caught = exceptions [0];
            rw_assert (0, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                       "unexpectedly%{;} caught %s",
                       __LINE__, 0 != expected, expected, caught);
        }

#endif   // _RWSTD_NO_EXCEPTIONS

        // FIXME: verify the number of blocks the function call
        // is expected to allocate and detect any memory leaks
        rw_check_leaks (s_res.get_allocator (), tcase.line,
                        std::size_t (-1), std::size_t (-1));

        if (caught) {
            // verify that an exception thrown during allocation
            // didn't cause a change in the state of the object
            str_state.assert_equal (rw_get_string_state (s_res),
                                    __LINE__, tcase.line, caught);

            if (0 == tcase.bthrow) {
                // allow this call to operator new to succeed and try
                // to make the next one to fail during the next call
                // to the same function again
                continue;
            }
        }
        else if (0 < tcase.bthrow) {
            rw_assert (caught == expected, 0, tcase.line,
                       "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
                       "%{:}unexpectedly caught %s%{;}",
                       __LINE__, 0 != expected, expected, caught, caught);
        }

        break;
    }

#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE

    // verify that if exceptions are enabled and when capacity changes
    // at least one exception is thrown
    const std::size_t expect_throws = str_state.capacity_ < s_res.capacity ();

#else   // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)

    const std::size_t expect_throws = 
        (StringIds::UserAlloc == func.alloc_id_) 
      ? str_state.capacity_ < s_res.capacity () : 0;

#endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE

    // we may got no more 2 bad_allocs
    rw_assert (expect_throws <= throw_count && throw_count <= 2, 0, tcase.line,
               "line %d: %{$FUNCALL}: expected at least 1 %s exception "
               "while changing capacity from %zu to %zu, got %zu",
               __LINE__, exceptions [3],
               str_state.capacity_, s_res.capacity (), throw_count);

    // disable bad_alloc exceptions
    *pst->throw_at_calls_ [0] = 0;
    pal->throw_at_calls_ [pal->m_allocate] = 0;

    if (wres != wres_buf)
        delete[] wres;
}
Exemple #4
0
void do_test (bool        intl,    // international?
              charT       which,   // which overload to exercise
              const char *cname,   // the name of the charT type
              const char *tname,   // the name of the floating point type
              int         lineno,  // line number
              LongDouble  val,     // the expected extracted value
              const char *str,     // the sequence to extract from
              int         consumed = -1,   // expected number extractions
              int         flags = 0,       // initial ios flags
              int         err_expect = -1, // expected final state
              int         frac_digits = 0, // fractional digits
              const char *fmat = 0,        // money_base::pattern
              const char *cursym = 0,      // currency symbol
              const char *grouping = "")   // grouping string
{
    if (!rw_enabled (lineno)) {
        rw_note (0, __FILE__, __LINE__, "test on line %d disabled", lineno);
        return;
    }

    if (!fmat) {
        // if fmat isn't set, use the default pattern
        static const std::money_base::pattern pat = { {
            std::money_base::symbol, std::money_base::sign,
            std::money_base::none,   std::money_base::value
        } };

        fmat = pat.field;
    }
    else
        fmat = set_pattern (fmat).field;

    // local format? (the opposite of interantional)
    const bool locl = !intl;

    // take care to initialize Punct static data before installing
    // the facet in case locale or the base facet calls the overridden
    // virtuals early to cache the results
    PunctData<charT>::format_ [intl][1].field [0] = fmat [0];
    PunctData<charT>::format_ [intl][1].field [1] = fmat [1];
    PunctData<charT>::format_ [intl][1].field [2] = fmat [2];
    PunctData<charT>::format_ [intl][1].field [3] = fmat [3];

    PunctData<charT>::format_ [locl][1].field [0] = fmat [3];
    PunctData<charT>::format_ [locl][1].field [1] = fmat [2];
    PunctData<charT>::format_ [locl][1].field [2] = fmat [1];
    PunctData<charT>::format_ [locl][1].field [3] = fmat [0];

    // zero out positive format (not used by money_get)
    PunctData<charT>::format_ [intl][0] = std::money_base::pattern ();
    PunctData<charT>::format_ [locl][0] = std::money_base::pattern ();

    // expand (widen) currency symbol
    PunctData<charT>::curr_symbol_ [intl] = rw_expand ((charT*)0, cursym);
    PunctData<charT>::curr_symbol_ [locl] = 0;
    
    PunctData<charT>::grouping_ [intl] = grouping;
    PunctData<charT>::grouping_ [locl] = 0;

    PunctData<charT>::frac_digits_ [intl] = frac_digits;
    PunctData<charT>::frac_digits_ [locl] = frac_digits + 1;

    Ios<charT> io;
    MoneyGet<charT> mg;

    // create distinct punctuation facets for each iteration to make sure
    // any data cached in between successive calls to the facet's public
    // member functions are flushed
    if (intl) {
        const std::moneypunct<charT, true> *pf = new Punct<charT, true>(0);
        io.imbue (std::locale (io.getloc (), pf));
    }
    else {
        const std::moneypunct<charT, false> *pf = new Punct<charT, false>(0);
        io.imbue (std::locale (io.getloc (), pf));
    }

    io.flags (std::ios_base::fmtflags (flags));

    // expand (widen) input sequence
    const charT* const next = rw_expand ((charT*)0, str);

    std::ios_base::iostate err = std::ios_base::goodbit;

    const charT *last;

    if (0 == which) {   // exercise get (..., long double)

        last = next + std::char_traits<charT>::length (next);

        LongDouble x = 0;

        last = mg.get (next, last, intl, io, err, x);

        if (-1 == err_expect)
            err_expect = err;

        const int success =
            !(-1 != consumed && last - next != consumed || err != err_expect);

        rw_assert (success, __FILE__, lineno,
                   "money_get<%s>::get (%{*Ac}, ..., %b, ..., %s&), "
                   "ate %d, expected %d, frac_digits = %d, "
                   "flags = %{If}, grouping = %#s, pattern = %{LM}, "
                   "state = %{Is}, expected %{Is}",
                   cname, int (sizeof *next), next, intl, tname,
                   last - next, consumed, frac_digits,
                   flags, grouping, fmat,
                   err, err_expect);

        rw_assert (2 > rw_ldblcmp (x, val), __FILE__, lineno,
                   "money_get<%s>::get (%{*Ac}, ..., %b, ..., %s&), "
                   "got %Lg, expected %Lg, frac_digits = %d, "
                   "flags = %{If}s, grouping = %#s, pattern = %{LM}, "
                   "state = %{Is}, expected %{Is}",
                   cname, int (sizeof *next), next, intl, tname,
                   x, val, frac_digits,
                   flags, grouping, fmat,
                   err, err_expect);
    }
    else {   // exercise get (..., string_type)

        static const charT initial[] = { '*', '*', '*', '\0' };
        typename std::money_get<charT, const charT*>::string_type bs (initial);

        last = next + std::char_traits<charT>::length (next);

        last = mg.get (next, last, intl, io, err, bs);

        int success =
            !(-1 != consumed && last - next != consumed || err != err_expect);

        rw_assert (success, __FILE__, lineno,
                   "money_get<%s>::get (%{*Ac}, ..., %b, ..., "
                   "basic_string<%s>&), ate %d, expected %d, "
                   "frac_digits = %d, flags = %{If}, grouping = %#s"
                   ", format = %{LM}, state = %{Is}, expected %{Is}",
                   cname, int (sizeof *next), next, intl,
                   cname, last - next, consumed,
                   frac_digits, flags, grouping,
                   fmat, err, err_expect);

        if (success) {

            char narrow_buf [4096];
            rw_narrow (narrow_buf, bs.c_str ());

            LongDouble x = 0;

            // prevent gcc warning: ANSI C does not support
            // the `L' length modifier
            const char fmt[] = "%" _RWSTD_LDBL_PRINTF_PREFIX "g";
            int n = std::sscanf (narrow_buf, fmt, &x);

            success = 
                !(   err_expect & std::ios::failbit && !*grouping
                  && (1 == n || bs != initial)
                  || !(err_expect & std::ios::failbit)
                  && 1 < rw_ldblcmp (x, val));

            rw_assert (success, __FILE__, lineno,
                       "money_get<%s>::get (%{*Ac}, ..., %b, ..., "
                       "basic_string<%s>&), got %s, expected %Lg, "
                       "frac_digits = %d, flags = %{If}, grouping = %#s,"
                       " pattern = %{LM}, iostate = %{Is}, expected %{Is}",
                       cname, int (sizeof *next), next, intl,
                       cname, bs.c_str (), val,
                       frac_digits, flags, grouping,
                       fmat, err, err_expect);
        }
    }

    delete[] PunctData<charT>::curr_symbol_ [intl];
    delete[] next;
}
Exemple #5
0
void test_copy (charT, Traits*, Allocator*,                
                const StringFunc     &func,
                const StringTestCase &tcase)
{
    typedef std::basic_string <charT, Traits, Allocator> String;

    static const std::size_t BUFSIZE = 256;

    static charT wstr_buf [BUFSIZE];
    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);

    static charT wres_buf [BUFSIZE];
    std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
    charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);

    // construct the string object 
    const String  str (wstr, str_len);

    if (wstr != wstr_buf)
        delete[] wstr;

    wstr = 0;

    const std::size_t min_len =
        str_len < std::size_t (tcase.size) ? str_len : tcase.size;

    std::size_t res = 0;

    // create destination array and initialize it with garbage
    charT* const s_res = new charT [min_len + 2];

    const char cgb [2] = "#";
    const charT wcgb = make_char (cgb [0], (charT*)0);
    Traits::assign (s_res, min_len + 1, wcgb);
    s_res [min_len + 1] = charT ();

    // save the state of the string object before the call
    // to detect wxception safety violations (changes to
    // the state of the object after an exception)
    const StringState str_state (rw_get_string_state (str));

#ifndef _RWSTD_NO_EXCEPTIONS

    // is some exception expected?
    const char* const expected = tcase.bthrow ? exceptions [1] : 0;
    const char* caught = 0;

#else   // if defined (_RWSTD_NO_EXCEPTIONS)

    if (tcase.bthrow) {
        if (wres != wres_buf)
            delete[] wres;

        return;
    }

#endif   // _RWSTD_NO_EXCEPTIONS

    try {
        switch (func.which_) {
        case Copy (ptr_size): {
            res = str.copy (s_res, tcase.size);
            break;
        }

        case Copy (ptr_size_size): {
            res = str.copy (s_res, tcase.size, tcase.off);
            break;
        }
        default:
            RW_ASSERT (!"logic error: unknown copy overload");
            return;
        }

        // verify the returned value
        rw_assert (res == res_len, 0, tcase.line,
                   "line %d. %{$FUNCALL} == %zu, got %zu", 
                   __LINE__, res_len, res);

        if (res == res_len) 
        {
            const std::size_t match = rw_match (tcase.res, s_res, res_len);
            bool success = match == res_len;

            rw_assert (success, 0, tcase.line,
                       "line %d. %{$FUNCALL} expected %{#*s}, "
                       "got %{/*.*Gs}, differ at pos %zu",
                       __LINE__, int (tcase.nres), tcase.res, 
                       int (sizeof (charT)), int (res), s_res, match);

            success = 1 == rw_match (cgb, s_res + min_len, 1);
            rw_assert (success, 0, tcase.line,
                       "line %d. %{$FUNCALL} detected writing past the end of "
                       "the provided buffer", __LINE__);
        }
    }

#ifndef _RWSTD_NO_EXCEPTIONS

    catch (const std::out_of_range &ex) {
        caught = exceptions [1];
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (const std::exception &ex) {
        caught = exceptions [4];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (...) {
        caught = exceptions [0];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught %s",
                   __LINE__, 0 != expected, expected, caught);
    }

    if (caught) {
        // verify that an exception thrown during allocation
        // didn't cause a change in the state of the object
        str_state.assert_equal (rw_get_string_state (str),
                                __LINE__, tcase.line, caught);
    }
    else if (-1 != tcase.bthrow) {
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s, caught %s"
                   "%{:}unexpectedly caught %s%{;}",
                   __LINE__, 0 != expected, expected, caught, caught);
    }

#endif   // _RWSTD_NO_EXCEPTIONS

    if (wres != wres_buf)
        delete[] wres;

    delete[] s_res;
}
void test_access (charT, Traits*, Allocator*, 
                  const StringFunc     &func,
                  const StringTestCase &tcase)
{
    typedef std::basic_string <charT, Traits, Allocator> String;
    typedef typename String::size_type                   SizeT;

    static const std::size_t BUFSIZE = 256;

    static charT wstr_buf [BUFSIZE];
    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);

    // construct the string object 
    /* const */ String str (wstr, str_len);
    const       String const_str = str;

    if (wstr != wstr_buf)
        delete[] wstr;

    wstr = 0;

    // save the state of the string object before the call
    // to detect wxception safety violations (changes to
    // the state of the object after an exception)
    const StringState str_state (rw_get_string_state (str));

#ifndef _RWSTD_NO_EXCEPTIONS

    // is some exception expected ?
    const char* expected = 1 == tcase.bthrow ? exceptions[1] : 0;
    const char* caught = 0;

#endif   // _RWSTD_NO_EXCEPTIONS

    try {

        const charT *pres = 0;

        switch (func.which_) {

        case OpIndex (size):
            pres = &str [SizeT (tcase.off)];
            break;

        case OpIndex (const_size):
            pres = &const_str [SizeT (tcase.off)];
            break;

        case At (size):
            pres = &str.at (SizeT (tcase.off));
            break;

        case At (const_size):
            pres = &const_str.at (SizeT (tcase.off));
            break;

        default:
            RW_ASSERT (!"test logic error: unknown access overload");
            return;
        }

        const char exp_res [2] = {
            NPOS != tcase.nres ? char (tcase.nres) : char (),
            char ()
        };

        const bool success = 1 == rw_match (exp_res, pres, 1);
        rw_assert (success, 0, tcase.line,
                   "line %d. %{$FUNCALL} == %{#c}, got %{#c}",
                   __LINE__, tcase.nres, *pres);
    }

#ifndef _RWSTD_NO_EXCEPTIONS

    catch (const std::out_of_range &ex) {
        caught = exceptions [1];
        rw_assert (caught == expected, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (const std::exception &ex) {
        caught = exceptions [4];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught std::%s(%#s)",
                   __LINE__, 0 != expected, expected, caught, ex.what ());
    }
    catch (...) {
        caught = exceptions [0];
        rw_assert (0, 0, tcase.line,
                   "line %d. %{$FUNCALL} %{?}expected %s,%{:}"
                   "unexpectedly%{;} caught %s",
                   __LINE__, 0 != expected, expected, caught);
    }

#endif   // _RWSTD_NO_EXCEPTIONS

    if (caught) {
        // verify that an exception thrown during allocation
        // didn't cause a change in the state of the object
        str_state.assert_equal (rw_get_string_state (str),
                                __LINE__, tcase.line, caught);
    }
}