#!/bin/sh
# $Id$

# cli

. ./sh/lib/setup
. ./sh/lib/repo-setup
. ./sh/lib/rpm-setup

ORIGREPO=
DESTINATION_REPO=
DEPENDENCY_SOLVER=3

setUp() {
    is_rpm_testing_off && return

    rpm_up
    # provide /bin/sh auto requirement
    rpm_build_installed sh -p /bin/sh

    local use_sudo="n"
    [ -n "$SUDO" ] && use_sudo=y

    RAW_POLDEK="$POLDEK_NOCONF -Ouse_sudo=$use_sudo"
    POLDEK="$RAW_POLDEK --st pndir -s $REPO --root $DESTINATION_REPO --justdb"

    $RAW_POLDEK clean
}

tearDown() {
    #rpm_down
}

build() {
    build_package $REPO $@
}

build_installed() {
    rpm_build_installed $@
}

index() {
    $RAW_POLDEK --st dir -s $REPO --index
}

testNoop() {
    return 0
}

testInstall()
{
    skip_if_rpm_testing_off && return

    build a
    index

    msg $POLDEK install -v a
    $POLDEK install -v a
    assertEquals "install failed" "$?" "0"
    rpm_state_check "a" ""
}

testInstallNoConfig()
{
    skip_if_rpm_testing_off && return

    build a
    index

    # any -O option creates a configuration, so run without RAW_POLDEK's ones
    msg $POLDEK_RAW --noconf --cachedir $CACHEDIR --st pndir -s $REPO --root $DESTINATION_REPO -t install -v a
    $POLDEK_RAW --noconf --cachedir $CACHEDIR --st pndir -s $REPO --root $DESTINATION_REPO -t install -v a
    assertEquals "install failed" "$?" "0"
}

testInstallPercentInFileName()
{
    skip_if_rpm_testing_off && return

    build a
    # as saved from a URL with an encoded space; "%20d" must not be read as a conversion
    mv $REPO/a-1-1.noarch.rpm "$REPO/a-1-1%20dev.noarch.rpm" || fail "renaming the package failed"
    index

    msg $POLDEK install -v a
    $POLDEK install -v a
    assertEquals "install failed" "$?" "0"
    rpm_state_check "a" ""
}

# https://github.com/poldek-pm/poldek/issues/27
testInstallAlreadyInstalled() {
    skip_if_rpm_testing_off && return

    msgn "Preparing repositories..."
    build_installed b

    build a
    build b
    index
    $POLDEK up                  # to create stubindex

    msg $POLDEK install -v a b
    $POLDEK install -v a b
    assertEquals "install failed" "$?" "0"
    rpm_state_check "a" ""
}

# an index made with --mo=nodesc keeps no package info: ls --qf shows (none)
# for the summary, desc -L no changelog
testIndexWithoutPackageInfo()
{
    skip_if_rpm_testing_off && return

    build a
    $RAW_POLDEK --st dir -s $REPO --mkidx --mo=nodesc || fail "mkidx failed"

    out=$($POLDEK ls --qf '%{NAME}:%{SUMMARY}\n' a)
    assertEquals "ls --qf failed ($out)" "$?" "0"
    echo "$out" | grep -qx 'a:(none)'
    assertEquals "no a:(none) line ($out)" "$?" "0"

    out=$($POLDEK desc -L a)
    assertEquals "desc -L failed ($out)" "$?" "0"
}

testUpgrade()
{
    skip_if_rpm_testing_off && return

    build a -v 2
    build a-libs -v 2
    index

    build_installed a
    build_installed a-libs

    n=$($POLDEK ls -u | grep -E '^(a|a-libs)' | wc -l)
    assertEquals "expected 2 packages to be upgradeable, got $n" "$n" "2"

    msg $POLDEK install -F -v a~
    $POLDEK install -F -v a~

    #$RPM -ev a --justdb
    #$RPM -ev a-libs --justdb
    #$RPM -qa

    rpm_state_check "a-2,a-libs-2" "a-1,a-libs-1"
}

# desc -B lists a package whose requirement the described version satisfies,
# not any requirer of its name
testDescRequiredByVersion()
{
    skip_if_rpm_testing_off && return

    build x 1-1
    build x 2-1
    build y 1-1 -r "'x < 2'"
    build z 1-1 -r "'x >= 2'"
    build w 1-1 -r x
    build py27 2.7.18-1 -p "'python(abi) = 2.7'"
    build py3 3.13.1-1 -p "'python(abi) = 3.13'"
    build d 1-1 -r "'python(abi) = 2.7'"
    build e 1-1 -r "'python(abi) = 3.13'"
    # as in the dependency solver, a capability without a version
    # does not satisfy a versioned requirement
    build u 1-1 -p foo
    build r 1-1 -r "'foo >= 2'"
    build s 1-1 -r foo
    index

    for t in "x-1-1:w, y" "x-2-1:w, z" "py27-2.7.18-1:d" "py3-3.13.1-1:e" "u-1-1:s"; do
        p=${t%%:*}
        out=$($POLDEK desc -B $p.noarch)
        assertEquals "desc $p failed" "$?" "0"
        reqby=$(echo "$out" | sed -n 's/^Required(by): *//p')
        assertEquals "$p required by" "${t#*:}" "$reqby"
    done
}

testUninstall()
{
    skip_if_rpm_testing_off && return

    build a
    index

    build_installed a
    build_installed b
    build_installed a-libs

    msg $POLDEK uninstall -y a~
    $POLDEK uninstall -y a~

    #$RPM -ev a --justdb
    #$RPM -ev a-libs --justdb
    #$RPM -qa

    rpm_state_check "b" "a,a-libs"
}

# without repositories desc runs in /installed: -R and -B look among the
# installed packages
testDescInstalled()
{
    skip_if_rpm_testing_off && return

    build_installed b
    build_installed a -r b
    build_installed c -r a

    msg $RAW_POLDEK --root $DESTINATION_REPO desc -R -B a
    out=$($RAW_POLDEK --root $DESTINATION_REPO desc -R -B a)
    assertEquals "desc failed" "$?" "0"
    echo "$out" | grep -qE '^Required\(pkgs\): +sh, b$'
    assertEquals "a should require b" "$?" "0"
    echo "$out" | grep -qE '^Required\(by\): +c$'
    assertEquals "a should be required by c" "$?" "0"
}

# -R finds the owners of a required file and directory also when the
# installed packages come from the cache
testDescInstalledPathsFromCache()
{
    skip_if_rpm_testing_off && return

    build_installed f -f /usr/bin/zzf
    build_installed d -fd /usr/share/zzd/sub
    build_installed a -r /usr/bin/zzf -r /usr/share/zzd/sub
    # older than the cache made below, which then counts as current
    touch -d '-1 hour' $DESTINATION_REPO$($RPM --eval %_dbpath)/*

    for src in rpmdb rpmdbcache; do
        out=$($RAW_POLDEK --root $DESTINATION_REPO desc -R a)
        echo "$out" | grep -q "^Loading \[$src\]"
        assertEquals "installed packages not loaded from $src" "$?" "0"

        req=$(echo "$out" | grep '^Required(pkgs):')
        for p in d f; do
            echo "$req" | grep -qE "[ ,]$p(,|$)"
            assertEquals "$src: a should require $p ($req)" "$?" "0"
        done
    done
}

# and right after an install in the shell, with the installed packages
# read from the cache before it
testDescInstalledAfterInstall()
{
    skip_if_rpm_testing_off && return

    build_installed f -f /opt/zzf/tool
    build a -r /opt/zzf/tool
    index
    touch -d '-1 hour' $DESTINATION_REPO$($RPM --eval %_dbpath)/*
    $RAW_POLDEK --root $DESTINATION_REPO --cmd ls >/dev/null  # makes the cache

    out=$(printf 'cd /installed\nls\ncd /all-avail\ninstall --justdb a\ncd /installed\ndesc -R a\nquit\n' |
          timeout 60 script -qec "$POLDEK --noask --shell" /dev/null |
          tr -d '\r' | sed 's/\x1b\[[0-9;?]*[A-Za-z]//g')
    echo "$out" | grep -q "Loading \[rpmdbcache\]"
    assertEquals "installed packages not loaded from the cache" "$?" "0"

    req=$(echo "$out" | grep 'Required(pkgs):')
    echo "$req" | grep -qE "[ ,]f(,|$)"
    assertEquals "a should require f ($req)" "$?" "0"
}

testClean()
{
    skip_if_rpm_testing_off && return

    typeset n=$(find $CACHEDIR | wc -l)
    assertEquals "$CACHEDIR should be empty" "$n" "1"

    rm -rf $CACHEDIR/*
    mkdir -p $CACHEDIR/foo/bar/baz
    touch $CACHEDIR/foo/foo.txt
    touch $CACHEDIR/foo/bar/bar.txt
    touch $CACHEDIR/foo/bar/baz/bar.txt
    mkfifo $CACHEDIR/fifo

    typeset OUTSIDEDIR="$CACHEDIR/../"
    touch $CACHEDIR/../existing-file

    ln -s ../existing-file $CACHEDIR/symlink
    ln -s ../non-existing $CACHEDIR/broken-symlink
    #ls -l $CACHEDIR/
    n=$(find $CACHEDIR | wc -l)
    #find $CACHEDIR | nl
    if [ "$n" -lt 8 ]; then
        find $CACHEDIR | nl
        fail "$CACHEDIR should contain at least 8 items"
    fi

    $RAW_POLDEK clean
    n=$(find $CACHEDIR | wc -l)
    [ "$n" != "1" ] && find $CACHEDIR
    assertEquals "$CACHEDIR should be empty after clean" "$n" "1"

    test -f $CACHEDIR/../existing-file || fail "$CACHEDIR/../existing-file should still be there"

}

# what the cache of installed packages leaves out (descriptions, file lists)
# comes from the --root database, not from the host's
testDescInstalledRootFromCache()
{
    skip_if_rpm_testing_off && return

    build_installed a -f /usr/bin/zzroot
    # a cache made within a second of a database change counts as stale;
    # back-date the database so the cache made below counts as current
    $SUDO touch -d '-1 hour' $DESTINATION_REPO$($RPM --eval %_dbpath)/* || fail "back-dating the rpm database failed"

    for src in rpmdb rpmdbcache; do
        out=$($RAW_POLDEK --root $DESTINATION_REPO desc -d -f a)
        echo "$out" | grep -q "^Loading \[$src\]"
        assertEquals "installed packages not loaded from $src" "$?" "0"
        echo "$out" | grep -qE '^Summary: +a$'
        assertEquals "$src: no summary of a ($out)" "$?" "0"
        echo "$out" | grep -qE '^/usr/bin: +zzroot$'
        assertEquals "$src: no files of a ($out)" "$?" "0"
    done
}


. ./sh/lib/shunit2
