#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


function ensure_cwd_is_solr() {
  local cwd=`pwd`
  if [[ "solr" != `basename $cwd` ]]
  then
    echo "ERROR: Please run this script from the 'solr' directory."
    exit 1
  fi
}

function run_suite_before_if_present() {
  if declare -f solr_suite_before > /dev/null ; then
    solr_suite_before
  fi
}

function run_suite_after_if_present() {
  if declare -f solr_suite_after > /dev/null ; then
    solr_suite_after
  fi
}

function run_test_before_if_present() {
  if declare -f solr_unit_test_before > /dev/null ; then
    solr_unit_test_before
  fi
}

function run_test_after_if_present() {
  if declare -f solr_unit_test_after > /dev/null ; then
    solr_unit_test_after
  fi
}

function run_test_suite() {
  local test_file=$1
  local test_name_filter="${2:-}"

  echo "Executing $test_file"
  source $test_file
  test_names="$(declare -F | awk '{print $3}' | grep 'solr_test')"

  run_suite_before_if_present
  for test_name in $test_names
  do
    if [[ -z "$test_name_filter" || "$test_name_filter" == "$test_name" ]]; then
      run_single_test $test_name
    fi
    unset -f $test_name
  done
  run_suite_after_if_present

  unset solr_suite_before
  unset solr_suite_after
  unset solr_unit_test_before
  unset solr_unit_test_after
}

function run_single_test() {
  local test_name=$1

  echo -n "  $test_name "
  run_test_before_if_present
  let NUM_TESTS+=1
  output=$($test_name)
  if [[ $? -ne 0 ]]; then
    let NUM_FAILURES+=1
    echo "FAILED"
    echo "---------------------------------------------------"
    echo "$output"
    echo "---------------------------------------------------"
  else
    let NUM_SUCCESSES+=1
    echo "SUCCEEDED"
  fi
  run_test_after_if_present
}

function ensure_param_arg_present() {
  if [[ $# -lt 2 || "$2" == -* ]]; then
    echo "Option '$1' requires a single argument, but none provided."
    exit 1
  fi
}

function print_help() {
  echo "Usage: bin-test/test [-h] [-s SUITE_NAME] [-t SUITE_NAME#TEST_NAME]"
  echo ""
  echo "  Run tests for the 'bin/solr' Solr startup/admin scripts.  By default all tests are run."
  echo "  Tests suites or single tests can be selected by use of the options below:"
  echo ""
  echo "  -s|--run-single-suite    Runs all tests living in the specified file.  Filename argument"
  echo "                           should include the full file extension, but no path prefix."
  echo "                           (e.g. test_help.sh works, bin-test/test_help.sh and test_help"
  echo "                           do not)"
  echo ""
  echo "  -t|--run-single-test     Runs the specified test from the specified test suite file."
  echo "                           Takes an argument in the form 'SUITE_NAME#TEST_NAME', where"
  echo "                           SUITE_NAME is the filename of a test suite (see -s above), and"
  echo "                           TEST_NAME matches the name of a bash test function present in"
  echo "                           that file"
  echo ""
  echo "  -h|--help                You're soaking in it."
  echo ""
  exit 0
}

function run_all_tests() {
  test_files="$(find bin-test -name "test_*.sh")"

  for test_file in $test_files
  do
    run_test_suite $test_file
  done
}


## MAIN ##
##########
ensure_cwd_is_solr

# Can be 'all', 'help', 'single-suite', or 'single-test'
MODE="all"
SUITE_NAME=""
TEST_NAME=""
NUM_TESTS=0
NUM_SUCCESSES=0
NUM_FAILURES=0

while [[ $# -gt 0 ]]
do
  case $1 in
    -h|--help)
      MODE="help"
      shift 1
    ;;
    -s|--run-single-suite)
      ensure_param_arg_present $@
      MODE="single-suite"
      SUITE_NAME="bin-test/$2"
      shift 2
    ;;
    -t|--run-single-test)
      ensure_param_arg_present $@
      MODE="single-test"
      SUITE_NAME="bin-test/$(echo "$2" | cut -d "#" -f 1 | tr -d " ")"
      TEST_NAME=$(echo "$2" | cut -d "#" -f 2 | tr -d " ")
      shift 2
    ;;
    *)
      echo "WARNING: Unexpected argument [$1] detected, ignoring."
      shift 1
    ;;
  esac
done

case $MODE in
  "help")
    print_help
    MAIN_RESULT=0
  ;;
  "single-suite")
    run_test_suite $SUITE_NAME
    MAIN_RESULT=$?
  ;;
  "single-test")
    run_test_suite $SUITE_NAME $TEST_NAME
    MAIN_RESULT=$?
  ;;
  "all")
    run_all_tests
    MAIN_RESULT=$?
esac
echo "Ran $NUM_TESTS tests, with $NUM_SUCCESSES passing, and $NUM_FAILURES failures"
exit $MAIN_RESULT
