#
# Dependency Integration Test script
#

# Runs a test to verify whether each service has the correct dependencies listed in setup.py
#
# Tests that depend on multiple services are assumed to be located in dedicated testfiles (and ignored during this test)
# (test_*_integration.py/test_*_cloudformation.py)
#
# ::Algorithm::
# For each valid service:
#   - Create a virtual environment
#   - Install only the necessary dependencies
#   - Run the tests for that service
#   - If the tests fail:
#     - This service is probably missing a dependency
#     - A log file with the test results will be created (test_results_service.log)
#   - Delete the virtual environment
#
# Note:
#   Only tested on Linux
#   Parallelized to test 4 services at the time.
#   Could take some time to run - around 20 minutes on the author's machine


overwrite() { echo -e "\r\033[1A\033[0K$@"; }

contains() {
    [[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && return 0 || return 1
}

valid_service() {
  # Verify whether this is a valid service
  # We'll ignore metadata folders, and folders that test generic Moto behaviour
  # We'll also ignore CloudFormation, as it will always depend on other services
  local ignore_moto_folders="core instance_metadata __pycache__ templates cloudformation moto_api resourcegroupstaggingapi packages utilities s3bucket_path"
  if echo $ignore_moto_folders | grep -q "$1"; then
    return 1
  else
    return 0
  fi
}

test_service() {
  service=$1
  path_to_test_file=$2
  venv_path="test_venv_${service}"
  overwrite "Running tests for ${service}.."
  python -m venv ${venv_path} > /dev/null
  source ${venv_path}/bin/activate > /dev/null
  # Can't just install requirements-file, as it points to all dependencies
  pip install -r requirements-tests.txt > /dev/null
  pip install .[$service] > /dev/null 2>&1
  pip install boto > /dev/null 2>&1
  if [[ $service != "xray" ]]; then
    pip uninstall setuptools pkg_resources -y > /dev/null 2>&1
  fi
  # Restart venv - ensure these deps are loaded
  deactivate
  source ${venv_path}/bin/activate > /dev/null
  # Run tests for this service
  test_result_filename="test_results_${service}.log"
  touch $test_result_filename
  pytest -sv --ignore-glob="**/test_server.py" --ignore-glob="**/test_*_cloudformation.py" --ignore-glob="**/test_*_integration.py" $path_to_test_file >$test_result_filename 2>&1
  RESULT=$?
  if [[ $RESULT != 0 ]]; then
    echo -e "Tests for ${service} have failed!\n"
  else
    rm $test_result_filename
  fi
  deactivate
  rm -rf ${venv_path}
}

echo "Running Dependency tests..."
ITER=0
for file in moto/*
do
    if [[ -d $file ]]; then
      service=${file:5}
      path_to_test_file="tests/test_${service}"
      if valid_service $service && [[ -d $path_to_test_file ]]; then
        test_service $service $path_to_test_file &
      elif valid_service $service; then
        echo -e "No tests for ${service} can be found on ${path_to_test_file}!\n"
      fi
      if (( $ITER % 4 == 0 )); then
        # Ensure we're only processing 4 services at the time
        wait
      fi
    fi
    ITER=$(expr $ITER + 1)
done
wait

nr_of_failed_services=$(ls -1q test_results*.log 2>/dev/null | wc -l)
echo "Nr of failed services: ${nr_of_failed_services}"
exit $((nr_of_failed_services))