#!/bin/sh
# test with rpm installations (--justdb is used)

. ./sh/lib/setup
. ./sh/lib/repo-setup
. ./sh/lib/solver-setup

ORIGREPO=
DESTINATION_REPO=
DEPENDENCY_SOLVER=3

# XXX for some reason rpm5 does not create its database correctly if running as ordinary user:
#  $ rpm --root /tmp/root --initdb
#  $ rpm --root /tmp/root -ivh --justdb foo-1-1.noarch.rpm
#  rpmdb: BDB0577 The primary and secondary must be opened in the same environment
#  error: db3associate:db3.c:1674: db->associate(22): Invalid argument
#  BDB0624 DBcursor->pget may only be used on secondary indices
#  error: db3cpget:db3.c:1537: dbcursor->pget(22): Invalid argument
#  error: error(22) getting keys from Triggername index
#
# ...and fakeroot does not help with above

SUDO="sudo"
[ $(id -u) == "0" ] && SUDO=""

setUp() {
    if [ -n "$SUDO" ]; then
        # skip testing if no sudo configured
        $SUDO -n /bin/rpm --version >/dev/null 2>/dev/null
        local ec=$?
        [ $ec -eq 0 ] || exit 0

        $SUDO -n /bin/rm --version >/dev/null 2>/dev/null
        local ec=$?
        [ $ec -eq 0 ] || exit 0
    fi

    [ -z "$ORIGREPO" ] && ORIGREPO=$REPO
    [ -z "$ORIGREPO" ] && fail "empty REPO env variable"

    REPO="$ORIGREPO/src"
    DESTINATION_REPO="$ORIGREPO-rpm";

    $SUDO rm -rf $DESTINATION_REPO
    rm -rf $ORIGREPO/*
    rm -rf $REPO $DESTINATION_REPO

    mkdir -p $REPO || fail "mkdir $REPO failed"
    mkdir -p $DESTINATION_REPO || fail "mkdir $DESTINATION_REPO failed"

    mkdir -p $DESTINATION_REPO || fail "mkdir $DESTINATION_REPO failed"
    RPM="$SUDO rpm --root $DESTINATION_REPO"
    $RPM --initdb

    # provide /bin/sh auto requirement
    build_installed sh -p /bin/sh
    RAW_POLDEK="$POLDEK_NOCONF -Odependency_solver=$DEPENDENCY_SOLVER -Oupgrade_multiple_instances=y --noask"
    POLDEK_INSTALL="$RAW_POLDEK --st dir -s $REPO --root $DESTINATION_REPO --justdb"
}

tearDown() {
    [ -n "$DESTINATION_REPO" ] && $SUDO rm -rf $DESTINATION_REPO
}

build() {
    build_package $REPO $@
}

build_installed() {
    mkdir -p $DESTINATION_REPO/RPMS/
    rm -f $DESTINATION_REPO/RPMS/*.rpm
    build_package $DESTINATION_REPO/RPMS/ $@
    $RPM -iv --quiet --justdb $DESTINATION_REPO/RPMS/*.rpm
    #echo $RPM --quiet -q $BUILT_PACKAGE_NVR
    $RPM --quiet -q $BUILT_PACKAGE_NVR
    [ $? -eq 0 ] || fail "$BUILT_PACKAGE_NVR: rpm installation failed"
}

try_install() {
  typeset package="$1"
  typeset expected="$2"
  typeset rm_expected="$3"

  [ -n "$expected" ] && expected=$(echo $expected | sed 's/,/ /g')

  e_rm_expected="non-existing-package"
  [ -n "$rm_expected" ] && e_rm_expected=$(echo $rm_expected | sed 's/,/|/g')
  [ -n "$rm_expected" ] && rm_expected=$(echo $rm_expected | sed 's/,/ /g')

  state=$($RPM -qa | sort | perl -pe "s|\n| |g")
  new_state=$($RPM -qa | sort | grep -Pv "($e_rm_expected)" | perl -pe "s|\n| |g")

  if is_verbose_mode; then
      msg "Current state: $state"
      msg "Expected state: $new_state"
  fi

  try_install_package "rpm" -uv $@

  RPMQ="$RPM --quiet -q"

  for i in $rm_expected; do
      #msg "rm  $i"
      $RPMQ $i && fail "$i: package expected to be removed"
  done

  for i in $expected; do
      #msg "new $i"
      $RPMQ $i || fail "$i: package expected to be installed"
      #[ $? -eq 0 ] || fail "$i: package expected to be installed"
  done

  for i in $new_state; do
      #msg "kept  $i"
      $RPMQ $i || fail "$i: package expected to be kept"
  done
}

testRPMdbcache() {
    build foo

    $RAW_POLDEK -Oauto_directory_dependencies=y --root $DESTINATION_REPO --cmd reload >/dev/null
    local rpmdb_cachedirname="$(echo $DESTINATION_REPO | sed -e 's|^/||' -e 's|/|.|g').var.lib.rpm"
    local suffix="rpmdbcache$(echo $DESTINATION_REPO | sed 's|/|.|g').var.lib.rpm"

    # check presence of dbcache
    for i in zst md zst.md5; do
        local name="packages.$suffix.$i"
        [ -f "$CACHEDIR/$name" ] || fail "missing expected $name in $CACHEDIR"
    done

    # check presence of dbcache's dirindex
    for i in tndb tndb.md5; do
        local name="dirindex.$suffix.$i"
        [ -f "$CACHEDIR/$name" ] || fail "missing expected $name in $CACHEDIR"
    done

    local dirindex_path="$CACHEDIR/$rpmdb_cachedirname/dirindex.rpmdb.tndb"
    local md5=$(md5sum $dirindex_path | cut -f1 -d' ')

    # will die (we're in test mode) if dirindex is missing
    $RAW_POLDEK -Oauto_directory_dependencies=y --st dir -s $REPO --root $DESTINATION_REPO --cmd ls -u
    assertEquals "died" "$?" "0"

    local md=$(md5sum $dirindex_path | cut -f1 -d' ')
    assertEquals "dirindex changed" "$md5" "$md"

    build a "1-1"
    sleep 0.8 # mtime based cache
    try_install a "a-1-1" ""

    # should load rpmdb and update dirindex
    $RAW_POLDEK -Oauto_directory_dependencies=y --st dir -s $REPO --root $DESTINATION_REPO --cmd ls -u

    local md=$(md5sum $dirindex_path | cut -f1 -d' ')
    if [ "$md5" = "$md" ]; then
        fail "$dirindex_path: dirindex not changed ($md5)"
    fi
}

testUpgradeMultipleInstalled() {
    msgn "Preparing repositories..."
    build_installed a 0.9.8c-1
    build_installed a 1.0.0o-1
    build_installed a 1.1.1j-1

    build a 1.1.1k-1
    try_install a "a-1.1.1k-1" "a-1.1.1j-1"
}

testUpgradeMultipleInstalledWithDeps() {
    msgn "Preparing repositories..."
    build_installed a 0.9.8c-1
    build_installed a 1.0.0o-1
    build_installed a 1.1.1j-1

    for i in b10 c10 d10; do
        build_installed $i 0.1-0.1 -r "'a = 1.0.0o'"
    done

# TODO
#    for i in b11 c11; do
#        build_installed $i 1.0-1 -r "'a = 1.1'"
#    done

    build a 1.1.1k-1
    try_install a "a-1.1.1k-1" "a-1.1.1j-1"
}

# not implemented yet
xtestUpgradeMultipleInstalledIndir() {
    msgn "Preparing repositories..."
    build_installed a 1.0-1
    build_installed a 1.1-1

    build a 1.2-1
    build b 1-1 -r "'a = 1.2'"

    try_install b-1-1 "a-1.2" "a-1.1-1"
}

. ./sh/lib/shunit2
