heap-checker-death_unittest.sh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #!/bin/sh
  2. # Copyright (c) 2005, Google Inc.
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are
  7. # met:
  8. #
  9. # * Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above
  12. # copyright notice, this list of conditions and the following disclaimer
  13. # in the documentation and/or other materials provided with the
  14. # distribution.
  15. # * Neither the name of Google Inc. nor the names of its
  16. # contributors may be used to endorse or promote products derived from
  17. # this software without specific prior written permission.
  18. #
  19. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. # ---
  31. # Author: Maxim Lifantsev
  32. #
  33. # Run the heap checker unittest in a mode where it is supposed to crash and
  34. # return an error if it doesn't.
  35. # We expect BINDIR to be set in the environment.
  36. # If not, we set it to some reasonable value.
  37. BINDIR="${BINDIR:-.}"
  38. if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
  39. echo "USAGE: $0 [unittest dir]"
  40. echo " By default, unittest_dir=$BINDIR"
  41. exit 1
  42. fi
  43. EXE="${1:-$BINDIR/heap-checker_unittest}"
  44. TMPDIR="/tmp/heap_check_death_info"
  45. ALARM() {
  46. # You need perl to run pprof, so I assume it's installed
  47. perl -e '
  48. $timeout=$ARGV[0]; shift;
  49. $retval = 255; # the default retval, for the case where we timed out
  50. eval { # need to run in an eval-block to trigger during system()
  51. local $SIG{ALRM} = sub { die "alarm\n" }; # \n is required!
  52. alarm $timeout;
  53. $retval = system(@ARGV);
  54. # Make retval bash-style: exit status, or 128+n if terminated by signal n
  55. $retval = ($retval & 127) ? (128 + $retval) : ($retval >> 8);
  56. alarm 0;
  57. };
  58. exit $retval; # return system()-retval, or 255 if system() never returned
  59. ' "$@"
  60. }
  61. # $1: timeout for alarm;
  62. # $2: regexp of expected exit code(s);
  63. # $3: regexp to match a line in the output;
  64. # $4: regexp to not match a line in the output;
  65. # $5+ args to pass to $EXE
  66. Test() {
  67. # Note: make sure these varnames don't conflict with any vars outside Test()!
  68. timeout="$1"
  69. shift
  70. expected_ec="$1"
  71. shift
  72. expected_regexp="$1"
  73. shift
  74. unexpected_regexp="$1"
  75. shift
  76. echo -n "Testing $EXE with $@ ... "
  77. output="$TMPDIR/output"
  78. ALARM $timeout env "$@" $EXE > "$output" 2>&1
  79. actual_ec=$?
  80. ec_ok=`expr "$actual_ec" : "$expected_ec$" >/dev/null || echo false`
  81. matches_ok=`test -z "$expected_regexp" || \
  82. grep "$expected_regexp" "$output" >/dev/null 2>&1 || echo false`
  83. negmatches_ok=`test -z "$unexpected_regexp" || \
  84. ! grep "$unexpected_regexp" "$output" >/dev/null 2>&1 || echo false`
  85. if $ec_ok && $matches_ok && $negmatches_ok; then
  86. echo "PASS"
  87. return 0 # 0: success
  88. fi
  89. # If we get here, we failed. Now we just need to report why
  90. echo "FAIL"
  91. if [ $actual_ec -eq 255 ]; then # 255 == SIGTERM due to $ALARM
  92. echo "Test was taking unexpectedly long time to run and so we aborted it."
  93. echo "Try the test case manually or raise the timeout from $timeout"
  94. echo "to distinguish test slowness from a real problem."
  95. else
  96. $ec_ok || \
  97. echo "Wrong exit code: expected: '$expected_ec'; actual: $actual_ec"
  98. $matches_ok || \
  99. echo "Output did not match '$expected_regexp'"
  100. $negmatches_ok || \
  101. echo "Output unexpectedly matched '$unexpected_regexp'"
  102. fi
  103. echo "Output from failed run:"
  104. echo "---"
  105. cat "$output"
  106. echo "---"
  107. return 1 # 1: failure
  108. }
  109. TMPDIR=/tmp/heap_check_death_info
  110. rm -rf $TMPDIR || exit 1
  111. mkdir $TMPDIR || exit 2
  112. export HEAPCHECK=strict # default mode
  113. # These invocations should pass (0 == PASS):
  114. # This tests that turning leak-checker off dynamically works fine
  115. Test 120 0 "^PASS$" "" HEAPCHECK="" || exit 1
  116. # This disables threads so we can cause leaks reliably and test finding them
  117. Test 120 0 "^PASS$" "" HEAP_CHECKER_TEST_NO_THREADS=1 || exit 2
  118. # Test that --test_cancel_global_check works
  119. Test 20 0 "Canceling .* whole-program .* leak check$" "" \
  120. HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 3
  121. Test 20 0 "Canceling .* whole-program .* leak check$" "" \
  122. HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK=1 || exit 4
  123. # Test that very early log messages are present and controllable:
  124. EARLY_MSG="Starting tracking the heap$"
  125. Test 60 0 "$EARLY_MSG" "" \
  126. HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
  127. PERFTOOLS_VERBOSE=10 || exit 5
  128. Test 60 0 "MemoryRegionMap Init$" "" \
  129. HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
  130. PERFTOOLS_VERBOSE=11 || exit 6
  131. Test 60 0 "" "$EARLY_MSG" \
  132. HEAPCHECK="" HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
  133. PERFTOOLS_VERBOSE=-11 || exit 7
  134. # These invocations should fail with very high probability,
  135. # rather than return 0 or hang (1 == exit(1), 134 == abort(), 139 = SIGSEGV):
  136. Test 60 1 "Exiting .* because of .* leaks$" "" \
  137. HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 8
  138. Test 60 1 "Exiting .* because of .* leaks$" "" \
  139. HEAP_CHECKER_TEST_TEST_LOOP_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 || exit 9
  140. # Test that we produce a reasonable textual leak report.
  141. Test 60 1 "MakeALeak" "" \
  142. HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 \
  143. || exit 10
  144. # Test that very early log messages are present and controllable:
  145. Test 60 1 "Starting tracking the heap$" "" \
  146. HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=10 \
  147. || exit 11
  148. Test 60 1 "" "Starting tracking the heap" \
  149. HEAP_CHECKER_TEST_TEST_LEAK=1 HEAP_CHECKER_TEST_NO_THREADS=1 PERFTOOLS_VERBOSE=-10 \
  150. || exit 12
  151. cd / # so we're not in TMPDIR when we delete it
  152. rm -rf $TMPDIR
  153. echo "PASS"
  154. exit 0