void test_fill (std::size_t N, const ForwardIterator& fill_iter, const T*) { static const char* const itname = type_name (fill_iter, (T*) 0); static const char* const tname = "X"; rw_info (0, 0, 0, "void std::fill (%s, %1$s, const %s&)", itname, tname); // generate sequential values for each default constructed T //T::gen_ = gen_seq; gen_ = gen_seq; // use ::operator new() to prevent default initialization T *buf = _RWSTD_STATIC_CAST (T*, ::operator new (N * sizeof (T))); // default-construct the first T at buf[0] new (buf) T (); for (std::size_t i = 0; i < N; ++i) { // default-construct a new X at the end of buf T* const new_t = new (buf + i) T (); // exercise 25.2.5 - std::fill<> () // std::size_t last_n_op_assign = T::n_total_op_assign_; std::size_t last_n_op_assign = n_total_op_assign_; T* const buf_end = buf + i + 1; const ForwardIterator begin = make_iter (buf, buf, buf_end, fill_iter); const ForwardIterator end = make_iter (buf_end, buf_end, buf_end, fill_iter); std::fill (begin, end, *new_t); // verify 25.2.5, p2 bool success = true; std::size_t j = 0; for ( ; j != i + 1; ++j) { success = buf[j].val_ == new_t->val_; if (!success) break; } if(!success) { failures++; std_log(LOG_FILENAME_LINE,"Reason: Failing as %d element has not expected value",j); } rw_assert (success, 0, __LINE__, "%zu. fill (%s, %1$s, const %s&): buf[%zu]: %d != %d", i + 1, itname, tname, j, buf[j].val_, new_t->val_); if (!success) break; // verify 25.2.5, p3 // success = T::n_total_op_assign_ - last_n_op_assign == i + 1; success = n_total_op_assign_ - last_n_op_assign == i + 1; /* rw_assert (success, 0, __LINE__, "%zu. fill (%s, %1$s, const %s&) complexity: " "%zu != %zu", i + 1, itname, tname, T::n_total_op_assign_ - last_n_op_assign, i + 1); */ if(!success) { failures++; std_log(LOG_FILENAME_LINE,"Reason: Failing ",j); } rw_assert (success, 0, __LINE__, "%zu. fill (%s, %1$s, const %s&) complexity: " "%zu != %zu", i + 1, itname, tname, n_total_op_assign_ - last_n_op_assign, i + 1); if (!success) break; } ::operator delete (buf); }
static int run_test (int, char**) { MyIos<char, std::char_traits<char> > nio; MyStreambuf<char, std::char_traits<char> > nsb; nio.rdbuf (&nsb); #ifndef _RWSTD_NO_WCHAR_T MyIos<wchar_t, std::char_traits<wchar_t> > wio; MyStreambuf<wchar_t, std::char_traits<wchar_t> > wsb; wio.rdbuf (&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 = RW_COUNT_OF (locales); for (const char *name = locale_list; *name; name += std::strlen (name) + 1) { const std::size_t inx = nlocales; locales [inx] = name; // fill in the value and results for this locale MyNumData& data = my_num_data [nlocales]; data.locale_name_ = name; try { const std::locale loc (data.locale_name_); data.value_ = nlocales & 1 ? -1 * nlocales : nlocales; data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max); // format data into buffers const std::num_put<char> &np = std::use_facet<std::num_put<char> >(loc); nio.imbue (loc); nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); put_data (data, np, std::ostreambuf_iterator<char>(&nsb), nio, ' ', '\0'); rw_fatal (!nio.fail (), __FILE__, __LINE__, "num_put<char>::put(...) failed for locale(%#s)", data.locale_name_); #ifndef _RWSTD_NO_WCHAR_T const std::num_put<wchar_t> &wp = std::use_facet<std::num_put<wchar_t> >(loc); wio.imbue (loc); wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb), wio, L' ', L'\0'); rw_fatal (!wio.fail (), __FILE__, __LINE__, "num_put<wchar_t>::put(...) failed for locale(%#s)", data.locale_name_); #endif // _RWSTD_NO_WCHAR_T if (opt_shared_locale) data.locale_ = loc; nlocales += 1; } catch (...) { rw_warn (!rw_opt_locales, 0, __LINE__, "failed to create locale(%#s)", name); } if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } // avoid divide by zero in thread if there are no locales to test rw_fatal (nlocales != 0, 0, __LINE__, "failed to create one or more usable locales!"); rw_info (0, 0, 0, "testing std::num_put<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::num_put<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::num_put<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::num_put<char> and std::num_put<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
// exercises an algorithmic multibyte encoding static void test_wcodecvt_byname_algorithmic () { rw_info (0, 0, 0, "locale (\"UTF-8@UCS\") [algorithmic encoding]"); // lowercase utf ==> relaxed checking (i.e., some, but not all, // invalid UTF-8 sequence are accepted) const WCodecvtByname cvt_relaxd ("utf-8@UCS"); // capital UTF ==> strict checking const WCodecvtByname cvt_strict ("UTF-8@UCS"); #undef STRICT #define STRICT(from, nc, maxi, res) \ test_length (wchar_t (), __LINE__, 0, cvt_strict, from, nc, maxi, res) #undef RELAXD #define RELAXD(from, nc, maxi, res) \ test_length (wchar_t (), __LINE__, 0, cvt_relaxd, from, nc, maxi, res) #undef TEST #define TEST(from, nc, maxi, res) \ STRICT (from, nc, maxi, res); \ RELAXD (from, nc, maxi, res) // 22.2.1.5.2 [lib.locale.codecvt.virtuals] // including the resolution of lwg issue 305 // // -9- Preconditions: (from<=from_end) well-defined and true; state // initialized, if at the beginning of a sequence, or else equal // to the result of converting the preceding characters in the // sequence. // // -9a- Effects: The effect on the state argument is "as if" it called // do_in(state, from, from_end, from, to, to+max, to) for to pointing // to a buffer of at least max elements. // // -10- Returns: (from_next-from) where from_next is the largest value // in the range [from,from_end] such that the sequence of values // in the range [from,from_next) represents max or fewer valid // complete characters of type internT. The instantiation // codecvt<char, char, mbstate_t> returns the lesser of max // and (from_end-from). // Note that the function returns the number of externT characters // (i.e., those of type char for the required instantiations) // +--------------- source sequence of externT characters // | +-------- size of sequence in externT characters // | | +----- maximum number of internT characters // | | | +-- expected result in externT characters // | | | | // V V V V TEST (0, 0, 0, 0); TEST ("", 0, 0, 0); TEST ("a", 1, 0, 0); TEST ("ab", 2, 1, 1); TEST ("ab", 2, 2, 2); TEST ("ab", 2, 3, 2); TEST ("abc", 3, 0, 0); TEST ("abc", 3, 1, 1); TEST ("abc", 3, 2, 2); TEST ("abc", 3, 3, 3); TEST ("abc", 3, 4, 3); // invalid sequences rejected in both the strict and relaxed mode TEST ("\x80", 1, 0, 0); TEST ("\xc0", 1, 0, 0); TEST ("\x80\x00", 2, 0, 0); TEST ("\xc0\x00", 2, 0, 0); // valid 2-byte UTF-8 sequences (except for overlong sequences) // 110x xxxx 10xx xxxx // i.e., first byte: c0-df // second byte: 80-bf TEST ("\xc2", 1, 0, 0); TEST ("\xc2\x81", 1, 1, 0); TEST ("\xc2\x82", 2, 1, 2); TEST ("\xc2\x83", 2, 2, 2); // the second byte doesn't follow the correct pattern // and will be rejected in strict mode (but will be // accepted in relaxed mode) STRICT ("\xc2\x01", 2, 1, 0); RELAXD ("\xc2\x01", 2, 1, 2); TEST ("\xc2\x80\xc0", 3, 0, 0); TEST ("\xc2\x80\xc0\x81", 3, 1, 2); TEST ("\xc2\x80\xc0\x82", 3, 2, 2); STRICT ("\xc2\x80\xc2\x01", 4, 2, 2); RELAXD ("\xc2\x80\xc2\x01", 4, 2, 4); TEST ("\xc2\x80\xc2\x81", 4, 0, 0); TEST ("\xc2\x80\xc2\x82", 4, 1, 2); TEST ("\xc2\x80\xc2\x83", 4, 2, 4); TEST ("\xc2\x80\xc2\x84", 4, 3, 4); }
void do_test (charT) { rw_info (0, 0, 0, "checking whether objects are initialized"); // objects must exist rw_assert ( 0 != &std::cin && 0 != &std::cout && 0 != &std::cerr && 0 != &std::clog, 0, __LINE__, "std::cin, cout, cerr, or clog address 0"); rw_info (0, 0, __LINE__, "checking tied stream objects"); int new_0 = new_calls; // exercise 27.3.1, p2 rw_assert (&std::cout == std::cin.tie (&std::cout), 0, __LINE__, "&std::cout == std::cin.tie (&std::cout)"); rw_assert (0 == std::cout.tie (), 0, __LINE__, "0 == std::cout.tie ()"); rw_assert (0 == std::cerr.tie (), 0, __LINE__, "0 == std::cerr.tie ()"); rw_assert (0 == std::clog.tie (), 0, __LINE__, "0 == std::clog.tie ()"); rw_assert (0 == new_calls - new_0, 0, __LINE__, "unexpected dynamic memory allocation"); rw_info (0, 0, __LINE__, "checking for std::ios_base::unitbuf in flags"); new_0 = new_calls; // exercise 27.3.1, p3 rw_assert (!(std::ios::unitbuf & std::cout.flags ()), 0, __LINE__, "std::ios::unitbuf & std::cout.flags ()"); // exercise 27.3.1, p5 rw_assert (!!(std::ios::unitbuf & std::cerr.flags ()), 0, __LINE__, "std::ios::unitbuf & std::cerr.flags ()"); // exercise 27.3.1, p6 rw_assert (!(std::ios::unitbuf & std::clog.flags ()), 0, __LINE__, "std::ios::unitbuf & std::clog.flags ()"); rw_assert (0 == new_calls - new_0, 0, __LINE__, "unexpected dynamic memory allocation"); #ifndef _RWSTD_NO_WCHAR_T rw_assert ( 0 != &std::wcin && 0 != &std::wcout && 0 != &std::wcerr && 0 != &std::wclog, 0, __LINE__, "std::wcin, wcout, wcerr, or wclog address 0"); new_0 = new_calls; // exercise 27.3.2, p2 rw_assert (&std::wcout == std::wcin.tie (&std::wcout), 0, __LINE__, "&std::wcout == std::wcin.tie (&std::wcout)"); rw_assert (0 == std::wcout.tie (), 0, __LINE__, "0 == std::wcout.tie ()"); rw_assert (0 == std::wcerr.tie (), 0, __LINE__, "0 == std::wcerr.tie ()"); rw_assert (0 == std::wclog.tie (), 0, __LINE__, "0 == std::wclog.tie ()"); rw_assert (0 == new_calls - new_0, 0, __LINE__, "unexpected dynamic memory allocation"); new_0 = new_calls; // exercise 27.3.2, p3 rw_assert (!(std::wios::unitbuf & std::wcout.flags ()), 0, __LINE__, "std::wios::unitbuf & std::wcout.flags ()"); // exercise 27.3.2, p5 rw_assert (!!(std::wios::unitbuf & std::wcerr.flags ()), 0, __LINE__, "std::wios::unitbuf & std::wcerr.flags ()"); // exercise 27.3.2, p6 rw_assert (!(std::wios::unitbuf & std::wclog.flags ()), 0, __LINE__, "std::wios::unitbuf & std::wclog.flags ()"); rw_assert (0 == new_calls - new_0, 0, __LINE__, "unexpected dynamic memory allocation"); #endif // _RWSTD_NO_WCHAR_T std::cout << 0.0; std::cerr << 0.0; std::clog << 0.0; #ifndef _RWSTD_NO_WCHAR_T std::wcout << 0.0; std::wcerr << 0.0; std::wclog << 0.0; #endif // _RWSTD_NO_WCHAR_T std::cout << std::endl; rw_info (0, 0, __LINE__, "exercising the ability to tie each stream " "to itself without causing a deadlock"); std::cout.tie (&std::cout); std::cout << std::cout.tie () << ' '; std::cerr.tie (&std::cerr); std::cerr << std::cerr.tie () << ' '; std::clog.tie (&std::clog); std::clog << std::clog.tie () << ' '; #ifndef _RWSTD_NO_WCHAR_T std::wcout.tie (&std::wcout); std::wcout << std::wcout.tie () << ' '; std::wcerr.tie (&std::wcerr); std::wcerr << std::wcerr.tie () << ' '; std::wclog.tie (&std::wclog); std::wclog << std::wclog.tie () << ' '; #endif // _RWSTD_NO_WCHAR_T rw_info (0, 0, __LINE__, "exercising the ability to tie stream objects " "together without causing a deadlock"); std::cout.tie (&std::cerr); std::cout << std::cout.tie () << ' '; std::cerr.tie (&std::cout); std::cerr << std::cerr.tie () << ' '; std::clog.tie (&std::cout); std::clog << std::clog.tie () << ' '; // untie all streams to free any memory dynamically // allocated by calling tie (p) with (p != 0) std::cin.tie (0); std::cout.tie (0); std::cerr.tie (0); std::clog.tie (0); #ifndef _RWSTD_NO_WCHAR_T std::wcout.tie (&std::wcerr); std::wcout << std::wcout.tie () << ' '; std::wcerr.tie (&std::wcout); std::wcerr << std::wcerr.tie () << ' '; std::wclog.tie (&std::wcout); std::wclog << std::wclog.tie () << ' '; // untie all streams to free any memory dynamically // allocated by calling tie (p) with (p != 0) std::wcin.tie (0); std::wcout.tie (0); std::wcerr.tie (0); std::wclog.tie (0); #endif // _RWSTD_NO_WCHAR_T std::cout << std::endl; }
static int run_test (int, char**) { // 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); // array of locale names to use for testing const char* locales [sizeof punct_data / sizeof *punct_data]; const std::size_t maxinx = sizeof locales / sizeof *locales; // iterate over locales, initializing a global punct_data array for (const char *name = locale_list; *name; name += std::strlen (name) +1) { std::locale loc; MoneypunctData* const pdata = punct_data + nlocales; pdata->locale_name_ = name; locales [nlocales] = name; try { loc = std::locale (name); typedef std::moneypunct<char, false> Punct; const Punct &mp = std::use_facet<Punct>(loc); const char dp = mp.decimal_point (); const char ts = mp.thousands_sep (); const std::string grp = mp.grouping (); const std::string cur = mp.curr_symbol (); const std::string pos = mp.positive_sign (); const std::string neg = mp.negative_sign (); const int fd = mp.frac_digits (); const Punct::pattern pfm = mp.pos_format (); const Punct::pattern nfm = mp.neg_format (); pdata->decimal_point_ = dp; pdata->thousands_sep_ = ts; pdata->frac_digits_ = fd; std::strcpy (pdata->grouping_, grp.c_str ()); std::strcpy (pdata->curr_symbol_, cur.c_str ()); std::strcpy (pdata->positive_sign_, pos.c_str ()); std::strcpy (pdata->negative_sign_, neg.c_str ()); std::memcpy (pdata->pos_format_, &pfm, sizeof pfm); std::memcpy (pdata->neg_format_, &nfm, sizeof nfm); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } try { typedef std::moneypunct<char, true> Punct; const Punct &mp = std::use_facet<Punct>(loc); const std::string cur = mp.curr_symbol (); const int fd = mp.frac_digits (); const Punct::pattern pfm = mp.pos_format (); const Punct::pattern nfm = mp.neg_format (); pdata->int_frac_digits_ = fd; std::strcpy (pdata->int_curr_symbol_, cur.c_str ()); std::memcpy (pdata->int_pos_format_, &pfm, sizeof pfm); std::memcpy (pdata->int_neg_format_, &nfm, sizeof nfm); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } #ifndef _RWSTD_NO_WCHAR_T try { typedef std::moneypunct<wchar_t, false> Punct; const Punct &mp = std::use_facet<Punct>(loc); const wchar_t dp = mp.decimal_point (); const wchar_t ts = mp.thousands_sep (); const std::wstring cur = mp.curr_symbol (); const std::wstring pos = mp.positive_sign (); const std::wstring neg = mp.negative_sign (); pdata->wdecimal_point_ = dp; pdata->wthousands_sep_ = ts; typedef std::wstring::traits_type Traits; Traits::copy (pdata->wcurr_symbol_, cur.data (), cur.size ()); Traits::copy (pdata->wpositive_sign_, pos.data (), pos.size ()); Traits::copy (pdata->wnegative_sign_, neg.data (), neg.size ()); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } try { typedef std::moneypunct<wchar_t, true> Punct; const Punct &mp = std::use_facet<Punct>(loc); const std::wstring cur = mp.curr_symbol (); const std::wstring pos = mp.positive_sign (); const std::wstring neg = mp.negative_sign (); typedef std::wstring::traits_type Traits; Traits::copy (pdata->wint_curr_symbol_, cur.data (), cur.size ()); } catch (...) { rw_warn (0, 0, __LINE__, "std::locale(%#s) threw an exception, skipping", name); continue; } #endif // _RWSTD_NO_WCHAR_T ++nlocales; if (nlocales == maxinx) break; } // unless the number of iterations was explicitly specified // on the command line, decrease the number to equal the number // of excericsed locales when only one thread is being tested if (1 == opt_nthreads && opt_nloops < 0) opt_nloops = int (nlocales); // when the number of iterations wasn't explicitly specified // on the command line set it to the default value if (opt_nloops < 0) opt_nloops = DFLT_LOOPS; rw_fatal (0 < nlocales, 0, __LINE__, "must have at least one valid locale to test"); rw_info (0, 0, 0, "testing std::moneypunct<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::moneypunct<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::moneypunct<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::moneypunct<char> " "and std::moneypunct<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
static int run_test (int, char**) { // 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 punct_data / sizeof *punct_data; // iterate over locales, initializing a global punct_data array for (const char *name = locale_list; *name; name += std::strlen (name) +1) { const std::size_t inx = nlocales; locales [inx] = name; NumPunctData& data = punct_data [inx]; try { std::locale loc(name); data.locale_name_ = name; const std::numpunct<char> &np = std::use_facet<std::numpunct<char> >(loc); data.grouping_ = np.grouping (); data.decimal_point_ = np.decimal_point (); data.thousands_sep_ = np.thousands_sep (); data.truename_ = np.truename (); data.falsename_ = np.falsename (); #ifndef _RWSTD_NO_WCHAR_T const std::numpunct<wchar_t> &wp = std::use_facet<std::numpunct<wchar_t> >(loc); data.wdecimal_point_ = wp.decimal_point (); data.wthousands_sep_ = wp.thousands_sep (); data.wtruename_ = wp.truename (); data.wfalsename_ = wp.falsename (); #endif if (opt_shared_locale) data.locale_ = loc; nlocales += 1; } catch (...) { rw_warn (!rw_opt_locales, 0, __LINE__, "failed to create locale(%#s)", name); } if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales)) break; } // avoid divide by zero in thread if there are no locales to test rw_fatal (nlocales != 0, 0, __LINE__, "failed to create one or more usable locales!"); rw_info (0, 0, 0, "testing std::numpunct<charT> with %d thread%{?}s%{;}, " "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", opt_nthreads, 1 != opt_nthreads, opt_nloops, 1 != opt_nloops, nlocales, int (nlocales), "%#s", locales); rw_info (0, 0, 0, "exercising std::numpunct<char>"); test_char = true; test_wchar = false; // create and start a pool of threads and wait for them to finish int result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #ifndef _RWSTD_NO_WCHAR_T rw_info (0, 0, 0, "exercising std::numpunct<wchar_t>"); test_char = false; test_wchar = true; // start a pool of threads to exercise the thread safety // of the wchar_t specialization result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); // exercise both the char and the wchar_t specializations // at the same time rw_info (0, 0, 0, "exercising both std::numpunct<char> and std::numpunct<wchar_t>"); test_char = true; test_wchar = true; // start a pool of threads to exercise wstring thread safety result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, thread_func, 0, std::size_t (opt_timeout)); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, thread_func); #endif // _RWSTD_NO_WCHAR_T return result; }
static void test_move () { rw_info (0, __FILE__, __LINE__, "std::move() function"); }
static void test_forward () { rw_info (0, __FILE__, __LINE__, "std::forward() function"); }
static int run_test (int, char**) { rw_info (0, 0, 0, "exercising the contents of the <cerrno> header"); for (unsigned i = 0; errors [i]; ++i) { if(0!=errors) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing for i=%d",i); rw_assert (0 == errors [i], 0, 0, "macro %s", errors [i]); } } // get the type of errno const char* const errno_type = rw_any_t (errno).type_name (); if(!( 'i' == errno_type [0] && 'n' == errno_type [1]&& 't' == errno_type [2] && '\0' == errno_type [3])) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing "); } // 7.5, p2 of C99: the type of errno must be int rw_assert ( 'i' == errno_type [0] && 'n' == errno_type [1] && 't' == errno_type [2] && '\0' == errno_type [3], 0, 0, "the type of errno is int, got %s", errno_type); if(!(0 == errno_at_startup)) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing as errno is not 0 at program startup "); } // 7.5, p3 of C99: errno must be 0 at program startup rw_assert (0 == errno_at_startup, 0, 0, "errno == 0 at program startup, got %d", errno_at_startup); #ifndef EDOM # define EDOM 33 /* Solaris value */ #endif // EDOM // 7.5, p2 of C99: errno must be a modifiable lvalue set_errno_value (errno, int (EDOM)); if(!(EDOM == errno)) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing"); } rw_assert (EDOM == errno, 0, 0, "errno == %d (%{#*m}, got %d (%{#m}) " "(errno not a modifiable lvalue?)", EDOM, EDOM, errno, errno); #ifndef ERANGE # define ERANGE 34 /* Solaris value */ #endif // ERANGE set_errno_value (errno, int (ERANGE)); if(!(ERANGE == errno)) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing"); } rw_assert (ERANGE == errno, 0, 0, "errno == %d (%{#*m}, got %d (%{#m}) " "(errno not a modifiable lvalue?)", ERANGE, ERANGE, errno, errno); #ifndef EILSEQ # define EILSEQ 84 /* Solaris value */ #endif // EILSEQ set_errno_value (errno, int (EILSEQ)); if(!(EILSEQ == errno)) { failures++; std_log(LOG_FILENAME_LINE,"Reason : Failing"); } rw_assert (EILSEQ == errno, 0, 0, "errno == %d (%{#*m}, got %d (%{#m}) " "(errno not a modifiable lvalue?)", EILSEQ, EILSEQ, errno, errno); return 0; }
void run_test (intT, thr_args_base::tag_t tag) { static const char* const tname = rw_any_t (intT ()).type_name (); if (!rw_enabled (tname)) { rw_note (0, 0, 0, "%s test disabled", tname); return; } #ifdef _RWSTD_REENTRANT static const char* const fun = "__rw_atomic_exchange"; rw_info (0, 0, 0, "__rw::%s (%s&, %2$s): %d iterations in %d threads", fun, tname, rw_opt_nloops, rw_opt_nthreads); rw_thread_t tid [MAX_THREADS]; typedef thr_args<intT> Args; Args::nthreads_ = unsigned (rw_opt_nthreads); Args::type_tag_ = tag; Args::nincr_ = unsigned (rw_opt_nloops); Args::shared_ [0] = intT (1); Args::shared_ [1] = intT (1); _RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid); Args args [sizeof tid / sizeof *tid]; for (unsigned long i = 0; i != Args::nthreads_; ++i) { args [i].threadno_ = i; args [i].niter_ = 0; args [i].nxchg_ = 0; rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i), 0, __LINE__, "thread_create() failed"); } for (unsigned long i = 0; i != Args::nthreads_; ++i) { rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__, "thread_join() failed"); if (args [i].niter_) { // compute the percantage of thread iterations that resulted // in increments of one of the shared variables const unsigned long incrpcnt = (100U * Args::nincr_) / args [i].niter_; printf ("thread %lu performed %lu exchanges in %lu iterations " "(%lu%% increments)\n", args [i].threadno_, args [i].nxchg_, args [i].niter_, incrpcnt); } } // compute the expected result, "skipping" zeros by incrementing // expect twice when it overflows and wraps around to 0 (zero is // used as the lock variable in thread_routine() above) intT expect = intT (1); const unsigned long nincr = (Args::nthreads_ * Args::nincr_) / 2U; for (unsigned long i = 0; i != nincr; ++i) { if (intT () == ++expect) ++expect; } // verify that the final value of the variables shared among all // threads equals the number of increments performed by the threads rw_assert (Args::shared_ [0] == expect, 0, __LINE__, "1. %s (%s&, %2$s); %s == %s failed", fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect)); rw_assert (Args::shared_ [1] == expect, 0, __LINE__, "2. %s (%s&, %2$s); %s == %s failed", fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect)); #else // if !defined (_RWSTD_REENTRANT) _RWSTD_UNUSED (tag); #endif // _RWSTD_REENTRANT }