Skip to content

Commit 366bd12

Browse files
avargitster
authored andcommitted
test-lib: add a SANITIZE=leak logging mode
Add the ability to run the test suite under a new "GIT_TEST_SANITIZE_LEAK_LOG=true" mode, when true we'll log the leaks we find an a new "test-results/<test-name>.leak" directory. That new path is consistent with the existing "test-results/<test-name>.<type>" results, except that those are all files, not directories. We also set "log_exe_name=1" to include the name of the executable in the filename. This gives us files like "trace.git.<pid>" instead of the default of "trace.<pid>". I.e. we'll be able to distinguish "git" leaks from "test-tool", "git-daemon" etc. We then set "dedup_token_length" to non-zero ("0" is the default) to succinctly log a token we can de-duplicate these stacktraces on. The string is simply a one-line stack-trace with only function names up to N frames, which we limit at "9999" as a shorthand for "infinite" (there appears to be no way to say "no limit"). With these combined we can now easily get e.g. the top 10 leaks in the test suite grouped by full stacktrace: grep -o -P -h '(?<=DEDUP_TOKEN: ).*' test-results/*.leak/trace.git.* | sort | uniq -c | sort -nr | head -n 10 Or add "grep -E -o '[^-]+'" to that to group by functions instead of stack traces: grep -o -P -h '(?<=DEDUP_TOKEN: ).*' test-results/*.leak/trace.git.* | grep -E -o '[^-]+' | sort | uniq -c | sort -nr | head -n 20 This new mode requires git to be compiled with SANITIZE=leak, rather than explaining that in the documentation let's make it self-documenting by bailing out if the user asks for this without git having been compiled with SANITIZE=leak, as we do with GIT_TEST_PASSING_SANITIZE_LEAK=true. Signed-off-by: Ævar Arnfjörð Bjarmason <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ac8e3e9 commit 366bd12

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

t/README

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ declared themselves as leak-free by setting
371371
"TEST_PASSES_SANITIZE_LEAK=true" before sourcing "test-lib.sh". This
372372
test mode is used by the "linux-leaks" CI target.
373373

374+
GIT_TEST_SANITIZE_LEAK_LOG=true will log memory leaks to
375+
"test-results/$TEST_NAME.leak/trace.*" files. The logs include a
376+
"dedup_token" (see +"ASAN_OPTIONS=help=1 ./git") and other options to
377+
make logs +machine-readable.
378+
374379
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
375380
default to n.
376381

t/test-lib.sh

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ TEST_NUMBER="${TEST_NAME%%-*}"
305305
TEST_NUMBER="${TEST_NUMBER#t}"
306306
TEST_RESULTS_DIR="$TEST_OUTPUT_DIRECTORY/test-results"
307307
TEST_RESULTS_BASE="$TEST_RESULTS_DIR/$TEST_NAME$TEST_STRESS_JOB_SFX"
308+
TEST_RESULTS_SAN_FILE_PFX=trace
309+
TEST_RESULTS_SAN_DIR_SFX=leak
310+
TEST_RESULTS_SAN_FILE=
311+
TEST_RESULTS_SAN_DIR="$TEST_RESULTS_DIR/$TEST_NAME.$TEST_RESULTS_SAN_DIR_SFX"
308312
TRASH_DIRECTORY="trash directory.$TEST_NAME$TEST_STRESS_JOB_SFX"
309313
test -n "$root" && TRASH_DIRECTORY="$root/$TRASH_DIRECTORY"
310314
case "$TRASH_DIRECTORY" in
@@ -1447,6 +1451,10 @@ then
14471451
test_done
14481452
fi
14491453

1454+
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK () {
1455+
BAIL_OUT "$1 has no effect except when compiled with SANITIZE=leak"
1456+
}
1457+
14501458
if test -n "$SANITIZE_LEAK"
14511459
then
14521460
if test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
@@ -1461,9 +1469,29 @@ then
14611469
test_done
14621470
fi
14631471
fi
1472+
1473+
if test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
1474+
then
1475+
if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
1476+
then
1477+
BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
1478+
fi &&
1479+
TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
1480+
1481+
# Don't litter *.leak dirs if there was nothing to report
1482+
test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
1483+
1484+
prepend_var LSAN_OPTIONS : dedup_token_length=9999
1485+
prepend_var LSAN_OPTIONS : log_exe_name=1
1486+
prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
1487+
export LSAN_OPTIONS
1488+
fi
14641489
elif test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
14651490
then
1466-
BAIL_OUT "GIT_TEST_PASSING_SANITIZE_LEAK=true has no effect except when compiled with SANITIZE=leak"
1491+
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"
1492+
elif test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
1493+
then
1494+
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
14671495
fi
14681496

14691497
# Last-minute variable setup

0 commit comments

Comments
 (0)