#!/bin/sh
# $Id$

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

ORIGREPO=
DESTINATION_REPO=
DEPENDENCY_SOLVER=3

#tearDown() {
#    [ -n "$REPO" ] && rm -f $REPO/*.*
#}

setUp() {
    [ -z "$ORIGREPO" ] && ORIGREPO=$REPO
    [ -z "$ORIGREPO" ] && fail "empty REPO env variable"
    rm -rf $ORIGREPO/*

    REPO="$ORIGREPO/src"
    REPO2="$ORIGREPO/src2"
    DESTINATION_REPO="$ORIGREPO/dest";

    rm -rf $REPO $REPO2 $DESTINATION_REPO

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

    # provide /bin/sh auto requirement
    build_installed sh -p /bin/sh

    RAW_POLDEK="$POLDEK_NOCONF"
    POLDEK_INSTALL="$RAW_POLDEK --st dir -s $REPO --st dir -s $REPO2 --dt dir --destination $DESTINATION_REPO"
    POLDEK_UNINSTALL="$RAW_POLDEK --dt dir --destination $DESTINATION_REPO"
}

build() {
   build_package $REPO "$@"
}

build2() {
   build_package $REPO2 "$@"
}

build_installed() {
   build_package $DESTINATION_REPO "$@"
}

# try to install package and check result
# usage: try_install <package> <expected installed> [<expected removed>] [<extra poldek switches>]
try_install() {
    local pkg=$1

    msg "try_install $pkg"
    $POLDEK_INSTALL -uv --test $pkg | grep -P '^%choose '
    local nchoices=$($POLDEK_INSTALL -uv --test $pkg | grep -P '^%choose ' | wc -l)
    assertEquals "user should not be asked to choose equivalents ($nchoices)" "$nchoices" "0"

    try_install_package "dir" "-uv --test" "$@"
}

try_install_with_ask_allowed() {
    try_install_package "dir" "-uv --test" "$@"
}

try_install_noask() {
    try_install_package "dir" "-uv --test -y" "$@"
}

try_install_a() {
    try_install "a" $@
}

try_install_a_should_fail() {
    try_install_package_should_fail "dir" "-uv --test" "a" $@
}

try_uninstall() {
    try_uninstall_package "dir" "-ev --test" "$@"
}

# 'c' has unmet requirement
testChooseTheRightAlternative1() {
  build a -r "CAP"
  build c -p "CAP" -r "unmetreq"
  build d -p "CAP"
  try_install_a "a,d"
}

# 'd' should be choosen instead of non-resolvable 'c'
testChooseTheRightAlternative2() {
  build a -r "b"
  build b -r "CAP"
  build c -p "CAP" -r "unmetreq"
  build d -p "CAP"
  try_install_a "a,b,d"
}

# as above, but 'c' has more (solvable) requirements
testChooseTheRightAlternative3() {
  build a -r "b"
  build b -r "CAP"
  build c -p "CAP" -r "foo" -r "bar" -r "unmetreq" -r "zfoo"
  build d -p "CAP"
  build foo
  build bar
  build zfoo
  try_install_a "a,b,d"
}

# first, but wrong resolved set is: a,b,c,e,g
testChooseTheRightAlternative4() {
  build a  -r "b"
  build b  -r "CAP"

  build c  2-1 -r "e" -p "CAP"
  build d  -r "f" -p "CAP"

  build e  -r "g"
  build f  2-1 -r "h"

  build g  2-1 -r "unmetreq"
  build h

  # c and d are both valid alternatives providing CAP
  try_install_with_ask_allowed a "a,b,d,f,h"
}

# package 'x' provides all 'a' requirements
testChooseMoreAccuratePackage() {
  build a -r "b" -r "c" -r "d" -r "x"
  build b -p "foo" -p "bar"
  build c
  build d
  build x -p "b" -p "c" -p "d"

  try_install_with_ask_allowed a "a,x"
}

testMissingDep() {
    build a -r "b"
    build b -r "unmetreq"

    try_install_a_should_fail "a,b" ""
    if is_verbose_mode; then
        msg "THE ERROR ABOVE (1 unresolved dependency) is EXPECTED"
    fi
    $POLDEK_INSTALL -uv --test a | grep -q "error: b-1-1: req unmetreq not found"
    assertEquals "poldek should report 1 dependency error" "$?" "0"
}

testMissingDepIndirect()
{
    build a -r "foo"
    build b -p "foo" -p "bar" -r "baz"
    build c -p "baz" -r "foo.so"
    build sh -p /bin/sh

    try_install_a_should_fail "a,b,c" ""
    if is_verbose_mode; then
       msg "THE ERROR ABOVE (1 unresolved dependency) is EXPECTED"
    fi
    $POLDEK_INSTALL -uv --test a | grep -q "error: c-1-1: req foo.so not found"
    assertEquals "poldek should report 1 dependency error" "$?" "0"
}

testConflict() {
    build a -r "foo" -r "bar"
    build b -p "foo" -p "bar" -c "a"
    build c -p "foo" -p "bar"

    try_install a "a,c" ""
}

# package 'b' conflicts with 'a'
testConflictUseAlternative() {
  build a -r "foo" -r "bar"
  build b -p "foo" -p "bar" -c "a"
  build c -p "foo" -p "bar"

  try_install_a "a,c"
}

# b conflicts with installed c
testConflictUpgrade() {
    build_installed a -r "foo" -r "bar"
    build_installed c -p "foo" -p "bar"

    build a 2-2 -r "b"
    build b 2-2 -r "'a > 1'" -c "'c < 2'"
    build c 2-2

    try_install_a "a,b,c"
}

# ...
testConflictSth() {
    build a -r "foo" -r "bar"
    build b -p "foo" -p "bar" -c "a"
    build c -p "foo" -p "bar"

    msgn "Preparing repositories..."
    build_installed a 2-1
    build_installed b 2-1  -r "'a = 2-1'" -r "'a >= 1-1'" -r "a" -r "'a > 1'"

    build a 2-2
    build b 2-2 -r "'a >= 1-1'" -r "'a = 2-2'"

    msgn "Upgrade"
    try_install a "a-2-2,b-2-2" "a-2-1,b-2-1"
}

# thunderbird and it's lang packages
testUpgradeMultipleByConflict() {
    build foo 2-2 -r "'libfoo >= 2'"
    build libfoo 2-2

    build a 2-2 -c "'a-lang-resources < 2'" -r "'libfoo = 2'"
    build a-lang-en 2-2 -p "'a-lang-resources = 2'"
    build a-lang-pl 2-2 -p "'a-lang-resources = 2'"

    build_installed libfoo 1-1
    build_installed a 1-1 -c "'a-lang-resources < 1'" -r "'libfoo = 1'"
    build_installed a-lang-en 1-1 -p "'a-lang-resources = 1'" -r "'a >= 1'"
    build_installed a-lang-pl 1-1 -p "'a-lang-resources = 1'" -r "'a >= 1'"

    msgn "Upgrade"
    try_install_noask foo "foo-2-2,libfoo-2-2,a-2-2,a-lang-en-2-2,a-lang-pl-2-2" "libfoo-1-1,a-1-1,a-lang-en-1-1,a-lang-pl-1-1"
}


# b-1-1 meets all 'a' requirements
testRedundantRequirement() {
  build a -r "b" -r "'b = 1'"
  build b 2-1
  build b 1-1
  try_install_a "a,b-1"
}

# #17
testPrePostRequirements() {
  build a -rpre "b" -rpost "c"
  build b
  build c
  try_install_a "a,b,c"
}


# if packages "bar" and "baz" have Obsoletes: foo, Provides: foo, Conflicts: foo,
# then librpm knows that you can only have "bar" or "baz" but not both
testRpmOrgMutualExclusive() {
    build_installed bar -o foo -p foo -c foo
    build baz -o foo -p foo -c foo

    try_install "baz" "baz" "bar"
}

testRpmOrgMutualExclusive_2() {
    build_installed baz -o foo -p foo -c foo
    build baz -v 2 -o foo -p foo -c foo

    try_install "baz" "baz" "baz"
}


# suggested packages should be installed
testSuggestsAll() {
    build_installed suggested
    build a -s "suggested" -s "b" -s "c"
    build b
    build c

    msgn "All suggested packages"
    POLDEK_TESTING_WITH_SUGGESTS="all" # choose all suggested packages
    export POLDEK_TESTING_WITH_SUGGESTS
    try_install_a "a,b,c"
}

# suggested packages should be installed
testSuggestsSome() {
    build_installed suggested
    build a -s "suggested" -s "b" -s "c"
    build b
    build c

    msgn "Some suggested packages"
    POLDEK_TESTING_WITH_SUGGESTS="b" # choose b only
    export POLDEK_TESTING_WITH_SUGGESTS
    try_install_a "a,b"
    POLDEK_TESTING_WITH_SUGGESTS=
}

testUpgradeSet() {
    msgn "Preparing repositories..."
    prev_i=
    for i in b c d e f a; do
        build_installed $i 1-1
        if [ -z "$prev_i" ]; then
           build_installed $i 1-1
           build $i 2-2
        else
           build_installed $i 1-1 -r "'$prev_i = 1-1'"
           build $i 2-2 -r "'$prev_i = 2-2'"
        fi
        prev_i=$i
    done

    try_install_a "a,b,c,d,e,f"
}

# all 'a*' must be upgraded at once
testUpgradeGreedy() {
    msgn "Preparing repositories..."
    for i in "1-1" "2-2"; do
        build a $i
        build a-devel $i -r "'a = $i'"
        build a-static $i -r "'a-devel = $i'"
    done
    mv $REPO/a*1-1*.rpm $DESTINATION_REPO || fail "mv failed"
    try_install a "a,a-devel,a-static"
    try_install a-devel "a,a-devel,a-static"
    try_install a-static "a,a-devel,a-static"
}

# should honour --greedy option
testGreedyOnOff() {
    msgn "Preparing repositories..."
    v=1-1
    build_installed foo $v -p "CAP"
    build_installed bar $v -r "CAP"

    v=2-2
    build foo $v
    build bar $v
    build baz 1-1 -p "CAP"

    msgn "Greedy..."
    try_install foo "foo,bar" "foo,bar" --greedy=yes
    msgn "Not so greedy..."
    try_install foo "foo,baz" "foo" --greedy=no
}

# should be greedy on unmet dependecies
testBeGreedyOnUnmetDeps() {
    msgn "Preparing repositories..."
    v=1-1
    build_installed foo $v -p "CAP"
    build_installed bar $v -r "CAP"

    v=2-2
    build foo $v
    build bar $v

    try_install foo "foo,bar" "foo,bar" --greedy=yes
}


# bar obsoletes foo
testUpgradeObsolete() {
    msgn "Preparing repositories..."
    build_installed a 1-1
    build_installed a-devel 1-1 -r "'a = 1-1'"
    build_installed a-static 1-1 -r "'a-devel = 1-1'"
    build_installed foo 1-1 -r "'a = 1-1'" -p "FOO" -o "FOO"

    build a 2-2
    build a-devel 2-2 -r "'a = 2-2'"
    build a-static 2-2 -r "'a-devel = 2-2'"
    build afoo 1-1 -p "FOO" -o "FOO" -o foo
    build bar 1-1 -o "foo"

    try_install a "a,a-devel,a-static,bar" "a,a-devel,a-static,foo"
}

testUpgradeMultilib() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    for i in i686 x86_64; do
        build_installed a 1-1 -a $i -f "/hello.$i"
        build_installed a-devel 1-1 -r "'a = 1'" -a $i # -f "/usr/include/foo.h"
        build_installed a-static 1-1 -r "'a = 1'" -a $i -f "/sbin/hello.$i"

        build a 2-2 -a $i -f "/hello.$i"
        build a-devel 2-2 -r "'a = 2-2'" -a $i # -f "/usr/include/foo.h"
        build a-static 2-2 -r "'a = 2-2'" -a $i -f "/sbin/hello.$i"
    done
    rm -f $DESTINATION_REPO/a-devel*i686* # remove duplicated uncolored package

    msgn "Multilib upgrades"
    msgn " colored package"
    try_install_with_ask_allowed a-2-2.x86_64 "a-2-2.x86_64" "a-1-1.x86_64"

    msgn " uncolored package #1"
    try_install_with_ask_allowed a-devel-2-2.x86_64 \
                                 "a-2-2.x86_64,a-devel-2-2.x86_64" \
                                 "a-1-1.x86_64,a-devel-1-1.x86_64"

    msgn " uncolored package #2"
    try_install_with_ask_allowed a-devel-2-2.i686 \
                                 "a-2-2.i686,a-devel-2-2.i686" \
                                 "a-1-1.i686,a-devel-1-1.x86_64"
    msgn "  upgrade-dist"
    runpoldek --upgrade-dist
    n=$(ls $DESTINATION_REPO/a* | grep 1-1 | wc -l)
    assertEquals "not all packages were upgraded by upgrade-dist" "$n" "0"

    msgn "  uncolored package #3"
    # Multilib upgrade uncolored package (arch flip-flop regardless of arch)
    try_install a-devel-2-2.i686 "a-devel-2-2.i686" "a-devel-2-2.x86_64"

    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

# https://github.com/poldek-pm/poldek/issues/1
testUpgradeMultilibSummary() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    for i in i686 x86_64; do
        build_installed a 1-1 -a $i -f "/hello.$i"
        build a 2-2 -a $i -f "/hello.$i"
    done

    # be verbose to test summary shape (ugly)
    local q=$QUIET
    QUIET="-v"

    #runpoldek --upgrade-dist --test -v
    local summary=$(runpoldek --upgrade-dist --test -v | grep -P ^U)
    local expected_summary="U a-(1-1 => 2-2).i686  a-(1-1 => 2-2).x86_64"
    assertEquals "expected [$expected_summary], got [$summary]" "$summary" "$expected_summary"

    # one updated and one new
    rm -f $DESTINATION_REPO/a*.x86_64.rpm
    summary=$(runpoldek --upgrade --test -v a-2-2.x86_64 a-2-2.i686 | grep -P ^U)
    expected_summary="U a-(1-1 => 2-2).i686"
    assertEquals "expected [$expected_summary], got [$summary]" "$summary" "$expected_summary"

    summary=$(runpoldek --upgrade --test -v a-2-2.x86_64 a-2-2.i686 | grep -P ^A)
    expected_summary="A a-2-2.x86_64"
    assertEquals "expected [$expected_summary], got [$summary]" "$summary" "$expected_summary"

    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
    QUIET=$q
}


# https://bugs.pld-linux.org/show_bug.cgi?id=83
testUpgradeMultilibOneTransactionForSamePackagesDifferentSource() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    for i in i686 x86_64; do
        build_installed FooBar 1-1 -a $i -f "/hello.$i" -f "/README"
    done
    build  FooBar 2-2 -a i686 -f "/hello.i686" -f "/README"
    build2 FooBar 2-2 -a x86_64 -f "/hello.x86_64" -f "/README"

    msgn "Up"
    try_install FooBar "FooBar-2-2.i686,FooBar-2-2.x86_64" "FooBar-1-1.i686,FooBar-1-1.x86_64"

    #"a-2-2.x86_64" "a-1-1.x86_64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

# Similar to testUpgradeOrphanIfItResolvesReq but obsoleted by different package
# http://lists.pld-linux.org/mailman/pipermail/pld-users-pl/2015-November/078844.html
testUpgradeOrphanByObsoletes() {
    msgn "Preparing repositories..."
    build_installed a -r "'a-lib = 1'" # udev
    build_installed a-lib              # udev-lib
    build_installed b -r "'a-lib = 1'" # udev-glib

    build a 2-2 -r "'a-lib = 2'"
    build a-lib 2-2
    build c -r "'a-lib'" -o "'b < 2'"  # libgudev

    msgn "Upgrade"
    try_install a "a-2,a-lib-2,c-1" "a-1,a-lib-1,b-1"
}

buildUpgradeOrphanRepos() {
    build_installed a-foo -r "'a-lib = 1'" -p "FOO"
    build_installed a-lib
    build_installed b -r "FOO"

    build a-foo 2-2 -r "'a-lib = 2'" -o "a-bar" -p "FOO"
    build a-bar 2-2 -r "'a-lib = 2'" -o "a-foo"
    build a-lib 2-2
}

# orphaned b should be upgraded as b-2-2 resolves missed FOO
testUpgradeOrphanIfItResolvesReq() {
    msgn "Preparing repositories..."
    buildUpgradeOrphanRepos
    build b 2-2

    msgn "Upgrade"
    try_install a-bar "a-bar-2,a-lib-2,b-2" "a-foo-1,a-lib-1,b-1"
}

# orphaned b should not be upgraded as b-2-2 do not resolve missed FOO
testUpgradeOrphanNotIfItNotResolvesReq() {
    msgn "Preparing repositories..."
    buildUpgradeOrphanRepos
    build b 2-2 -r "FOO"
    build c 2-2 -p "FOO"

    msgn "Upgrade"
    try_install a-bar "a-bar-2,a-lib-2,c-2" "a-foo-1,a-lib-1"
}

# b should not be upgraded as in fact it is not an orphan
testUpgradeNotFakeOrphan() {
    msgn "Preparing repositories..."
    build_installed a 1-1
    build_installed b 1-1 -r "'a = 1.1'" # notice 1.1 not 1-1

    build a 2-2
    build b 2-2
    try_install a "a-2-2" "a-1-1"
}

# orphaned b should not be upgraded as b-2-2 do not resolve missed FOO
testUpgradeOrphanGiveUp() {
    msgn "Preparing repositories..."
    buildUpgradeOrphanRepos
    build b 2-2 -r "FOO"

    msgn "Upgrade"
    if is_verbose_mode; then
       $POLDEK_INSTALL -uvt a-bar
       msg "THE ERROR ABOVE (give up) is EXPECTED"
    fi
    $POLDEK_INSTALL -uvt a-bar | grep -q "error: FOO is required by installed b-1-1, give up"
    assertEquals "poldek should give up" "$?" "0"

}

# multiple 'b' alternatives to choose from
testUpgradeOrphanMultipleAvailable()
{
    build_installed a 1-1 -r "'a-libs = 1'"
    build_installed a-libs 1-1 -p "liba.so.1"
    build_installed b 1-1 -r "'a-libs = 1'"

    build a 2-1 -r "'a-libs = 2'"
    build a-libs 2-1 -r "'a-libs = 2'" -p "liba.so.2"
    build b 3 -r "'a-libs = 2'"

    build a 2-2 -r "'a-libs = 2'"
    build a-libs 2-2 -p "liba.so.2"
    build b 2 -r "'a-libs = 2'" -r "'c'" -r "d"
    build c
    build d

    # b-3-1 should be choosen as it's newer and requires less
    try_install a "a-2-2,a-libs-2-2,b-3-1" "a-1-1,a-libs-1-1,b-1-1"

    # rebuild b-3-1 with req liba.so.1
    build b 3 -r "'a-libs = 2'" -r "a-libs" -r "liba.so.1"

    # b-2-1 should be choosen => a-libs-1-1 is beeing upgraded to 2-2 and
    # liba.so.1 will not be available anymore
    try_install a "a-2-2,a-libs-2-2,b-2-1,c-1-1,d-1-1" "a-1-1,a-libs-1-1,b-1-1"

}

# alternatives suggested by noarch packages should be scored by rpmArchScore
# https://bugs.pld-linux.org/show_bug.cgi?id=127
testMultilibSuggestedByNoarchShouldUseArchScore() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    build n 1-1 -a "noarch" -s "a"
    for i in i686 x86_64; do
        build a 1-1 -a $i -f "/hello.$i"
    done
    POLDEK_TESTING_WITH_SUGGESTS="all" # choose all suggested packages
    export POLDEK_TESTING_WITH_SUGGESTS
    arch=$(uname -m)
    try_install_with_ask_allowed n "n-1-1.noarch,a-1-1.${arch}"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
    POLDEK_TESTING_WITH_SUGGESTS=""
}

# https://bugs.pld-linux.org/show_bug.cgi?id=117
testMultilibCandidatesAssertion() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    i=i686
    build a 2-2 -a $i -r "'a-misc = 2-2'" -f "/hello.$i"
    build a-misc 2-2 -a $i -r "'a = 2-2'" -f "/sbin/hello.$i"

    i=x86_64
    build2 a 2-2 -a $i -r "'a-misc = 2-2'" -f "/hello.$i"
    build2 a-misc 2-2 -a $i -r "'a = 2-2'" -f "/sbin/hello.$i"

    for i in i686 x86_64; do
        build_installed a 1-1 -a $i -f "/hello.$i"
        build_installed a-misc 1-1 -a $i -r "'a = 1-1'" -f "/sbin/hello.$i"
    done
    try_install_with_ask_allowed a-2-2.x86_64 \
                                 "a-2-2.x86_64,a-misc-2-2.x86_64" \
                                 "a-1-1.x86_64,a-misc-1-1.x86_64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

# https://bugs.pld-linux.org/show_bug.cgi?id=143
testMultilibDifferentArchSameColor() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    arch=amd64
    build_installed a 1-1 -a $arch -f "/hello.x86_64"
    build_installed a-misc 1-1 -a $arch -r "'a = 1-1'" -f "/bin/hello.x86_64"

    arch=x86_64
    build a 2-2 -a $arch -f "/hello.x86_64"
    build a-misc 2-2 -a $arch -f "/sbin/hello.x86_64"

    try_install a-2-2.$arch "a-2-2.x86_64,a-misc-2-2.x86_64" "a-1-1.amd64,a-misc-1-1.amd64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

#https://bugs.pld-linux.org/show_bug.cgi?id=143#c7
testMultilibDifferentArchNoColor() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    arch=amd64
    build_installed a 1-1 -a $arch -f "/hello.x86_64"
    build_installed a-misc 1-1 -a $arch -r "'a = 1-1'" -f "/bin/hello.x86_64"
    build_installed a-devel 1-1 -a $arch -r "'a = 1-1'" -f "/bin/a.h"

    arch=x86_64
    build a 2-2 -a $arch -f "/hello.x86_64"
    build a-misc 2-2 -a $arch -f "/sbin/hello.x86_64"
    build a-devel 2-2 -a $arch -r "'a = 2-2'" -f "/bin/aa.h"
    build a-devel 2-2 -a athlon -r "'a = 2-2'" -f "/bin/aaa.h"

    # arch choice of a-devel dependends on environment (rpm/platform)
    try_install a-2-2.$arch "a-2-2.x86_64,a-misc-2-2.x86_64,a-devel-2-2" "a-1-1.amd64,a-misc-1-1.amd64,a-devel-1-1.amd64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

# XXX: fails with rpmorg, i686 and x86_64 has the same color=1??
XXXtestMultilibNoSuccesor() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    arch=x86_64
    build_installed a 1-1 -a $arch -f "/hello.$arch"
    build_installed a-misc 1-1 -a $arch -r "'a = 1-1'" -f "/bin/hello.$arch"
    build_installed a-devel 1-1 -a $arch -r "'a = 1-1'" -f "/sbin/hello.$arch"

    build a 2-2 -a $arch -f "/hello.$arch"
    build a-misc 2-2 -a $arch -f "/sbin/hello.$arch"
    build a-devel 2-2 -a $arch -r "'a = 2-2'" -f "/bin/hello.i686"
    build a-devel 2-2 -a i686 -r "'a = 2-2'" -f "/bin/hello.i686"

    if is_verbose_mode; then
       $POLDEK_INSTALL -uvt a-2-2.$arch
       msg "THE ERROR ABOVE (a = 1-1 is required by installed) is EXPECTED"
    fi
    $POLDEK_INSTALL -uvt a-2-2.$arch | grep -q "error: a = 1-1 is required by installed a-devel-1-1.x86_64"
    assertEquals "poldek should fail" "$?" "0"

    nerrors=$($POLDEK_INSTALL -uvt a-2-2.$arch | grep "^error: " | wc -l)
    assertEquals "poldek should fail with 2 error:'s" "$nerrors" "2"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}


# https://bugs.launchpad.net/poldek/+bug/299685
# poldek should allow any color -> no-color and no-color -> color upgrades
testMultilibNoColorDiffrentArchUpgrade() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    build_installed a 1-1 -a x86_64 -f "/hello.x86_64"
    build a 2-2 -a noarch -f "/hello.sh"
    try_install a-2-2.noarch "a-2-2.noarch" "a-1-1.x86_64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}

# same https://bugs.launchpad.net/poldek/+bug/299685
testMultilibNoColorToColorUpgrade() {
    ORIG_POLDEK_INSTALL="$POLDEK_INSTALL"
    POLDEK_INSTALL="$POLDEK_INSTALL -Omultilib=1"

    msgn "Preparing repositories..."
    build_installed a 1-1 -a x86_64 -f "/hello.sh"
    build a 2-2 -a amd64 -f "/hello.x86_64"
    try_install a-2-2.amd64 "a-2-2.amd64" "a-1-1.x86_64"
    POLDEK_INSTALL="$ORIG_POLDEK_INSTALL"
}


# Should score orphan successors and choose best fit
testOrhpanSuccessorScore() {
    msgn "Preparing repositories..."
    build_installed a 1.0-1
    build_installed a-tools 1.0-1 -r "'a = 1.0'"

    build a 1.5-1
    build a-tools 1.5-1 -r "'a = 1.5'"

    build a 2.0-1
    build a-tools 2.0-1 -r "'a = 2.0'"


    try_install a-1.5-1 "a-1.5-1,a-tools-1.5-1" "a-1.0-1,a-tools-1.0-1"
}

testUpgradeMultipleInstalledGiveUp() {
    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

    is_verbose_mode && $POLDEK_INSTALL -uvt a

    typeset out=$($POLDEK_INSTALL -uvt a)
    #[ $? -eq 0 ] || fail "$POLDEK_INSTALL $cmd failed"
    echo $out | grep -q 'error' || fail "unexpected success (missing 'error')"
    echo $out | grep 'error' | grep -q 'give up' || fail "unexpected success (missing 'give up')"
}

# https://github.com/poldek-pm/poldek/issues/5
testUpgradeMultipleAvailable() {
    msgn "Preparing repositories..."
    build_installed mtools 4.0.23-1

    build mtools 4.0.24-1
    build mtools 4.0.24-2

    try_install mtools "mtools-4.0.24-2" "mtools-4.0.23-1"
}

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

    POLDEK_INSTALL="$POLDEK_INSTALL -Oupgrade_multiple_instances=y"
    try_install a "a-1.1.1k-1" "a-1.1.1j-1"
}

# https://github.com/poldek-pm/poldek/issues/15
# https://github.com/poldek-pm/poldek/issues/24
testMultilibCrash() {
    msgn "Preparing repositories..."
    build_installed a 1
    build_installed b 1 -r "'a = 1'"
    build_installed c 1 -r "'a = 1'"

    build b 2 -r "'a > 2'"
    build c 2 -r "'a > 2'" -r "aa"

    build a 4 -c "'c >= 2'"
    build a 3 -p "aa"

    # a) simulate score a-3-1 down
    # b) a-4 winning, but is's conflicted, and
    # c) removing winning a-4 from pool causes crash
    export POLDEK_TESTING_SIMULATE_MULTILIB_CRASH="a-3-1"
    try_install c "a-3,b,c"
    unset POLDEK_TESTING_SIMULATE_MULTILIB_CRASH
}


# https://github.com/poldek-pm/poldek/issues/13
# trying to reproduce this bug (muti set upgrade), unfortunately it "works for me"
testUpgradeMultiset() {
    build_installed coreutils 1 -r "'setup >= 1'"
    build_installed setup 1

    build_installed dirmngr 1 -r "'gnupg2-common = 1'"
    build_installed gnupg2-common 1
    build_installed gnupg-agent 1 -r "'gnupg2-common = 1'"
    build_installed gnupg-smime 1 -r "'gnupg2-common = 1'"
    build_installed gnupg2 1 -r "'gnupg2-common = 1'"

    build coreutils 2 -r "'setup >= 2'"
    build setup 2
    build dirmngr 2 -r "'gnupg2-common = 2'"
    build gnupg2-common 2
    build gnupg-agent 2 -r "'gnupg2-common = 2'"
    build gnupg-smime 2 -r "'gnupg2-common = 2'"
    build gnupg2 2 -r "'gnupg2-common = 2'"

    try_install "coreutils dirmngr" "setup-2,coreutils-2,dirmngr-2,gnupg2-common-2,gnupg-agent-2,gnupg-smime-2,gnupg2-2"
}

testUpgradeMultisetMultiVersions() {
    build_installed coreutils 1 -r "'setup >= 1'"
    build_installed setup 1

    build_installed dirmngr 1 -r "'gnupg2-common = 1'"
    build_installed gnupg2-common 1
    build_installed gnupg-agent 1 -r "'gnupg2-common = 1'"
    build_installed gnupg-smime 1 -r "'gnupg2-common = 1'"
    build_installed gnupg2 1 -r "'gnupg2-common = 1'"

    build coreutils 2 -r "'setup >= 2'"
    build setup 2

    build dirmngr 2 -r "'gnupg2-common = 2'"
    build gnupg2-common 2
    build gnupg-agent 2 -r "'gnupg2-common = 2'"
    build gnupg-smime 2 -r "'gnupg2-common = 2'"
    build gnupg2 2 -r "'gnupg2-common = 2'"

    build dirmngr 3 -r "'gnupg2-common = 3'"
    build gnupg2-common 3
    build gnupg-agent 3 -r "'gnupg2-common = 3'"
    build gnupg-smime 3 -r "'gnupg2-common = 3'"
    build gnupg2 3 -r "'gnupg2-common = 3'"

    build dirmngr 4 -r "'gnupg2-common = 4'"
    build gnupg2-common 4
    build gnupg-agent 4 -r "'gnupg2-common = 4'"
    build gnupg-smime 4 -r "'gnupg2-common = 4'"
    build gnupg2 4 -r "'gnupg2-common = 4'"

    try_install "coreutils dirmngr" "setup-2,coreutils-2,dirmngr-4,gnupg2-common-4,gnupg-agent-4,gnupg-smime-4,gnupg2-4"
}


testChooseRightVersion() {
    msgn "Preparing repositories..."
    build a 1-1
    build a-devel 1-1 -r "'a = 1'"
    build a-static 1-1 -r "'a-devel = 1'"
    build a 1-2
    build a-devel 1-2 -r "'a = 1'"
    build a-static 1-2 -r "'a-devel = 1'"

    msgn "1-2"
    try_install a-static-1-2 "a-1-2,a-devel-1-2,a-static-1-2" ""

    msgn "1-1"
    try_install a-static-1-1 "a-1-1,a-devel-1-1,a-static-1-1" ""
}

testChooseRightVersionB() {
    msgn "Preparing repositories..."
    build a 1-1
    build a-devel 1-1 -r "'a = 1'"
    build a-static 1-1 -r "'a-devel = 1'"
    build a 1-2
    build a-devel 1-2 -r "'a = 1'"
    build a-static 1-2 -r "'a-devel = 1'"
    build b 1-1 -p "'a = 1'"

    try_install_with_ask_allowed a-static-1-1 "a-1-1,a-devel-1-1,a-static-1-1" ""
}

# https://bugs.launchpad.net/poldek/+bug/1722104
testChooseMoreAccurateOrphanReq() {
    msgn "Preparing repositories..."
    build_installed a 1-1 -p "liba.so.1"
    build_installed b 1-1 -r "liba.so.1"

    build a 2-1 -p "liba.so.2"
    build a 2-2 -p "liba.so.2"
    build b 2-2 -r "liba.so.2" -r "'a = 2-2'"

    msgn "Upgrade"
    try_install b "a-2-2,b-2-2" "a-1-1,b-1-1"
}

testRedundantSuccessorReqs() {
    msgn "Preparing repositories..."
    build_installed a 2-1
    build_installed b 2-1  -r "'a = 2-1'" -r "'a >= 1-1'" -r "a" -r "'a > 1'"

    build a 2-2
    build b 2-2 -r "'a >= 1-1'" -r "'a = 2-2'"

    msgn "Upgrade"
    try_install a "a-2-2,b-2-2" "a-2-1,b-2-1"
}

testCaplookup() {
    msgn "Preparing repositories..."
    build a -p "foo"
    build b -p "foo"

    msgn "install foo"
    try_install_package "dir" "-uv --caplookup" "foo" "a"
}


testUninstall() {
    msgn "Preparing repositories..."
    build_installed a 1-1
    build_installed a-devel 1-1 -r "'a = 1'"

    msgn "Uninstall a"
    try_uninstall a "a-1-1,a-devel-1-1"
}

testUninstallGreedy() {
    msgn "Preparing repositories..."
    build_installed d 1-1       # to prevent sh from uninstalling
    build_installed c 1-1
    build_installed b 1-1 -r "'c = 1'"
    build_installed a 1-1 -r "'b = 1'"
    build_installed a-devel 1-1 -r "'a = 1'"

    msgn "--greedy"
    try_uninstall_package "dir" "-evt --greedy" a "a-1-1,a-devel-1-1,b-1-1"

    msgn "-g"
    try_uninstall_package "dir" -evtg  a "a-1-1,a-devel-1-1,b-1-1"

    msgn "--greedy=2"
    try_uninstall_package "dir" "-evt --greedy=2" a "a-1-1,a-devel-1-1,b-1-1,c-1-1"

    msgn "-gg"
    try_uninstall_package "dir" "-evtgg" a "a-1-1,a-devel-1-1,b-1-1,c-1-1"
}

# TODO
xtestUninstallHold() {
    msgn "Preparing repositories..."
    build_installed a 1-1
    build_installed a-devel 1-1 -r "'a = 1'"

    msgn "Uninstall a"
    try_uninstall a "a-1-1,a-devel-1-1"
}



. ./sh/lib/shunit2
