#!/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 # # 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 (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" check '^\$[0-9]+ = \{"a", "bb"\}$' "PIVector" check '^\$[0-9]+ = \{\{10\}, \{1, 2, 3\}\}$' "PIVector>" 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 =="