Skip to content

Commit 75ab97d

Browse files
committed
test(callgrind): wire underflow + py3.14 reproducers, strengthen post-checks
- runtime_obj_skip_c.vgtest: post-check now greps for any fn=skipme_*. The previous check only looked for skipme_func, which obj-skip folded into the caller so the test passed even with the bug live. - runtime_obj_skip_underflow: wire .vgtest/.post.exp/.stderr.exp + Makefile.am entries (was only checked-in as bare .c sources). - runtime_obj_skip_py314.vgtest: same shim driver as the 3.13 test, exercised with python3.14 (tail-call interpreter). Skipped by prereq if python3.14 isn't on PATH. - filter_stderr: drop diagnostic logging lines added during this investigation (instrument_state, obj_skip HIT/miss, underflow reset, reconstruct_call_stack, python fn summary, fn=...obj=... summary) so .stderr.exp matching stays stable. All four reproducers go RED before the fix, GREEN after.
1 parent 958b7cf commit 75ab97d

10 files changed

Lines changed: 53 additions & 5 deletions

callgrind/tests/Makefile.am

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ EXTRA_DIST = \
1313
find_debuginfo.vgtest find_debuginfo.stderr.exp find_debuginfo.post.exp \
1414
runtime_obj_skip_py.vgtest runtime_obj_skip_py.stderr.exp runtime_obj_skip_py.post.exp \
1515
runtime_obj_skip_py.py runtime_obj_skip_py_shim.c \
16+
runtime_obj_skip_py314.vgtest runtime_obj_skip_py314.stderr.exp runtime_obj_skip_py314.post.exp \
1617
runtime_obj_skip_c.vgtest runtime_obj_skip_c.stderr.exp runtime_obj_skip_c.post.exp \
1718
runtime_obj_skip_c.c runtime_obj_skip_c_lib.c \
19+
runtime_obj_skip_underflow.vgtest runtime_obj_skip_underflow.stderr.exp runtime_obj_skip_underflow.post.exp \
20+
runtime_obj_skip_underflow.c runtime_obj_skip_underflow_lib.c \
1821
bug497723.stderr.exp bug497723.post.exp bug497723.vgtest \
1922
simwork1.vgtest simwork1.stdout.exp simwork1.stderr.exp \
2023
simwork2.vgtest simwork2.stdout.exp simwork2.stderr.exp \
@@ -33,7 +36,7 @@ EXTRA_DIST = \
3336
inline-crossfile.vgtest inline-crossfile.stderr.exp inline-crossfile.stdout.exp inline-crossfile.post.exp \
3437
inline-crossfile-helper1.h inline-crossfile-helper2.h filter_inline
3538

36-
check_PROGRAMS = clreq find_debuginfo simwork threads inline-samefile inline-crossfile runtime_obj_skip_c
39+
check_PROGRAMS = clreq find_debuginfo simwork threads inline-samefile inline-crossfile runtime_obj_skip_c runtime_obj_skip_underflow
3740

3841
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
3942
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
@@ -46,7 +49,7 @@ threads_LDADD = -lpthread
4649

4750
# Shim loaded by runtime_obj_skip_py.py via ctypes. Built unconditionally;
4851
# the test's prereq skips it if the .so is missing.
49-
check_DATA = runtime_obj_skip_py_shim.so runtime_obj_skip_c_lib.so
52+
check_DATA = runtime_obj_skip_py_shim.so runtime_obj_skip_c_lib.so runtime_obj_skip_underflow_lib.so
5053

5154
runtime_obj_skip_py_shim.so: runtime_obj_skip_py_shim.c
5255
$(CC) -shared -fPIC -O2 -I$(top_srcdir) -I$(top_srcdir)/include \
@@ -63,4 +66,14 @@ runtime_obj_skip_c_LDFLAGS = $(AM_LDFLAGS) -L. -l:runtime_obj_skip_c_lib.so \
6366
-Wl,-rpath,'$$ORIGIN'
6467
runtime_obj_skip_c_DEPENDENCIES = runtime_obj_skip_c_lib.so
6568

66-
CLEANFILES = runtime_obj_skip_py_shim.so runtime_obj_skip_c_lib.so
69+
# Shared lib for the runtime_obj_skip_underflow test.
70+
runtime_obj_skip_underflow_lib.so: runtime_obj_skip_underflow_lib.c
71+
$(CC) -shared -fPIC -O2 -I$(top_srcdir) -I$(top_srcdir)/include \
72+
$< -o $@
73+
74+
runtime_obj_skip_underflow_LDADD = -ldl
75+
runtime_obj_skip_underflow_LDFLAGS = $(AM_LDFLAGS) -L. -l:runtime_obj_skip_underflow_lib.so \
76+
-Wl,-rpath,'$$ORIGIN'
77+
runtime_obj_skip_underflow_DEPENDENCIES = runtime_obj_skip_underflow_lib.so
78+
79+
CLEANFILES = runtime_obj_skip_py_shim.so runtime_obj_skip_c_lib.so runtime_obj_skip_underflow_lib.so

callgrind/tests/filter_stderr

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ sed "/warning: L4 cache found, using its data for the LL simulation./d" |
3030
sed "/Warning: Cannot auto-detect cache config, using defaults./d" |
3131
sed "/Run with -v to see./d" |
3232
sed "/warning: specified LL cache: line_size .*$/d" |
33-
sed "/warning: simulated LL cache: line_size .*$/d"
33+
sed "/warning: simulated LL cache: line_size .*$/d" |
34+
35+
# Drop callgrind diagnostic logs (verbose obj-skip / cxt / underflow tracing).
36+
# These are chore-level diagnostics that vary by run/host and aren't assertions.
37+
sed -E "/^(add_obj_to_skip|obj-skip list now has| \[[0-9]+\] '|fn_nodes already obj_skip_checked|instrument_state ->|new_fn_node:|obj_skip (HIT|miss):| vs \[[0-9]+\] strcmp=|push_cxt FORCED|underflow reset:|reconstruct_call_stack:|=== python fn summary| fn='[^']*' obj=)/d"
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
Events : Ir
4+
Collected :
5+
6+
I refs:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
prereq: test -f runtime_obj_skip_c && test -f runtime_obj_skip_c_lib.so
22
prog-asis: ./runtime_obj_skip_c
33
vgopts: --instr-atstart=no --compress-strings=no --callgrind-out-file=callgrind.out.runtime_obj_skip_c
4-
post: sh -c 'if grep -q "^fn=skipme_func" callgrind.out.runtime_obj_skip_c; then echo "FAIL: skipme_func leaked into top-level fn= block"; else echo OK; fi'
4+
post: sh -c 'leaked=$(grep "^fn=skipme_" callgrind.out.runtime_obj_skip_c); if [ -n "$leaked" ]; then echo "FAIL: skipped fn leaked into top-level fn= block:"; echo "$leaked"; exit 1; else echo OK; fi'
55
cleanup: rm -f callgrind.out.runtime_obj_skip_c
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OK
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
Events : Ir
4+
Collected :
5+
6+
I refs:
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
prereq: command -v python3.14 >/dev/null && test -f runtime_obj_skip_py_shim.so
2+
prog-asis: python3.14
3+
args: runtime_obj_skip_py.py
4+
vgopts: --instr-atstart=no --compress-strings=no --callgrind-out-file=callgrind.out.runtime_obj_skip_py314
5+
post: sh -c 'c=$(awk "/^ob=/{p=(\$0~/libpython/)} /^fn=/&&p{c++} END{print c+0}" callgrind.out.runtime_obj_skip_py314); if [ "$c" -lt 100 ]; then echo OK; else echo "FAIL libpython fns=$c"; fi'
6+
cleanup: rm -f callgrind.out.runtime_obj_skip_py314
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OK
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
3+
Events : Ir
4+
Collected :
5+
6+
I refs:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
prereq: test -f runtime_obj_skip_underflow && test -f runtime_obj_skip_underflow_lib.so
2+
prog-asis: ./runtime_obj_skip_underflow
3+
vgopts: --instr-atstart=no --compress-strings=no --callgrind-out-file=callgrind.out.runtime_obj_skip_underflow
4+
post: sh -c 'leaked=$(grep "^fn=skipme_" callgrind.out.runtime_obj_skip_underflow); if [ -n "$leaked" ]; then echo "FAIL: skipped fn leaked into top-level fn= block:"; echo "$leaked"; exit 1; else echo OK; fi'
5+
cleanup: rm -f callgrind.out.runtime_obj_skip_underflow

0 commit comments

Comments
 (0)