static void test_max_size_ctor1 () { rw_info (0, __FILE__, __LINE__, "21.3.1, p7"); // establish a chekpoint for memory leaks rwt_check_leaks (0, 0); int thrown = 0; try { // throws std::out_of_range if n > max_size () (*) // (*) see also lwg issue 83 String s1 (s0.data (), s0.max_size () + 1); } catch (int id) { thrown = _RWSTD_ERROR_LENGTH_ERROR == id; } catch (...) { /* empty */ } std::size_t nbytes; /* uninitialized */ std::size_t nblocks = rwt_check_leaks (&nbytes, 0); _RWSTD_UNUSED (nblocks); rw_assert (1 == thrown, __FILE__, __LINE__, "string::string (const char_type*, size_type) " "failed to use __rw::__rw_throw()"); rw_assert (0 == nbytes, __FILE__, __LINE__, "string::string (const char_type*, size_type)" "leaked %u bytes", nbytes); rw_assert (s == s0, __FILE__, __LINE__, "original const string modified"); }
static void test_replace3 () { rw_info (0, __FILE__, __LINE__, "21.3.5.6, p5"); int thrown = 0; String s1 (s0); const String::const_pointer s1_data = s1.data (); const String::size_type s1_size = s1.size (); const String::size_type s1_cap = s1.capacity (); // establish a chekpoint for memory leaks rwt_check_leaks (0, 0); try { // make sure max_size() isn't too big assert (s1.max_size () == _RWSTD_NEW_CAPACITY (String, &s1, 0)); thrown = -1; // must not throw String s2 (s1.max_size () - s1.size () + 2, Char ()); thrown = 0; // throws std::length_error if: // size () - xlen >= max_size () - rlen (*) // where xlen = min (n1, this->size () - pos1) // and rlen = min (n2, str.size () - pos2) // (*) see also lwg issue 86 s1.replace (0, 1, s2, 0, s2.size ()); } catch (int id) { thrown = 0 == thrown && _RWSTD_ERROR_LENGTH_ERROR == id; } catch (...) { /* empty */ } std::size_t nbytes; /* uninitialized */ std::size_t nblocks = rwt_check_leaks (&nbytes, 0); _RWSTD_UNUSED (nblocks); rw_assert (1 == thrown, __FILE__, __LINE__, "string::replace (size_type, size_type, const string&, " "size_type, size_type) failed to use __rw::__rw_throw()"); // verify that string wasn't modified rw_assert (s1_data == s1.data () && s1_size == s1.size () && s1_cap == s1.capacity (), __FILE__, __LINE__, "string::replace (size_type, size_type, const string&, " "size_type, size_type) modified *this"); // tests not only replace() but also string ctor (s2 above) rw_assert (1 == thrown, __FILE__, __LINE__, "string::replace (size_type, size_type, const string&, " "size_type, size_type) leaked %u bytes", nbytes); }
static void test_size_ctor () { rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (size)"); // establish a chekpoint for memory leaks rwt_check_leaks (0, 0); int thrown = 0; try { // throws std::out_of_range if pos > str.size () String s1 (s0, s0.size () + 1); } #ifndef _RWSTD_NO_EXCEPTIONS catch (std::out_of_range&) { thrown = 1; } #else // if defined (_RWSTD_NO_EXCEPTIONS) catch (int id) { thrown = id == _RWSTD_ERROR_OUT_OF_RANGE; } #endif // _RWSTD_NO_EXCEPTIONS catch (...) { thrown = -1; } std::size_t nbytes; /* uninitialized */ std::size_t nblocks = rwt_check_leaks (&nbytes, 0); _RWSTD_UNUSED (nblocks); rw_assert (1 == thrown, __FILE__, __LINE__, ("string::string (const string&, size_type, size_type, " "const allocator_type&) failed to throw std::out_of_range")); rw_assert (s == s0, __FILE__, __LINE__, "original const string modified"); rw_assert (0 == nbytes, __FILE__, __LINE__, "string::string (const string&, size_type, size_type, " "const allocator_type&) leaked %u bytes", nbytes); }
static void test_npos_ctor () { rw_info (0, __FILE__, __LINE__, "21.3.1, p4 (npos)"); _RW::__rw_throw_proc = user_throw; // establish a chekpoint for memory leaks rwt_check_leaks (0, 0); int thrown = 0; try { // throws std::out_of_range if pos > str.size () String s1 (s0, String::npos); } catch (int id) { thrown = _RWSTD_ERROR_OUT_OF_RANGE == id; } catch (...) { /* empty */ } std::size_t nbytes; /* uninitialized */ std::size_t nblocks = rwt_check_leaks (&nbytes, 0); _RWSTD_UNUSED (nblocks); rw_assert (1 == thrown, __FILE__, __LINE__, "string::string (const string&, size_type, size_type, " "const allocator_type&) failed to use __rw::__rw_throw()"); rw_assert (0 == nbytes, __FILE__, __LINE__, "string::string (const string&, size_type, size_type, " "const allocator_type&) leaked %u bytes", nbytes); rw_assert (s == s0, __FILE__, __LINE__, "original const string modified"); }
static void test_simple_throw () { rw_info (0, __FILE__, __LINE__, "exception handling test setup"); // establish a chekpoint for memory leaks rwt_check_leaks (0, 0); #ifdef _RWSTD_NO_EXCEPTIONS // prevent library from aborting if exception support is disabled _RW::__rw_throw_proc = user_throw; #endif // _RWSTD_NO_EXCEPTIONS int thrown = 0; try { // throw and catch a bogus exception in order to initialize // data structures internal to the library to prevent any // memory allocation from throwing off memory leak detection _RWSTD_REQUIRES (0, (_RWSTD_ERROR_OUT_OF_RANGE, _RWSTD_FUNC ("test_simple_throw ()"), 0, 0)); } #ifndef _RWSTD_NO_EXCEPTIONS catch (std::out_of_range&) { thrown = 1; } #else // if defined (_RWSTD_NO_EXCEPTIONS) catch (int id) { thrown = id == _RWSTD_ERROR_OUT_OF_RANGE; } #endif // _RWSTD_NO_EXCEPTIONS catch (...) { thrown = -1; } rw_assert (1 == thrown, __FILE__, __LINE__, "_RWSTD_REQUIRES (_RWSTD_ERROR_OUT_OF_RANGE) failed to " "throw std::out_of_range"); }
void test_success (T*, const char *tname) { RW_ASSERT (0 != tname); rw_info (0, 0, __LINE__, "std::get_temporary_buffer<%s>(ptrdiff_t)", tname); // verify that passing 0 as the argument either returns pair (0, 0) // or pair (p, N) with p being a unique pointer in consecutive calls // and N >= 0 static const unsigned pa_size = 32; #ifndef __HP_aCC std::pair<T*, std::ptrdiff_t> pa [pa_size]; #else // if defined (__HP_aCC) // working around an HP aCC bug (PR #27302) std::pair<T*, std::ptrdiff_t>* const pa = new std::pair<T*, std::ptrdiff_t>[pa_size]; #endif // __HP_aCC // establish a checkpoint for memory leaks rwt_check_leaks (0, 0); pa [0] = std::get_temporary_buffer<T>(0); if (pa [0].first) { std::memset (pa [0].first, ~0U, pa [0].second * sizeof (T)); pa [1] = std::get_temporary_buffer<T>(0); if (pa [1].first) std::memset (pa [1].first, ~1U, pa [1].second * sizeof (T)); rw_assert (pa [0].first != pa [1].first, 0, __LINE__, "get_temporary_buffer<%s>(0).first not unique: " "got %#p and %#p", tname, pa [0].first, pa [1].first); } else { rw_assert (0 == pa [0].second, 0, __LINE__, "get_temporary_buffer<%s>(0) == { 0, 0 }, got " "{ %#p, %td }", tname, pa [0].first, pa [0].second); } pa [2] = std::get_temporary_buffer<T>(2); rw_assert (0 != pa [2].first, 0, __LINE__, "get_temporary_buffer<%s>(2).first != 0, got 0", tname); if (0 == pa [2].first) return; std::memset (pa [2].first, ~2U, pa [2].second * sizeof (T)); rw_assert (2 <= pa [2].second, 0, __LINE__, "get_temporary_buffer<%s>(2).second >= 2, got %td", tname, pa [2].second); pa [3] = std::get_temporary_buffer<T>(3); rw_assert (0 != pa [3].first, 0, __LINE__, "get_temporary_buffer<%s>(3).first != 0, got 0", tname); if (!pa [3].first) return; rw_assert (3 <= pa [3].second, 0, __LINE__, "get_temporary_buffer<%s>(3).second >= 3, got %td", tname, pa [3].second); // verify correct alignment (if the storage isn't properly aligned, // expect SIGBUS on RISC machines, or SIGSEGV on HP-UX/PA-RISC) pa [3].first [0] = T (); pa [3].first [1] = T (); pa [3].first [2] = T (); std::memset (pa [3].first, ~3U, pa [3].second * sizeof (T)); // get the remaining temporary buffers and verify that they // are each distinct from one another for (unsigned i = 4; i != pa_size; ++i) { const std::ptrdiff_t size = std::ptrdiff_t (i % 2 ? i : _RWSTD_TMPBUF_SIZE + i); pa [i] = std::get_temporary_buffer<T>(size); if (pa [i].first) std::memset (pa [i].first, ~i, pa [i].second * sizeof (T)); } // verify the uniqueness of all ranges for (unsigned i = 0; i < pa_size; ++i) { for (unsigned j = 0; j < pa_size; ++j) { const bool fail = i != j && pa [i].first && pa [i].first >= pa [j].first && pa [i].first < pa [j].first + pa [j].second; rw_assert (!fail, 0, __LINE__, "pair { %#p, %td } returned from call %u overlaps " "pair { %#p, %td } returned from call %u", pa [i].first, pa [i].second, i, pa [j].first, pa [j].second, j); if (fail) { // break out of both loops i = j = unsigned (-1); } } } rw_info (0, 0, __LINE__, "std::return_temporary_buffer<%s>(%1$s*)", tname); // call return_temporary_buffer() on each returned pointer // and verify that the contents of the buffers pointed to // by all remaining unallocated pointers are unchanged for (unsigned i = 0; i < pa_size; ++i) { std::return_temporary_buffer (pa [i].first); for (unsigned j = i + 1; j < pa_size; ++j) { const bool success = 0 == compare (pa [j].first, pa [j].first + pa [j].second, ~j); rw_assert (success, 0, __LINE__, "return_temporary_buffer<%s>(%#p) corrupted " "a buffer designated by { %#p %td }", tname, pa [i].first, pa [j].first, pa [j].second); if (!success) { // break out of both loops i = j = unsigned (-1); } } } std::size_t nbytes; const std::size_t nblocks = rwt_check_leaks (&nbytes, 0); // verify the absence of memory leaks rw_assert (!nblocks && !nbytes, 0, __LINE__, "temporary buffer leaked %d bytes in %d blocks", nbytes, nblocks); #ifdef __HP_aCC delete[] pa; #endif // __HP_aCC }