You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by hb...@apache.org on 2017/01/17 19:31:01 UTC
[07/51] [partial] incubator-quickstep git commit: Added shell script
to download prerequisite third party libs
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/debugallocation_test.cc
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/debugallocation_test.cc b/third_party/gperftools/src/tests/debugallocation_test.cc
deleted file mode 100644
index d935dbb..0000000
--- a/third_party/gperftools/src/tests/debugallocation_test.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// Author: Fred Akalin
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h> // for memcmp
-#include <vector>
-#include "gperftools/malloc_extension.h"
-#include "gperftools/tcmalloc.h"
-#include "base/logging.h"
-
-using std::vector;
-
-vector<void (*)()> g_testlist; // the tests to run
-
-#define TEST(a, b) \
- struct Test_##a##_##b { \
- Test_##a##_##b() { g_testlist.push_back(&Run); } \
- static void Run(); \
- }; \
- static Test_##a##_##b g_test_##a##_##b; \
- void Test_##a##_##b::Run()
-
-
-static int RUN_ALL_TESTS() {
- vector<void (*)()>::const_iterator it;
- for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
- (*it)(); // The test will error-exit if there's a problem.
- }
- fprintf(stderr, "\nPassed %d tests\n\nPASS\n",
- static_cast<int>(g_testlist.size()));
- return 0;
-}
-
-// The death tests are meant to be run from a shell-script driver, which
-// passes in an integer saying which death test to run. We store that
-// test-to-run here, and in the macro use a counter to see when we get
-// to that test, so we can run it.
-static int test_to_run = 0; // set in main() based on argv
-static int test_counter = 0; // incremented every time the macro is called
-#define IF_DEBUG_EXPECT_DEATH(statement, regex) do { \
- if (test_counter++ == test_to_run) { \
- fprintf(stderr, "Expected regex:%s\n", regex); \
- statement; \
- } \
-} while (false)
-
-// This flag won't be compiled in in opt mode.
-DECLARE_int32(max_free_queue_size);
-
-// Test match as well as mismatch rules. But do not test on OS X; on
-// OS X the OS converts new/new[] to malloc before it gets to us, so
-// we are unable to catch these mismatch errors.
-#ifndef __APPLE__
-TEST(DebugAllocationTest, DeallocMismatch) {
- // malloc can be matched only by free
- // new can be matched only by delete and delete(nothrow)
- // new[] can be matched only by delete[] and delete[](nothrow)
- // new(nothrow) can be matched only by delete and delete(nothrow)
- // new(nothrow)[] can be matched only by delete[] and delete[](nothrow)
-
- // Allocate with malloc.
- {
- int* x = static_cast<int*>(malloc(sizeof(*x)));
- IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete");
- IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]");
- // Should work fine.
- free(x);
- }
-
- // Allocate with new.
- {
- int* x = new int;
- int* y = new int;
- IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
- IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]");
- delete x;
- ::operator delete(y, std::nothrow);
- }
-
- // Allocate with new[].
- {
- int* x = new int[1];
- int* y = new int[1];
- IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
- IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete");
- delete [] x;
- ::operator delete[](y, std::nothrow);
- }
-
- // Allocate with new(nothrow).
- {
- int* x = new(std::nothrow) int;
- int* y = new(std::nothrow) int;
- IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
- IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]");
- delete x;
- ::operator delete(y, std::nothrow);
- }
-
- // Allocate with new(nothrow)[].
- {
- int* x = new(std::nothrow) int[1];
- int* y = new(std::nothrow) int[1];
- IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
- IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete");
- delete [] x;
- ::operator delete[](y, std::nothrow);
- }
-}
-#endif // #ifdef OS_MACOSX
-
-TEST(DebugAllocationTest, DoubleFree) {
- int* pint = new int;
- delete pint;
- IF_DEBUG_EXPECT_DEATH(delete pint, "has been already deallocated");
-}
-
-TEST(DebugAllocationTest, StompBefore) {
- int* pint = new int;
-#ifndef NDEBUG // don't stomp memory if we're not in a position to detect it
- pint[-1] = 5;
- IF_DEBUG_EXPECT_DEATH(delete pint, "a word before object");
-#endif
-}
-
-TEST(DebugAllocationTest, StompAfter) {
- int* pint = new int;
-#ifndef NDEBUG // don't stomp memory if we're not in a position to detect it
- pint[1] = 5;
- IF_DEBUG_EXPECT_DEATH(delete pint, "a word after object");
-#endif
-}
-
-TEST(DebugAllocationTest, FreeQueueTest) {
- // Verify that the allocator doesn't return blocks that were recently freed.
- int* x = new int;
- int* old_x = x;
- delete x;
- x = new int;
- #if 1
- // This check should not be read as a universal guarantee of behavior. If
- // other threads are executing, it would be theoretically possible for this
- // check to fail despite the efforts of debugallocation.cc to the contrary.
- // It should always hold under the controlled conditions of this unittest,
- // however.
- EXPECT_NE(x, old_x); // Allocator shouldn't return recently freed blocks
- #else
- // The below check passes, but since it isn't *required* to pass, I've left
- // it commented out.
- // EXPECT_EQ(x, old_x);
- #endif
- old_x = NULL; // avoid breaking opt build with an unused variable warning.
- delete x;
-}
-
-TEST(DebugAllocationTest, DanglingPointerWriteTest) {
- // This test can only be run if debugging.
- //
- // If not debugging, the 'new' following the dangling write might not be
- // safe. When debugging, we expect the (trashed) deleted block to be on the
- // list of recently-freed blocks, so the following 'new' will be safe.
-#if 1
- int* x = new int;
- delete x;
- int poisoned_x_value = *x;
- *x = 1; // a dangling write.
-
- char* s = new char[FLAGS_max_free_queue_size];
- // When we delete s, we push the storage that was previously allocated to x
- // off the end of the free queue. At that point, the write to that memory
- // will be detected.
- IF_DEBUG_EXPECT_DEATH(delete [] s, "Memory was written to after being freed.");
-
- // restore the poisoned value of x so that we can delete s without causing a
- // crash.
- *x = poisoned_x_value;
- delete [] s;
-#endif
-}
-
-TEST(DebugAllocationTest, DanglingWriteAtExitTest) {
- int *x = new int;
- delete x;
- int old_x_value = *x;
- *x = 1;
- // verify that dangling writes are caught at program termination if the
- // corrupted block never got pushed off of the end of the free queue.
- IF_DEBUG_EXPECT_DEATH(exit(0), "Memory was written to after being freed.");
- *x = old_x_value; // restore x so that the test can exit successfully.
-}
-
-TEST(DebugAllocationTest, StackTraceWithDanglingWriteAtExitTest) {
- int *x = new int;
- delete x;
- int old_x_value = *x;
- *x = 1;
- // verify that we also get a stack trace when we have a dangling write.
- // The " @ " is part of the stack trace output.
- IF_DEBUG_EXPECT_DEATH(exit(0), " @ .*main");
- *x = old_x_value; // restore x so that the test can exit successfully.
-}
-
-static size_t CurrentlyAllocatedBytes() {
- size_t value;
- CHECK(MallocExtension::instance()->GetNumericProperty(
- "generic.current_allocated_bytes", &value));
- return value;
-}
-
-TEST(DebugAllocationTest, CurrentlyAllocated) {
- // Clear the free queue
-#if 1
- FLAGS_max_free_queue_size = 0;
- // Force a round-trip through the queue management code so that the
- // new size is seen and the queue of recently-freed blocks is flushed.
- free(malloc(1));
- FLAGS_max_free_queue_size = 1048576;
-#endif
-
- // Free something and check that it disappears from allocated bytes
- // immediately.
- char* p = new char[1000];
- size_t after_malloc = CurrentlyAllocatedBytes();
- delete[] p;
- size_t after_free = CurrentlyAllocatedBytes();
- EXPECT_LE(after_free, after_malloc - 1000);
-}
-
-TEST(DebugAllocationTest, GetAllocatedSizeTest) {
-#if 1
- // When debug_allocation is in effect, GetAllocatedSize should return
- // exactly requested size, since debug_allocation doesn't allow users
- // to write more than that.
- for (int i = 0; i < 10; ++i) {
- void *p = malloc(i);
- EXPECT_EQ(i, MallocExtension::instance()->GetAllocatedSize(p));
- free(p);
- }
-#endif
- void* a = malloc(1000);
- EXPECT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000);
- // This is just a sanity check. If we allocated too much, alloc is broken
- EXPECT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000);
- EXPECT_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000);
- free(a);
-}
-
-TEST(DebugAllocationTest, HugeAlloc) {
- // This must not be a const variable so it doesn't form an
- // integral-constant-expression which can be *statically* rejected by the
- // compiler as too large for the allocation.
- size_t kTooBig = ~static_cast<size_t>(0);
- void* a = NULL;
-
-#ifndef NDEBUG
-
- a = malloc(kTooBig);
- EXPECT_EQ(NULL, a);
-
- // kAlsoTooBig is small enough not to get caught by debugallocation's check,
- // but will still fall through to tcmalloc's check. This must also be
- // a non-const variable. See kTooBig for more details.
- size_t kAlsoTooBig = kTooBig - 1024;
-
- a = malloc(kAlsoTooBig);
- EXPECT_EQ(NULL, a);
-#endif
-}
-
-// based on test program contributed by mikesart@gmail.com aka
-// mikesart@valvesoftware.com. See issue-464.
-TEST(DebugAllocationTest, ReallocAfterMemalign) {
- char stuff[50];
- memset(stuff, 0x11, sizeof(stuff));
- void *p = tc_memalign(16, sizeof(stuff));
- EXPECT_NE(p, NULL);
- memcpy(stuff, p, sizeof(stuff));
-
- p = realloc(p, sizeof(stuff) + 10);
- EXPECT_NE(p, NULL);
-
- int rv = memcmp(stuff, p, sizeof(stuff));
- EXPECT_EQ(rv, 0);
-}
-
-int main(int argc, char** argv) {
- // If you run without args, we run the non-death parts of the test.
- // Otherwise, argv[1] should be a number saying which death-test
- // to run. We will output a regexp we expect the death-message
- // to include, and then run the given death test (which hopefully
- // will produce that error message). If argv[1] > the number of
- // death tests, we will run only the non-death parts. One way to
- // tell when you are done with all tests is when no 'expected
- // regexp' message is printed for a given argv[1].
- if (argc < 2) {
- test_to_run = -1; // will never match
- } else {
- test_to_run = atoi(argv[1]);
- }
- return RUN_ALL_TESTS();
-}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/debugallocation_test.sh
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/debugallocation_test.sh b/third_party/gperftools/src/tests/debugallocation_test.sh
deleted file mode 100755
index faa6c79..0000000
--- a/third_party/gperftools/src/tests/debugallocation_test.sh
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2009, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# ---
-# Author: Craig Silverstein
-
-BINDIR="${BINDIR:-.}"
-
-if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
- echo "USAGE: $0 [unittest dir]"
- echo " By default, unittest_dir=$BINDIR"
- exit 1
-fi
-
-DEBUGALLOCATION_TEST="${1:-$BINDIR/debugallocation_test}"
-
-num_failures=0
-
-# Run the i-th death test and make sure the test has the expected
-# regexp. We can depend on the first line of the output being
-# Expected regex:<regex>
-# Evaluates to "done" if we are not actually a death-test (so $1 is
-# too big a number, and we can stop). Evaluates to "" otherwise.
-# Increments num_failures if the death test does not succeed.
-OneDeathTest() {
- "$DEBUGALLOCATION_TEST" "$1" 2>&1 | {
- regex_line='dummy'
- # Normally the regex_line is the first line of output, but not
- # always (if tcmalloc itself does any logging to stderr).
- while test -n "$regex_line"; do
- read regex_line
- regex=`expr "$regex_line" : "Expected regex:\(.*\)"`
- test -n "$regex" && break # found the regex line
- done
- test -z "$regex" && echo "done" || grep "$regex" 2>&1
- }
-}
-
-death_test_num=0 # which death test to run
-while :; do # same as 'while true', but more portable
- echo -n "Running death test $death_test_num..."
- output="`OneDeathTest $death_test_num`"
- case $output in
- # Empty string means grep didn't find anything.
- "") echo "FAILED"; num_failures=`expr $num_failures + 1`;;
- "done"*) echo "done with death tests"; break;;
- # Any other string means grep found something, like it ought to.
- *) echo "OK";;
- esac
- death_test_num=`expr $death_test_num + 1`
-done
-
-# Test the non-death parts of the test too
-echo -n "Running non-death tests..."
-if "$DEBUGALLOCATION_TEST"; then
- echo "OK"
-else
- echo "FAILED"
- num_failures=`expr $num_failures + 1`
-fi
-
-if [ "$num_failures" = 0 ]; then
- echo "PASS"
-else
- echo "Failed with $num_failures failures"
-fi
-exit $num_failures
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/frag_unittest.cc
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/frag_unittest.cc b/third_party/gperftools/src/tests/frag_unittest.cc
deleted file mode 100644
index c4016f9..0000000
--- a/third_party/gperftools/src/tests/frag_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2003, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// Author: Sanjay Ghemawat
-//
-// Test speed of handling fragmented heap
-
-#include "config_for_unittests.h"
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/time.h> // for struct timeval
-#include <sys/resource.h> // for getrusage
-#endif
-#ifdef _WIN32
-#include <windows.h> // for GetTickCount()
-#endif
-#include <vector>
-#include "base/logging.h"
-#include "common.h"
-#include <gperftools/malloc_extension.h>
-
-using std::vector;
-
-int main(int argc, char** argv) {
- // Make kAllocSize one page larger than the maximum small object size.
- static const int kAllocSize = kMaxSize + kPageSize;
- // Allocate 400MB in total.
- static const int kTotalAlloc = 400 << 20;
- static const int kAllocIterations = kTotalAlloc / kAllocSize;
-
- // Allocate lots of objects
- vector<char*> saved(kAllocIterations);
- for (int i = 0; i < kAllocIterations; i++) {
- saved[i] = new char[kAllocSize];
- }
-
- // Check the current "slack".
- size_t slack_before;
- MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
- &slack_before);
-
- // Free alternating ones to fragment heap
- size_t free_bytes = 0;
- for (int i = 0; i < saved.size(); i += 2) {
- delete[] saved[i];
- free_bytes += kAllocSize;
- }
-
- // Check that slack delta is within 10% of expected.
- size_t slack_after;
- MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
- &slack_after);
- CHECK_GE(slack_after, slack_before);
- size_t slack = slack_after - slack_before;
-
- CHECK_GT(double(slack), 0.9*free_bytes);
- CHECK_LT(double(slack), 1.1*free_bytes);
-
- // Dump malloc stats
- static const int kBufSize = 1<<20;
- char* buffer = new char[kBufSize];
- MallocExtension::instance()->GetStats(buffer, kBufSize);
- VLOG(1, "%s", buffer);
- delete[] buffer;
-
- // Now do timing tests
- for (int i = 0; i < 5; i++) {
- static const int kIterations = 100000;
-#ifdef HAVE_SYS_RESOURCE_H
- struct rusage r;
- getrusage(RUSAGE_SELF, &r); // figure out user-time spent on this
- struct timeval tv_start = r.ru_utime;
-#elif defined(_WIN32)
- long long int tv_start = GetTickCount();
-#else
-# error No way to calculate time on your system
-#endif
-
- for (int i = 0; i < kIterations; i++) {
- size_t s;
- MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
- &s);
- }
-
-#ifdef HAVE_SYS_RESOURCE_H
- getrusage(RUSAGE_SELF, &r);
- struct timeval tv_end = r.ru_utime;
- int64 sumsec = static_cast<int64>(tv_end.tv_sec) - tv_start.tv_sec;
- int64 sumusec = static_cast<int64>(tv_end.tv_usec) - tv_start.tv_usec;
-#elif defined(_WIN32)
- long long int tv_end = GetTickCount();
- int64 sumsec = (tv_end - tv_start) / 1000;
- // Resolution in windows is only to the millisecond, alas
- int64 sumusec = ((tv_end - tv_start) % 1000) * 1000;
-#else
-# error No way to calculate time on your system
-#endif
- fprintf(stderr, "getproperty: %6.1f ns/call\n",
- (sumsec * 1e9 + sumusec * 1e3) / kIterations);
- }
-
- printf("PASS\n");
- return 0;
-}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/getpc_test.cc
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/getpc_test.cc b/third_party/gperftools/src/tests/getpc_test.cc
deleted file mode 100644
index d75e40b..0000000
--- a/third_party/gperftools/src/tests/getpc_test.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// Author: Craig Silverstein
-//
-// This verifies that GetPC works correctly. This test uses a minimum
-// of Google infrastructure, to make it very easy to port to various
-// O/Ses and CPUs and test that GetPC is working.
-
-#include "config.h"
-#include "getpc.h" // should be first to get the _GNU_SOURCE dfn
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/time.h> // for setitimer
-
-// Needs to be volatile so compiler doesn't try to optimize it away
-static volatile void* getpc_retval = NULL; // what GetPC returns
-static volatile bool prof_handler_called = false;
-
-static void prof_handler(int sig, siginfo_t*, void* signal_ucontext) {
- if (!prof_handler_called)
- getpc_retval = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext));
- prof_handler_called = true; // only store the retval once
-}
-
-static void RoutineCallingTheSignal() {
- struct sigaction sa;
- sa.sa_sigaction = prof_handler;
- sa.sa_flags = SA_RESTART | SA_SIGINFO;
- sigemptyset(&sa.sa_mask);
- if (sigaction(SIGPROF, &sa, NULL) != 0) {
- perror("sigaction");
- exit(1);
- }
-
- struct itimerval timer;
- timer.it_interval.tv_sec = 0;
- timer.it_interval.tv_usec = 1000;
- timer.it_value = timer.it_interval;
- setitimer(ITIMER_PROF, &timer, 0);
-
- // Now we need to do some work for a while, that doesn't call any
- // other functions, so we can be guaranteed that when the SIGPROF
- // fires, we're the routine executing.
- int r = 0;
- for (int i = 0; !prof_handler_called; ++i) {
- for (int j = 0; j < i; j++) {
- r ^= i;
- r <<= 1;
- r ^= j;
- r >>= 1;
- }
- }
-
- // Now make sure the above loop doesn't get optimized out
- srand(r);
-}
-
-// This is an upper bound of how many bytes the instructions for
-// RoutineCallingTheSignal might be. There's probably a more
-// principled way to do this, but I don't know how portable it would be.
-// (The function is 372 bytes when compiled with -g on Mac OS X 10.4.
-// I can imagine it would be even bigger in 64-bit architectures.)
-const int kRoutineSize = 512 * sizeof(void*)/4; // allow 1024 for 64-bit
-
-int main(int argc, char** argv) {
- RoutineCallingTheSignal();
-
- // Annoyingly, C++ disallows casting pointer-to-function to
- // pointer-to-object, so we use a C-style cast instead.
- char* expected = (char*)&RoutineCallingTheSignal;
- char* actual = (char*)getpc_retval;
-
- // For ia64, ppc64v1, and parisc64, the function pointer is actually
- // a struct. For instance, ia64's dl-fptr.h:
- // struct fdesc { /* An FDESC is a function descriptor. */
- // ElfW(Addr) ip; /* code entry point */
- // ElfW(Addr) gp; /* global pointer */
- // };
- // We want the code entry point.
- // NOTE: ppc64 ELFv2 (Little Endian) does not have function pointers
-#if defined(__ia64) || \
- (defined(__powerpc64__) && _CALL_ELF != 2)
- expected = ((char**)expected)[0]; // this is "ip"
-#endif
-
- if (actual < expected || actual > expected + kRoutineSize) {
- printf("Test FAILED: actual PC: %p, expected PC: %p\n", actual, expected);
- return 1;
- } else {
- printf("PASS\n");
- return 0;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/heap-checker-death_unittest.sh
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/heap-checker-death_unittest.sh b/third_party/gperftools/src/tests/heap-checker-death_unittest.sh
deleted file mode 100755
index 752a7ad..0000000
--- a/third_party/gperftools/src/tests/heap-checker-death_unittest.sh
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/bin/sh
-# Copyright (c) 2005, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ---
-# Author: Maxim Lifantsev
-#
-# Run the heap checker unittest in a mode where it is supposed to crash and
-# return an error if it doesn't.
-
-# We expect BINDIR to be set in the environment.
-# If not, we set it to some reasonable value.
-BINDIR="${BINDIR:-.}"
-
-if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
- echo "USAGE: $0 [unittest dir]"
- echo " By default, unittest_dir=$BINDIR"
- exit 1
-fi
-
-EXE="${1:-$BINDIR/heap-checker_unittest}"
-TMPDIR="/tmp/heap_check_death_info"
-
-ALARM() {
- # You need perl to run pprof, so I assume it's installed
- perl -e '
- $timeout=$ARGV[0]; shift;
- $retval = 255; # the default retval, for the case where we timed out
- eval { # need to run in an eval-block to trigger during system()
- local $SIG{ALRM} = sub { die "alarm\n" }; # \n is required!
- alarm $timeout;
- $retval = system(@ARGV);
- # Make retval bash-style: exit status, or 128+n if terminated by signal n
- $retval = ($retval & 127) ? (128 + $retval) : ($retval >> 8);
- alarm 0;
- };
- exit $retval; # return system()-retval, or 255 if system() never returned
-' "$@"
-}
-
-# $1: timeout for alarm;
-# $2: regexp of expected exit code(s);
-# $3: regexp to match a line in the output;
-# $4: regexp to not match a line in the output;
-# $5+ args to pass to $EXE
-Test() {
- # Note: make sure these varnames don't conflict with any vars outside Test()!
- timeout="$1"
- shift
- expected_ec="$1"
- shift
- expected_regexp="$1"
- shift
- unexpected_regexp="$1"
- shift
-
- echo -n "Testing $EXE with $@ ... "
- output="$TMPDIR/output"
- ALARM $timeout env "$@" $EXE > "$output" 2>&1
- actual_ec=$?
- ec_ok=`expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false`
- matches_ok=`test -z "$expected_regexp" || \
- grep "$expected_regexp" "$output" >/dev/null 2>&1 || echo false`
- negmatches_ok=`test -z "$unexpected_regexp" || \
- ! grep "$unexpected_regexp" "$output" >/dev/null 2>&1 || echo false`
- if $ec_ok && $matches_ok && $negmatches_ok; then
- echo "PASS"
- return 0 # 0: success
- fi
- # If we get here, we failed. Now we just need to report why
- echo "FAIL"
- if [ $actual_ec -eq 255 ]; then # 255 == SIGTERM due to $ALARM
- echo "Test was taking unexpectedly long time to run and so we aborted it."
- echo "Try the test case manually or raise the timeout from $timeout"
- echo "to distinguish test slowness from a real problem."
- else
- $ec_ok || \
- echo "Wrong exit code: expected: '$expected_ec'; actual: $actual_ec"
- $matches_ok || \
- echo "Output did not match '$expected_regexp'"
- $negmatches_ok || \
- echo "Output unexpectedly matched '$unexpected_regexp'"
- fi
- echo "Output from failed run:"
- echo "---"
- cat "$output"
- echo "---"
- return 1 # 1: failure
-}
-
-TMPDIR=/tmp/heap_check_death_info
-rm -rf $TMPDIR || exit 1
-mkdir $TMPDIR || exit 2
-
-export HEAPCHECK=strict # default mode
-
-# These invocations should pass (0 == PASS):
-
-# This tests that turning leak-checker off dynamically works fine
-Test 120 0 "^PASS$" "" HEAPCHECK="" || exit 1
-
-# This disables threads so we can cause leaks reliably and test finding them
-Test 120 0 "^PASS$" "" HEAP_CHECKER_TEST_NO_THREADS=1 || exit 2
-
-# Test that --test_cancel_global_check works
-Test 20 0 "Canceling .* whole-program .* leak check$" "" \
- HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 3
-Test 20 0 "Canceling .* whole-program .* leak check$" "" \
- HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 4
-
-# Test that very early log messages are present and controllable:
-EARLY_MSG="Starting tracking the heap$"
-
-Test 60 0 "$EARLY_MSG" "" \
- HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
- PERFTOOLS_VERBOSE=10 || exit 5
-Test 60 0 "MemoryRegionMap Init$" "" \
- HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
- PERFTOOLS_VERBOSE=11 || exit 6
-Test 60 0 "" "$EARLY_MSG" \
- HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
- PERFTOOLS_VERBOSE=-11 || exit 7
-
-# These invocations should fail with very high probability,
-# rather than return 0 or hang (1 == exit(1), 134 == abort(), 139 = SIGSEGV):
-
-Test 60 1 "Exiting .* because of .* leaks$" "" \
- HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 8
-Test 60 1 "Exiting .* because of .* leaks$" "" \
- HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 9
-
-# Test that we produce a reasonable textual leak report.
-Test 60 1 "MakeALeak" "" \
- HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECK_TEST_NO_THREADS=1 \
- || exit 10
-
-# Test that very early log messages are present and controllable:
-Test 60 1 "Starting tracking the heap$" "" \
- HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=10 \
- || exit 11
-Test 60 1 "" "Starting tracking the heap" \
- HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=-10 \
- || exit 12
-
-cd / # so we're not in TMPDIR when we delete it
-rm -rf $TMPDIR
-
-echo "PASS"
-
-exit 0
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/heap-checker_unittest.cc
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/heap-checker_unittest.cc b/third_party/gperftools/src/tests/heap-checker_unittest.cc
deleted file mode 100644
index 13cbb86..0000000
--- a/third_party/gperftools/src/tests/heap-checker_unittest.cc
+++ /dev/null
@@ -1,1526 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// Author: Maxim Lifantsev
-//
-// Running:
-// ./heap-checker_unittest
-//
-// If the unittest crashes because it can't find pprof, try:
-// PPROF_PATH=/usr/local/someplace/bin/pprof ./heap-checker_unittest
-//
-// To test that the whole-program heap checker will actually cause a leak, try:
-// HEAPCHECK_TEST_LEAK= ./heap-checker_unittest
-// HEAPCHECK_TEST_LOOP_LEAK= ./heap-checker_unittest
-//
-// Note: Both of the above commands *should* abort with an error message.
-
-// CAVEAT: Do not use vector<> and string on-heap objects in this test,
-// otherwise the test can sometimes fail for tricky leak checks
-// when we want some allocated object not to be found live by the heap checker.
-// This can happen with memory allocators like tcmalloc that can allocate
-// heap objects back to back without any book-keeping data in between.
-// What happens is that end-of-storage pointers of a live vector
-// (or a string depending on the STL implementation used)
-// can happen to point to that other heap-allocated
-// object that is not reachable otherwise and that
-// we don't want to be reachable.
-//
-// The implication of this for real leak checking
-// is just one more chance for the liveness flood to be inexact
-// (see the comment in our .h file).
-
-#include "config_for_unittests.h"
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
-#if defined HAVE_STDINT_H
-#include <stdint.h> // to get uint16_t (ISO naming madness)
-#elif defined HAVE_INTTYPES_H
-#include <inttypes.h> // another place uint16_t might be defined
-#endif
-#include <sys/types.h>
-#include <stdlib.h>
-#include <errno.h> // errno
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> // for sleep(), geteuid()
-#endif
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#include <fcntl.h> // for open(), close()
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h> // backtrace
-#endif
-#ifdef HAVE_GRP_H
-#include <grp.h> // getgrent, getgrnam
-#endif
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-#include <algorithm>
-#include <iostream> // for cout
-#include <iomanip> // for hex
-#include <list>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/commandlineflags.h"
-#include "base/googleinit.h"
-#include "base/logging.h"
-#include "base/commandlineflags.h"
-#include "base/thread_lister.h"
-#include <gperftools/heap-checker.h>
-#include "memory_region_map.h"
-#include <gperftools/malloc_extension.h>
-#include <gperftools/stacktrace.h>
-
-// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
-// form of the name instead.
-#ifndef MAP_ANONYMOUS
-# define MAP_ANONYMOUS MAP_ANON
-#endif
-
-using namespace std;
-
-// ========================================================================= //
-
-// TODO(maxim): write a shell script to test that these indeed crash us
-// (i.e. we do detect leaks)
-// Maybe add more such crash tests.
-
-DEFINE_bool(test_leak,
- EnvToBool("HEAP_CHECKER_TEST_TEST_LEAK", false),
- "If should cause a leak crash");
-DEFINE_bool(test_loop_leak,
- EnvToBool("HEAP_CHECKER_TEST_TEST_LOOP_LEAK", false),
- "If should cause a looped leak crash");
-DEFINE_bool(test_register_leak,
- EnvToBool("HEAP_CHECKER_TEST_TEST_REGISTER_LEAK", false),
- "If should cause a leak crash by hiding a pointer "
- "that is only in a register");
-DEFINE_bool(test_cancel_global_check,
- EnvToBool("HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK", false),
- "If should test HeapLeakChecker::CancelGlobalCheck "
- "when --test_leak or --test_loop_leak are given; "
- "the test should not fail then");
-DEFINE_bool(maybe_stripped,
- EnvToBool("HEAP_CHECKER_TEST_MAYBE_STRIPPED", true),
- "If we think we can be a stripped binary");
-DEFINE_bool(interfering_threads,
- EnvToBool("HEAP_CHECKER_TEST_INTERFERING_THREADS", true),
- "If we should use threads trying "
- "to interfere with leak checking");
-DEFINE_bool(hoarding_threads,
- EnvToBool("HEAP_CHECKER_TEST_HOARDING_THREADS", true),
- "If threads (usually the manager thread) are known "
- "to retain some old state in their global buffers, "
- "so that it's hard to force leaks when threads are around");
- // TODO(maxim): Chage the default to false
- // when the standard environment used NTPL threads:
- // they do not seem to have this problem.
-DEFINE_bool(no_threads,
- EnvToBool("HEAP_CHECKER_TEST_NO_THREADS", false),
- "If we should not use any threads");
- // This is used so we can make can_create_leaks_reliably true
- // for any pthread implementation and test with that.
-
-DECLARE_int64(heap_check_max_pointer_offset); // heap-checker.cc
-DECLARE_string(heap_check); // in heap-checker.cc
-
-#define WARN_IF(cond, msg) LOG_IF(WARNING, cond, msg)
-
-// This is an evil macro! Be very careful using it...
-#undef VLOG // and we start by evilling overriding logging.h VLOG
-#define VLOG(lvl) if (FLAGS_verbose >= (lvl)) cout << "\n"
-// This is, likewise, evil
-#define LOGF VLOG(INFO)
-
-static void RunHeapBusyThreads(); // below
-
-
-class Closure {
- public:
- virtual ~Closure() { }
- virtual void Run() = 0;
-};
-
-class Callback0 : public Closure {
- public:
- typedef void (*FunctionSignature)();
-
- inline Callback0(FunctionSignature f) : f_(f) {}
- virtual void Run() { (*f_)(); delete this; }
-
- private:
- FunctionSignature f_;
-};
-
-template <class P1> class Callback1 : public Closure {
- public:
- typedef void (*FunctionSignature)(P1);
-
- inline Callback1<P1>(FunctionSignature f, P1 p1) : f_(f), p1_(p1) {}
- virtual void Run() { (*f_)(p1_); delete this; }
-
- private:
- FunctionSignature f_;
- P1 p1_;
-};
-
-template <class P1, class P2> class Callback2 : public Closure {
- public:
- typedef void (*FunctionSignature)(P1,P2);
-
- inline Callback2<P1,P2>(FunctionSignature f, P1 p1, P2 p2) : f_(f), p1_(p1), p2_(p2) {}
- virtual void Run() { (*f_)(p1_, p2_); delete this; }
-
- private:
- FunctionSignature f_;
- P1 p1_;
- P2 p2_;
-};
-
-inline Callback0* NewCallback(void (*function)()) {
- return new Callback0(function);
-}
-
-template <class P1>
-inline Callback1<P1>* NewCallback(void (*function)(P1), P1 p1) {
- return new Callback1<P1>(function, p1);
-}
-
-template <class P1, class P2>
-inline Callback2<P1,P2>* NewCallback(void (*function)(P1,P2), P1 p1, P2 p2) {
- return new Callback2<P1,P2>(function, p1, p2);
-}
-
-
-// Set to true at end of main, so threads know. Not entirely thread-safe!,
-// but probably good enough.
-static bool g_have_exited_main = false;
-
-// If we can reliably create leaks (i.e. make leaked object
-// really unreachable from any global data).
-static bool can_create_leaks_reliably = false;
-
-// We use a simple allocation wrapper
-// to make sure we wipe out the newly allocated objects
-// in case they still happened to contain some pointer data
-// accidentally left by the memory allocator.
-struct Initialized { };
-static Initialized initialized;
-void* operator new(size_t size, const Initialized&) {
- // Below we use "p = new(initialized) Foo[1];" and "delete[] p;"
- // instead of "p = new(initialized) Foo;"
- // when we need to delete an allocated object.
- void* p = malloc(size);
- memset(p, 0, size);
- return p;
-}
-void* operator new[](size_t size, const Initialized&) {
- char* p = new char[size];
- memset(p, 0, size);
- return p;
-}
-
-static void DoWipeStack(int n); // defined below
-static void WipeStack() { DoWipeStack(20); }
-
-static void Pause() {
- poll(NULL, 0, 77); // time for thread activity in HeapBusyThreadBody
-
- // Indirectly test malloc_extension.*:
- CHECK(MallocExtension::instance()->VerifyAllMemory());
- int blocks;
- size_t total;
- int histogram[kMallocHistogramSize];
- if (MallocExtension::instance()
- ->MallocMemoryStats(&blocks, &total, histogram) && total != 0) {
- VLOG(3) << "Malloc stats: " << blocks << " blocks of "
- << total << " bytes";
- for (int i = 0; i < kMallocHistogramSize; ++i) {
- if (histogram[i]) {
- VLOG(3) << " Malloc histogram at " << i << " : " << histogram[i];
- }
- }
- }
- WipeStack(); // e.g. MallocExtension::VerifyAllMemory
- // can leave pointers to heap objects on stack
-}
-
-// Make gcc think a pointer is "used"
-template <class T>
-static void Use(T** foo) {
- VLOG(2) << "Dummy-using " << static_cast<void*>(*foo) << " at " << foo;
-}
-
-// Arbitrary value, but not such that xor'ing with it is likely
-// to map one valid pointer to another valid pointer:
-static const uintptr_t kHideMask =
- static_cast<uintptr_t>(0xF03A5F7BF03A5F7BLL);
-
-// Helpers to hide a pointer from live data traversal.
-// We just xor the pointer so that (with high probability)
-// it's not a valid address of a heap object anymore.
-// Both Hide and UnHide must be executed within RunHidden() below
-// to prevent leaving stale data on active stack that can be a pointer
-// to a heap object that is not actually reachable via live variables.
-// (UnHide might leave heap pointer value for an object
-// that will be deallocated but later another object
-// can be allocated at the same heap address.)
-template <class T>
-static void Hide(T** ptr) {
- // we cast values, not dereferenced pointers, so no aliasing issues:
- *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask);
- VLOG(2) << "hid: " << static_cast<void*>(*ptr);
-}
-
-template <class T>
-static void UnHide(T** ptr) {
- VLOG(2) << "unhiding: " << static_cast<void*>(*ptr);
- // we cast values, not dereferenced pointers, so no aliasing issues:
- *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask);
-}
-
-static void LogHidden(const char* message, const void* ptr) {
- LOGF << message << " : "
- << ptr << " ^ " << reinterpret_cast<void*>(kHideMask) << endl;
-}
-
-// volatile to fool the compiler against inlining the calls to these
-void (*volatile run_hidden_ptr)(Closure* c, int n);
-void (*volatile wipe_stack_ptr)(int n);
-
-static void DoRunHidden(Closure* c, int n) {
- if (n) {
- VLOG(10) << "Level " << n << " at " << &n;
- (*run_hidden_ptr)(c, n-1);
- (*wipe_stack_ptr)(n);
- sleep(0); // undo -foptimize-sibling-calls
- } else {
- c->Run();
- }
-}
-
-/*static*/ void DoWipeStack(int n) {
- VLOG(10) << "Wipe level " << n << " at " << &n;
- if (n) {
- const int sz = 30;
- volatile int arr[sz] ATTRIBUTE_UNUSED;
- for (int i = 0; i < sz; ++i) arr[i] = 0;
- (*wipe_stack_ptr)(n-1);
- sleep(0); // undo -foptimize-sibling-calls
- }
-}
-
-// This executes closure c several stack frames down from the current one
-// and then makes an effort to also wipe out the stack data that was used by
-// the closure.
-// This way we prevent leak checker from finding any temporary pointers
-// of the closure execution on the stack and deciding that
-// these pointers (and the pointed objects) are still live.
-static void RunHidden(Closure* c) {
- DoRunHidden(c, 15);
- DoWipeStack(20);
-}
-
-static void DoAllocHidden(size_t size, void** ptr) {
- void* p = new(initialized) char[size];
- Hide(&p);
- Use(&p); // use only hidden versions
- VLOG(2) << "Allocated hidden " << p << " at " << &p;
- *ptr = p; // assign the hidden versions
-}
-
-static void* AllocHidden(size_t size) {
- void* r;
- RunHidden(NewCallback(DoAllocHidden, size, &r));
- return r;
-}
-
-static void DoDeAllocHidden(void** ptr) {
- Use(ptr); // use only hidden versions
- void* p = *ptr;
- VLOG(2) << "Deallocating hidden " << p;
- UnHide(&p);
- delete [] reinterpret_cast<char*>(p);
-}
-
-static void DeAllocHidden(void** ptr) {
- RunHidden(NewCallback(DoDeAllocHidden, ptr));
- *ptr = NULL;
- Use(ptr);
-}
-
-void PreventHeapReclaiming(size_t size) {
-#ifdef NDEBUG
- if (true) {
- static void** no_reclaim_list = NULL;
- CHECK(size >= sizeof(void*));
- // We can't use malloc_reclaim_memory flag in opt mode as debugallocation.cc
- // is not used. Instead we allocate a bunch of heap objects that are
- // of the same size as what we are going to leak to ensure that the object
- // we are about to leak is not at the same address as some old allocated
- // and freed object that might still have pointers leading to it.
- for (int i = 0; i < 100; ++i) {
- void** p = reinterpret_cast<void**>(new(initialized) char[size]);
- p[0] = no_reclaim_list;
- no_reclaim_list = p;
- }
- }
-#endif
-}
-
-static bool RunSilent(HeapLeakChecker* check,
- bool (HeapLeakChecker::* func)()) {
- // By default, don't print the 'we detected a leak' message in the
- // cases we're expecting a leak (we still print when --v is >= 1).
- // This way, the logging output is less confusing: we only print
- // "we detected a leak", and how to diagnose it, for *unexpected* leaks.
- int32 old_FLAGS_verbose = FLAGS_verbose;
- if (!VLOG_IS_ON(1)) // not on a verbose setting
- FLAGS_verbose = FATAL; // only log fatal errors
- const bool retval = (check->*func)();
- FLAGS_verbose = old_FLAGS_verbose;
- return retval;
-}
-
-#define RUN_SILENT(check, func) RunSilent(&(check), &HeapLeakChecker::func)
-
-enum CheckType { SAME_HEAP, NO_LEAKS };
-
-static void VerifyLeaks(HeapLeakChecker* check, CheckType type,
- int leaked_bytes, int leaked_objects) {
- WipeStack(); // to help with can_create_leaks_reliably
- const bool no_leaks =
- type == NO_LEAKS ? RUN_SILENT(*check, BriefNoLeaks)
- : RUN_SILENT(*check, BriefSameHeap);
- if (can_create_leaks_reliably) {
- // these might still fail occasionally, but it should be very rare
- CHECK_EQ(no_leaks, false);
- CHECK_EQ(check->BytesLeaked(), leaked_bytes);
- CHECK_EQ(check->ObjectsLeaked(), leaked_objects);
- } else {
- WARN_IF(no_leaks != false,
- "Expected leaks not found: "
- "Some liveness flood must be too optimistic");
- }
-}
-
-// not deallocates
-static void TestHeapLeakCheckerDeathSimple() {
- HeapLeakChecker check("death_simple");
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- void* bar = AllocHidden(300);
- Use(&bar);
- LogHidden("Leaking", foo);
- LogHidden("Leaking", bar);
- Pause();
- VerifyLeaks(&check, NO_LEAKS, 300 + 100 * sizeof(int), 2);
- DeAllocHidden(&foo);
- DeAllocHidden(&bar);
-}
-
-static void MakeDeathLoop(void** arr1, void** arr2) {
- PreventHeapReclaiming(2 * sizeof(void*));
- void** a1 = new(initialized) void*[2];
- void** a2 = new(initialized) void*[2];
- a1[1] = reinterpret_cast<void*>(a2);
- a2[1] = reinterpret_cast<void*>(a1);
- Hide(&a1);
- Hide(&a2);
- Use(&a1);
- Use(&a2);
- VLOG(2) << "Made hidden loop at " << &a1 << " to " << arr1;
- *arr1 = a1;
- *arr2 = a2;
-}
-
-// not deallocates two objects linked together
-static void TestHeapLeakCheckerDeathLoop() {
- HeapLeakChecker check("death_loop");
- void* arr1;
- void* arr2;
- RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2));
- Use(&arr1);
- Use(&arr2);
- LogHidden("Leaking", arr1);
- LogHidden("Leaking", arr2);
- Pause();
- VerifyLeaks(&check, NO_LEAKS, 4 * sizeof(void*), 2);
- DeAllocHidden(&arr1);
- DeAllocHidden(&arr2);
-}
-
-// deallocates more than allocates
-static void TestHeapLeakCheckerDeathInverse() {
- void* bar = AllocHidden(250 * sizeof(int));
- Use(&bar);
- LogHidden("Pre leaking", bar);
- Pause();
- HeapLeakChecker check("death_inverse");
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- LogHidden("Leaking", foo);
- DeAllocHidden(&bar);
- Pause();
- VerifyLeaks(&check, SAME_HEAP,
- 100 * static_cast<int64>(sizeof(int)),
- 1);
- DeAllocHidden(&foo);
-}
-
-// deallocates more than allocates
-static void TestHeapLeakCheckerDeathNoLeaks() {
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- void* bar = AllocHidden(250 * sizeof(int));
- Use(&bar);
- HeapLeakChecker check("death_noleaks");
- DeAllocHidden(&bar);
- CHECK_EQ(check.BriefNoLeaks(), true);
- DeAllocHidden(&foo);
-}
-
-// have less objecs
-static void TestHeapLeakCheckerDeathCountLess() {
- void* bar1 = AllocHidden(50 * sizeof(int));
- Use(&bar1);
- void* bar2 = AllocHidden(50 * sizeof(int));
- Use(&bar2);
- LogHidden("Pre leaking", bar1);
- LogHidden("Pre leaking", bar2);
- Pause();
- HeapLeakChecker check("death_count_less");
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- LogHidden("Leaking", foo);
- DeAllocHidden(&bar1);
- DeAllocHidden(&bar2);
- Pause();
- VerifyLeaks(&check, SAME_HEAP,
- 100 * sizeof(int),
- 1);
- DeAllocHidden(&foo);
-}
-
-// have more objecs
-static void TestHeapLeakCheckerDeathCountMore() {
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- LogHidden("Pre leaking", foo);
- Pause();
- HeapLeakChecker check("death_count_more");
- void* bar1 = AllocHidden(50 * sizeof(int));
- Use(&bar1);
- void* bar2 = AllocHidden(50 * sizeof(int));
- Use(&bar2);
- LogHidden("Leaking", bar1);
- LogHidden("Leaking", bar2);
- DeAllocHidden(&foo);
- Pause();
- VerifyLeaks(&check, SAME_HEAP,
- 100 * sizeof(int),
- 2);
- DeAllocHidden(&bar1);
- DeAllocHidden(&bar2);
-}
-
-static void TestHiddenPointer() {
- int i;
- void* foo = &i;
- HiddenPointer<void> p(foo);
- CHECK_EQ(foo, p.get());
-
- // Confirm pointer doesn't appear to contain a byte sequence
- // that == the pointer. We don't really need to test that
- // the xor trick itself works, as without it nothing in this
- // test suite would work. See the Hide/Unhide/*Hidden* set
- // of helper methods.
- void **pvoid = reinterpret_cast<void**>(&p);
- CHECK_NE(foo, *pvoid);
-}
-
-// simple tests that deallocate what they allocated
-static void TestHeapLeakChecker() {
- { HeapLeakChecker check("trivial");
- int foo = 5;
- int* p = &foo;
- Use(&p);
- Pause();
- CHECK(check.BriefSameHeap());
- }
- Pause();
- { HeapLeakChecker check("simple");
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- void* bar = AllocHidden(200 * sizeof(int));
- Use(&bar);
- DeAllocHidden(&foo);
- DeAllocHidden(&bar);
- Pause();
- CHECK(check.BriefSameHeap());
- }
-}
-
-// no false positives
-static void TestHeapLeakCheckerNoFalsePositives() {
- { HeapLeakChecker check("trivial_p");
- int foo = 5;
- int* p = &foo;
- Use(&p);
- Pause();
- CHECK(check.BriefSameHeap());
- }
- Pause();
- { HeapLeakChecker check("simple_p");
- void* foo = AllocHidden(100 * sizeof(int));
- Use(&foo);
- void* bar = AllocHidden(200 * sizeof(int));
- Use(&bar);
- DeAllocHidden(&foo);
- DeAllocHidden(&bar);
- Pause();
- CHECK(check.SameHeap());
- }
-}
-
-// test that we detect leaks when we have same total # of bytes and
-// objects, but different individual object sizes
-static void TestLeakButTotalsMatch() {
- void* bar1 = AllocHidden(240 * sizeof(int));
- Use(&bar1);
- void* bar2 = AllocHidden(160 * sizeof(int));
- Use(&bar2);
- LogHidden("Pre leaking", bar1);
- LogHidden("Pre leaking", bar2);
- Pause();
- HeapLeakChecker check("trick");
- void* foo1 = AllocHidden(280 * sizeof(int));
- Use(&foo1);
- void* foo2 = AllocHidden(120 * sizeof(int));
- Use(&foo2);
- LogHidden("Leaking", foo1);
- LogHidden("Leaking", foo2);
- DeAllocHidden(&bar1);
- DeAllocHidden(&bar2);
- Pause();
-
- // foo1 and foo2 leaked
- VerifyLeaks(&check, NO_LEAKS, (280+120)*sizeof(int), 2);
-
- DeAllocHidden(&foo1);
- DeAllocHidden(&foo2);
-}
-
-// no false negatives from pprof
-static void TestHeapLeakCheckerDeathTrick() {
- void* bar1 = AllocHidden(240 * sizeof(int));
- Use(&bar1);
- void* bar2 = AllocHidden(160 * sizeof(int));
- Use(&bar2);
- HeapLeakChecker check("death_trick");
- DeAllocHidden(&bar1);
- DeAllocHidden(&bar2);
- void* foo1 = AllocHidden(280 * sizeof(int));
- Use(&foo1);
- void* foo2 = AllocHidden(120 * sizeof(int));
- Use(&foo2);
- // TODO(maxim): use the above if we make pprof work in automated test runs
- if (!FLAGS_maybe_stripped) {
- CHECK_EQ(RUN_SILENT(check, SameHeap), false);
- // pprof checking should catch the leak
- } else {
- WARN_IF(RUN_SILENT(check, SameHeap) != false,
- "death_trick leak is not caught; "
- "we must be using a stripped binary");
- }
- DeAllocHidden(&foo1);
- DeAllocHidden(&foo2);
-}
-
-// simple leak
-static void TransLeaks() {
- AllocHidden(1 * sizeof(char));
-}
-
-// range-based disabling using Disabler
-static void ScopedDisabledLeaks() {
- HeapLeakChecker::Disabler disabler;
- AllocHidden(3 * sizeof(int));
- TransLeaks();
- (void)malloc(10); // Direct leak
-}
-
-// have different disabled leaks
-static void* RunDisabledLeaks(void* a) {
- ScopedDisabledLeaks();
- return a;
-}
-
-// have different disabled leaks inside of a thread
-static void ThreadDisabledLeaks() {
- if (FLAGS_no_threads) return;
- pthread_t tid;
- pthread_attr_t attr;
- CHECK_EQ(pthread_attr_init(&attr), 0);
- CHECK_EQ(pthread_create(&tid, &attr, RunDisabledLeaks, NULL), 0);
- void* res;
- CHECK_EQ(pthread_join(tid, &res), 0);
-}
-
-// different disabled leaks (some in threads)
-static void TestHeapLeakCheckerDisabling() {
- HeapLeakChecker check("disabling");
-
- RunDisabledLeaks(NULL);
- RunDisabledLeaks(NULL);
- ThreadDisabledLeaks();
- RunDisabledLeaks(NULL);
- ThreadDisabledLeaks();
- ThreadDisabledLeaks();
-
- Pause();
-
- CHECK(check.SameHeap());
-}
-
-typedef set<int> IntSet;
-
-static int some_ints[] = { 1, 2, 3, 21, 22, 23, 24, 25 };
-
-static void DoTestSTLAlloc() {
- IntSet* x = new(initialized) IntSet[1];
- *x = IntSet(some_ints, some_ints + 6);
- for (int i = 0; i < 1000; i++) {
- x->insert(i*3);
- }
- delete [] x;
-}
-
-// Check that normal STL usage does not result in a leak report.
-// (In particular we test that there's no complex STL's own allocator
-// running on top of our allocator with hooks to heap profiler
-// that can result in false leak report in this case.)
-static void TestSTLAlloc() {
- HeapLeakChecker check("stl");
- RunHidden(NewCallback(DoTestSTLAlloc));
- CHECK_EQ(check.BriefSameHeap(), true);
-}
-
-static void DoTestSTLAllocInverse(IntSet** setx) {
- IntSet* x = new(initialized) IntSet[1];
- *x = IntSet(some_ints, some_ints + 3);
- for (int i = 0; i < 100; i++) {
- x->insert(i*2);
- }
- Hide(&x);
- *setx = x;
-}
-
-static void FreeTestSTLAllocInverse(IntSet** setx) {
- IntSet* x = *setx;
- UnHide(&x);
- delete [] x;
-}
-
-// Check that normal leaked STL usage *does* result in a leak report.
-// (In particular we test that there's no complex STL's own allocator
-// running on top of our allocator with hooks to heap profiler
-// that can result in false absence of leak report in this case.)
-static void TestSTLAllocInverse() {
- HeapLeakChecker check("death_inverse_stl");
- IntSet* x;
- RunHidden(NewCallback(DoTestSTLAllocInverse, &x));
- LogHidden("Leaking", x);
- if (can_create_leaks_reliably) {
- WipeStack(); // to help with can_create_leaks_reliably
- // these might still fail occasionally, but it should be very rare
- CHECK_EQ(RUN_SILENT(check, BriefNoLeaks), false);
- CHECK_GE(check.BytesLeaked(), 100 * sizeof(int));
- CHECK_GE(check.ObjectsLeaked(), 100);
- // assumes set<>s are represented by some kind of binary tree
- // or something else allocating >=1 heap object per set object
- } else {
- WARN_IF(RUN_SILENT(check, BriefNoLeaks) != false,
- "Expected leaks not found: "
- "Some liveness flood must be too optimistic");
- }
- RunHidden(NewCallback(FreeTestSTLAllocInverse, &x));
-}
-
-template<class Alloc>
-static void DirectTestSTLAlloc(Alloc allocator, const char* name) {
- HeapLeakChecker check((string("direct_stl-") + name).c_str());
- static const int kSize = 1000;
- typename Alloc::pointer ptrs[kSize];
- for (int i = 0; i < kSize; ++i) {
- typename Alloc::pointer p = allocator.allocate(i*3+1);
- HeapLeakChecker::IgnoreObject(p);
- // This will crash if p is not known to heap profiler:
- // (i.e. STL's "allocator" does not have a direct hook to heap profiler)
- HeapLeakChecker::UnIgnoreObject(p);
- ptrs[i] = p;
- }
- for (int i = 0; i < kSize; ++i) {
- allocator.deallocate(ptrs[i], i*3+1);
- ptrs[i] = NULL;
- }
- CHECK(check.BriefSameHeap()); // just in case
-}
-
-static struct group* grp = NULL;
-static const int kKeys = 50;
-static pthread_key_t key[kKeys];
-
-static void KeyFree(void* ptr) {
- delete [] reinterpret_cast<char*>(ptr);
-}
-
-static bool key_init_has_run = false;
-
-static void KeyInit() {
- for (int i = 0; i < kKeys; ++i) {
- CHECK_EQ(pthread_key_create(&key[i], KeyFree), 0);
- VLOG(2) << "pthread key " << i << " : " << key[i];
- }
- key_init_has_run = true; // needed for a sanity-check
-}
-
-// force various C library static and thread-specific allocations
-static void TestLibCAllocate() {
- CHECK(key_init_has_run);
- for (int i = 0; i < kKeys; ++i) {
- void* p = pthread_getspecific(key[i]);
- if (NULL == p) {
- if (i == 0) {
- // Test-logging inside threads which (potentially) creates and uses
- // thread-local data inside standard C++ library:
- VLOG(0) << "Adding pthread-specifics for thread " << pthread_self()
- << " pid " << getpid();
- }
- p = new(initialized) char[77 + i];
- VLOG(2) << "pthread specific " << i << " : " << p;
- pthread_setspecific(key[i], p);
- }
- }
-
- strerror(errno);
- const time_t now = time(NULL);
- ctime(&now);
-#ifdef HAVE_EXECINFO_H
- void *stack[1];
- backtrace(stack, 1);
-#endif
-#ifdef HAVE_GRP_H
- gid_t gid = getgid();
- getgrgid(gid);
- if (grp == NULL) grp = getgrent(); // a race condition here is okay
- getgrnam(grp->gr_name);
-#endif
-#ifdef HAVE_PWD_H
- getpwuid(geteuid());
-#endif
-}
-
-// Continuous random heap memory activity to try to disrupt heap checking.
-static void* HeapBusyThreadBody(void* a) {
- const int thread_num = reinterpret_cast<intptr_t>(a);
- VLOG(0) << "A new HeapBusyThread " << thread_num;
- TestLibCAllocate();
-
- int user = 0;
- // Try to hide ptr from heap checker in a CPU register:
- // Here we are just making a best effort to put the only pointer
- // to a heap object into a thread register to test
- // the thread-register finding machinery in the heap checker.
-#if defined(__i386__) && defined(__GNUC__)
- register int** ptr asm("esi");
-#elif defined(__x86_64__) && defined(__GNUC__)
- register int** ptr asm("r15");
-#else
- register int** ptr;
-#endif
- ptr = NULL;
- typedef set<int> Set;
- Set s1;
- while (1) {
- // TestLibCAllocate() calls libc functions that don't work so well
- // after main() has exited. So we just don't do the test then.
- if (!g_have_exited_main)
- TestLibCAllocate();
-
- if (ptr == NULL) {
- ptr = new(initialized) int*[1];
- *ptr = new(initialized) int[1];
- }
- set<int>* s2 = new(initialized) set<int>[1];
- s1.insert(random());
- s2->insert(*s1.begin());
- user += *s2->begin();
- **ptr += user;
- if (random() % 51 == 0) {
- s1.clear();
- if (random() % 2 == 0) {
- s1.~Set();
- new(&s1) Set;
- }
- }
- VLOG(3) << pthread_self() << " (" << getpid() << "): in wait: "
- << ptr << ", " << *ptr << "; " << s1.size();
- VLOG(2) << pthread_self() << " (" << getpid() << "): in wait, ptr = "
- << reinterpret_cast<void*>(
- reinterpret_cast<uintptr_t>(ptr) ^ kHideMask)
- << "^" << reinterpret_cast<void*>(kHideMask);
- if (FLAGS_test_register_leak && thread_num % 5 == 0) {
- // Hide the register "ptr" value with an xor mask.
- // If one provides --test_register_leak flag, the test should
- // (with very high probability) crash on some leak check
- // with a leak report (of some x * sizeof(int) + y * sizeof(int*) bytes)
- // pointing at the two lines above in this function
- // with "new(initialized) int" in them as the allocators
- // of the leaked objects.
- // CAVEAT: We can't really prevent a compiler to save some
- // temporary values of "ptr" on the stack and thus let us find
- // the heap objects not via the register.
- // Hence it's normal if for certain compilers or optimization modes
- // --test_register_leak does not cause a leak crash of the above form
- // (this happens e.g. for gcc 4.0.1 in opt mode).
- ptr = reinterpret_cast<int **>(
- reinterpret_cast<uintptr_t>(ptr) ^ kHideMask);
- // busy loop to get the thread interrupted at:
- for (int i = 1; i < 10000000; ++i) user += (1 + user * user * 5) / i;
- ptr = reinterpret_cast<int **>(
- reinterpret_cast<uintptr_t>(ptr) ^ kHideMask);
- } else {
- poll(NULL, 0, random() % 100);
- }
- VLOG(2) << pthread_self() << ": continuing";
- if (random() % 3 == 0) {
- delete [] *ptr;
- delete [] ptr;
- ptr = NULL;
- }
- delete [] s2;
- }
- return a;
-}
-
-static void RunHeapBusyThreads() {
- KeyInit();
- if (!FLAGS_interfering_threads || FLAGS_no_threads) return;
-
- const int n = 17; // make many threads
-
- pthread_t tid;
- pthread_attr_t attr;
- CHECK_EQ(pthread_attr_init(&attr), 0);
- // make them and let them run
- for (int i = 0; i < n; ++i) {
- VLOG(0) << "Creating extra thread " << i + 1;
- CHECK(pthread_create(&tid, &attr, HeapBusyThreadBody,
- reinterpret_cast<void*>(i)) == 0);
- }
-
- Pause();
- Pause();
-}
-
-// ========================================================================= //
-
-// This code section is to test that objects that are reachable from global
-// variables are not reported as leaks
-// as well as that (Un)IgnoreObject work for such objects fine.
-
-// An object making functions:
-// returns a "weird" pointer to a new object for which
-// it's worth checking that the object is reachable via that pointer.
-typedef void* (*ObjMakerFunc)();
-static list<ObjMakerFunc> obj_makers; // list of registered object makers
-
-// Helper macro to register an object making function
-// 'name' is an identifier of this object maker,
-// 'body' is its function body that must declare
-// pointer 'p' to the nex object to return.
-// Usage example:
-// REGISTER_OBJ_MAKER(trivial, int* p = new(initialized) int;)
-#define REGISTER_OBJ_MAKER(name, body) \
- void* ObjMaker_##name##_() { \
- VLOG(1) << "Obj making " << #name; \
- body; \
- return p; \
- } \
- static ObjMakerRegistrar maker_reg_##name##__(&ObjMaker_##name##_);
-// helper class for REGISTER_OBJ_MAKER
-struct ObjMakerRegistrar {
- ObjMakerRegistrar(ObjMakerFunc obj_maker) { obj_makers.push_back(obj_maker); }
-};
-
-// List of the objects/pointers made with all the obj_makers
-// to test reachability via global data pointers during leak checks.
-static list<void*>* live_objects = new list<void*>;
- // pointer so that it does not get destructed on exit
-
-// Exerciser for one ObjMakerFunc.
-static void TestPointerReach(ObjMakerFunc obj_maker) {
- HeapLeakChecker::IgnoreObject(obj_maker()); // test IgnoreObject
-
- void* obj = obj_maker();
- HeapLeakChecker::IgnoreObject(obj);
- HeapLeakChecker::UnIgnoreObject(obj); // test UnIgnoreObject
- HeapLeakChecker::IgnoreObject(obj); // not to need deletion for obj
-
- live_objects->push_back(obj_maker()); // test reachability at leak check
-}
-
-// Test all ObjMakerFunc registred via REGISTER_OBJ_MAKER.
-static void TestObjMakers() {
- for (list<ObjMakerFunc>::const_iterator i = obj_makers.begin();
- i != obj_makers.end(); ++i) {
- TestPointerReach(*i);
- TestPointerReach(*i); // a couple more times would not hurt
- TestPointerReach(*i);
- }
-}
-
-// A dummy class to mimic allocation behavior of string-s.
-template<class T>
-struct Array {
- Array() {
- size = 3 + random() % 30;
- ptr = new(initialized) T[size];
- }
- ~Array() { delete [] ptr; }
- Array(const Array& x) {
- size = x.size;
- ptr = new(initialized) T[size];
- for (size_t i = 0; i < size; ++i) {
- ptr[i] = x.ptr[i];
- }
- }
- void operator=(const Array& x) {
- delete [] ptr;
- size = x.size;
- ptr = new(initialized) T[size];
- for (size_t i = 0; i < size; ++i) {
- ptr[i] = x.ptr[i];
- }
- }
- void append(const Array& x) {
- T* p = new(initialized) T[size + x.size];
- for (size_t i = 0; i < size; ++i) {
- p[i] = ptr[i];
- }
- for (size_t i = 0; i < x.size; ++i) {
- p[size+i] = x.ptr[i];
- }
- size += x.size;
- delete [] ptr;
- ptr = p;
- }
- private:
- size_t size;
- T* ptr;
-};
-
-// to test pointers to objects, built-in arrays, string, etc:
-REGISTER_OBJ_MAKER(plain, int* p = new(initialized) int;)
-REGISTER_OBJ_MAKER(int_array_1, int* p = new(initialized) int[1];)
-REGISTER_OBJ_MAKER(int_array, int* p = new(initialized) int[10];)
-REGISTER_OBJ_MAKER(string, Array<char>* p = new(initialized) Array<char>();)
-REGISTER_OBJ_MAKER(string_array,
- Array<char>* p = new(initialized) Array<char>[5];)
-REGISTER_OBJ_MAKER(char_array, char* p = new(initialized) char[5];)
-REGISTER_OBJ_MAKER(appended_string,
- Array<char>* p = new Array<char>();
- p->append(Array<char>());
-)
-REGISTER_OBJ_MAKER(plain_ptr, int** p = new(initialized) int*;)
-REGISTER_OBJ_MAKER(linking_ptr,
- int** p = new(initialized) int*;
- *p = new(initialized) int;
-)
-
-// small objects:
-REGISTER_OBJ_MAKER(0_sized, void* p = malloc(0);) // 0-sized object (important)
-REGISTER_OBJ_MAKER(1_sized, void* p = malloc(1);)
-REGISTER_OBJ_MAKER(2_sized, void* p = malloc(2);)
-REGISTER_OBJ_MAKER(3_sized, void* p = malloc(3);)
-REGISTER_OBJ_MAKER(4_sized, void* p = malloc(4);)
-
-static int set_data[] = { 1, 2, 3, 4, 5, 6, 7, 21, 22, 23, 24, 25, 26, 27 };
-static set<int> live_leak_set(set_data, set_data+7);
-static const set<int> live_leak_const_set(set_data, set_data+14);
-
-REGISTER_OBJ_MAKER(set,
- set<int>* p = new(initialized) set<int>(set_data, set_data + 13);
-)
-
-class ClassA {
- public:
- explicit ClassA(int a) : ptr(NULL) { }
- mutable char* ptr;
-};
-static const ClassA live_leak_mutable(1);
-
-template<class C>
-class TClass {
- public:
- explicit TClass(int a) : ptr(NULL) { }
- mutable C val;
- mutable C* ptr;
-};
-static const TClass<Array<char> > live_leak_templ_mutable(1);
-
-class ClassB {
- public:
- ClassB() { }
- char b[7];
- virtual void f() { }
- virtual ~ClassB() { }
-};
-
-class ClassB2 {
- public:
- ClassB2() { }
- char b2[11];
- virtual void f2() { }
- virtual ~ClassB2() { }
-};
-
-class ClassD1 : public ClassB {
- char d1[15];
- virtual void f() { }
-};
-
-class ClassD2 : public ClassB2 {
- char d2[19];
- virtual void f2() { }
-};
-
-class ClassD : public ClassD1, public ClassD2 {
- char d[3];
- virtual void f() { }
- virtual void f2() { }
-};
-
-// to test pointers to objects of base subclasses:
-
-REGISTER_OBJ_MAKER(B, ClassB* p = new(initialized) ClassB;)
-REGISTER_OBJ_MAKER(D1, ClassD1* p = new(initialized) ClassD1;)
-REGISTER_OBJ_MAKER(D2, ClassD2* p = new(initialized) ClassD2;)
-REGISTER_OBJ_MAKER(D, ClassD* p = new(initialized) ClassD;)
-
-REGISTER_OBJ_MAKER(D1_as_B, ClassB* p = new(initialized) ClassD1;)
-REGISTER_OBJ_MAKER(D2_as_B2, ClassB2* p = new(initialized) ClassD2;)
-REGISTER_OBJ_MAKER(D_as_B, ClassB* p = new(initialized) ClassD;)
-REGISTER_OBJ_MAKER(D_as_D1, ClassD1* p = new(initialized) ClassD;)
-// inside-object pointers:
-REGISTER_OBJ_MAKER(D_as_B2, ClassB2* p = new(initialized) ClassD;)
-REGISTER_OBJ_MAKER(D_as_D2, ClassD2* p = new(initialized) ClassD;)
-
-class InterfaceA {
- public:
- virtual void A() = 0;
- virtual ~InterfaceA() { }
- protected:
- InterfaceA() { }
-};
-
-class InterfaceB {
- public:
- virtual void B() = 0;
- virtual ~InterfaceB() { }
- protected:
- InterfaceB() { }
-};
-
-class InterfaceC : public InterfaceA {
- public:
- virtual void C() = 0;
- virtual ~InterfaceC() { }
- protected:
- InterfaceC() { }
-};
-
-class ClassMltD1 : public ClassB, public InterfaceB, public InterfaceC {
- public:
- char d1[11];
- virtual void f() { }
- virtual void A() { }
- virtual void B() { }
- virtual void C() { }
-};
-
-class ClassMltD2 : public InterfaceA, public InterfaceB, public ClassB {
- public:
- char d2[15];
- virtual void f() { }
- virtual void A() { }
- virtual void B() { }
-};
-
-// to specifically test heap reachability under
-// inerface-only multiple inheritance (some use inside-object pointers):
-REGISTER_OBJ_MAKER(MltD1, ClassMltD1* p = new(initialized) ClassMltD1;)
-REGISTER_OBJ_MAKER(MltD1_as_B, ClassB* p = new(initialized) ClassMltD1;)
-REGISTER_OBJ_MAKER(MltD1_as_IA, InterfaceA* p = new(initialized) ClassMltD1;)
-REGISTER_OBJ_MAKER(MltD1_as_IB, InterfaceB* p = new(initialized) ClassMltD1;)
-REGISTER_OBJ_MAKER(MltD1_as_IC, InterfaceC* p = new(initialized) ClassMltD1;)
-
-REGISTER_OBJ_MAKER(MltD2, ClassMltD2* p = new(initialized) ClassMltD2;)
-REGISTER_OBJ_MAKER(MltD2_as_B, ClassB* p = new(initialized) ClassMltD2;)
-REGISTER_OBJ_MAKER(MltD2_as_IA, InterfaceA* p = new(initialized) ClassMltD2;)
-REGISTER_OBJ_MAKER(MltD2_as_IB, InterfaceB* p = new(initialized) ClassMltD2;)
-
-// to mimic UnicodeString defined in third_party/icu,
-// which store a platform-independent-sized refcount in the first
-// few bytes and keeps a pointer pointing behind the refcount.
-REGISTER_OBJ_MAKER(unicode_string,
- char* p = new char[sizeof(uint32) * 10];
- p += sizeof(uint32);
-)
-// similar, but for platform-dependent-sized refcount
-REGISTER_OBJ_MAKER(ref_counted,
- char* p = new char[sizeof(int) * 20];
- p += sizeof(int);
-)
-
-struct Nesting {
- struct Inner {
- Nesting* parent;
- Inner(Nesting* p) : parent(p) {}
- };
- Inner i0;
- char n1[5];
- Inner i1;
- char n2[11];
- Inner i2;
- char n3[27];
- Inner i3;
- Nesting() : i0(this), i1(this), i2(this), i3(this) {}
-};
-
-// to test inside-object pointers pointing at objects nested into heap objects:
-REGISTER_OBJ_MAKER(nesting_i0, Nesting::Inner* p = &((new Nesting())->i0);)
-REGISTER_OBJ_MAKER(nesting_i1, Nesting::Inner* p = &((new Nesting())->i1);)
-REGISTER_OBJ_MAKER(nesting_i2, Nesting::Inner* p = &((new Nesting())->i2);)
-REGISTER_OBJ_MAKER(nesting_i3, Nesting::Inner* p = &((new Nesting())->i3);)
-
-// allocate many objects reachable from global data
-static void TestHeapLeakCheckerLiveness() {
- live_leak_mutable.ptr = new(initialized) char[77];
- live_leak_templ_mutable.ptr = new(initialized) Array<char>();
- live_leak_templ_mutable.val = Array<char>();
-
- TestObjMakers();
-}
-
-// ========================================================================= //
-
-// Get address (PC value) following the mmap call into addr_after_mmap_call
-static void* Mmapper(uintptr_t* addr_after_mmap_call) {
- void* r = mmap(NULL, 100, PROT_READ|PROT_WRITE,
- MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
- // Get current PC value into addr_after_mmap_call
- void* stack[1];
- CHECK_EQ(GetStackTrace(stack, 1, 0), 1);
- *addr_after_mmap_call = reinterpret_cast<uintptr_t>(stack[0]);
- sleep(0); // undo -foptimize-sibling-calls
- return r;
-}
-
-// On PPC64 the stacktrace returned by GetStatcTrace contains the function
-// address from .text segment while function pointers points to ODP entries.
-// The following code decodes the ODP to get the actual symbol address.
-#if defined(__linux) && defined(__PPC64__) && (_CALL_ELF != 2)
-static inline uintptr_t GetFunctionAddress (void* (*func)(uintptr_t*))
-{
- struct odp_entry_t {
- unsigned long int symbol;
- unsigned long int toc;
- unsigned long int env;
- } *odp_entry = reinterpret_cast<odp_entry_t*>(func);
-
- return static_cast<uintptr_t>(odp_entry->symbol);
-}
-#else
-static inline uintptr_t GetFunctionAddress (void* (*func)(uintptr_t*))
-{
- return reinterpret_cast<uintptr_t>(func);
-}
-#endif
-
-// to trick complier into preventing inlining
-static void* (*mmapper_addr)(uintptr_t* addr) = &Mmapper;
-
-// TODO(maxim): copy/move this to memory_region_map_unittest
-// TODO(maxim): expand this test to include mmap64, mremap and sbrk calls.
-static void VerifyMemoryRegionMapStackGet() {
- uintptr_t caller_addr_limit;
- void* addr = (*mmapper_addr)(&caller_addr_limit);
- uintptr_t caller = 0;
- { MemoryRegionMap::LockHolder l;
- for (MemoryRegionMap::RegionIterator
- i = MemoryRegionMap::BeginRegionLocked();
- i != MemoryRegionMap::EndRegionLocked(); ++i) {
- if (i->start_addr == reinterpret_cast<uintptr_t>(addr)) {
- CHECK_EQ(caller, 0);
- caller = i->caller();
- }
- }
- }
- // caller must point into Mmapper function:
- if (!(GetFunctionAddress(mmapper_addr) <= caller &&
- caller < caller_addr_limit)) {
- LOGF << std::hex << "0x" << caller
- << " does not seem to point into code of function Mmapper at "
- << "0x" << reinterpret_cast<uintptr_t>(mmapper_addr)
- << "! Stack frame collection must be off in MemoryRegionMap!";
- LOG(FATAL, "\n");
- }
- munmap(addr, 100);
-}
-
-static void* Mallocer(uintptr_t* addr_after_malloc_call) {
- void* r = malloc(100);
- sleep(0); // undo -foptimize-sibling-calls
- // Get current PC value into addr_after_malloc_call
- void* stack[1];
- CHECK_EQ(GetStackTrace(stack, 1, 0), 1);
- *addr_after_malloc_call = reinterpret_cast<uintptr_t>(stack[0]);
- return r;
-}
-
-// to trick complier into preventing inlining
-static void* (*mallocer_addr)(uintptr_t* addr) = &Mallocer;
-
-// non-static for friendship with HeapProfiler
-// TODO(maxim): expand this test to include
-// realloc, calloc, memalign, valloc, pvalloc, new, and new[].
-extern void VerifyHeapProfileTableStackGet() {
- uintptr_t caller_addr_limit;
- void* addr = (*mallocer_addr)(&caller_addr_limit);
- uintptr_t caller =
- reinterpret_cast<uintptr_t>(HeapLeakChecker::GetAllocCaller(addr));
- // caller must point into Mallocer function:
- if (!(GetFunctionAddress(mallocer_addr) <= caller &&
- caller < caller_addr_limit)) {
- LOGF << std::hex << "0x" << caller
- << " does not seem to point into code of function Mallocer at "
- << "0x" << reinterpret_cast<uintptr_t>(mallocer_addr)
- << "! Stack frame collection must be off in heap profiler!";
- LOG(FATAL, "\n");
- }
- free(addr);
-}
-
-// ========================================================================= //
-
-static void MakeALeak(void** arr) {
- PreventHeapReclaiming(10 * sizeof(int));
- void* a = new(initialized) int[10];
- Hide(&a);
- *arr = a;
-}
-
-// Helper to do 'return 0;' inside main(): insted we do 'return Pass();'
-static int Pass() {
- fprintf(stdout, "PASS\n");
- g_have_exited_main = true;
- return 0;
-}
-
-int main(int argc, char** argv) {
- run_hidden_ptr = DoRunHidden;
- wipe_stack_ptr = DoWipeStack;
- if (!HeapLeakChecker::IsActive()) {
- CHECK_EQ(FLAGS_heap_check, "");
- LOG(WARNING, "HeapLeakChecker got turned off; we won't test much...");
- } else {
- VerifyMemoryRegionMapStackGet();
- VerifyHeapProfileTableStackGet();
- }
-
- KeyInit();
-
- // glibc 2.4, on x86_64 at least, has a lock-ordering bug, which
- // means deadlock is possible when one thread calls dl_open at the
- // same time another thread is calling dl_iterate_phdr. libunwind
- // calls dl_iterate_phdr, and TestLibCAllocate calls dl_open (or the
- // various syscalls in it do), at least the first time it's run.
- // To avoid the deadlock, we run TestLibCAllocate once before getting
- // multi-threaded.
- // TODO(csilvers): once libc is fixed, or libunwind can work around it,
- // get rid of this early call. We *want* our test to
- // find potential problems like this one!
- TestLibCAllocate();
-
- if (FLAGS_interfering_threads) {
- RunHeapBusyThreads(); // add interference early
- }
- TestLibCAllocate();
-
- LOGF << "In main(): heap_check=" << FLAGS_heap_check << endl;
-
- CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good
-
- if (FLAGS_test_leak) {
- void* arr;
- RunHidden(NewCallback(MakeALeak, &arr));
- Use(&arr);
- LogHidden("Leaking", arr);
- if (FLAGS_test_cancel_global_check) {
- HeapLeakChecker::CancelGlobalCheck();
- } else {
- // Verify we can call NoGlobalLeaks repeatedly without deadlocking
- HeapLeakChecker::NoGlobalLeaks();
- HeapLeakChecker::NoGlobalLeaks();
- }
- return Pass();
- // whole-program leak-check should (with very high probability)
- // catch the leak of arr (10 * sizeof(int) bytes)
- // (when !FLAGS_test_cancel_global_check)
- }
-
- if (FLAGS_test_loop_leak) {
- void* arr1;
- void* arr2;
- RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2));
- Use(&arr1);
- Use(&arr2);
- LogHidden("Loop leaking", arr1);
- LogHidden("Loop leaking", arr2);
- if (FLAGS_test_cancel_global_check) {
- HeapLeakChecker::CancelGlobalCheck();
- } else {
- // Verify we can call NoGlobalLeaks repeatedly without deadlocking
- HeapLeakChecker::NoGlobalLeaks();
- HeapLeakChecker::NoGlobalLeaks();
- }
- return Pass();
- // whole-program leak-check should (with very high probability)
- // catch the leak of arr1 and arr2 (4 * sizeof(void*) bytes)
- // (when !FLAGS_test_cancel_global_check)
- }
-
- if (FLAGS_test_register_leak) {
- // make us fail only where the .sh test expects:
- Pause();
- for (int i = 0; i < 100; ++i) { // give it some time to crash
- CHECK(HeapLeakChecker::NoGlobalLeaks());
- Pause();
- }
- return Pass();
- }
-
- TestHeapLeakCheckerLiveness();
-
- HeapLeakChecker heap_check("all");
-
- TestHiddenPointer();
-
- TestHeapLeakChecker();
- Pause();
- TestLeakButTotalsMatch();
- Pause();
-
- TestHeapLeakCheckerDeathSimple();
- Pause();
- TestHeapLeakCheckerDeathLoop();
- Pause();
- TestHeapLeakCheckerDeathInverse();
- Pause();
- TestHeapLeakCheckerDeathNoLeaks();
- Pause();
- TestHeapLeakCheckerDeathCountLess();
- Pause();
- TestHeapLeakCheckerDeathCountMore();
- Pause();
-
- TestHeapLeakCheckerDeathTrick();
- Pause();
-
- CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good
-
- TestHeapLeakCheckerNoFalsePositives();
- Pause();
-
- TestHeapLeakCheckerDisabling();
- Pause();
-
- TestSTLAlloc();
- Pause();
- TestSTLAllocInverse();
- Pause();
-
- // Test that various STL allocators work. Some of these are redundant, but
- // we don't know how STL might change in the future. For example,
- // http://wiki/Main/StringNeStdString.
-#define DTSL(a) { DirectTestSTLAlloc(a, #a); \
- Pause(); }
- DTSL(std::allocator<char>());
- DTSL(std::allocator<int>());
- DTSL(std::string().get_allocator());
- DTSL(string().get_allocator());
- DTSL(vector<int>().get_allocator());
- DTSL(vector<double>().get_allocator());
- DTSL(vector<vector<int> >().get_allocator());
- DTSL(vector<string>().get_allocator());
- DTSL((map<string, string>().get_allocator()));
- DTSL((map<string, int>().get_allocator()));
- DTSL(set<char>().get_allocator());
-#undef DTSL
-
- TestLibCAllocate();
- Pause();
-
- CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good
-
- Pause();
-
- if (!FLAGS_maybe_stripped) {
- CHECK(heap_check.SameHeap());
- } else {
- WARN_IF(heap_check.SameHeap() != true,
- "overall leaks are caught; we must be using a stripped binary");
- }
-
- CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good
-
- return Pass();
-}
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/bb3371c3/third_party/gperftools/src/tests/heap-checker_unittest.sh
----------------------------------------------------------------------
diff --git a/third_party/gperftools/src/tests/heap-checker_unittest.sh b/third_party/gperftools/src/tests/heap-checker_unittest.sh
deleted file mode 100755
index 3c9c0e9..0000000
--- a/third_party/gperftools/src/tests/heap-checker_unittest.sh
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/sh
-
-# Copyright (c) 2005, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# ---
-# Author: Craig Silverstein
-#
-# Runs the heap-checker unittest with various environment variables.
-# This is necessary because we turn on features like the heap profiler
-# and heap checker via environment variables. This test makes sure
-# they all play well together.
-
-# We expect BINDIR and PPROF_PATH to be set in the environment.
-# If not, we set them to some reasonable values
-BINDIR="${BINDIR:-.}"
-PPROF_PATH="${PPROF_PATH:-$BINDIR/src/pprof}"
-
-if [ "x$1" = "x-h" -o "$1" = "x--help" ]; then
- echo "USAGE: $0 [unittest dir] [path to pprof]"
- echo " By default, unittest_dir=$BINDIR, pprof_path=$PPROF_PATH"
- exit 1
-fi
-
-HEAP_CHECKER="${1:-$BINDIR/heap-checker_unittest}"
-PPROF_PATH="${2:-$PPROF_PATH}"
-
-TMPDIR=/tmp/heap_check_info
-rm -rf $TMPDIR || exit 2
-mkdir $TMPDIR || exit 3
-
-# $1: value of heap-check env. var.
-run_check() {
- export PPROF_PATH="$PPROF_PATH"
- [ -n "$1" ] && export HEAPCHECK="$1" || unset HEAPPROFILE
-
- echo -n "Testing $HEAP_CHECKER with HEAPCHECK=$1 ... "
- if $HEAP_CHECKER > $TMPDIR/output 2>&1; then
- echo "OK"
- else
- echo "FAILED"
- echo "Output from the failed run:"
- echo "----"
- cat $TMPDIR/output
- echo "----"
- exit 4
- fi
-
- # If we set HEAPPROFILE, then we expect it to actually have emitted
- # a profile. Check that it did.
- if [ -n "$HEAPPROFILE" ]; then
- [ -e "$HEAPPROFILE.0001.heap" ] || exit 5
- fi
-}
-
-run_check ""
-run_check "local"
-run_check "normal"
-run_check "strict"
-
-rm -rf $TMPDIR # clean up
-
-echo "PASS"