summaryrefslogtreecommitdiff
path: root/tests/symbols_test.sh
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-12 17:49:34 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-12 17:49:34 +0300
commit4384435941b8c7658856b381d071aee2e0035e89 (patch)
tree5ece99c3dd1decb8ec3fd404c0ece2b5865a552a /tests/symbols_test.sh
term: move the term core to subprojects/term
The core now builds, tests, and benchmarks alone, as a Meson subproject with no dependency on the main tree. - include/term/ holds term.h and the header-only unicode/. src/ holds the core and its private headers. The main tree gets only include/term through term_dep, so it cannot reach a private header. - The term tests, the term benchmarks, the Kitty parser suite, and tools/amalgamate.py and tools/generate_unicode.py move with it. The tests run as term:<name>. - The main build passes its -march (arch_flag) and b_ndebug to the subproject. A directory configured before this commit needs meson configure -Dterm:arch_flag=-march=... once. - The term tests compile with -UNDEBUG. They do work inside assert. - The subproject exports term_test_dep with term_api.h, for the main tree's render, thumbnail, color, and selection tests. - The Kitty bridge used struct vector2i and has not compiled since the public API redesign. It builds again. 2 of its 14 tests fail: REP after a tab, and a cursor report after a resize. - dirgraph.py drops the term and unicode layers. Its self-test uses pty. - The symbols test ignores the __odr_asan symbols that ASan adds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests/symbols_test.sh')
-rw-r--r--tests/symbols_test.sh63
1 files changed, 63 insertions, 0 deletions
diff --git a/tests/symbols_test.sh b/tests/symbols_test.sh
new file mode 100644
index 0000000..4c7aee1
--- /dev/null
+++ b/tests/symbols_test.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+# Every global symbol of the term library starts with term_. A host links
+# the library next to its own code, so a bare name such as palette_init can
+# collide with a host symbol. Every function that term.h declares is also
+# defined, so the library cannot leave one out. A shared build exports
+# exactly the functions of term.h.
+set -euo pipefail
+lib=$1
+src=${2:-$(dirname "$0")/../include/term}
+
+syms=$(nm -g --defined-only -P "$lib")
+# ASan adds an __odr_asan.<name> symbol for each global variable.
+defined=$(awk 'NF >= 2 && $2 ~ /^[A-Z]$/ && $2 != "U" { print $1 }' <<<"$syms" |
+ grep -v '^_*odr_asan\.' | sed 's/^_//' | sort -u)
+
+status=0
+bad=$(grep -v '^term_' <<<"$defined" || true)
+if [[ -n $bad ]]; then
+ echo "$lib: global symbols without the term_ prefix:" >&2
+ echo "$bad" >&2
+ status=1
+fi
+
+declared=$("${CC:-cc}" -std=c11 -E -P -I"$src" "$src/term.h" | python3 -c '
+import re, sys
+text = re.sub(r"\s+", " ", sys.stdin.read())
+depth, flat = 0, []
+for ch in text:
+ depth += ch == "{"
+ if depth == 0:
+ flat.append(ch)
+ depth -= ch == "}"
+ if ch == "}" and depth == 0:
+ flat.append(";")
+for stmt in "".join(flat).split(";"):
+ if "static" in stmt or "typedef" in stmt:
+ continue
+ m = re.search(r"\b(term_\w+)\s*\(", stmt)
+ if m:
+ print(m.group(1))
+' | sort -u)
+missing=$(comm -23 <(echo "$declared") <(echo "$defined"))
+if [[ -n $missing ]]; then
+ echo "$lib: functions declared in term.h but not defined:" >&2
+ echo "$missing" >&2
+ status=1
+fi
+
+# The shared library exports term.h and nothing else.
+shared=${3:-}
+if [[ -n $shared ]]; then
+ exported=$(nm -D --defined-only -P "$shared" | awk '$2 ~ /^[TDBRVW]$/ { print $1 }' |
+ sed 's/^_//' | sort -u)
+ extra=$(comm -13 <(echo "$declared") <(echo "$exported"))
+ absent=$(comm -23 <(echo "$declared") <(echo "$exported"))
+ if [[ -n $extra || -n $absent ]]; then
+ echo "$shared: exports differ from term.h" >&2
+ [[ -n $extra ]] && echo "not in term.h: $extra" >&2
+ [[ -n $absent ]] && echo "not exported: $absent" >&2
+ status=1
+ fi
+fi
+exit $status