#!/bin/bash
cvmfs_test_name="Reference Log Handling"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

CVMFS_TEST_627_REPLICA_NAME=
cleanup() {
  [ -z $CVMFS_TEST_627_REPLICA_NAME ] || sudo cvmfs_server rmfs -f $CVMFS_TEST_627_REPLICA_NAME
}

check_stratum1_tmp_dir_emptiness() {
  local tmp_dir="$1"
  local tmp_dir_entries
  echo "check stratum1 tmp directory"
  tmp_dir_entries=$(ls $tmp_dir | wc -l)
  echo "$tmp_dir contains: $tmp_dir_entries"
  [ $tmp_dir_entries -eq 0 ]
}

check_reflog_contains() {
  local repo_name="$1"
  local needles="$2"
  local sqlite_file=$(mktemp "${repo_name}.sqlite.XXXXXX")
  download_from_backend $repo_name ".cvmfsreflog" $sqlite_file || return 1
  local refs="$(sqlite3 $sqlite_file "SELECT hash FROM refs")" || return 2
  local found_all=0
  for n in $needles; do
    echo -n "checking ${n}... "
    if ! contains "$refs" "$n"; then
      echo "not found"
      found_all=1
    else
      echo "found"
    fi
  done
  return $found_all
}

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

  local mnt_point="$(pwd)/mountpount"
  local replica_name="$(get_stratum1_name $CVMFS_TEST_REPO)"

  echo -n "check that we have 'sqlite3'... "
  which sqlite3 > /dev/null 2>&1 && echo "done" || { echo "fail"; return 1; }

  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 "install a cleanup function"
  trap cleanup EXIT HUP INT TERM

  echo "create Stratum1 repository on the same machine"
  load_repo_config $CVMFS_TEST_REPO
  CVMFS_TEST_627_REPLICA_NAME=$replica_name
  create_stratum1 $replica_name                          \
                  $CVMFS_TEST_USER                       \
                  $CVMFS_STRATUM0                        \
                  /etc/cvmfs/keys/${CVMFS_TEST_REPO}.pub || return 1

  echo -n "get Stratum 1 spool directory: "
  load_repo_config $replica_name
  local s1_spool_tmp_dir="${CVMFS_SPOOL_DIR}/tmp"
  load_repo_config $CVMFS_TEST_REPO
  echo "$s1_spool_tmp_dir"

  echo "create a Snapshot of the Stratum0 repository in the just created Stratum1 replica"
  sudo cvmfs_server snapshot $replica_name || return 2

  echo "check that Stratum1 spooler tmp dir is empty"
  check_stratum1_tmp_dir_emptiness $s1_spool_tmp_dir || return 3

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "extracting root hashes from Stratum0"
  local root_hash_1=$(get_manifest_field $CVMFS_TEST_REPO 'C')
  local history_1=$(get_manifest_field $CVMFS_TEST_REPO 'H')
  local meta_info_1=$(get_manifest_field $CVMFS_TEST_REPO 'M')
  local certificate_1=$(get_manifest_field $CVMFS_TEST_REPO 'X')
  echo "C: $root_hash_1"
  echo "H: $history_1"
  echo "M: $meta_info_1"
  echo "X: $certificate_1"

  echo "check Reflog from Stratum0"
  check_reflog_contains $CVMFS_TEST_REPO "$root_hash_1 $history_1 $meta_info_1 $certificate_1" || return 4

  echo "check Reflog from Stratum1"
  check_reflog_contains $replica_name "$root_hash_1 $history_1 $meta_info_1 $certificate_1" || return 5

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "creating a tag in Stratum0"
  cvmfs_server tag -a "foobar"                          \
                   -m "new tag to create a new history" \
                   -h "$root_hash_1" $CVMFS_TEST_REPO || return 6

  echo "extracting root hashes from Stratum0"
  local root_hash_2=$(get_manifest_field $CVMFS_TEST_REPO 'C')
  local history_2=$(get_manifest_field $CVMFS_TEST_REPO 'H')
  local meta_info_2=$(get_manifest_field $CVMFS_TEST_REPO 'M')
  local certificate_2=$(get_manifest_field $CVMFS_TEST_REPO 'X')
  echo "C: $root_hash_2"
  echo "H: $history_2"
  echo "M: $meta_info_2"
  echo "X: $certificate_2"

  echo "check hash sanity"
  [ x"$root_hash_2"    = x"$root_hash_1"   ] || return  7
  [ x"$history_2"     != x"$history_1"     ] || return  8
  [ x"$meta_info_2"    = x"$meta_info_1"   ] || return  9
  [ x"$certificate_2"  = x"$certificate_1" ] || return 10

  echo "check Reflog from Stratum0"
  check_reflog_contains $CVMFS_TEST_REPO "$history_1 $history_2" || return 11

  echo "check that Reflog from Stratum1 doesn't contain new history"
  check_reflog_contains $replica_name "$history_2" && return 12

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "Update metainfo in Stratum 0"
  local json_file="test_json_file.json"
  cat >> $json_file << EOF
{
  "administrator" : "Rene Meusel",
  "email"         : "dont.send.me.spam@cern.ch",
  "organisation"  : "CERN",
  "description"   : "This is just a test repository"
}
EOF

  cvmfs_server update-repoinfo -f $json_file $CVMFS_TEST_REPO || return 13

  echo "extracting root hashes from Stratum0"
  local root_hash_3=$(get_manifest_field $CVMFS_TEST_REPO 'C')
  local history_3=$(get_manifest_field $CVMFS_TEST_REPO 'H')
  local meta_info_3=$(get_manifest_field $CVMFS_TEST_REPO 'M')
  local certificate_3=$(get_manifest_field $CVMFS_TEST_REPO 'X')
  echo "C: $root_hash_3"
  echo "H: $history_3"
  echo "M: $meta_info_3"
  echo "X: $certificate_3"

  echo "check hash sanity"
  [ x"$root_hash_3"    = x"$root_hash_1"   ] || return 13
  [ x"$history_3"     != x"$history_1"     ] || return 14
  [ x"$history_3"      = x"$history_2"     ] || return 15
  [ x"$meta_info_3"   != x"$meta_info_1"   ] || return 16
  [ x"$certificate_3"  = x"$certificate_1" ] || return 17

  echo "check Reflog from Stratum0"
  check_reflog_contains $CVMFS_TEST_REPO "$history_1 $history_2 $meta_info_3 $meta_info_1" || return 18

  echo "check that Reflog from Stratum1 doesn't contain new meta info"
  check_reflog_contains $replica_name "$meta_info_3" && return 19

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "Update revision in Stratum0"
  start_transaction $CVMFS_TEST_REPO || return 20
  publish_repo $CVMFS_TEST_REPO      || return 21

  echo "extracting root hashes from Stratum0"
  local root_hash_4=$(get_manifest_field $CVMFS_TEST_REPO 'C')
  local history_4=$(get_manifest_field $CVMFS_TEST_REPO 'H')
  local meta_info_4=$(get_manifest_field $CVMFS_TEST_REPO 'M')
  local certificate_4=$(get_manifest_field $CVMFS_TEST_REPO 'X')
  echo "C: $root_hash_4"
  echo "H: $history_4"
  echo "M: $meta_info_4"
  echo "X: $certificate_4"

  echo "check hash sanity"
  [ x"$root_hash_4"   != x"$root_hash_1"   ] || return 22
  [ x"$history_4"     != x"$history_3"     ] || return 23
  [ x"$meta_info_3"    = x"$meta_info_3"   ] || return 24
  [ x"$certificate_4"  = x"$certificate_1" ] || return 25

  echo "check Reflog from Stratum0"
  check_reflog_contains $CVMFS_TEST_REPO "$root_hash_4 $root_hash_1 $history_4 $history_2 $history_1" || return 26

  echo "check that Reflog from Stratum1 doesn't contain new root catalog"
  check_reflog_contains $replica_name "$root_hash_4" && return 27

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "Update revision in Stratum0"
  start_transaction $CVMFS_TEST_REPO || return 28
  publish_repo $CVMFS_TEST_REPO      || return 29

  echo "extracting root hashes from Stratum0"
  local root_hash_5=$(get_manifest_field $CVMFS_TEST_REPO 'C')
  local history_5=$(get_manifest_field $CVMFS_TEST_REPO 'H')
  local meta_info_5=$(get_manifest_field $CVMFS_TEST_REPO 'M')
  local certificate_5=$(get_manifest_field $CVMFS_TEST_REPO 'X')
  echo "C: $root_hash_5"
  echo "H: $history_5"
  echo "M: $meta_info_5"
  echo "X: $certificate_5"

  echo "check hash sanity"
  [ x"$root_hash_5"   != x"$root_hash_4"   ] || return 30
  [ x"$history_5"     != x"$history_4"     ] || return 31
  [ x"$meta_info_5"    = x"$meta_info_3"   ] || return 32
  [ x"$certificate_5"  = x"$certificate_1" ] || return 33

  echo "check Reflog from Stratum0"
  check_reflog_contains $CVMFS_TEST_REPO "$root_hash_5 $root_hash_4 $root_hash_1 $history_5 $history_4 $history_2 $history_1 $meta_info_3 $meta_info_1 $certificate_1" || return 34

  echo "check that Reflog from Stratum1 doesn't contain new root catalog"
  check_reflog_contains $replica_name "$root_hash_5" && return 35

  # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  echo "create a snapshot in Stratum1"
  cvmfs_server snapshot $replica_name || return 37

  echo "check Reflog from Stratum1"
  check_reflog_contains $replica_name "$root_hash_5 $root_hash_4 $root_hash_1 $history_5 $history_1 $meta_info_3 $meta_info_1 $certificate_1" || return 38

  return 0
}
