#!/bin/bash
cvmfs_test_name="cvmfs_server snapshot -a and gc -a"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

CVMFS_TEST_621_REPLICA_NAMES=
CVMFS_TEST_621_LOG_OWNER=

cleanup() {
  if [ -n "$CVMFS_TEST_621_REPLICA_NAMES" ]; then
    for repo in $CVMFS_TEST_621_REPLICA_NAMES; do
      sudo cvmfs_server rmfs -f $repo
    done
  fi
  if [ -n "$CVMFS_TEST_621_LOG_OWNER" ]; then
    for log in snapshots.log gc.log; do
      if [ -f /var/log/cvmfs/$log ]; then
        echo "*** contents of $log"
        cat /var/log/cvmfs/$log
      fi
    done
    sudo chown -R $CVMFS_TEST_621_LOG_OWNER /var/log/cvmfs
  fi
}

has_jq() {
  which jq >/dev/null 2>&1
}

get_last_gc() {
  curl -f -s "$(get_repo_url $1)/.cvmfs_status.json"|grep last_gc
}

cvmfs_run_test() {
  logfile=$1

  echo -n "*** checking for curl... "
  which curl > /dev/null 2>&1 || { echo "fail"; return 1; }
  echo "done"

  echo "*** create a fresh gc-able repository named $CVMFS_TEST_REPO with user $CVMFS_TEST_USER"
  create_empty_repo $CVMFS_TEST_REPO $CVMFS_TEST_USER NO -z || return $?

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

  local replica_name="$(get_stratum1_name $CVMFS_TEST_REPO)"

  CVMFS_TEST_621_REPLICA_NAMES="${replica_name}-0 ${replica_name}-1 ${replica_name}-2 ${replica_name}-3 ${replica_name}-4 ${replica_name}-5"
  echo "*** install a cleanup function"
  trap cleanup EXIT HUP INT TERM || return $?

  echo "*** create 6 Stratum1 replicas on the same machine"
  load_repo_config $CVMFS_TEST_REPO

  # First replica is pass-through
  create_passthrough_stratum1 ${replica_name}-0    \
                              $CVMFS_TEST_USER     \
                              $CVMFS_STRATUM0      \
                              || return 9
  for num in 1 2 3 4 5; do
    local groupopt
    groupopt=""
    if [ "$num" -eq 4 ]; then
      groupopt="-g other"
    fi
    create_stratum1 ${replica_name}-$num                   \
                    $CVMFS_TEST_USER                       \
                    $CVMFS_STRATUM0                        \
                    /etc/cvmfs/keys/${CVMFS_TEST_REPO}.pub \
                    $groupopt                              \
                    || return $num
  done

  echo "*** disabling snapshots to second replica"
  sudo $SHELL -c "echo "CVMFS_REPLICA_ACTIVE=no" >> /etc/cvmfs/repositories.d/${replica_name}-2/replica.conf"
  echo "*** corrupting third replica's download URL"
  sudo $SHELL -c "sed -i 's,^\(CVMFS_STRATUM0=.*\),\1Bogus,' /etc/cvmfs/repositories.d/${replica_name}-3/server.conf"

  echo "*** making /var/log/cvmfs user-writable"
  if [ -d /var/log/cvmfs ]; then
    CVMFS_TEST_621_LOG_OWNER=$(stat --format='%U' /var/log/cvmfs)
  else
    sudo mkdir -p /var/log/cvmfs
  fi
  sudo chown -R $CVMFS_TEST_USER /var/log/cvmfs
  echo "*** removing old snapshots.log and gc.log"
  rm -f /var/log/cvmfs/snapshots.log /var/log/cvmfs/gc.log

  echo "*** running cvmfs_server snapshot -a"
  cvmfs_server snapshot -an || return 10

  echo "*** download manifests of stratum 0 and replica 0, 1 and 5"
  if running_on_s3; then
    echo "skipping pass-through test"
  else
    curl -so mr0 "$(get_repo_url ${replica_name}-0)/.cvmfspublished" || return 11
  fi
  curl -so mr1 "$(get_repo_url ${replica_name}-1)/.cvmfspublished" || return 12
  curl -so mr5 "$(get_repo_url ${replica_name}-5)/.cvmfspublished" || return 13
  curl -so ms0 "$(get_repo_url $CVMFS_TEST_REPO)/.cvmfspublished"  || return 14

  echo "*** ms0 ***"
  cat ms0
  echo "*** mr0 ***"
  cat mr0
  echo "*** mr1 ***"
  cat mr1
  echo "*** mr5 ***"
  cat mr5
  echo "*** checking if snapshot worked on replicas 0, 1 and 5"
  if running_on_s3; then
    echo "skipping pass-through test"
  else
    cmp ms0 mr0 || return 15
  fi
  cmp ms0 mr1 || return 16
  cmp ms0 mr5 || return 17

  echo "*** checking if replica 2 was skipped"
  curl -f -sI "$(get_repo_url ${replica_name}-2)/.cvmfspublished" && return 20
  echo "*** checking if replica 3 detected an error"
  curl -f -sI "$(get_repo_url ${replica_name}-3)/.cvmfs_last_snapshot" && return 21
  echo "*** checking if replica 4 was skipped"
  curl -f -sI "$(get_repo_url ${replica_name}-4)/.cvmfspublished" && return 22

  echo "*** running cvmfs_server snapshot -a -g other"
  cvmfs_server snapshot -an -g other || return 30

  echo "*** download manifest of replica 4"
  curl -so mr4 "$(get_repo_url ${replica_name}-5)/.cvmfspublished" || return 31

  echo "*** checking if snapshot worked on replica 4"
  cmp ms0 mr4 || return  32

  echo "*** restoring replica 3's download URL"
  sudo $SHELL -c "sed -i 's,Bogus,,' /etc/cvmfs/repositories.d/${replica_name}-3/server.conf"

  echo '*** checking snapshot wildcard "*-?"'
  # make sure wildcard expansion does not happen in current working dir
  touch "afilewithadash-1"
  cvmfs_server snapshot "*-?" || return 40

  echo "*** checking that replicas 2 & 3 worked this time"
  # the wildcard does not look at CVMFS_REPLICA_ACTIVE
  curl -f -sI "$(get_repo_url ${replica_name}-2)/.cvmfspublished" || return 41
  curl -f -sI "$(get_repo_url ${replica_name}-3)/.cvmfs_last_snapshot" || return 42

  echo "*** corrupting third replica's download URL again"
  sudo $SHELL -c "sed -i 's,^\(CVMFS_STRATUM0=.*\),\1Bogus,' /etc/cvmfs/repositories.d/${replica_name}-3/server.conf"

  echo "*** remove evidence of initial repo gc"
  ! has_jq || delete_from_backend $CVMFS_TEST_REPO .cvmfs_status.json || return 43

  echo "*** running cvmfs_server gc -Af"
  cvmfs_server gc -Af || return 44

  if ! has_jq; then
    return 0
  fi

  echo "*** checking if gc worked on test repo and replicas 1 and 4"
  get_last_gc $CVMFS_TEST_REPO                            || return 50
  get_last_gc ${replica_name}-1                           || return 51
  get_last_gc ${replica_name}-4                           || return 52

  echo "*** verifying gc did not work on replicas 2 and 3"
  get_last_gc ${replica_name}-2                           && return 53
  get_last_gc ${replica_name}-3                           && return 54

  if ! running_on_s3; then
    echo "*** checking if (only) replica 0 is marked as pass-through"
    curl -f -s "$(get_local_repo_url info)/v1/repositories.json" | \
      jq ".replicas[] | select(.alias == \"${replica_name}-0\")" | grep pass-through || return 55
    curl -f -s "$(get_local_repo_url info)/v1/repositories.json" | \
      jq ".replicas[] | select(.alias == \"${replica_name}-1\")" | grep pass-through && return 56
  else
    echo "skipping pass-through test"
  fi

  echo "*** checking if updating and gc locks have been removed on test repo"
  load_repo_config $CVMFS_TEST_REPO
  test -f ${CVMFS_SPOOL_DIR}/is_updating.lock && return 60
  test -f ${CVMFS_SPOOL_DIR}/is_collecting.lock && return 61

  echo "*** checking to make sure gc -af skips repos collected more recently than upstream"

  cvmfs_server gc -f $CVMFS_TEST_REPO                     || return 70
  sleep 2 # make sure the timestamp is newer
  cvmfs_server gc -f ${replica_name}-1                    || return 71

  local rep1_last_gc rep4_last_gc rep1_now_gc rep4_now_gc
  rep1_last_gc="$(get_last_gc ${replica_name}-1)"
  [ -n "$rep1_last_gc" ]                                  || return 72
  rep4_last_gc="$(get_last_gc ${replica_name}-4)"
  [ -n "$rep4_last_gc" ]                                  || return 73

  # Disable gc on the main repo so only replicas are collected
  sudo sed -i 's/^\(CVMFS_GARBAGE_COLLECTION\)=.*/\1=false/' \
   /etc/cvmfs/repositories.d/$CVMFS_TEST_REPO/server.conf || return 74

  # keep a copy of the gc.log for comparison
  cp /var/log/cvmfs/gc.log .                              || return 75

  sleep 2 # make sure these timestamps are newer
  cvmfs_server gc -af                                     || return 76

  rep1_now_gc="$(get_last_gc ${replica_name}-1)"
  [ -n "$rep1_now_gc" ]                                   || return 80
  rep4_now_gc="$(get_last_gc ${replica_name}-4)"
  [ -n "$rep4_now_gc" ]                                   || return 81

  echo "*** checking that the timestamps were updated in replica 1 and 4"
  [ "$rep1_last_gc" != "$rep1_now_gc" ]                   || return 82
  [ "$rep4_last_gc" != "$rep4_now_gc" ]                   || return 83

  echo "*** checking that gc only ran in replica 4"
  diff gc.log /var/log/cvmfs | grep ${replica_name}-1     && return 85
  diff gc.log /var/log/cvmfs | grep ${replica_name}-4     || return 86

  return 0
}
