#!/usr/bin/env bash # Regression test for newest_matching_file() in tools/install.sh. # # The function used to pipe `ls -1t` into `head -1`. Under `set -o pipefail` head # closes the pipe after the first line, ls dies on SIGPIPE, and the function returns # 141 with no output -- so once a directory holds enough matches to fill a pipe # buffer (~1600 names), "find the newest backup" starts failing the install instead # of answering. Its callers assign it at top level under `set -e`, so a 141 aborts # the run. # # The large-population case is the whole point: with two or three files the old code # passes, which is why this went unnoticed. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" TMP="$(mktemp -d "${TMPDIR:-/tmp}/mosaic-newest-match-test-XXXXXX")" trap 'rm -rf "$TMP"' EXIT # Load just the function under test, with the same shell options install.sh runs under. eval "$(sed -n '/^newest_matching_file()/,/^}/p' "$ROOT/tools/install.sh")" POPULATED="$TMP/many" mkdir -p "$POPULATED" # Enough names to overflow a 64 KiB pipe buffer several times over. for i in $(seq 1 5000); do : > "$POPULATED/mosaicstack-mosaic-0.0.${i}.tgz" done sleep 1 : > "$POPULATED/mosaicstack-mosaic-9.9.9.tgz" echo "[test] the newest match is returned from a directory large enough to fill a pipe" GOT="$(newest_matching_file "$POPULATED" 'mosaicstack-mosaic-*.tgz')" [[ "$(basename "$GOT")" == "mosaicstack-mosaic-9.9.9.tgz" ]] || { echo "expected the newest tarball, got '${GOT}'" >&2 exit 1 } echo "[test] a large population does not make the lookup fail" set +e newest_matching_file "$POPULATED" 'mosaicstack-mosaic-*.tgz' >/dev/null RC=$? set -e [[ "$RC" -eq 0 ]] || { echo "expected rc=0, got ${RC} (141 means the SIGPIPE regression is back)" >&2; exit 1; } echo "[test] a small population still works" SMALL="$TMP/few" mkdir -p "$SMALL" : > "$SMALL/mosaicstack-gateway-0.0.1.tgz" sleep 1 : > "$SMALL/mosaicstack-gateway-0.0.2.tgz" GOT="$(newest_matching_file "$SMALL" 'mosaicstack-gateway-*.tgz')" [[ "$(basename "$GOT")" == "mosaicstack-gateway-0.0.2.tgz" ]] || { echo "expected the newer gateway tarball, got '${GOT}'" >&2 exit 1 } echo "[test] no match is an empty answer, not an error" EMPTY="$TMP/none" mkdir -p "$EMPTY" set +e GOT="$(newest_matching_file "$EMPTY" 'nothing-*.tgz')" RC=$? set -e [[ "$RC" -eq 0 && -z "$GOT" ]] || { echo "expected empty output and rc=0, got '${GOT}' rc=${RC}" >&2; exit 1; } echo "[test] a directory that does not exist is an empty answer, not an error" set +e GOT="$(newest_matching_file "$TMP/absent" 'nothing-*.tgz')" RC=$? set -e [[ "$RC" -eq 0 && -z "$GOT" ]] || { echo "expected empty output and rc=0, got '${GOT}' rc=${RC}" >&2; exit 1; } echo "[test] newest_matching_file tests passed"