15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/bin/sh 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2005, Google Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# All rights reserved. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Redistribution and use in source and binary forms, with or without 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# modification, are permitted provided that the following conditions are 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# met: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# * Redistributions of source code must retain the above copyright 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# notice, this list of conditions and the following disclaimer. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# * Redistributions in binary form must reproduce the above 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# copyright notice, this list of conditions and the following disclaimer 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# in the documentation and/or other materials provided with the 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# distribution. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# * Neither the name of Google Inc. nor the names of its 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# contributors may be used to endorse or promote products derived from 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# this software without specific prior written permission. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# --- 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Author: Maxim Lifantsev 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Run the heap checker unittest in a mode where it is supposed to crash and 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# return an error if it doesn't. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# We expect BINDIR to be set in the environment. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# If not, we set it to some reasonable value. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BINDIR="${BINDIR:-.}" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "USAGE: $0 [unittest dir]" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo " By default, unittest_dir=$BINDIR" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit 1 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fi 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EXE="${1:-$BINDIR}/heap-checker_unittest" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TMPDIR="/tmp/heap_check_death_info" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ALARM() { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # You need perl to run pprof, so I assume it's installed 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perl -e ' 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $timeout=$ARGV[0]; shift; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $retval = 255; # the default retval, for the case where we timed out 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) eval { # need to run in an eval-block to trigger during system() 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) local $SIG{ALRM} = sub { die "alarm\n" }; # \n is required! 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm $timeout; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $retval = system(@ARGV); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Make retval bash-style: exit status, or 128+n if terminated by signal n 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $retval = ($retval & 127) ? (128 + $retval) : ($retval >> 8); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alarm 0; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit $retval; # return system()-retval, or 255 if system() never returned 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)' "$@" 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $1: timeout for alarm; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $2: regexp of expected exit code(s); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $3: regexp to match a line in the output; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $4: regexp to not match a line in the output; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# $5+ args to pass to $EXE 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test() { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Note: make sure these varnames don't conflict with any vars outside Test()! 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) timeout="$1" 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected_ec="$1" 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected_regexp="$1" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unexpected_regexp="$1" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo -n "Testing $EXE with $@ ... " 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output="$TMPDIR/output" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ALARM $timeout env "$@" $EXE > "$output" 2>&1 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) actual_ec=$? 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ec_ok=`expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false` 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches_ok=`test -z "$expected_regexp" || \ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) grep "$expected_regexp" "$output" >/dev/null 2>&1 || echo false` 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) negmatches_ok=`test -z "$unexpected_regexp" || \ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ! grep "$unexpected_regexp" "$output" >/dev/null 2>&1 || echo false` 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if $ec_ok && $matches_ok && $negmatches_ok; then 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "PASS" 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 # 0: success 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fi 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If we get here, we failed. Now we just need to report why 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "FAIL" 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if [ $actual_ec -eq 255 ]; then # 255 == SIGTERM due to $ALARM 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Test was taking unexpectedly long time to run and so we aborted it." 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Try the test case manually or raise the timeout from $timeout" 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "to distinguish test slowness from a real problem." 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $ec_ok || \ 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Wrong exit code: expected: '$expected_ec'; actual: $actual_ec" 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $matches_ok || \ 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Output did not match '$expected_regexp'" 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) $negmatches_ok || \ 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Output unexpectedly matched '$unexpected_regexp'" 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fi 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "Output from failed run:" 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "---" 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cat "$output" 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) echo "---" 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1 # 1: failure 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TMPDIR=/tmp/heap_check_death_info 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)rm -rf $TMPDIR || exit 1 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)mkdir $TMPDIR || exit 2 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)export HEAPCHECK=strict # default mode 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# These invocations should pass (0 == PASS): 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This tests that turning leak-checker off dynamically works fine 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 120 0 "^PASS$" "" HEAPCHECK="" || exit 1 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# This disables threads so we can cause leaks reliably and test finding them 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 120 0 "^PASS$" "" HEAP_CHECKER_TEST_NO_THREADS=1 || exit 2 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Test that --test_cancel_global_check works 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 20 0 "Canceling .* whole-program .* leak check$" "" \ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 3 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 20 0 "Canceling .* whole-program .* leak check$" "" \ 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 4 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Test that very early log messages are present and controllable: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EARLY_MSG="Starting tracking the heap$" 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 0 "$EARLY_MSG" "" \ 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PERFTOOLS_VERBOSE=10 || exit 5 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 0 "MemoryRegionMap Init$" "" \ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PERFTOOLS_VERBOSE=11 || exit 6 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 0 "" "$EARLY_MSG" \ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \ 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PERFTOOLS_VERBOSE=-11 || exit 7 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# These invocations should fail with very high probability, 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# rather than return 0 or hang (1 == exit(1), 134 == abort(), 139 = SIGSEGV): 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 1 "Exiting .* because of .* leaks$" "" \ 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 8 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 1 "Exiting .* because of .* leaks$" "" \ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 9 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Test that we produce a reasonable textual leak report. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 1 "MakeALeak" "" \ 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECK_TEST_NO_THREADS=1 \ 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || exit 10 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Test that very early log messages are present and controllable: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 1 "Starting tracking the heap$" "" \ 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=10 \ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || exit 11 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Test 60 1 "" "Starting tracking the heap" \ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=-10 \ 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || exit 12 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cd / # so we're not in TMPDIR when we delete it 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)rm -rf $TMPDIR 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)echo "PASS" 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)exit 0 177