#!/bin/bash
#
# Tests configured redirects by running `curl` against the provided URL
# and comparing the expected result with the actual result.
#
# Test syntax (see tests below for examples):
#
# test "$BASE_URL/<relative url>" <expected status> ["$BASE_URL/<expected value in Location header>
#
# By default, when run without any arguments, script tests against
# `https://localhost` as `$BASE_URL`, this is convenient when running
# with Apache HTTP (see ../support directory on how to do that).
#
# An URL can be provided to test against a different `$BASE_URL`, e.g.
#
# $ test/redirect.sh https://camel.apache.org
#
# With `-s`/`--serve` parameter a container will be spun with the Apache
# HTTP, serving the content from the `public` directory (generated by
# the build). For this `podman` or `docker` installation is required.
#
# By default output for only failing tests and the summary is printed,
# for more verbose output run with `-v`/`--verbose`. For debug output
# run with `-x`/`--debug` parameter
#
# Some redirects are generated dynamically, for example those generated
# by Antora for the _latest_ version, so they're grepped from the
# `.htaccess` file generated in `documentation` directory to ease the
# maintenance. See `*_VERSION` variables below.

set -eu -o pipefail

BASE_URL="https://localhost"
VERBOSE=0
DEBUG=0
SERVE=0
while [[ $# -gt 0 ]]; do
  opt="$1"

  case $opt in
    -v|--verbose)
      VERBOSE=1
      shift
      ;;
    -x|--debug)
      set -x
      DEBUG=1
      shift
      ;;
    -s|--serve)
      SERVE=1
      shift
      ;;
    *)
      BASE_URL="$1"
      shift
      ;;
  esac
done

GIT_ROOT=$(realpath "$(dirname "${BASH_SOURCE[0]}")/..")

# run Apache HTTP in a container with the content from `public`
if [ "$SERVE" == 1 ]; then
  CONTAINER_CMD=podman
  if ! command -v $CONTAINER_CMD &> /dev/null; then
    CONTAINER_CMD=docker
    if ! command -v $CONTAINER_CMD &> /dev/null; then
      echo -e "\e[1mFAILURE\e[0m: Nether podman nor docker command found"
      exit 1
    fi
  fi

  CONTAINER_ID=$($CONTAINER_CMD run -d -v "$GIT_ROOT/public":/usr/local/apache2/htdocs/:Z -v "$GIT_ROOT/support/http":/support:Z -p 443 httpd:2.4 /bin/bash -c "cp /support/* /usr/local/apache2/conf/ && httpd-foreground")
  trap '$CONTAINER_CMD stop $CONTAINER_ID > /dev/null; $CONTAINER_CMD rm $CONTAINER_ID > /dev/null' EXIT
  if [ "$DEBUG" == 1 ]; then
    $CONTAINER_CMD logs "$CONTAINER_ID"
  fi
  if [ -n "$($CONTAINER_CMD ps -q --filter id="$(hostname)")" ]; then
    # running within a container, we'll assume running on the same network, so we should be able to connect directly
    BASE_URL="https://$($CONTAINER_CMD inspect -f "{{ range .NetworkSettings.Networks }}{{.IPAddress}}{{ end }}" "$CONTAINER_ID")"
  else
    BASE_URL="https://$($CONTAINER_CMD port "$CONTAINER_ID" 443 | head -1)"
  fi
fi

# make sure we can reach the web site
CURL_CMD=curl
set +e
$CURL_CMD -sS -k -o /dev/null --retry-all-errors --retry-delay 3 --retry 5 "$BASE_URL" || {
  set -e
  if [ -n "${CONTAINER_ID+x}" ]; then
    echo Reverting to using curl from within the HTTP container
    $CONTAINER_CMD exec "$CONTAINER_ID" apt-get update -y
    $CONTAINER_CMD exec "$CONTAINER_ID" apt-get install -y curl
    CURL_CMD="$CONTAINER_CMD exec $CONTAINER_ID curl"
    BASE_URL=https://localhost
    $CURL_CMD -sS -k -o /dev/null --retry-all-errors --retry-delay 3 --retry 5 "$BASE_URL"
  else
    exit 1
  fi
}
set -e

TOTAL=0
SUCCESS=0

# runs `curl` and records the `Status` and `Location` (if provided)
# header values and compares it with expected values provided as
# parameters.
# Usage: test <url> <expected status> [expected location]
function test {
  local url=$1
  local code=$2
  local location=${3:-}

  local output
  set +e
  output=$($CURL_CMD -k -w '%{http_code},%{redirect_url}' -o /dev/null -s "${url}")
  set -e
  TOTAL=$((TOTAL + 1))

  if [ "${output}" == "${code},${location}" ]; then
    SUCCESS=$((SUCCESS + 1))
    if [ "${VERBOSE}" == 1 ]; then
      echo -e " OK : ${url}"
    fi
  else
    echo -e "\e[1m\e[31mFAIL\e[m: ${url}\n    expected: \e[1m${code},${location}\e[0m\n         got: \e[1m${output}\e[0m"
  fi
}

HTACCESS_FILE="$GIT_ROOT/documentation/.htaccess"
if [ ! -f "$HTACCESS_FILE" ]; then
  echo "No $HTACCESS_FILE found, using last published version. If you have made changes to the Antora playbook make sure to build the site first to test those."
  $CURL_CMD -s -o "$HTACCESS_FILE" 'https://gitbox.apache.org/repos/asf?p=camel-website.git;a=blob_plain;f=.htaccess;hb=refs/heads/asf-site'
fi

# determine current _latest_ versions
COMPONENTS_VERSION="$(grep '^Redirect 302 /components/latest' "$HTACCESS_FILE" | grep -Z -o '[^/]*$')"
CAMEL_K_VERSION="$(grep '^Redirect 302 /camel-k/latest' "$HTACCESS_FILE" | grep -Z -o '[^/]*$')"
CAMEL_KAFKA_CONNECTOR_VERSION="$(grep '^Redirect 302 /camel-kafka-connector/latest' "$HTACCESS_FILE" | grep -Z -o '[^/]*$')"
CAMEL_QUARKUS_VERSION="$(grep '^Redirect 302 /camel-quarkus/latest' "$HTACCESS_FILE" | grep -Z -o '[^/]*$')"
CAMEL_KAMELETS_VERSION="$(grep '^Redirect 302 /camel-kamelets/latest' "$HTACCESS_FILE" | grep -Z -o '[^/]*$')"

#
# TESTS
#

test "$BASE_URL/components" 302 "$BASE_URL/components/${COMPONENTS_VERSION}/"
test "$BASE_URL/components/" 302 "$BASE_URL/components/${COMPONENTS_VERSION}/"
test "$BASE_URL/components/next" 301 "$BASE_URL/components/next/"
test "$BASE_URL/components/next/" 200
test "$BASE_URL/components/latest" 302 "$BASE_URL/components/${COMPONENTS_VERSION}"
test "$BASE_URL/components/latest/" 302 "$BASE_URL/components/${COMPONENTS_VERSION}/"
test "$BASE_URL/components/jms-component.html" 302 "$BASE_URL/components/${COMPONENTS_VERSION}/jms-component.html"
test "$BASE_URL/components/latest/jms-component.html" 302 "$BASE_URL/components/${COMPONENTS_VERSION}/jms-component.html"
test "$BASE_URL/components/${COMPONENTS_VERSION}/jms-component.html" 200
test "$BASE_URL/components/next/jms-component.html" 200

test "$BASE_URL/camel-spring-boot" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/"
test "$BASE_URL/camel-spring-boot/" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/"
test "$BASE_URL/camel-spring-boot/next" 301 "$BASE_URL/camel-spring-boot/next/"
test "$BASE_URL/camel-spring-boot/next/" 200
test "$BASE_URL/camel-spring-boot/latest" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}"
test "$BASE_URL/camel-spring-boot/latest/" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/"
test "$BASE_URL/camel-spring-boot/list.html" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/list.html"
test "$BASE_URL/camel-spring-boot/latest/list.html" 302 "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/list.html"
test "$BASE_URL/camel-spring-boot/${COMPONENTS_VERSION}/list.html" 200
test "$BASE_URL/camel-spring-boot/next/list.html" 200

test "$BASE_URL/camel-k" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}/"
test "$BASE_URL/camel-k/" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}/"
test "$BASE_URL/camel-k/next" 301 "$BASE_URL/camel-k/next/"
test "$BASE_URL/camel-k/next/" 200
test "$BASE_URL/camel-k/latest" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}"
test "$BASE_URL/camel-k/latest/" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}/"
test "$BASE_URL/camel-k/traits/master.html" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}/traits/master.html"
test "$BASE_URL/camel-k/latest/traits/master.html" 302 "$BASE_URL/camel-k/${CAMEL_K_VERSION}/traits/master.html"
test "$BASE_URL/camel-k/${CAMEL_K_VERSION}/traits/master.html" 200
test "$BASE_URL/camel-k/next/traits/master.html" 200

#test "$BASE_URL/camel-karaf" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/"
#test "$BASE_URL/camel-karaf/" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/"
#test "$BASE_URL/camel-karaf/next" 301 "$BASE_URL/camel-karaf/next/"
#test "$BASE_URL/camel-karaf/next/" 200
#test "$BASE_URL/camel-karaf/latest" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}"
#test "$BASE_URL/camel-karaf/latest/" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/"
#test "$BASE_URL/camel-karaf/latest/components.html" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/components.html"
#test "$BASE_URL/camel-karaf/latest/components.html" 302 "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/components.html"
#test "$BASE_URL/camel-karaf/${COMPONENTS_VERSION}/components.html" 200
#test "$BASE_URL/camel-karaf/next/components.html" 200

test "$BASE_URL/camel-kafka-connector" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/"
test "$BASE_URL/camel-kafka-connector/" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/"
test "$BASE_URL/camel-kafka-connector/next" 301 "$BASE_URL/camel-kafka-connector/next/"
test "$BASE_URL/camel-kafka-connector/next/" 200
test "$BASE_URL/camel-kafka-connector/latest" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}"
test "$BASE_URL/camel-kafka-connector/latest/" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/"
test "$BASE_URL/camel-kafka-connector/contributor-guide/release-guide.html" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/contributor-guide/release-guide.html"
test "$BASE_URL/camel-kafka-connector/latest/contributor-guide/release-guide.html" 302 "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/contributor-guide/release-guide.html"
test "$BASE_URL/camel-kafka-connector/${CAMEL_KAFKA_CONNECTOR_VERSION}/contributor-guide/release-guide.html" 200
test "$BASE_URL/camel-kafka-connector/next/contributor-guide/release-guide.html" 200

test "$BASE_URL/camel-kamelets" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}/"
test "$BASE_URL/camel-kamelets/" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}/"
test "$BASE_URL/camel-kamelets/next" 301 "$BASE_URL/camel-kamelets/next/"
test "$BASE_URL/camel-kamelets/next/" 200
test "$BASE_URL/camel-kamelets/latest" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}"
test "$BASE_URL/camel-kamelets/latest/" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}/"
test "$BASE_URL/camel-kamelets/aws-s3-source.html" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}/aws-s3-source.html"
test "$BASE_URL/camel-kamelets/latest/aws-s3-source.html" 302 "$BASE_URL/camel-kamelets/${CAMEL_KAMELETS_VERSION}/aws-s3-source.html"
test "$BASE_URL/camel-kamelets/next/aws-s3-source.html" 200
test "$BASE_URL/camel-kamelets/next/aws-s3-source.html" 200

test "$BASE_URL/camel-quarkus" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/"
test "$BASE_URL/camel-quarkus/" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/"
test "$BASE_URL/camel-quarkus/next" 301 "$BASE_URL/camel-quarkus/next/"
test "$BASE_URL/camel-quarkus/next/" 200
test "$BASE_URL/camel-quarkus/latest" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}"
test "$BASE_URL/camel-quarkus/latest/" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/"
test "$BASE_URL/camel-quarkus/user-guide/cdi.html" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/user-guide/cdi.html"
test "$BASE_URL/camel-quarkus/latest/user-guide/cdi.html" 302 "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/user-guide/cdi.html"
test "$BASE_URL/camel-quarkus/${CAMEL_QUARKUS_VERSION}/user-guide/cdi.html" 200
test "$BASE_URL/camel-quarkus/next/user-guide/cdi.html" 200

test "$BASE_URL/manual" 301 "$BASE_URL/manual/"
test "$BASE_URL/manual/latest" 302 "$BASE_URL/manual"
test "$BASE_URL/manual/latest/" 302 "$BASE_URL/manual/"
test "$BASE_URL/manual/latest/component-dsl.html" 302 "$BASE_URL/manual/component-dsl.html"
test "$BASE_URL/manual/" 200
test "$BASE_URL/manual/component-dsl.html" 200

test "$BASE_URL/_/img/logo-d.svg" 301 "$BASE_URL/_/$(jq -r '."img/logo-d.svg"' documentation/_/data/rev-manifest.json)"
test "$BASE_URL/_/$(jq -r '."img/logo-d.svg"' documentation/_/data/rev-manifest.json)" 200

# prints summary
if [ "$TOTAL" == "$SUCCESS" ]; then
  echo -e "$0 \e[1mSUCCESSFULLY\e[0m ran $TOTAL tests"
else
  echo -e "$0 \e[1m\e[31mFAILURE\e[0m: $((TOTAL - SUCCESS)) tests failed out of ${TOTAL}"
  exit 1
fi
