Files
pip/tools/gdb/test/test_pp.sh
T

117 lines
3.8 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Verification for the PIP GDB pretty-printers (tools/gdb/pip_pp.py).
#
# Builds demo_pp.cpp with debug info against an already-built PIP library,
# runs it under GDB in batch mode with the pretty-printers loaded, and
# checks that the expected pretty output is produced.
#
# Usage:
# tools/gdb/test/test_pp.sh <pip-build-dir>
#
# <pip-build-dir> must contain libpip.so and pip_export.h, e.g. build_linux.
# Requires g++ and gdb.
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PIP_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
BUILD_DIR="${1:-}"
if [[ -z "${BUILD_DIR}" ]]; then
echo "usage: $0 <pip-build-dir> (e.g. build_linux)" >&2
exit 2
fi
BUILD_DIR="$(cd "${BUILD_DIR}" && pwd)"
if [[ ! -f "${BUILD_DIR}/libpip.so" ]]; then
echo "error: ${BUILD_DIR}/libpip.so not found" >&2
exit 2
fi
if [[ ! -f "${BUILD_DIR}/pip_export.h" ]]; then
echo "error: ${BUILD_DIR}/pip_export.h not found (is this a PIP build dir?)" >&2
exit 2
fi
WORK="$(mktemp -d)"
trap 'rm -rf "${WORK}"' EXIT
# Include dirs: libs/main plus each of its subdirectories, plus the build dir.
INCS="-I${PIP_ROOT}/libs/main -I${BUILD_DIR}"
for d in "${PIP_ROOT}"/libs/main/*/; do
INCS+=" -I${d%/}"
done
echo "== building demo =="
g++ -g -O0 -std=c++11 "${SCRIPT_DIR}/demo_pp.cpp" \
${INCS} \
-L"${BUILD_DIR}" -lpip -Wl,-rpath,"${BUILD_DIR}" \
-o "${WORK}/demo_pp"
echo "== running gdb =="
OUT="$(gdb -batch -nx \
-ex "source ${PIP_ROOT}/tools/gdb/pip_pp.py" \
-ex "break main" -ex run \
-ex "print str_hello" \
-ex "print str_cyr" \
-ex "print str_empty" \
-ex "print str_esc" \
-ex "print chr_a" \
-ex "print chr_cyr" \
-ex "print ba_hello" \
-ex "print vec_int" \
-ex "print vec_str" \
-ex "print vec_vec" \
-ex "print vec_big" \
-ex "print map_str_int" \
-ex "print set_int" \
-ex "print list_str" \
-ex "print pair_str_int" \
-ex "print var_int" \
-ex "print var_invalid" \
-ex "print addr" \
-ex "print addr_null" \
-ex "print ptr_str" \
-ex "print *ptr_str" \
"${WORK}/demo_pp" 2>&1)"
echo "${OUT}" | grep -E '^\$[0-9]+ = ' || true
fail=0
check() {
local pattern="$1" desc="$2"
if grep -qE -- "${pattern}" <<<"${OUT}"; then
echo "ok ${desc}"
else
echo "FAIL ${desc} (expected to match: ${pattern})"
fail=1
fi
}
check '^\$[0-9]+ = "hello"$' "PIString ascii"
check '^\$[0-9]+ = "мир"$' "PIString utf-8"
check '^\$[0-9]+ = ""$' "PIString empty"
check '^\$[0-9]+ = "a\\"b\\\\c\\nd\\te"$' "PIString escapes"
check '^\$[0-9]+ = '"'"'a'"'"'$' "PIChar printable"
check '^\$[0-9]+ = U\+043c$' "PIChar non-ascii"
check '^\$[0-9]+ = \{0x48, 0x65, 0x6c, 0x6c, 0x6f\}$' "PIByteArray hex"
check '^\$[0-9]+ = \{1, 2, 3\}$' "PIVector<int>"
check '^\$[0-9]+ = \{"a", "bb"\}$' "PIVector<PIString>"
check '^\$[0-9]+ = \{\{10\}, \{1, 2, 3\}\}$' "PIVector<PIVector<int>>"
check '\.\.\. \(40 total\)\}$' "element count limit"
check '^\$[0-9]+ = \{"x": 1, "y": 2\}$' "PIMap"
check '^\$[0-9]+ = \{3, 5\}$' "PISet"
check '^\$[0-9]+ = \{"one", "two"\}$' "PIStringList"
check '^\$[0-9]+ = \{"k", 7\}$' "PIPair"
check '^\$[0-9]+ = PIVariant\(pivInt, 4 bytes\)$' "PIVariant typed"
check '^\$[0-9]+ = PIVariant\(pivInvalid, 0 bytes\)$' "PIVariant invalid"
check '^\$[0-9]+ = 192\.168\.1\.10:8080$' "PINetworkAddress"
check '^\$[0-9]+ = 0\.0\.0\.0:0$' "PINetworkAddress null"
check '^\$[0-9]+ = \(PIString \*\) 0x[0-9a-f]+ "hello"$' "pointer to PIString"
check '^\$[0-9]+ = "hello"$' "dereferenced pointer"
if [[ "${fail}" -ne 0 ]]; then
echo "== FAILED =="
exit 1
fi
echo "== all checks passed =="