Author: sebor
Date: Tue Jan 24 13:03:38 2006
New Revision: 372017
URL: http://svn.apache.org/viewcvs?rev=372017&view=rev
Log:
2006-01-24 Liviu Nicoara <[EMAIL PROTECTED]>
Martin Sebor <[EMAIL PROTECTED]>
STDCXX-4
* 0.new.cpp: New test exercising the testsuite's replacement operators
new and delete.
Added:
incubator/stdcxx/trunk/tests/self/0.new.cpp (with props)
Added: incubator/stdcxx/trunk/tests/self/0.new.cpp
URL:
http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/self/0.new.cpp?rev=372017&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.new.cpp (added)
+++ incubator/stdcxx/trunk/tests/self/0.new.cpp Tue Jan 24 13:03:38 2006
@@ -0,0 +1,505 @@
+/***************************************************************************
+ *
+ * 0.new.cpp - test exercising replacement operator new and delete
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
+ * applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under
+ * the License.
+ *
+ **************************************************************************/
+
+#include <new> // for bad_alloc
+
+#include <cstddef> // for size_t
+
+#include <setjmp.h> // for longjmp(), setjmp()
+#include <signal.h> // for SIGABRT, signal()
+
+#include <rw_new.h>
+#include <driver.h>
+
+/**************************************************************************/
+
+// program exit status
+int exit_status /* = 0 */;
+
+extern "C" {
+
+volatile int line; // currently executed line
+volatile int fail; // non-zero when line failed
+
+jmp_buf env;
+
+static void
+handle_ABRT (int)
+{
+ fail = 0;
+
+ longjmp (env, 1);
+}
+
+}
+
+#define FAIL(code) \
+ fail = line = __LINE__; \
+ signal (SIGABRT, handle_ABRT); \
+ if (0 == setjmp (env)) { \
+ code; \
+ exit_status = 1; \
+ rw_assert (0, __FILE__, line, "expected assertion"); \
+ } \
+ else \
+ (void)0
+
+#define PASS(code) \
+ fail = -1; line = __LINE__; \
+ signal (SIGABRT, handle_ABRT); \
+ if (0 == setjmp (env)) { \
+ code; \
+ } \
+ else if (fail != line) { \
+ exit_status = 1; \
+ rw_assert (0, __FILE__, line, "unexpected assertion"); \
+ } (void)0
+
+/**************************************************************************/
+
+void test_new_delete ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising successful allocation and deallocation");
+
+ {
+ void *p = 0;
+ PASS (p = operator new (0));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new(0) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ PASS (p = operator new (1));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new(1) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ PASS (p = operator new (2));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new(2) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ PASS (p = operator new (1024));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new(1024) != 0");
+ operator delete (p);
+ }
+}
+
+/**************************************************************************/
+
+#define CATCH(code) \
+ try { code; fail = 1; } \
+ catch (_RWSTD_BAD_ALLOC) { fail = 0; } \
+ catch (...) { fail = 2; } \
+ rw_assert (!fail, __FILE__, __LINE__, \
+ "%s", 1 == fail ? "failed to throw" : \
+ "threw an unknown exception")
+
+#define NOTHROW(code) \
+ try { fail = 0; code; } \
+ catch (...) { fail = 1; } \
+ rw_assert (!fail, __FILE__, __LINE__, \
+ "unexpected exception")
+
+void test_bad_alloc ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability of ordinary "
+ "operator new to throw std::bad_alloc");
+
+ rwt_free_store* const pst = rwt_get_free_store (0);
+
+ *pst->throw_at_blocks_ [0] = pst->blocks_ [0];
+
+ CATCH (operator new (0));
+ CATCH (operator new (1));
+ CATCH (operator new (2));
+ CATCH (operator new (1024));
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new[](0));
+ operator delete[](p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new[](1));
+ operator delete[](p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new[](2));
+ operator delete[](p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new[](1024));
+ operator delete[](p);
+ }
+
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability of the array form "
+ "of operator new to throw std::bad_alloc");
+
+ *pst->throw_at_blocks_ [0] = std::size_t (-1);
+ *pst->throw_at_blocks_ [1] = pst->blocks_ [1];
+
+ CATCH (operator new[](0));
+ CATCH (operator new[](1));
+ CATCH (operator new[](2));
+ CATCH (operator new[](1024));
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new (0));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new[](0) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new (1));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new[](1) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new (32));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new[](32) != 0");
+ operator delete (p);
+ }
+
+ {
+ void *p = 0;
+ NOTHROW (p = operator new (4096));
+ rw_assert (p != 0, __FILE__, __LINE__, "operator new[](4096) != 0");
+ operator delete (p);
+ }
+
+ *pst->throw_at_blocks_ [1] = std::size_t (-1);
+}
+
+/**************************************************************************/
+
+void test_mismatch ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability to detect "
+ "allocation/deallocation mismatches");
+
+ {
+ // detect allocations by operator new() deallocated
+ // using (the array form of) operator delete[]
+ void *p = 0;
+ PASS (p = operator new (0));
+ FAIL (operator delete[](p));
+ PASS (operator delete (p));
+ }
+
+ {
+ void *p = 0;
+ PASS (p = operator new (1));
+ FAIL (operator delete[](p));
+ PASS (operator delete (p));
+ }
+
+ {
+ void *p = 0;
+ PASS (p = operator new[](33));
+ FAIL (operator delete (p));
+ PASS (operator delete[] (p));
+ }
+}
+
+/**************************************************************************/
+
+void test_bad_delete ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability to detect "
+ "deletion of unallocated storage");
+
+ {
+ char *p = 0;
+ PASS (p = new char);
+
+ FAIL (delete (p - 1));
+ FAIL (delete (p + 1));
+
+ PASS (delete (p));
+ }
+
+ {
+ char *p = 0;
+ PASS (p = new char [4]);
+
+ FAIL (delete (p - 1));
+ FAIL (delete (p + 1));
+ FAIL (delete (p + 2));
+ FAIL (delete (p + 3));
+ FAIL (delete (p + 4));
+
+ FAIL (delete[] (p - 1));
+ FAIL (delete[] (p + 1));
+ FAIL (delete[] (p + 2));
+ FAIL (delete[] (p + 3));
+ FAIL (delete[] (p + 4));
+
+ PASS (delete[] p);
+ }
+}
+
+/**************************************************************************/
+
+void test_double_delete ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability to detect double deletion");
+
+ {
+ char *p = 0;
+ PASS (p = new char);
+
+ PASS (delete (p));
+ FAIL (delete (p));
+ }
+
+ {
+ char *p = 0;
+ PASS (p = new char [32]);
+
+ PASS (delete[] p);
+ FAIL (delete[] p);
+ FAIL (delete p);
+ }
+}
+
+/**************************************************************************/
+
+void test_corruption ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability to detect memory corruption");
+
+ // corrupt (and restore) memory past the end of the allocated block
+ for (std::size_t i = 1; i != 8; ++i) {
+ char *p = 0;
+ PASS (p = new char);
+
+ // save the value of the byte past the end of the block
+ // and temporarily overwrite it with another value
+ const char save = p [i];
+ p [i] = ~p [i];
+
+ // expect operator delete to diagnose the corruption
+ // and call abort() without actually freeing the block
+ FAIL (delete p);
+
+ // restore the corrupted byte to its original value
+ p [i] = save;
+
+ // expect operator delete not to complain
+ PASS (delete p);
+ }
+}
+
+/**************************************************************************/
+
+#define LEAK(code, bytes, blks) \
+ do { \
+ /* establish a checkpoint for memory leaks */ \
+ rwt_check_leaks (0, 0); \
+ \
+ code; \
+ \
+ /* find memory leaks since the last checkpoint */ \
+ std::size_t nbytes; \
+ const std::size_t nblocks = rwt_check_leaks (&nbytes, 0); \
+ \
+ rw_assert (blks == nblocks && bytes == nbytes, \
+ __FILE__, __LINE__, \
+ "failed to detect a leak of %d bytes in " \
+ "%d blocks: got %zu bytes in %zu blocks", \
+ bytes, blks, nbytes, nblocks); \
+ } while (0)
+
+
+void test_leaks ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "exercising the ability to detect memory leaks");
+
+ {
+ void *p = 0;
+ LEAK (p = operator new (0), 0, 1);
+ PASS (operator delete (p));
+ }
+
+ {
+ void *p = 0;
+ LEAK (p = operator new (1), 1, 1);
+ PASS (operator delete (p));
+ }
+
+ {
+ void *p = 0;
+ LEAK (p = operator new (1234), 1234, 1);
+ PASS (operator delete (p));
+ }
+
+ {
+ void *p0 = 0;
+ void *p1 = 0;
+ LEAK (p0 = operator new (32);
+ p1 = operator new (64), 96, 2);
+ PASS (operator delete (p0));
+ PASS (operator delete (p1));
+ }
+
+ {
+ void *p = 0;
+ LEAK (p = operator new[] (12345), 12345, 1);
+ PASS (operator delete[] (p));
+ }
+}
+
+/**************************************************************************/
+
+void test_stress ()
+{
+ rw_info (0, __FILE__, __LINE__,
+ "stress-testing replacement operators new and delete");
+
+ rwt_free_store* const pst = rwt_get_free_store (0);
+
+ std::size_t nblocks = pst->blocks_ [0] + pst->blocks_ [1];
+ std::size_t nbytes = pst->bytes_ [0] + pst->bytes_ [1];
+
+ void* ptrs [1000];
+
+ const std::size_t N = sizeof ptrs / sizeof *ptrs;
+
+ for (std::size_t i = 0; i != N; ++i) {
+ if (i % 2) {
+ PASS (ptrs [i] = operator new[](i));
+ }
+ else {
+ PASS (ptrs [i] = operator new (i));
+ }
+ }
+
+ for (std::size_t i = 0; i < N; ++i) {
+
+ const std::size_t j = (i * (i + 17)) % N;
+
+ if (j % 2) {
+ PASS (operator delete[](ptrs [j]));
+ }
+ else {
+ PASS (operator delete (ptrs [j]));
+ }
+
+ ptrs [j] = 0;
+ }
+
+ for (std::size_t i = 0; i < N; ++i) {
+ if (i % 2) {
+ PASS (operator delete[](ptrs [i]));
+ }
+ else {
+ PASS (operator delete (ptrs [i]));
+ }
+ }
+
+ nblocks = pst->blocks_ [0] + pst->blocks_ [1] - nblocks;
+ nbytes = pst->bytes_ [0] + pst->bytes_ [1] - nbytes;
+
+ rw_assert (0 == nblocks && 0 == nbytes, __FILE__, __LINE__,
+ "false leaks detected: %zu bytes in %zu blocks",
+ nbytes, nblocks);
+}
+
+/**************************************************************************/
+
+static int rw_opt_no_new_delete; // for --no-new-delete
+static int rw_opt_no_bad_alloc; // for --no-bad_alloc
+static int rw_opt_no_mismatch; // for --no-mismatch
+static int rw_opt_no_bad_delete; // for --no-bad-delete
+static int rw_opt_no_double_delete; // for --no-double-delete
+static int rw_opt_no_corruption; // for --no-corruption
+static int rw_opt_no_leaks; // for --no-leaks
+static int rw_opt_no_stress; // for --no-stress
+
+int run_test (int, char**)
+{
+#define TEST(name) \
+ if (rw_opt_no_ ## name) \
+ rw_note (0, 0, __LINE__, "%s test disabled", #name); \
+else \
+ test_ ## name ()
+
+
+ TEST (bad_alloc);
+ TEST (mismatch);
+ TEST (double_delete);
+ TEST (bad_delete);
+ TEST (corruption);
+ TEST (leaks);
+ TEST (stress);
+
+ return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char** argv)
+{
+ return rw_test (argc, argv, __FILE__,
+ 0 /* no clause */,
+ 0 /* no comment */,
+ run_test,
+ "|-no-new-delete# "
+ "|-no-bad_alloc# "
+ "|-no-mismatch# "
+ "|-no-bad-delete# "
+ "|-no-double-delete# "
+ "|-no-corruption# "
+ "|-no-leaks# "
+ "|-no-stress-test#",
+ &rw_opt_no_new_delete,
+ &rw_opt_no_bad_alloc,
+ &rw_opt_no_mismatch,
+ &rw_opt_no_bad_delete,
+ &rw_opt_no_double_delete,
+ &rw_opt_no_corruption,
+ &rw_opt_no_leaks,
+ &rw_opt_no_stress);
+}
Propchange: incubator/stdcxx/trunk/tests/self/0.new.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/self/0.new.cpp
------------------------------------------------------------------------------
svn:keywords = Id