static int _rw_vsystem (const char *cmd, va_list va) { RW_ASSERT (0 != cmd); char *buf = 0; rw_vasnprintf (&buf, 0, cmd, va); rw_note (0, "file:" __FILE__, __LINE__, "executing \"%s\"", buf); // avoid using const in order to prevent gcc warning on Linux // issued for WIFSIGNALED() et al: cast from `const int*' to // `int*' discards qualifiers from pointer target type: // see http://sourceware.org/bugzilla/show_bug.cgi?id=1392 /* const */ int ret = system (buf); if (ret) { #ifndef _WIN32 if (-1 == ret) { // system() failed, e.g., because fork() failed rw_error (0, __FILE__, __LINE__, "system (\"%s\") failed: errno = %{#m} (%{m})", buf); } else if (WIFSIGNALED (ret)) { // command exited with a signal const int signo = WTERMSIG (ret); rw_error (0, __FILE__, __LINE__, "the command \"%s\" exited with signal %d (%{K})", buf, signo, signo); } else { // command exited with a non-zero status const int status = WEXITSTATUS (ret); rw_error (0, __FILE__, __LINE__, "the command \"%s\" exited with status %d", buf, status); } #else // if defined (_WIN32) // FIXME: make this more descriptive rw_error (0, __FILE__, __LINE__, "the command \"%s\" failed with code %d", buf, ret); #endif // _WIN32 } free (buf); return ret; }
std::size_t winsock2_streambuf::write_some(const char_type * data, std::size_t count) { //if (!is_valid()) return 0; auto until = time_point::clock::now() + m_timeout; do { #ifdef EXT_ENABLE_OPENSSL if (ssl_started()) { int res = ::SSL_write(m_sslhandle, data, count); if (res > 0) return res; if (ssl_rw_error(res, m_lasterror)) return 0; continue; } #endif // EXT_ENABLE_OPENSSL int res = ::send(m_sockhandle, data, count, 0); if (res > 0) return res; if (rw_error(res, ::WSAGetLastError(), m_lasterror)) return 0; continue; } while (wait_readable(until)); return 0; }
std::size_t bsdsock_streambuf::read_some(char_type * data, std::size_t count) { //if (!is_valid()) return 0; auto until = time_point::clock::now() + m_timeout; do { #ifdef EXT_ENABLE_OPENSSL if (ssl_started()) { int res = ::SSL_read(m_sslhandle, data, count); if (res > 0) return res; if (ssl_rw_error(res, m_lasterror)) return 0; continue; } #endif // EXT_ENABLE_OPENSSL int res = ::recv(m_sockhandle, data, count, 0); if (res > 0) return res; if (rw_error(res, errno, m_lasterror)) return 0; continue; } while (wait_readable(until)); return 0; }
static int run_test (int, char*[]) { // exercise with the default setting of TOPDIR rw_error (0 == test_localedef (), 0, __LINE__, ""); // exercise with TOPDIR set but empty rw_putenv ("TOPDIR="); rw_error (0 == test_localedef (), 0, __LINE__, ""); // exercise with TOPDIR unset rw_putenv ("TOPDIR"); rw_error (0 == test_localedef (), 0, __LINE__, ""); return 0; }
// exercises a table-based multibyte encoding static void test_wcodecvt_byname_table_based () { const char* const locname = create_locale (); if (!rw_error (0 != locname, 0, __LINE__, "failed to create a locale database")) { return; } std::locale loc; _TRY { loc = std::locale (locname); } _CATCH (...) { rw_error (0, 0, __LINE__, "locale(\"%s\") unexpectedly threw an exception", locname); return; }
void test_assign (charT*, Traits*, Allocator*, const StringTestCaseData<charT> &tdata) { typedef std::basic_string<charT, Traits, Allocator> String; if (tdata.func_.which_ == Assign (range)) { switch (tdata.func_.iter_id_) { // exercise possible overloads of the member function template // on common RandomAccessIterator types #undef TEST #define TEST(Iterator) do { \ typedef typename String::Iterator Iter; \ static const \ AssignRangeOverload<String, Iter> rng; \ test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \ } while (0) case StringIds::Pointer: TEST (pointer); break; case StringIds::ConstPointer: TEST (const_pointer); break; case StringIds::Iterator: TEST (iterator); break; case StringIds::ConstIterator: TEST (const_iterator); break; case StringIds::ReverseIterator: TEST (reverse_iterator); break; case StringIds::ConstReverseIterator: TEST (const_reverse_iterator); break; // exercise specializations of the member function template // on the required iterator categories #undef TEST #define TEST(Iterator) do { \ typedef Iterator<charT> Iter; \ static const \ AssignRange<String, Iter> rng; \ test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); \ } while (0) case StringIds::Input: TEST (InputIter); break; case StringIds::Forward: TEST (ConstFwdIter); break; case StringIds::Bidir: TEST (ConstBidirIter); break; case StringIds::Random: TEST (ConstRandomAccessIter); break; default: rw_error (0, 0, __LINE__, "bad iterator id"); } } else { // exercise ordinary overloads of the member function static const RangeBase<String> rng; test_assign ((charT*)0, (Traits*)0, (Allocator*)0, rng, tdata); } }
bool winsock2_streambuf::wait_state(time_point until, int fstate) { int wsaerr; int solen; again: struct timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set read_set, write_set, err_set; fd_set * pread_set = nullptr; fd_set * pwrite_set = nullptr; if (fstate & freadable) { pread_set = &read_set; FD_ZERO(pread_set); FD_SET(m_sockhandle, pread_set); } if (fstate & fwritable) { pwrite_set = &write_set; FD_ZERO(pwrite_set); FD_SET(m_sockhandle, pwrite_set); } FD_ZERO(&err_set); FD_SET(m_sockhandle, &err_set); int res = ::select(m_sockhandle + 1, pread_set, pwrite_set, &err_set, &timeout); if (res == 0) // timeout { m_lasterror = make_error_code(sock_errc::timeout); return false; } if (res == -1) goto sockerror; assert(res >= 1); solen = sizeof(wsaerr); res = ::getsockopt(m_sockhandle, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&wsaerr), &solen); if (res != 0) goto sockerror; if (wsaerr != 0) goto wsaerror; return true; sockerror: wsaerr = ::WSAGetLastError(); wsaerror: if (rw_error(-1, wsaerr, m_lasterror)) return false; goto again; }
_TEST_EXPORT rw_pid_t rw_process_create (const char* path, char* const argv[]) { #if defined (_WIN32) return rw_process_create ("\"%s\" %{ As}", path, argv + 1); #else // #if !defined (_WIN32) if (0 == access (path, X_OK)) { const rw_pid_t child_pid = fork (); if (0 == child_pid) { // the child process execvp (path, argv); // the execvp returns only if an error occurs rw_fprintf (rw_stderr, "%s:%d execvp (%#s, %{As}) failed: " "errno = %{#m} (%{m})\n", __FILE__, __LINE__, path, argv); exit (1); } else if (-1 == child_pid) rw_error (0, __FILE__, __LINE__, "fork () failed: errno = %{#m} (%{m})"); return child_pid; } else rw_error (0, __FILE__, __LINE__, "access (%#s, X_OK) failed: errno = %{#m} (%{m})", path); return -1; #endif // #if defined (_WIN32) }
static rw_pid_t _rw_vprocess_create (const char* cmd, va_list va) { RW_ASSERT (0 != cmd); char *buf = 0; rw_vasnprintf (&buf, 0, cmd, va); rw_pid_t ret = -1; #ifdef _WIN32 STARTUPINFO si = { sizeof (si) }; PROCESS_INFORMATION pi; if (CreateProcess (0, buf, 0, 0, FALSE, CREATE_NEW_PROCESS_GROUP, 0, 0, &si, &pi)) { CloseHandle (pi.hThread); ret = rw_pid_t (pi.hProcess); } else { const DWORD err = GetLastError (); rw_error (0, __FILE__, __LINE__, "CreateProcess () failed: GetLastError() = %zu", size_t (err)); errno = _rw_map_errno (err); } #else // #if !defined (_WIN32) const size_t MAX_PARAMS = 63; char* argv [MAX_PARAMS + 1] = { 0 }; size_t argc = _rw_split_cmd (buf, argv, MAX_PARAMS); if (0 < argc && MAX_PARAMS >= argc) ret = rw_process_create (argv [0], argv); else errno = E2BIG; #endif // _WIN32 free (buf); return ret; }
bool bsdsock_streambuf::wait_state(time_point until, int fstate) { int err; sockoptlen_t solen; again: struct timeval timeout; make_timeval(timeout, until - time_point::clock::now()); fd_set read_set, write_set; fd_set * pread_set = nullptr; fd_set * pwrite_set = nullptr; if (fstate & freadable) { pread_set = &read_set; FD_ZERO(pread_set); FD_SET(m_sockhandle, pread_set); } if (fstate & fwritable) { pwrite_set = &write_set; FD_ZERO(pwrite_set); FD_SET(m_sockhandle, pwrite_set); } int res = ::select(m_sockhandle + 1, pread_set, pwrite_set, nullptr, &timeout); if (res == 0) // timeout { m_lasterror = make_error_code(sock_errc::timeout); return false; } if (res == -1) goto sockerror; solen = sizeof(err); res = ::getsockopt(m_sockhandle, SOL_SOCKET, SO_ERROR, &err, &solen); if (res != 0) goto sockerror; if (err != 0) goto error; return true; sockerror: err = errno; error: if (rw_error(-1, err, m_lasterror)) return false; goto again; }
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 locales / sizeof *locales; for (const char *name = locale_list; *name; name += std::strlen (name) +1) { locales [nlocales++] = name; if (nlocales == maxinx) break; } int result; rw_info (0, 0, 0, "testing std::locale ctors 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); // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, test_ctors, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, test_ctors); return result; }
_TEST_EXPORT int rw_process_kill (rw_pid_t pid, int signo) { // timeout for rw_wait_pid const int timeout = 1; #if defined (_WIN32) // send signal if (!TerminateProcess (HANDLE (pid), DWORD (signo))) { const DWORD err = GetLastError (); rw_error (0, __FILE__, __LINE__, "TerminateProcess (%{P}, %i) failed: GetLastError() = %zu", pid, signo, size_t (err)); if (ERROR_INVALID_HANDLE == err) errno = ESRCH; else if (ERROR_ACCESS_DENIED == err) errno = EPERM; else errno = _rw_map_errno (err); return -1; } // wait for process termination rw_pid_t res = rw_waitpid (pid, 0, timeout); if (pid == res) return 0; if (-1 == res) rw_error (0, __FILE__, __LINE__, "rw_waitpid (%{P}, 0, %i) failed: errno = %{#m} (%{m})", pid, timeout); return 1; #else // #if !defined (_WIN32) static const int signals_ [] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGKILL }; const int* const signals = (-1 == signo) ? signals_ : &signo; const unsigned sigcount = (-1 == signo) ? sizeof (signals_) / sizeof (*signals_) : 1; int ret = -1; for (unsigned i = 0; i < sigcount; ++i) { // send signal ret = kill (pid, signals [i]); if (-1 == ret) { rw_error (0, __FILE__, __LINE__, "kill (%{P}, %{K}) failed: errno = %{#m} (%{m})", pid, signals [i]); continue; } // wait for process termination rw_pid_t res = rw_waitpid (pid, 0, timeout); if (pid == res) return 0; if (-1 == res) rw_error (0, __FILE__, __LINE__, "rw_waitpid (%{P}, 0, %i) failed: errno = %{#m} (%{m})", pid, timeout); ret = 1; } return ret; #endif // #if defined (_WIN32) }
_TEST_EXPORT rw_pid_t rw_waitpid (rw_pid_t pid, int* presult, int timeout/* = -1*/) { #ifdef _RWSTD_EDG_ECCP # define _RWSTD_NO_SIGACTION #endif #ifndef _RWSTD_NO_SIGACTION struct sigaction prev_alarm_action; #else signal_handler_t prev_alarm_handler = 0; #endif int prev_alarm_timeout = 0; alarm_timeout = 0; if (0 < timeout) { #ifndef _RWSTD_NO_SIGACTION struct sigaction alarm_action; memset (&alarm_action, 0, sizeof alarm_action); const signal_handler_t handler_fun = handle_alarm_signal; memcpy (&alarm_action.sa_handler, &handler_fun, sizeof alarm_action.sa_handler); sigaction (SIGALRM, &alarm_action, &prev_alarm_action); #else prev_alarm_handler = signal (SIGALRM, handle_alarm_signal); #endif prev_alarm_timeout = alarm (timeout); } int result = 0; if (!presult) presult = &result; const time_t start = time(0); int status = 0; rw_pid_t ret = 0; do { ret = waitpid (pid, &status, 0); if (-1 == ret) { if (EINTR == errno && alarm_timeout) { // we are expected to return 0 on timeout ret = 0; } else if (EINTR == errno) { rw_warn (0, __FILE__, __LINE__, "waitpid (%{P}, %#p, 0) interrupted: " "errno = %{#m} (%{m})", pid, &status); continue; // try again } else { rw_error (0, __FILE__, __LINE__, "waitpid (%{P}, %#p, 0) failed: " "errno = %{#m} (%{m})", pid, &status); } } else if (ret == pid) { if (WIFSIGNALED (status)) { // process exited with a signal const int signo = WTERMSIG (status); rw_error (0, __FILE__, __LINE__, "the process (pid=%{P}) exited with signal %d (%{K})", pid, signo, signo); *presult = signo; } else if (WIFEXITED (status)) { // process exited with a status const int retcode = WEXITSTATUS (status); if (retcode) rw_error (0, __FILE__, __LINE__, "the process (pid=%{P}) exited with return code %d", pid, retcode); *presult = retcode; } else { *presult = -1; } } else { *presult = -1; } } while(false); if (0 < timeout) { if (prev_alarm_timeout) { const int delta = time(0) - start; if (delta < prev_alarm_timeout) prev_alarm_timeout -= delta; else prev_alarm_timeout = 1; } alarm (prev_alarm_timeout); #ifndef _RWSTD_NO_SIGACTION sigaction (SIGALRM, &prev_alarm_action, 0); #else signal (SIGALRM, prev_alarm_handler); #endif } return ret; }
_TEST_EXPORT rw_pid_t rw_waitpid (rw_pid_t pid, int* result, int timeout/* = -1*/) { /* Explicitly check for process_id being -1 or -2. In Windows NT, * -1 is a handle on the current process, -2 is a handle on the * current thread, and it is perfectly legal to to wait (forever) * on either */ if (-1 == pid || -2 == pid) { errno = ECHILD; return -1; } const HANDLE handle = HANDLE (pid); const DWORD milliseconds = 0 > timeout ? INFINITE : DWORD (timeout * 1000); const DWORD res = WaitForSingleObject (handle, milliseconds); DWORD err = ERROR_SUCCESS; if (WAIT_OBJECT_0 == res) { DWORD dwExitCode; if (GetExitCodeProcess (handle, &dwExitCode)) { CloseHandle (handle); if (dwExitCode) rw_error (0, __FILE__, __LINE__, "the process (pid=%{P}) exited with return code %d", pid, int (dwExitCode)); if (result) *result = int (dwExitCode); return pid; } err = GetLastError (); rw_error (0, __FILE__, __LINE__, "GetExitCodeProcess (%{P}, %#p) failed: GetLastError() = %zu", pid, &dwExitCode, size_t (err)); } else if (WAIT_FAILED == res) { err = GetLastError (); rw_error (0, __FILE__, __LINE__, "WaitForSingleObject (%{P}, %{?}INFINITE%{:}%zu%{;}) failed: " "GetLastError() = %zu", pid, INFINITE == milliseconds, size_t (milliseconds), size_t (err)); } else { // time-out elapsed RW_ASSERT (WAIT_TIMEOUT == res); return 0; } if (ERROR_INVALID_HANDLE == err) errno = ECHILD; else errno = _rw_map_errno (err); return -1; }
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 int run_test (int, char**) { for (std::size_t i = 0; i != opt_nfacets; ++i) { if (0 < opt_facets [i]) { for (std::size_t j = 0; j != opt_nfacets; ++j) { if (opt_facets [j] == 0) opt_facets [j] = -1; } break; } } rw_note (0 <= opt_facets [opt_inx_codecvt], 0, __LINE__, "std::codecvt tests disabled"); rw_note (0 <= opt_facets [opt_inx_collate], 0, __LINE__, "std::collate tests disabled"); rw_note (0 <= opt_facets [opt_inx_ctype], 0, __LINE__, "std::ctype tests disabled"); rw_note (0 <= opt_facets [opt_inx_messages], 0, __LINE__, "std::messages tests disabled"); rw_note (0 <= opt_facets [opt_inx_moneypunct], 0, __LINE__, "std::moneypunct<charT, false> tests disabled"); rw_note (0 <= opt_facets [opt_inx_moneypunct_intl], 0, __LINE__, "std::moneypunct<charT, true> tests disabled"); rw_note (0 <= opt_facets [opt_inx_money_get], 0, __LINE__, "std::money_get tests disabled"); rw_note (0 <= opt_facets [opt_inx_money_put], 0, __LINE__, "std::money_put tests disabled"); rw_note (0 <= opt_facets [opt_inx_numpunct], 0, __LINE__, "std::numpunct tests disabled"); rw_note (0 <= opt_facets [opt_inx_num_get], 0, __LINE__, "std::num_get tests disabled"); rw_note (0 <= opt_facets [opt_inx_num_put], 0, __LINE__, "std::num_put tests disabled"); rw_note (0 <= opt_facets [opt_inx_time_get], 0, __LINE__, "std::time_get tests disabled"); rw_note (0 <= opt_facets [opt_inx_time_put], 0, __LINE__, "std::time_put tests disabled"); rw_note (0 == opt_no_exceptions, 0, __LINE__, "tests involving exceptions disabled"); // 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; // set to true if the classic "C" locale is on the lost bool has_classic = false; for (const char *name = locale_list; *name; name += std::strlen (name) +1) { locales [nlocales++] = name; if (!has_classic && 0 == std::strcmp ("C", name)) has_classic = true; if (nlocales == maxinx) break; } // when the classic "C" locale isn't on the list put it there // unless the list was explicitly specified on the command line if (1 < nlocales && !has_classic && 0 == rw_opt_locales) locales [0] = "C"; int result; rw_info (0, 0, 0, "testing std::locale globals 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); if (opt_has_facet >= 0) { rw_info (0, 0, 0, "template <class T> bool std::has_facet (const locale&)"); // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, test_has_facet, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, test_has_facet); } else { rw_note (0, 0, 0, "std::has_facet test disabled"); } if (opt_use_facet >= 0) { rw_info (0, 0, 0, "template <class T> const T& std::use_facet (const locale&)"); #ifdef _RWSTD_NO_DYNAMIC_CAST // if dynamic_cast isn't supported, then [has,use]_facet() // can't reliably detect if a facet is installed or not. rw_warn (0 != opt_no_exceptions, 0, __LINE__, "dynamic_cast not supported " "(macro _RWSTD_NO_DYNAMIC_CAST is #defined), " "disabling exceptions tests"); opt_no_exceptions = 1; #endif // _RWSTD_NO_DYNAMIC_CAST #ifdef _RWSTD_NO_THREAD_SAFE_EXCEPTIONS // avoid exercising exceptions (triggered by use_facet) if // their implementation in the runtime isn't thread-safe rw_warn (0, 0, 0, "exceptions not thread safe (macro " "_RWSTD_NO_THREAD_SAFE_EXCEPTIONS is #defined), " "disabling exceptions tests"); opt_no_exceptions = 1; #endif // _RWSTD_NO_THREAD_SAFE_EXCEPTIONS // create and start a pool of threads and wait for them to finish result = rw_thread_pool (0, std::size_t (opt_nthreads), 0, test_use_facet, 0); rw_error (result == 0, 0, __LINE__, "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", opt_nthreads, test_use_facet); } else { rw_note (0, 0, 0, "std::use_facet test disabled"); } return result; }
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; }
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**) { 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 money and results for this locale MyMoneyData& data = my_money_data [inx]; data.locale_name_ = name; try { const std::locale loc (data.locale_name_); // initialize with random but valid values data.money_value_ = inx; data.type_ = MyMoneyData::PutId (nlocales % MyMoneyData::put_max); data.money_index_ = inx % RW_COUNT_OF (n_money_vals); // exercise domestic formats every other iteration // and international formats the rest data.intl_ = 0 == (inx & 1); // exercise postive and negative values if (inx & 1) data.money_value_ *= -1.; // add some random fractional digits if (inx & 2) data.money_value_ += data.money_value_ / 3.14; const std::money_put<char> &np = std::use_facet<std::money_put<char> >(loc); nio.imbue (loc); nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); switch (data.type_) { case MyMoneyData::put_ldbl: *np.put (std::ostreambuf_iterator<char>(&nsb), data.intl_, nio, ' ', data.money_value_) = '\0'; break; case MyMoneyData::put_string: *np.put (std::ostreambuf_iterator<char>(&nsb), data.intl_, nio, ' ', n_money_vals [data.money_index_]) = '\0'; break; case MyMoneyData::put_max: // avoid enumeration value `put_max' not handled in switch // this case should never happen break; } rw_assert (!nio.fail (), __FILE__, __LINE__, "money_put<char>::put(...) " "failed for locale(%#s)", data.locale_name_); #ifndef _RWSTD_NO_WCHAR_T const std::money_put<wchar_t> &wp = std::use_facet<std::money_put<wchar_t> >(loc); wio.imbue (loc); wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); switch (data.type_) { case MyMoneyData::put_ldbl: *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb), data.intl_, wio, L' ', data.money_value_) = '\0'; break; case MyMoneyData::put_string: *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb), data.intl_, wio, L' ', w_money_vals [data.money_index_]) = L'\0'; break; case MyMoneyData::put_max: // avoid enumeration value `put_max' not handled in switch // this case should never happen break; } rw_assert (!nio.fail (), __FILE__, __LINE__, "money_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::money_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::money_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, 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::money_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, 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::money_put<char> " "and std::money_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, 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; }
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 }