Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions test/harness_selftest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -305,11 +305,59 @@ rm -f "$_fx"
#
# This check is what keeps the property true. Without it the order decays the
# first time somebody appends by hand, and the reduction quietly goes away.
_sorted_expected="$(listed_suites | sort)"
#
# LC_ALL=C, and the collation is part of the property rather than a detail (#552).
# "Sorted" is not machine-independent: C compares byte by byte so `_` (0x5F)
# precedes `e`, while en_US.UTF-8 ignores punctuation at the first level and
# compares `sortstatus` against `sortedprojection`. The array holds sort_status
# then sorted_projection, so it is sorted in one and unsorted in the other, and
# this check pinned neither. On a clean main it FAILED under en_US.UTF-8 and
# passed here only because the container defaults to C.UTF-8, which collates
# like C.
#
# The ambiguity is worse than the false red. Sorted order is what gives two
# agents' new suites different insertion points; if two contributors disagree
# about what sorted means they insert in different places, and the property stops
# delivering the merges it exists for.
_sorted_expected="$(listed_suites | LC_ALL=C sort)"
_sorted_actual="$(listed_suites)"
check "the suite list is sorted, so two new suites land in different places" \
check "the suite list is sorted in C order, so two new suites land in different places" \
"$([ "$_sorted_actual" = "$_sorted_expected" ] && echo sorted || echo "not sorted")" "sorted"

# The pair that decides it, asserted directly so a future edit that "fixes" the
# order to UTF-8 collation fails here with the reason rather than only failing
# the comparison above.
check "premise: C collation puts sort_status before sorted_projection" \
"$(printf 'sorted_projection\nsort_status\n' | LC_ALL=C sort | head -1)" "sort_status"

# ---- and comm's two inputs must be sorted the SAME way (#552 follow-up) -----
#
# `comm` requires both inputs sorted in one collation and does not check. Fed
# inconsistently-sorted input it does not error; it returns the wrong lines.
#
# test/rebuild.sh:130 does `comm -23` over two `sort -u` outputs, neither pinned.
# They agree today because they share a locale. The plausible next edit is
# somebody pinning ONE of them because this PR taught them to, and the result is
# a symbol check that silently reports the wrong unresolved symbols -- either a
# false red, or the worse direction, a real unresolved symbol not reported.
#
# Asserted over source text, which is the weaker kind, because reproducing it
# needs two locales and a built .so. Premised on the comm still existing, or the
# grep approves a file that no longer has one.
_cm_files="$(grep -ln 'comm -' "$(dirname "${BASH_SOURCE[0]}")"/*.sh 2>/dev/null)"
check "premise: some suite still uses comm, or the check below is vacuous" \
"$([ -n "$_cm_files" ] && echo yes || echo no)" "yes"

_cm_unpinned=""
for _f in $_cm_files; do
# every `| sort` in a file that uses comm must carry LC_ALL=C
if grep -qE '\|[[:space:]]*sort' "$_f" && grep -E '\|[[:space:]]*sort' "$_f" | grep -qv 'LC_ALL=C'; then
_cm_unpinned="$_cm_unpinned $(basename "$_f")"
fi
done
check "a file that uses comm pins the collation of every sort feeding it" \
"$(printf '%s' "$_cm_unpinned" | sed 's/^ //')" ""

# A case over the cached list rather than `listed_suites | grep -qx`. The pipe
# was the defect: grep -q returns on its match, printf takes EPIPE, and pipefail
# turns that into a failed pipeline for a suite that IS registered. See the note
Expand Down
11 changes: 7 additions & 4 deletions test/rebuild.sh
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,21 @@ if command -v nm >/dev/null 2>&1; then
IGNORE='^(_ITM_|__gmon_start__$|__cxa_finalize$)'

undef="$(nm -D --undefined-only "$SO" 2>/dev/null | awk '{print $NF}' |
strip_ver | grep -Ev "$IGNORE" | sort -u)"
strip_ver | grep -Ev "$IGNORE" | LC_ALL=C sort -u)"
# The .so is dlopen'd into the running postgres, so its symbols resolve against
# the server binary, everything the server itself links (libm, libssl, ...), and
# the .so's own dependencies. All three belong in the reference set.
defined="$(nm -D --defined-only "$BINDIR/postgres" 2>/dev/null | awk '{print $NF}')"
for lib in $(ldd "$SO" "$BINDIR/postgres" 2>/dev/null |
awk '/=>/ {print $3}' | grep -v '^$' | sort -u); do
awk '/=>/ {print $3}' | grep -v '^$' | LC_ALL=C sort -u); do
defined="$defined
$(nm -D --defined-only "$lib" 2>/dev/null | awk '{print $NF}')"
done
defined="$(echo "$defined" | strip_ver | sort -u)"
missing="$(comm -23 <(echo "$undef") <(echo "$defined"))"
defined="$(echo "$defined" | strip_ver | LC_ALL=C sort -u)"
# comm requires ONE collation across both inputs and does not check. Both
# sorts above are pinned to C, so comm is pinned to C too -- inputs sorted one
# way and compared another is the same defect with an extra step (#552).
missing="$(LC_ALL=C comm -23 <(echo "$undef") <(echo "$defined"))"
if [ -n "$missing" ]; then
echo "rebuild: UNRESOLVED SYMBOLS against $PGVER:" >&2
echo "$missing" | head -20 >&2
Expand Down
Loading