#!/bin/sh
# Build + full test (mock, pg_regress, TAP) inside the official postgres
# Docker image.
#
# Usage: sh test/docker_check.sh [16|17]
#        SANITIZE=1 sh test/docker_check.sh 17   # ASan+UBSan build
set -eu

PGVER="${1:-17}"
IMG="postgres:${PGVER}"
SRC="$(cd "$(dirname "$0")/.." && pwd)"
SANITIZE="${SANITIZE:-0}"

docker run --rm -v "$SRC":/src:ro -e PGVER="$PGVER" -e SANITIZE="$SANITIZE" \
  "$IMG" bash -ec '
  export DEBIAN_FRONTEND=noninteractive
  apt-get update -qq
  apt-get install -y -qq --no-install-recommends \
    postgresql-server-dev-$PGVER libcurl4-openssl-dev libipc-run-perl \
    pkg-config gcc make >/dev/null

  COPT="-Werror"
  SRV_ENV=""
  if [ "$SANITIZE" = 1 ]; then
    COPT="-Werror -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer -Og"
    LIBASAN=$(gcc -print-file-name=libasan.so)
    LIBUBSAN=$(gcc -print-file-name=libubsan.so)
    # the server is not instrumented, so the sanitizer runtimes must be
    # preloaded into every backend; leak detection would flag the
    # server allocator itself, so keep it off.
    SRV_ENV="LD_PRELOAD=$LIBASAN:$LIBUBSAN ASAN_OPTIONS=detect_leaks=0:abort_on_error=1:log_path=/tmp/asan UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1:log_path=/tmp/ubsan"
  fi

  cp -r /src /build && cd /build
  rm -f typesafe.o typesafe.so typesafe.dylib typesafe.bc
  make COPT="$COPT" with_llvm=no PG_CONFIG=/usr/lib/postgresql/$PGVER/bin/pg_config
  make COPT="$COPT" with_llvm=no PG_CONFIG=/usr/lib/postgresql/$PGVER/bin/pg_config install

  # cluster owned by postgres, trust auth on the socket
  su postgres -c "/usr/lib/postgresql/$PGVER/bin/initdb -D /tmp/data --locale=C" >/dev/null
  su postgres -c "env $SRV_ENV /usr/lib/postgresql/$PGVER/bin/pg_ctl -D /tmp/data -l /tmp/pg.log -o \"-k /tmp -c listen_addresses=\" start"

  export PGHOST=/tmp PGUSER=postgres PGDATABASE=postgres
  su postgres -c "/usr/lib/postgresql/$PGVER/bin/createdb -h /tmp typesafe_ci" || true
  PGDATABASE=typesafe_ci sh test/ci.sh

  chown -R postgres /build
  su postgres -c "cd /build && PGHOST=/tmp env $SRV_ENV make COPT=\"$COPT\" with_llvm=no PG_CONFIG=/usr/lib/postgresql/$PGVER/bin/pg_config installcheck" \
    || { cat /build/regression.diffs 2>/dev/null; find /build/tmp_check -name "*.log" -exec tail -50 {} + 2>/dev/null; exit 1; }

  if [ "$SANITIZE" = 1 ]; then
    if ls /tmp/asan.* /tmp/ubsan.* 2>/dev/null; then
      echo "=== SANITIZER REPORTS FOUND ==="
      cat /tmp/asan.* /tmp/ubsan.* 2>/dev/null
      exit 1
    fi
    echo "=== PG$PGVER (ASan+UBSan): ALL CHECKS PASSED, no reports ==="
  else
    echo "=== PG$PGVER: ALL CHECKS PASSED ==="
  fi
'
