#!/bin/bash
cvmfs_test_name="Creation and validation of reflog checksum"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

CVMFS_TEST634_REPLICA_NAME=

cleanup() {
  sudo cvmfs_server rmfs -f $CVMFS_TEST634_REPLICA_NAME > /dev/null 2>&1
}

cvmfs_run_test() {
  logfile=$1
  local repo_dir=/cvmfs/$CVMFS_TEST_REPO
  local checksum=/var/spool/cvmfs/${CVMFS_TEST_REPO}/reflog.chksum

  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 "*** check for checksum presence"
  [ -f $checksum ] || return 10
  local checksum_content=$(cat $checksum)

  echo "*** check if checksum changes during publishes"
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return $?
  [ -f $checksum ] || return 11
  [ "x$checksum_content" != "x$(cat $checksum)" ] || return 12
  check_repository $CVMFS_TEST_REPO || return 13

  echo "*** check validation of checksum"
  mv $checksum $checksum.backup
  cat /dev/zero | head -c 40 > $checksum
  check_repository $CVMFS_TEST_REPO && return 21
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO && return 20
  mv $checksum.backup $checksum
  publish_repo $CVMFS_TEST_REPO || return $?

  # The stratum 0 reflog checksum is now stored in the manifest but it can
  # be overwritten by the local reflog checksum, e.g. on stratum 1.
  # Deleting the checksum therefore means setting it to the null hash
  echo "*** check missing checksum"
  echo -n "0000000000000000000000000000000000000000" > $checksum
  check_repository $CVMFS_TEST_REPO && return 31
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO && return 30

  echo "*** check missing checksum and missing reflog"
  delete_from_backend $CVMFS_TEST_REPO ".cvmfsreflog" || return 40
  publish_repo $CVMFS_TEST_REPO || return 41
  check_repository $CVMFS_TEST_REPO || return 43

  echo "*** check reflog reconstruction"
  toggle_gc $CVMFS_TEST_REPO || return 50
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return 51
  cvmfs_server gc -f $CVMFS_TEST_REPO || return 52
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return 54
  check_repository $CVMFS_TEST_REPO || return 56

  echo "*** check missing reflog"
  delete_from_backend $CVMFS_TEST_REPO ".cvmfsreflog" || return 57
  check_repository $CVMFS_TEST_REPO && return 58
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO && return 59
  abort_transaction $CVMFS_TEST_REPO || return $?
  echo -n "0000000000000000000000000000000000000000" > $checksum
  cvmfs_server gc -f $CVMFS_TEST_REPO || return 59
  check_repository $CVMFS_TEST_REPO || return 59

  echo "*** set stratum 1 cleanup trap"
  CVMFS_TEST634_REPLICA_NAME="$(get_stratum1_name $CVMFS_TEST_REPO)"
  local replica_checksum=/var/spool/cvmfs/${CVMFS_TEST634_REPLICA_NAME}/reflog.chksum
  trap cleanup EXIT HUP INT TERM

  echo "*** check reflog checksum for fresh replica"
  load_repo_config $CVMFS_TEST_REPO
  create_stratum1 $CVMFS_TEST634_REPLICA_NAME            \
                  $CVMFS_TEST_USER                       \
                  $CVMFS_STRATUM0                        \
                  /etc/cvmfs/keys/${CVMFS_TEST_REPO}.pub || return 60
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 61
  [ -f $replica_checksum ] || return 62
  [ "x$(cat $checksum)" != "x$(cat $replica_checksum)" ] || return 62
  check_repository $CVMFS_TEST634_REPLICA_NAME || return 63

  echo "*** check reflog maintenance on replica"
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return 70
  mv $replica_checksum $replica_checksum.backup
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 74
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME && return 71
  echo -n "0000000000000000000000000000000000000000" > $replica_checksum
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 75
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME && return 72
  mv $replica_checksum.backup $replica_checksum
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 73
  check_repository $CVMFS_TEST634_REPLICA_NAME || return 76

  echo "*** check missing checksum and missing reflog on replica"
  rm -f $replica_checksum
  delete_from_backend $CVMFS_TEST634_REPLICA_NAME ".cvmfsreflog" || return 80
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return 82
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 83
  check_repository $CVMFS_TEST634_REPLICA_NAME || return 84

  echo "*** check reflog reconstruction on replica"
  cvmfs_server gc -f $CVMFS_TEST634_REPLICA_NAME || return 90
  [ -f $replica_checksum ] || return 91
  start_transaction $CVMFS_TEST_REPO || return $?
  publish_repo $CVMFS_TEST_REPO || return 92
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 93
  [ -f $replica_checksum ] || return 94
  check_repository $CVMFS_TEST634_REPLICA_NAME || return 95

  echo "*** check missing reflog on replica"
  delete_from_backend $CVMFS_TEST634_REPLICA_NAME ".cvmfsreflog" || return 100
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 101
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME && return 102
  rm -f $replica_checksum
  [ -f $replica_checksum ] && return 103
  cvmfs_server gc -f $CVMFS_TEST634_REPLICA_NAME || return 104
  [ -f $replica_checksum ] || return 105
  check_repository $CVMFS_TEST634_REPLICA_NAME || return 106
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 107

  echo "*** check repairing reflog problems"
  echo -n "0000000000000000000000000000000000000000" > $checksum
  echo -n "0000000000000000000000000000000000000000" > $replica_checksum
  check_repository $CVMFS_TEST_REPO && return 110
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 110
  check_repository $CVMFS_TEST_REPO -r || return 111
  check_repository $CVMFS_TEST634_REPLICA_NAME -r || return 111
  echo "abc" > $checksum
  echo "abc" > $replica_checksum
  check_repository $CVMFS_TEST_REPO && return 112
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 112
  check_repository $CVMFS_TEST_REPO -r || return 113
  check_repository $CVMFS_TEST634_REPLICA_NAME -r || return 113
  delete_from_backend $CVMFS_TEST_REPO ".cvmfsreflog" || return 114
  delete_from_backend $CVMFS_TEST634_REPLICA_NAME ".cvmfsreflog" || return 114
  check_repository $CVMFS_TEST_REPO && return 115
  check_repository $CVMFS_TEST634_REPLICA_NAME && return 115
  check_repository $CVMFS_TEST_REPO -r || return 116
  check_repository $CVMFS_TEST634_REPLICA_NAME -r || return 116

  echo "*** check repairing missing reflog with a zombie hash registered in the manifest"
  delete_from_backend $CVMFS_TEST_REPO ".cvmfsreflog" || return 30
  delete_from_backend $CVMFS_TEST634_REPLICA_NAME ".cvmfsreflog" || return 30
  rm -f $checksum $replica_checksum
  start_transaction $CVMFS_TEST_REPO || return $?
  # Note: in this situation, gc on the S0 recreates the reflog automatically
  # and thus does not fail (libcvmfs_server should handle the reflog more consistently)
  publish_repo $CVMFS_TEST_REPO && return 31
  check_repository $CVMFS_TEST_REPO -r || return 32
  publish_repo $CVMFS_TEST_REPO || return 32
  cvmfs_server gc -f $CVMFS_TEST_REPO || return 33
  # Note: swissknife_pull looks only that reflog.chksum file (not in the manifest)
  # Therefore, it would continue to work
  # libcvmfs_server should handle the reflog more consistently
  # cvmfs_server gc -f $CVMFS_TEST634_REPLICA_NAME && return 34
  check_repository $CVMFS_TEST634_REPLICA_NAME -r || return 35
  sudo cvmfs_server snapshot $CVMFS_TEST634_REPLICA_NAME || return 36
  cvmfs_server gc -f $CVMFS_TEST634_REPLICA_NAME || return 36

  return 0
}
