#!/bin/bash

cvmfs_test_name="Simulate CVMFS Development"
cvmfs_test_autofs_on_startup=false

# cvmfs source tarballs to be downloaded and used as test data
# TODO: replace this by upcoming CVMFS versions...
cvmfs_versions="http://ecsft.cern.ch/dist/cvmfs/archive/cvmfs-2.1.11/cvmfs-2.1.11.tar.gz
http://ecsft.cern.ch/dist/cvmfs/archive/cvmfs-2.1.12/cvmfs-2.1.12.tar.gz
http://ecsft.cern.ch/dist/cvmfs/archive/cvmfs-2.1.14/cvmfs-2.1.14.tar.gz
http://ecsft.cern.ch/dist/cvmfs/archive/cvmfs-2.1.15/cvmfs-2.1.15.tar.gz"


# retrieve the URL at a given index (dash workaround)
get_url() {
  local version=$1

  i=0
  for url in $cvmfs_versions; do
    if [ $i = $version ]; then
      echo "$url"
      break
    fi
    i=$(( $i + 1 ))
  done
}

# downloads and extracts a number of CVMFS source packages
# from the electric commander server (URLs above)
download_and_untar_cvmfs_versions() {
  for cvmfs_version in $cvmfs_versions
  do
    echo $cvmfs_version

    curl -LO --silent $cvmfs_version || return 200
    tarname=$(basename $cvmfs_version)
    tar -xzf $tarname || return 202
  done
}

# copies one version of the downloaded CVMFS source tree
# to the given position while overwriting existing files.
# @param working_dir    the destination directory
# @param version        the CVMFS version to be copied (index in array above)
copy_cvmfs_version() {
  local working_dir=$1
  local version=$2
  local source_dir
  local url=$(get_url $version)
  source_dir=$(basename $url | sed 's/\.tar\.gz//')

  cp -uR $source_dir/* $working_dir
}

# set some nested catalogs in the CVMFS source tree
# @param working_dir   the destination directory
# @param version       the version of CVMFS to be copied (index in array on top)
configure_nested_catalogs() {
  local working_dir=$1
  local version=$2

  case $version in
    0)
      touch $working_dir/externals/.cvmfscatalog
      touch $working_dir/cvmfs/.cvmfscatalog
      touch $working_dir/test/.cvmfscatalog
      ;;
    1)
      touch $working_dir/externals/zlib/.cvmfscatalog
      touch $working_dir/externals/sqlite3/.cvmfscatalog
      rm -f $working_dir/cvmfs/.cvmfscatalog
      ;;
    2)
      touch $working_dir/test/cloud_testing/platforms/.cvmfscatalog
      touch $working_dir/test/cloud_testing/steering/.cvmfscatalog
      rm -f $working_dir/test/.cvmfscatalog
      ;;
    3)
      rm -f $working_dir/externals/.cvmfscatalog
      rm -f $working_dir/externals/zlib/.cvmfscatalog
      rm -f $working_dir/externals/sqlite3/.cvmfscatalog
      rm -f $working_dir/cvmfs/.cvmfscatalog
      rm -f $working_dir/test/cloud_testing/steering/.cvmfscatalog
      rm -f $working_dir/test/cloud_testing/platforms/.cvmfscatalog
      ;;
  esac
}

# checks if all nested catalogs that were requested by configure_nested_catalogs()
# are actually present in the catalog tree.
# @param version    the repository version to be checked
#                   (same as for configure_nested_catalogs())
# @param repo_name  the name of the repository to be checked
check_catalog_configuration() {
  local version=$1
  local repo_name=$2

  case $version in
    0)
      if [ $(get_catalog_count $repo_name) -ne 4 ]; then
        return 2
      fi
      if check_catalog_presence /                  $repo_name && \
         check_catalog_presence /externals         $repo_name && \
         check_catalog_presence /cvmfs             $repo_name && \
         check_catalog_presence /test              $repo_name
      then
        return 0
      else
        return 1
      fi
      ;;
    1)
      if [ $(get_catalog_count $repo_name) -ne 5 ]; then
        return 2
      fi
      if check_catalog_presence /                  $repo_name && \
         check_catalog_presence /externals         $repo_name && \
         check_catalog_presence /externals/zlib    $repo_name && \
         check_catalog_presence /externals/sqlite3 $repo_name && \
         check_catalog_presence /test              $repo_name
      then
        return 0
      else
        return 1
      fi
      ;;
    2)
      if [ $(get_catalog_count $repo_name) -ne 6 ]; then
        return 2
      fi
      if check_catalog_presence /                             $repo_name && \
         check_catalog_presence /externals                    $repo_name && \
         check_catalog_presence /externals/zlib               $repo_name && \
         check_catalog_presence /externals/sqlite3            $repo_name && \
         check_catalog_presence /test/cloud_testing/platforms $repo_name && \
         check_catalog_presence /test/cloud_testing/steering  $repo_name
      then
        return 0
      else
        return 1
      fi
      ;;
    3)
      if [ $(get_catalog_count $repo_name) -ne 1 ]; then
        return 2
      fi
      if check_catalog_presence /                  $repo_name
      then
        return 0
      else
        return 1
      fi
      ;;
  esac
}

# does a whole version update
# @param version        the version to be copied (index in array on top)
# @param repo_dir       the repository directory to copy to
# @param repo_name      the repository name to copy to
# @param reference_dir  the reference directory to copy to
copy_version() {
  local version=$1
  local repo_dir=$2
  local repo_name=$3
  local reference_dir=$4

  echo "COPY VERSION === $version === ..."

  echo "starting transaction to edit repository"
  start_transaction $CVMFS_TEST_REPO || return $?

  echo "putting some stuff in the new repository"
  copy_cvmfs_version $repo_dir $version || return 3
  configure_nested_catalogs $repo_dir $version || return 4

  echo "putting exactly the same stuff in the scratch space for comparison"
  copy_cvmfs_version $reference_dir $version || return 5
  configure_nested_catalogs $reference_dir $version || return 6

  echo "creating CVMFS snapshot"
  publish_repo $CVMFS_TEST_REPO || return $?

  echo "compare the results of cvmfs to our reference copy"
  compare_directories $repo_dir $reference_dir || return $?

  echo "check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i || return $?

  echo "check if requested nested catalogs are present"
  check_catalog_configuration $version $repo_name || return $?
}

cvmfs_run_test() {
  logfile=$1
  local repo_dir=/cvmfs/$CVMFS_TEST_REPO

  local scratch_dir=$(pwd)
  mkdir reference_dir
  local reference_dir=$scratch_dir/reference_dir

  echo "create a fresh repository named $CVMFS_TEST_REPO with user $CVMFS_TEST_USER"
  create_empty_repo $CVMFS_TEST_REPO $CVMFS_TEST_USER || return $?

  echo "downloading some previous versions of the CVMFS code as test data..."
  download_and_untar_cvmfs_versions || return $?

  echo "do the business"
  for i in 0 1 2 3
  do
    copy_version $i $repo_dir $CVMFS_TEST_REPO $reference_dir || return $?
  done

  return 0
}
