| git.druid.rocks | index | druid520 | mp | test/ | suites/ | slots_advanced.sh |
test/suites/slots_advanced.sh
# suite: advanced slot machinery -- multi-axis slot backtracking (%tag
# pick across static + USE-composed axes), circular slot-shifted dep
# chains, microarch-specific compound slots, hook-induced slot changes,
# and USE-flag-axis slot coexistence.
# one backtracking scenario over a %tag with two same-name providers on
# different slot axes: installs $blocker (if any), applies $conf, then
# resolves a consumer and asserts which provider got picked.
bt_case() {
# $1 name, $2 conf lines, $3 blocker (or ""), $4 expected marker
t_begin "$1"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport "${1}block" <<EOF
pkg_name="${1}block"
pkg_ver="1.0"
install:
touch \$MP_PREFIX/${1}block-installed
remove:
rm -f \$MP_PREFIX/${1}block-installed
EOF
mkport "${1}p1" <<EOF
pkg_name="${1}p"
pkg_ver="1.0"
pkg_slot="12"
pkg_tags="${1}tag"
pkg_pref="10"
pkg_conflicts="${3}"
install:
touch \$MP_PREFIX/${1}p1-installed
remove:
rm -f \$MP_PREFIX/${1}p1-installed
EOF
mkport "${1}p2" <<EOF
pkg_name="${1}p"
pkg_ver="1.0"
pkg_slot="13"
pkg_tags="${1}tag"
pkg_pref="20"
install:
touch \$MP_PREFIX/${1}p2-installed
remove:
rm -f \$MP_PREFIX/${1}p2-installed
EOF
mkport "${1}need" <<EOF
pkg_name="${1}need"
pkg_ver="1.0"
pkg_deps="%${1}tag"
install:
touch \$MP_PREFIX/${1}need-installed
remove:
rm -f \$MP_PREFIX/${1}need-installed
EOF
if [ -n "$2" ]; then
printf '%s\n' "$2" >> "$CONF"
fi
if [ -n "$3" ]; then
mp install "$3" >/tmp/"$1".out 2>&1
fi
mp install "${1}need" >>/tmp/"$1".out 2>&1
rc=$?
if [ "$4" = "FAIL" ]; then
if [ "$rc" -eq 0 ]; then t_fail "$CUR_TEST (expected resolution failure, got success)"; return; fi
t_pass
return
fi
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/$4" "$CUR_TEST" || return
t_pass
}
run_backtrack_matrix() {
bt_case bt_clean_lowest_pref "" "" "${1}none" 2>/dev/null || true
# placeholder replaced below
}
# backtracking across static slot axes: lowest pref wins with no
# conflicts; a conflict on the lowest-pref axis moves the pick to the
# next axis.
test_backtrack_static_axis() {
bt_clean_lowest_pref
}
bt_clean_lowest_pref() {
t_begin "bt_clean_lowest_pref"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport btp1 <<'EOF'
pkg_name="btp"
pkg_ver="1.0"
pkg_slot="12"
pkg_tags="bttag"
pkg_pref="10"
install:
touch $MP_PREFIX/btp1-installed
remove:
rm -f $MP_PREFIX/btp1-installed
EOF
mkport btp2 <<'EOF'
pkg_name="btp"
pkg_ver="1.0"
pkg_slot="13"
pkg_tags="bttag"
pkg_pref="20"
install:
touch $MP_PREFIX/btp2-installed
remove:
rm -f $MP_PREFIX/btp2-installed
EOF
mkport btneed <<'EOF'
pkg_name="btneed"
pkg_ver="1.0"
pkg_deps="%bttag"
install:
touch $MP_PREFIX/btneed-installed
remove:
rm -f $MP_PREFIX/btneed-installed
EOF
mp install btneed >/tmp/bt.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/btp-12/btp1-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/btp-13/btp2-installed" "$CUR_TEST" || return
t_pass
}
test_backtrack_static_conflict() {
t_begin "backtrack_static_conflict"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport bx <<'EOF'
pkg_name="bx"
pkg_ver="1.0"
install:
touch $MP_PREFIX/bx-installed
remove:
rm -f $MP_PREFIX/bx-installed
EOF
mkport bxp1 <<'EOF'
pkg_name="bxp"
pkg_ver="1.0"
pkg_slot="12"
pkg_tags="bxtag"
pkg_pref="10"
pkg_conflicts="bx"
install:
touch $MP_PREFIX/bxp1-installed
remove:
rm -f $MP_PREFIX/bxp1-installed
EOF
mkport bxp2 <<'EOF'
pkg_name="bxp"
pkg_ver="1.0"
pkg_slot="13"
pkg_tags="bxtag"
pkg_pref="20"
install:
touch $MP_PREFIX/bxp2-installed
remove:
rm -f $MP_PREFIX/bxp2-installed
EOF
mkport bxneed <<'EOF'
pkg_name="bxneed"
pkg_ver="1.0"
pkg_deps="%bxtag"
install:
touch $MP_PREFIX/bxneed-installed
remove:
rm -f $MP_PREFIX/bxneed-installed
EOF
mp install bx >/tmp/bx.out 2>&1
mp install bxneed >>/tmp/bx.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/bxp-13/bxp2-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/bxp-12/bxp1-installed" "$CUR_TEST" || return
t_pass
}
# backtracking across a static+use-composed axis: the composed candidate
# (pkg_slot_use "ssl" enabled) conflicts, so the plain-static one wins.
test_backtrack_use_composed_axis() {
t_begin "backtrack_use_composed_axis"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport by <<'EOF'
pkg_name="by"
pkg_ver="1.0"
install:
touch $MP_PREFIX/by-installed
remove:
rm -f $MP_PREFIX/by-installed
EOF
mkport byp1 <<'EOF'
pkg_name="byp"
pkg_ver="1.0"
pkg_slot="12"
pkg_slot_use="ssl"
pkg_use="ssl"
pkg_tags="bytag"
pkg_pref="10"
pkg_conflicts="by"
install:
touch $MP_PREFIX/byp1-installed
remove:
rm -f $MP_PREFIX/byp1-installed
EOF
mkport byp2 <<'EOF'
pkg_name="byp2"
pkg_ver="1.0"
pkg_tags="bytag"
pkg_pref="20"
install:
touch $MP_PREFIX/byp2-installed
remove:
rm -f $MP_PREFIX/byp2-installed
EOF
mkport byneed <<'EOF'
pkg_name="byneed"
pkg_ver="1.0"
pkg_deps="%bytag"
install:
touch $MP_PREFIX/byneed-installed
remove:
rm -f $MP_PREFIX/byneed-installed
EOF
cat >> "$CONF" <<'EOF'
byp:
USE=ssl
EOF
mp install by >/tmp/by.out 2>&1
mp install byneed >>/tmp/by.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/byp2-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/byp-12-ssl/byp1-installed" "$CUR_TEST" || return
t_pass
}
# a masked candidate on the preferred axis is skipped just like a
# conflicting one, handing the pick to the next axis.
test_backtrack_masked_axis() {
t_begin "backtrack_masked_axis"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport bzp1 <<'EOF'
pkg_name="bzp"
pkg_ver="1.0"
pkg_slot="12"
pkg_tags="bztag"
pkg_pref="10"
install:
touch $MP_PREFIX/bzp1-installed
remove:
rm -f $MP_PREFIX/bzp1-installed
EOF
mkport bzp2 <<'EOF'
pkg_name="bzp"
pkg_ver="1.0"
pkg_slot="13"
pkg_tags="bztag"
pkg_pref="20"
install:
touch $MP_PREFIX/bzp2-installed
remove:
rm -f $MP_PREFIX/bzp2-installed
EOF
mkport bzneed <<'EOF'
pkg_name="bzneed"
pkg_ver="1.0"
pkg_deps="%bztag"
install:
touch $MP_PREFIX/bzneed-installed
remove:
rm -f $MP_PREFIX/bzneed-installed
EOF
cat >> "$CONF" <<'EOF'
bzp:12:
MASK=yes
EOF
mp install bzneed >/tmp/bz.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/bzp-13/bzp2-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/bzp-12/bzp1-installed" "$CUR_TEST" || return
t_pass
}
# a slot-shifted circular chain (A:1 -> B:1 -> A:2 -> B:2) is not a
# cycle at all: every canon is distinct, so the whole chain installs.
test_circular_slot_shifted_chain() {
t_begin "circular_slot_shifted_chain"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport cs-1 <<'EOF'
pkg_name="csa"
pkg_ver="1.0"
pkg_slot="1"
pkg_deps="csb:1"
install:
touch $MP_PREFIX/csa1-installed
remove:
rm -f $MP_PREFIX/csa1-installed
EOF
mkport cs-2 <<'EOF'
pkg_name="csa"
pkg_ver="1.0"
pkg_slot="2"
pkg_deps="csb:2"
install:
touch $MP_PREFIX/csa2-installed
remove:
rm -f $MP_PREFIX/csa2-installed
EOF
mkport csb-1 <<'EOF'
pkg_name="csb"
pkg_ver="1.0"
pkg_slot="1"
pkg_deps="csa:2"
install:
touch $MP_PREFIX/csb1-installed
remove:
rm -f $MP_PREFIX/csb1-installed
EOF
mkport csb-2 <<'EOF'
pkg_name="csb"
pkg_ver="1.0"
pkg_slot="2"
install:
touch $MP_PREFIX/csb2-installed
remove:
rm -f $MP_PREFIX/csb2-installed
EOF
mp install csa:1 >/tmp/cs.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/csa-1/csa1-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/csa-2/csa2-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/csb-1/csb1-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/csb-2/csb2-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
for k in csa:1 csa:2 csb:1 csb:2; do
assert_contains "$db" "$k" "$CUR_TEST" || return
done
t_pass
}
# the same names in the SAME slots are a true cycle and must fail loudly
# instead of hanging or half-installing.
test_circular_same_slot_fails() {
t_begin "circular_same_slot_fails"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport cya <<'EOF'
pkg_name="cya"
pkg_ver="1.0"
pkg_deps="cyb"
install:
touch $MP_PREFIX/cya-installed
remove:
rm -f $MP_PREFIX/cya-installed
EOF
mkport cyb <<'EOF'
pkg_name="cyb"
pkg_ver="1.0"
pkg_deps="cya"
install:
touch $MP_PREFIX/cyb-installed
remove:
rm -f $MP_PREFIX/cyb-installed
EOF
out=$(mp install cya 2>&1)
rc=$?
assert_exit_nonzero "$rc" "$CUR_TEST" || return
assert_contains "$out" "cycle" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/cya-installed" "$CUR_TEST" || return
t_pass
}
# microarch-specific slot composition: two static compound slots carrying
# different microarch suffixes coexist, and a consumer pinning the
# znver3 slot gets exactly that variant's prefix wired in.
test_microarch_slot_composition() {
t_begin "microarch_slot_composition"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport mc-12 <<'EOF'
pkg_name="mcp"
pkg_ver="12.0"
pkg_slot="12-znver2"
pkg_pref="10"
install:
touch $MP_PREFIX/mcp-znver2-installed
remove:
rm -f $MP_PREFIX/mcp-znver2-installed
EOF
mkport mc-13 <<'EOF'
pkg_name="mcp"
pkg_ver="12.0"
pkg_slot="12-znver3-O3"
pkg_pref="20"
install:
touch $MP_PREFIX/mcp-znver3-installed
remove:
rm -f $MP_PREFIX/mcp-znver3-installed
EOF
mkport mcneed <<'EOF'
pkg_name="mcneed"
pkg_ver="1.0"
pkg_deps="mcp:12-znver3-O3"
install:
echo "DEPLOG=[$MP_DEP_PREFIXES]" > $MP_PREFIX/mcneed-deplog
touch $MP_PREFIX/mcneed-installed
remove:
rm -f $MP_PREFIX/mcneed-installed $MP_PREFIX/mcneed-deplog
EOF
cat >> "$CONF" <<'EOF'
mcneed:
MICROARCH=znver3
EOF
mp install mcneed >/tmp/mc.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/mcp-12-znver3-O3/mcp-znver3-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/mcp-12-znver2/mcp-znver2-installed" "$CUR_TEST" || return
deplog=$(cat "$MP_PREFIX/mcneed-deplog" 2>/dev/null)
assert_contains "$deplog" "mcp-12-znver3-O3" "$CUR_TEST" || return
t_pass
}
# the per-package MICROARCH override reaches the build env as
# -march=<microarch> while a sibling package without the override sees
# none.
test_microarch_env_injection() {
t_begin "microarch_env_injection"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport mea <<'EOF'
pkg_name="mea"
pkg_ver="1.0"
install:
echo "MARCH=[$MICROARCH]" > $MP_PREFIX/mea-march
touch $MP_PREFIX/mea-installed
remove:
rm -f $MP_PREFIX/mea-installed $MP_PREFIX/mea-march
EOF
mkport meb <<'EOF'
pkg_name="meb"
pkg_ver="1.0"
install:
echo "MARCH=[$MICROARCH]" > $MP_PREFIX/meb-march
touch $MP_PREFIX/meb-installed
remove:
rm -f $MP_PREFIX/meb-installed $MP_PREFIX/meb-march
EOF
cat >> "$CONF" <<'EOF'
mea:
MICROARCH=znver3
EOF
mp install mea meb >/tmp/me.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
ma=$(cat "$MP_PREFIX/mea-march" 2>/dev/null)
mb=$(cat "$MP_PREFIX/meb-march" 2>/dev/null)
assert_contains "$ma" "MARCH=[znver3]" "$CUR_TEST" || return
assert_contains "$mb" "MARCH=[]" "$CUR_TEST" || return
t_pass
}
# a post_install hook can mutate another package's USE state via the mp
# sugar commands, so the NEXT install of that package lands in a newly
# composed slot.
test_hook_induced_slot_change() {
t_begin "hook_induced_slot_change"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport hoa <<'EOF'
pkg_name="hoa"
pkg_ver="1.0"
install:
touch $MP_PREFIX/hoa-installed
remove:
rm -f $MP_PREFIX/hoa-installed
EOF
mkport hob <<'EOF'
pkg_name="hob"
pkg_ver="1.0"
pkg_slot_use="v"
pkg_use="v"
install:
touch $MP_PREFIX/hob-installed
remove:
rm -f $MP_PREFIX/hob-installed
EOF
cat >> "$CONF" <<'EOF'
hook_post_install="/root/mpbuildtest/mp use hob +v"
EOF
mp install hob >/tmp/ho.out 2>&1
assert_file_exists "$MP_PREFIX/hob-installed" "$CUR_TEST" || return
mp install hoa >>/tmp/ho.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
mp install hob >>/tmp/ho.out 2>&1
assert_file_exists "$MP_PREFIX/hob-v/hob-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "hob" "$CUR_TEST" || return
assert_contains "$db" "hob:v" "$CUR_TEST" || return
t_pass
}
# a hook-induced HOLD blocks the very next install of the held package,
# proving hook state changes persist across invocations.
test_hook_induced_hold() {
t_begin "hook_induced_hold"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport hp_holder <<'EOF'
pkg_name="hp_holder"
pkg_ver="1.0"
install:
touch $MP_PREFIX/hp_holder-installed
remove:
rm -f $MP_PREFIX/hp_holder-installed
EOF
mkport hp_target <<'EOF'
pkg_name="hp_target"
pkg_ver="1.0"
install:
touch $MP_PREFIX/hp_target-installed
remove:
rm -f $MP_PREFIX/hp_target-installed
EOF
cat >> "$CONF" <<'EOF'
hook_post_install="/root/mpbuildtest/mp hold hp_target"
EOF
mp install hp_holder >/tmp/hp.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
out=$(mp install hp_target 2>&1)
assert_contains "$out" "held" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/hp_target-installed" "$CUR_TEST" || return
t_pass
}
# pkg_slot_use composition over multiple enabled flags: every subset of
# {ssl, lto} is a distinct, coexisting slot with its own prefix.
test_use_flag_axis_matrix() {
t_begin "use_flag_axis_matrix"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport uf <<'EOF'
pkg_name="uf"
pkg_ver="1.0"
pkg_slot_use="ssl lto"
pkg_use="ssl lto"
install:
touch $MP_PREFIX/uf-installed
remove:
rm -f $MP_PREFIX/uf-installed
EOF
mp use uf +ssl >/tmp/uf.out 2>&1
mp install uf >>/tmp/uf.out 2>&1
mp use uf +lto >>/tmp/uf.out 2>&1
mp install uf >>/tmp/uf.out 2>&1
mp use uf -ssl >>/tmp/uf.out 2>&1
mp install uf >>/tmp/uf.out 2>&1
assert_file_exists "$MP_PREFIX/uf-ssl/uf-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/uf-ssl-lto/uf-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/uf-lto/uf-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "uf:ssl" "$CUR_TEST" || return
assert_contains "$db" "uf:ssl-lto" "$CUR_TEST" || return
assert_contains "$db" "uf:lto" "$CUR_TEST" || return
t_pass
}
# a dep on a static+use-composed slot reference resolves to the composed
# canon and coexists with the un-composed slot of the same port.
test_static_use_combined_slot() {
t_begin "static_use_combined_slot"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport su <<'EOF'
pkg_name="su"
pkg_ver="1.0"
pkg_slot="12"
pkg_slot_use="ssl"
pkg_use="ssl"
install:
touch $MP_PREFIX/su-installed
remove:
rm -f $MP_PREFIX/su-installed
EOF
mkport suneed <<'EOF'
pkg_name="suneed"
pkg_ver="1.0"
pkg_deps="su:12-ssl"
install:
echo "DEPLOG=[$MP_DEP_PREFIXES]" > $MP_PREFIX/suneed-deplog
touch $MP_PREFIX/suneed-installed
remove:
rm -f $MP_PREFIX/suneed-installed $MP_PREFIX/suneed-deplog
EOF
cat >> "$CONF" <<'EOF'
su:
USE=ssl
EOF
mp install suneed >/tmp/su.out 2>&1
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/su-12-ssl/su-installed" "$CUR_TEST" || return
deplog=$(cat "$MP_PREFIX/suneed-deplog" 2>/dev/null)
assert_contains "$deplog" "su-12-ssl" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_contains "$db" "su:12-ssl" "$CUR_TEST" || return
t_pass
}
# two variants of one pkg_slot_use port are fully independent installs:
# removing one leaves the other's files and db entry alone.
test_variant_remove_independent() {
t_begin "variant_remove_independent"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport vr <<'EOF'
pkg_name="vr"
pkg_ver="1.0"
pkg_slot_use="v"
pkg_use="v"
install:
touch $MP_PREFIX/vr-installed
remove:
rm -f $MP_PREFIX/vr-installed
EOF
mp use vr +v >/tmp/vr.out 2>&1
mp install vr >>/tmp/vr.out 2>&1
mp use vr -v >>/tmp/vr.out 2>&1
mp install vr >>/tmp/vr.out 2>&1
assert_file_exists "$MP_PREFIX/vr-v/vr-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/vr-installed" "$CUR_TEST" || return
mp remove vr:v >>/tmp/vr.out 2>&1
assert_file_absent "$MP_PREFIX/vr-v/vr-installed" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/vr-installed" "$CUR_TEST" || return
db=$(cat "$WD/db")
assert_not_contains "$db" "vr:v" "$CUR_TEST" || return
assert_contains "$db" "vr 1.0" "$CUR_TEST" || return
t_pass
}
# a soft dep that would close a slot-shifted cycle is skipped while the
# hard part of the graph still installs.
test_slot_cycle_soft_edge_skipped() {
t_begin "slot_cycle_soft_edge_skipped"
reset_state
printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
mkport sca <<'EOF'
pkg_name="sca"
pkg_ver="1.0"
pkg_deps_soft="scb"
install:
touch $MP_PREFIX/sca-installed
remove:
rm -f $MP_PREFIX/sca-installed
EOF
mkport scb <<'EOF'
pkg_name="scb"
pkg_ver="1.0"
pkg_deps="sca"
install:
touch $MP_PREFIX/scb-installed
remove:
rm -f $MP_PREFIX/scb-installed
EOF
out=$(mp install sca 2>&1)
rc=$?
assert_exit0 "$rc" "$CUR_TEST" || return
assert_contains "$out" "skipping" "$CUR_TEST" || return
assert_file_exists "$MP_PREFIX/sca-installed" "$CUR_TEST" || return
assert_file_absent "$MP_PREFIX/scb-installed" "$CUR_TEST" || return
t_pass
}
run_slots_advanced_suite() {
bt_clean_lowest_pref
test_backtrack_static_conflict
test_backtrack_use_composed_axis
test_backtrack_masked_axis
test_circular_slot_shifted_chain
test_circular_same_slot_fails
test_microarch_slot_composition
test_microarch_env_injection
test_hook_induced_slot_change
test_hook_induced_hold
test_use_flag_axis_matrix
test_static_use_combined_slot
test_variant_remove_independent
test_slot_cycle_soft_edge_skipped
}