#!/bin/bash

# Check that selected examples can build and run without segfaulting

err_code=0

export PRTE_MCA_plm_ssh_agent=/bin/false
export PRTE_MCA_rmaps_default_mapping_policy=:oversubscribe
# MPI is typically more efficient with 1 thread per process
export OMP_NUM_THREADS=1

DEB_HOST_ARCH=$(dpkg-architecture -qDEB_HOST_ARCH)
DEB_HOST_MULTIARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH)
DEB_HOST_ARCH_ENDIAN=$(dpkg-architecture -qDEB_HOST_ARCH_ENDIAN)

cd examples
TEST_DIR=`pwd`

cp CMakeLists.txt CMakeLists.txt.orig

# enable examples CMakeLists.txt to operate standalone
cat <<END >CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(adios2_examples C CXX Fortran)

find_package(adios2 REQUIRED)

# Force C++11 (No extensions) and C99
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED True)

END
cat CMakeLists.txt.orig >>CMakeLists.txt

mkdir test_build
cd test_build

export HOME=${PWD}

# build examples
cmake -DCMAKE_PREFIX_PATH=/usr/lib/${DEB_HOST_MULTIARCH}/cmake/adios2/mpi \
	-DCMAKE_CXX_COMPILER=mpicxx \
	-DCMAKE_BUILD_TYPE=Debug \
	-DCMAKE_VERBOSE_MAKEFILE=ON \
	..
err_code=$(( $? | err_code ))
make
err_code=$(( $? | err_code ))
echo

# don't run examples which do not run cleanly
declare -a SKIP_TEST_LIST
SKIP_TEST_LIST=(${SKIP_TEST_LIST[@]} \
 adios2_simulations_gray-scott-struct adios2_simulations_gray-scott\
 adios2_basics_queryWorker)

# insituGlobalArraysReaderNxN_mpi is flakey, Bug#1062356
SKIP_TEST_LIST=(${SKIP_TEST_LIST[@]} adios2_useCases_insituGlobalArraysReaderNxN_mpi \
    adios2_basics_globalArray1DRead_*)

# some tests fail or time out on s390x
# Assume all big-endian arches are affected (build with -DADIOS2_USE_Endian_Reverse=ON)
if [ "x${DEB_HOST_ARCH_ENDIAN}" = "xbig" ]; then
  SKIP_TEST_LIST=(${SKIP_TEST_LIST[@]} adios2_basics_joinedArrayWrite)
fi

SKIP_TESTS=""
for t in ${SKIP_TEST_LIST[@]}; do
  SKIP_TESTS="${SKIP_TESTS} -not -name $t"
done
echo "skipping examples: SKIP_TEST_LIST=${SKIP_TEST_LIST[@]}"

# *Write should be run before *Read to generate the test file needed to read
# and *Read before *Write_mpi or the read may fail
declare -a TEST_LIST
TEST_LIST=(`find . -maxdepth 3 -executable -type f \( -name *Write -o -name *Writer \) ${SKIP_TESTS}`)
TEST_LIST=(${TEST_LIST[@]} `find . -maxdepth 3 -executable -type f \( -name *Read -o -name *Reader \) ${SKIP_TESTS}`)
TEST_LIST=(${TEST_LIST[@]} `find . -maxdepth 3 -executable -type f -not -path "*CMakeFiles*" ${SKIP_TESTS}`)
# get a unique list (preserving order) cf. https://stackoverflow.com/questions/13648410/how-can-i-get-unique-values-from-an-array-in-bash#comment99138701_13648438
TEST_LIST=(`echo "${TEST_LIST[@]}" | tr " " "\n" | awk '!seen[$0]++'`)

# run examples
for f in ${TEST_LIST[@]}; do
  echo Running $f
  ADIOS2_PLUGIN_PATH=/usr/lib/${DEB_HOST_MULTIARCH}/adios2/mpi/plugins mpirun -n 3 $f 2>$f.err >$f.out
  this_err=$?
  if [ $this_err -ne 0 ]; then
    echo "Error ${this_err} in $f"
    cat $f.out
    cat $f.err
  else
    echo "Passed: $f"
  fi
  err_code=$(( this_err | err_code ))
done

cd ..
cp CMakeLists.txt.orig CMakeLists.txt

# confirm MPI Python module is accessible
for pyver in `py3versions -sv`; do
  echo -e "\nChecking Python $pyver installation"
  mpirun -n 1 python$pyver -c "import adios2; print('adios2 version', adios2.__version__); assert adios2.is_built_with_mpi"
  err_code=$(( $? | err_code ))
  mpirun -n 3 python$pyver -c "import adios2; print('adios2 version', adios2.__version__); assert adios2.is_built_with_mpi"
  err_code=$(( $? | err_code ))

  # check python examples run successfully
  # (only a couple of them run freely)
  for f in hello/bpWriter/bpWriter.py hello/bpReader/bpReaderHeatMap2D.py; do
    echo Running python$pyver example $f
    cd `dirname $f`
    pyscript=`basename $f`
    ADIOS2_PLUGIN_PATH=/usr/lib/${DEB_HOST_MULTIARCH}/adios2/mpi/plugins mpirun -n 3 python$pyver $pyscript 2>$pyscript.err >$pyscript.out
    this_err=$?
    if [ $this_err -ne 0 ]; then
      echo "Error ${this_err} in $f"
      cat $pyscript.out
      cat $pyscript.err
    else
      echo "Passed: $f"
    fi
    err_code=$(( this_err | err_code ))
    cd $TEST_DIR
  done
done

exit ${err_code}
