#!/usr/bin/env bash # What tests/profile-summary.py makes of a collapsed profile. # # The fixture is hand-written rather than a captured profile: the interesting # cases are a parked EDT, a working EDT and another thread entirely, and three # lines say that more clearly than 12000 real ones. set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT command -v python3 >/dev/null || { echo "SKIP: python3 is not installed"; exit 0; } pass=0; fail=0 check() { local name="$1"; shift if "$@" >/dev/null 2>&1; then echo "ok $name"; pass=$((pass + 1)) else echo "FAIL $name"; fail=$((fail + 1)); fi } summary() { python3 "$ROOT/tests/profile-summary.py" "$@" 2>&1; } # A parked EDT, an EDT painting through the encode path, an EDT painting # without encoding, and a worker thread that is not the EDT at all. cat > "$TMP/p.collapsed" <<'EOF' java/awt/EventDispatchThread.run;java/awt/EventQueue.getNextEvent 900 java/awt/EventDispatchThread.run;megamek/BoardView.drawHex;org/webswing/model/ImageConst.;com/manticore/tools/ZPNG.encode 70 java/awt/EventDispatchThread.run;megamek/BoardView.drawHex;java/awt/Graphics.fillRect 30 java/lang/Thread.run;java/util/concurrent/ThreadPoolExecutor.getTask 500 EOF out="$(summary "$TMP/p.collapsed")" check "it runs against a collapsed file" test -n "$out" check " it counts every sample in the file, not only the EDT's" \ grep -q "1,500 samples" <<<"$out" check " a parked EDT is waiting, not working" grep -q "900 waiting" <<<"$out" check " and the rest is working" grep -q "100 running" <<<"$out" # The buckets nest: an encode happens inside a paint, so 100% paint and 70% # encode is the correct reading of this fixture, not a double count. check " everything running was under paint" grep -q "100.0% paint" <<<"$out" check " and the png share is of the working samples" \ grep -q "70.0% png+deflate" <<<"$out" check " a thread that is not the EDT is left out" \ bash -c '! grep -q "ThreadPoolExecutor" <<<"$1"' _ "$out" # Widening past the EDT has to keep counting parked threads as parked: a # pooled worker sitting in getTask is not doing work, and wall-clock sampling # records a lot of them. check "--thread '' counts every thread" \ bash -c 'python3 "$1/tests/profile-summary.py" --thread "" "$2" | grep -q "1,400 waiting"' \ _ "$ROOT" "$TMP/p.collapsed" # zlib internals name neither ZPNG nor PNG, and missing them undercounted the # encode share by nearly 3x on the first real profile. printf 'java/awt/EventDispatchThread.run;megamek/BoardView.drawHex;deflate_slow;longest_match 40\n' \ >> "$TMP/p.collapsed" check " zlib internals count as encode, not as something else" \ bash -c 'python3 "$1/tests/profile-summary.py" "$2" | grep -q "78.6% png+deflate"' \ _ "$ROOT" "$TMP/p.collapsed" # A profile with nothing running says so rather than dividing by zero. printf 'java/awt/EventDispatchThread.run;java/awt/EventQueue.getNextEvent 10\n' \ > "$TMP/idle.collapsed" check "an entirely idle profile does not divide by zero" \ bash -c 'python3 "$1/tests/profile-summary.py" "$2" | grep -q "nothing was running"' \ _ "$ROOT" "$TMP/idle.collapsed" check "an empty file is an error, not a crash" \ bash -c ': > "$2"; ! python3 "$1/tests/profile-summary.py" "$2"' \ _ "$ROOT" "$TMP/empty.collapsed" echo echo "$pass passed, $fail failed" [ "$fail" -eq 0 ]