#!/bin/bash
set -e

pkg=acedb-other

export LC_ALL=C.UTF-8
if [ "${AUTOPKGTEST_TMP}" = "" ] ; then
  AUTOPKGTEST_TMP=$(mktemp -d /tmp/${pkg}-test.XXXXXX)
  # shellcheck disable=SC2064
  trap "rm -rf ${AUTOPKGTEST_TMP}" 0 INT QUIT ABRT PIPE TERM
fi

cp -a /usr/share/doc/${pkg}/examples/* "${AUTOPKGTEST_TMP}"

cd "${AUTOPKGTEST_TMP}"

# efetch retrieves entries from sequence databases using EMBL CD-ROM format
# binary index files.  This test queries a small SWISS-PROT-style pre-generated
# database and checks that efetch works in the main output modes.
#
# The database files were generated from this SWISS-PROT
# data (entrynam.idx: record_size 22, entry names padded to 12 bytes,
# big-endian numeric fields; division.lkp maps division code 1 to seq.dat):
#   ALBU_HUMAN / P02768 / ALBUMIN (HUMAN).
#   CYC_HUMAN  / P99999 / CYTOCHROME C (HUMAN).
#   G3P_HUMAN  / P04406 / GLYCERALDEHYDE-3-PHOSPHATE DEHYDROGENASE (HUMAN).
#
# NOTE: efetch's main() is declared void, so the exit status of a successful
# run is undefined (it happens to be 2 on current builds).  This test
# therefore checks output content, not exit status, for the success cases.
# The explicit exit(1) on "not found" is reliable and is tested below.

set -eu

# Expect $1 to appear in the combined output of the efetch command in $@.
check_contains()
{
    needle=$1
    shift
    output=$("$@" 2>&1) || true
    case "$output" in
        *"$needle"*)
            ;;
        *)
            echo "FAIL: output of '$*' does not contain '$needle'" >&2
            echo "----- output -----" >&2
            echo "$output" >&2
            echo "------------------" >&2
            exit 1
            ;;
    esac
}

# Command must fail (used for the "not found" error path, which exits 1).
check_fails()
{
    if "$@" >/dev/null 2>&1; then
        echo "FAIL: command unexpectedly succeeded: $*" >&2
        exit 1
    fi
}

D="$(pwd)/"

# Annotation output for the first, middle and last index records.
check_contains "P02768" efetch -D "$D" ALBU_HUMAN
check_contains "ALBUMIN (HUMAN)." efetch -D "$D" ALBU_HUMAN
check_contains "P99999" efetch -D "$D" CYC_HUMAN
check_contains "P04406" efetch -D "$D" G3P_HUMAN

# Fasta output.
check_contains ">ALBU_HUMAN" efetch -D "$D" -f ALBU_HUMAN
check_contains "MKWVTFISL" efetch -D "$D" -f ALBU_HUMAN

# Sequence-only output equals the full sequence on a single line.
out=$(efetch -D "$D" -q ALBU_HUMAN) || true
exp="MKWVTFISLLFLFSSAYSRGVFRRDTHKSEIAHRFKDLGEENFKALVLIAFAQYLQQCPFEDHVKLVNEVTEFAKTCVADESAENCDKSLHTLFGDKLCTVATLRETYGEMADCCAKQEPERNECFLQHKDDNPNLPRLVRPEVDVMCTAFHDNEETFLKKYLYEIARRHPYFYAPELLFFAKRYKAAFTECCQAADKAACLLPKLDELRDEGKASSAKQRLKCASLQKFGERAFKAWAVARLSQRFPKAEFAEVSKLVTDLTKVHTECCHGDLLECADDRADLAKYICENQDSISSKLKECCEKPLLEKSHCIAEVENDEMPADLPSLAADFVESKDVCKNYAEAKDVFLGMFLYEYARRHPDYSVVLLLRLAKTYETTLEKCCAAADPHECYAKVFDEFKPLVEEPQNLIKQNCELFEQLGEYKFQNALLVRYTKKVPQVSTPTLVEVSRNLGKVGSKCCKHPEAKRMPCAEDYLSVVLNQLCVLHEKTPVSDRVTKCCTESLVNRRPCFSALEVDETYVPKEFNAETFTFHADICTLSEKERQIKKQTALVELVKHKPKATKEQLKAVMDDFAAFVEKCCKADDKETCFAEEGKKLVAASQAALGL"
if [ "$out" != "$exp" ]; then
    echo "FAIL: sequence-only output mismatch" >&2
    exit 1
fi

# Subsequence extraction.
check_contains "MKWVT" efetch -D "$D" -f -s 1 -e 5 ALBU_HUMAN

# Unknown entry must fail with a non-zero exit status.
check_fails efetch -D "$D" NOSUCH

# -h prints usage.
check_contains "EFETCH - retrieve entries from sequence databases" efetch -h

echo "All efetch autopkgtests passed."

# acediff / acediffsorted emit the ACE commands needed to transform one
# ACE-format text file into another (the acedb equivalent of diff for ACE
# data).  acediff sorts the input internally, acediffsorted expects the
# input files to be pre-sorted.

cat > old.ace <<'EOF'
Object : "Gene_A"
  Locus "A1";
  Chromosome "I";
  Notes "original";
EOF

cat > new.ace <<'EOF'
Object : "Gene_A"
  Locus "A1";
  Chromosome "I";
  Notes "updated";
  Evidence "curated";
EOF

# acediff must emit the ACE commands that turn old.ace into new.ace.
check_contains 'Object "Gene_A"' acediff old.ace new.ace
check_contains 'Evidence "curated";' acediff old.ace new.ace
check_contains 'Notes "updated";' acediff old.ace new.ace
check_contains '-D Notes "original";' acediff old.ace new.ace

# acediffsorted must emit the same commands.
check_contains 'Object "Gene_A"' acediffsorted old.ace new.ace
check_contains 'Evidence "curated";' acediffsorted old.ace new.ace
check_contains 'Notes "updated";' acediffsorted old.ace new.ace
check_contains '-D Notes "original";' acediffsorted old.ace new.ace

# Identical files yield an empty diff, just the header/footer comments.
check_contains '// end of file' acediff old.ace old.ace
check_contains '// end of file' acediffsorted old.ace old.ace

echo "All acediff/acediffsorted autopkgtests passed."
