do not edit — generated by btf.
git.druid.rocksindexdruid520mptest/suites/hooks.sh

test/suites/hooks.sh


# suite: HOOKS_DIR/<phase>/hooks.conf's IF_USE/AFTER pipeline, the custom
# $MP_HOOK trigger's reserved-name guard, and per-sysroot hook/mpx.conf
# isolation (both a phase-boundary hook and a $MP_HOOK-triggered one, run
# by the separate mp.hook process, must resolve against the active
# sysroot, never silently fall back to the default root's).
 
# hooks.conf: IF_USE gating + AFTER reordering on a HOOKS_DIR/<phase>
# file group, including a large (30-item) pipeline with a diamond
# dependency among the hooks.
test_hooks_conf_pipeline() {
	t_begin "hooks_conf_pipeline"
	reset_state
	mkdir -p "$WD/hooks/rt11step"
	i=1
	while [ "$i" -le 30 ]; do
		n=$(printf '%02d' "$i")
		# $MP_PREFIX (single-quoted so IT expands inside the generated
		# hook script at hook-run time, not here) -- these hooks fire via
		# "$MP_HOOK rt11step" from inside rt11test's own install: phase,
		# which mpx sandboxes by default (see src/sandbox.c: root read-
		# only except the stage dir and the prefix), so /tmp isn't
		# actually writable from in there.
		printf '#!/bin/sh\necho h%s >> $MP_PREFIX/rt11.log\n' "$n" > "$WD/hooks/rt11step/h$n"
		chmod +x "$WD/hooks/rt11step/h$n"
		i=$((i + 1))
	done
	cat > "$WD/hooks/rt11step/hooks.conf" <<'EOF'
h10:
	AFTER=h08 h09
 
h08:
	AFTER=h07
 
h09:
	AFTER=h07
 
h25:
	IF_USE=rt11nonexistentflag
EOF
	mkport rt11test <<'EOF'
pkg_name="rt11test"
pkg_ver="1.0"
install:
	$MP_HOOK rt11step
	touch $MP_PREFIX/rt11test-installed
remove:
	rm -f $MP_PREFIX/rt11test-installed
EOF
	rm -f "$MP_PREFIX/rt11.log"
	mp install rt11test >/tmp/rt11.out 2>&1
	log=$(cat "$MP_PREFIX/rt11.log" 2>/dev/null)
	count=$(wc -l < "$MP_PREFIX/rt11.log" 2>/dev/null || echo 0)
	rm -rf "$WD/hooks/rt11step" "$MP_PREFIX/rt11.log"
	if [ "$count" -ne 29 ]; then t_fail "$CUR_TEST (expected 29 hooks ran, got $count)"; return; fi
	# h07 must appear before both h08 and h09, both before h10.
	l07=$(echo "$log" | grep -n '^h07$' | cut -d: -f1)
	l08=$(echo "$log" | grep -n '^h08$' | cut -d: -f1)
	l09=$(echo "$log" | grep -n '^h09$' | cut -d: -f1)
	l10=$(echo "$log" | grep -n '^h10$' | cut -d: -f1)
	if [ "$l07" -ge "$l08" ] || [ "$l07" -ge "$l09" ] || [ "$l08" -ge "$l10" ] || [ "$l09" -ge "$l10" ]; then
		t_fail "$CUR_TEST (diamond ordering wrong: h07=$l07 h08=$l08 h09=$l09 h10=$l10)"
		return
	fi
	t_pass
}
 
# custom hook trigger: a phase script firing $MP_HOOK with a reserved
# built-in lifecycle name must be rejected, not silently double-fire it.
test_custom_hook_reserved_name() {
	t_begin "custom_hook_reserved_name"
	reset_state
	out=$(MP_PKG=rt14test "$(dirname "$MP_BIN")/mp.hook" pre_install 2>&1)
	rc=$?
	assert_exit_nonzero "$rc" "$CUR_TEST" || return
	assert_contains "$out" "reserved" "$CUR_TEST" || return
	t_pass
}
 
# with_sysroot_scope must swap HOOKSDIR too, not just WD/DBFILE/MANDIR/
# INSTPREFIX -- a phase-boundary hook and a custom $MP_HOOK-triggered one
# (a separate process, propagated via MP_SYSROOT -> --sysroot=) must both
# resolve against the sysroot's own hooks dir, never the default root's.
test_sysroot_hooks_isolation() {
	t_begin "sysroot_hooks_isolation"
	reset_state
	mkdir -p /usr/ports/sysroots
	echo 'MP_PREFIX=/usr/local-rt15-sysroot' > /usr/ports/sysroots/rt15root.conf
	rm -rf /usr/local-rt15-sysroot "$WD/sysroots/rt15root"
	mkdir -p /usr/local-rt15-sysroot
	mkdir -p "$WD/sysroots/rt15root/hooks/post_install" "$WD/sysroots/rt15root/hooks/rt15custom"
	mkdir -p "$WD/hooks/post_install"
	# $MP_PREFIX, not /tmp: rt15custom fires via "$MP_HOOK rt15custom"
	# from inside rt15test's own install: phase, which mpx sandboxes by
	# default (root read-only except the stage dir and the prefix, see
	# src/sandbox.c) -- /tmp isn't actually writable from in there. the
	# two real pre_/post_* lifecycle hooks below run unsandboxed (a
	# direct Perl system() in mplib::hooks::run_hook, never through mpx),
	# so /tmp would work fine for them alone, but landing every marker in
	# the one file this test already reads back keeps the assertions
	# below simple regardless.
	cat > "$WD/hooks/post_install/notify" <<'EOF'
#!/bin/sh
echo DEFAULT_FIRED >> $MP_PREFIX/rt15.log
EOF
	cat > "$WD/sysroots/rt15root/hooks/post_install/notify" <<'EOF'
#!/bin/sh
echo SYSROOT_FIRED >> $MP_PREFIX/rt15.log
EOF
	cat > "$WD/sysroots/rt15root/hooks/rt15custom/notify" <<'EOF'
#!/bin/sh
echo SYSROOT_CUSTOM_FIRED >> $MP_PREFIX/rt15.log
EOF
	chmod +x "$WD/hooks/post_install/notify" "$WD/sysroots/rt15root/hooks/post_install/notify" "$WD/sysroots/rt15root/hooks/rt15custom/notify"
	mkport rt15test <<'EOF'
pkg_name="rt15test"
pkg_ver="1.0"
install:
	$MP_HOOK rt15custom
	touch $MP_PREFIX/rt15test-installed
remove:
	rm -f $MP_PREFIX/rt15test-installed
EOF
	cat >> "$CONF" <<'EOF'
rt15test:
	SYSROOT=rt15root
EOF
	rm -f /usr/local-rt15-sysroot/rt15.log
	mp install rt15test >/tmp/rt15.out 2>&1
	log=$(cat /usr/local-rt15-sysroot/rt15.log 2>/dev/null)
	rm -rf /usr/ports/sysroots/rt15root.conf /usr/local-rt15-sysroot
	assert_contains "$log" "SYSROOT_FIRED" "$CUR_TEST" || return
	assert_not_contains "$log" "DEFAULT_FIRED" "$CUR_TEST" || return
	assert_contains "$log" "SYSROOT_CUSTOM_FIRED" "$CUR_TEST" || return
	t_pass
}
 
# mpx.conf (the C-side backend config) must be per-sysroot too, not one
# global file shared by every sysroot and the default root alike -- a
# sysroot with its own mpx.conf (at $WD/mpx.conf, already the sysroot-
# swapped WD) gets its own TARGET_CC/JOBS/MICROARCH/SANDBOX overrides;
# the default root, and a sysroot with no override file of its own, both
# still fall back to the single global /etc/mpx.conf unchanged.
test_sysroot_mpxconf_isolation() {
	t_begin "sysroot_mpxconf_isolation"
	reset_state
	mkdir -p /usr/ports/sysroots
	echo 'MP_PREFIX=/usr/local-rt21-sysroot' > /usr/ports/sysroots/rt21root.conf
	rm -rf /usr/local-rt21-sysroot "$WD/sysroots/rt21root"
	mkdir -p /usr/local-rt21-sysroot "$WD/sysroots/rt21root"
	cat > "$WD/sysroots/rt21root/mpx.conf" <<'EOF'
rt21test:
	MICROARCH="rt21-sysroot-march"
EOF
	mkport rt21test <<'EOF'
pkg_name="rt21test"
pkg_ver="1.0"
install:
	echo "MPXCONF=[$MP_MPXCONF] MICROARCH=[$MP_MICROARCH]" > $MP_PREFIX/rt21-log
	touch $MP_PREFIX/rt21test-installed
remove:
	rm -f $MP_PREFIX/rt21test-installed $MP_PREFIX/rt21-log
EOF
	cat >> "$CONF" <<'EOF'
rt21test:
	SYSROOT=rt21root
EOF
	mp install rt21test >/tmp/rt21.out 2>&1
	log=$(cat /usr/local-rt21-sysroot/rt21-log 2>/dev/null)
	rm -rf /usr/ports/sysroots/rt21root.conf /usr/local-rt21-sysroot
	assert_contains "$log" "MICROARCH=[rt21-sysroot-march]" "$CUR_TEST" || return
	t_pass
}
 
# inline hook_pre_install= config (global and per-package) both fire,
# in that order, before the package's own install phase runs.
test_inline_config_hooks() {
	t_begin "inline_config_hooks"
	reset_state
	printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
	mkport rt33h <<'EOF'
pkg_name="rt33h"
pkg_ver="1.0"
install:
	touch $MP_PREFIX/rt33h-installed
remove:
	rm -f $MP_PREFIX/rt33h-installed
EOF
	cat >> "$CONF" <<'EOF'
hook_pre_install=touch /tmp/rt33-global.log
rt33h:
	hook_pre_install=touch /tmp/rt33-perpkg.log
EOF
	rm -f /tmp/rt33-global.log /tmp/rt33-perpkg.log
	mp install rt33h >/tmp/rt33.out 2>&1
	rc=$?
	assert_exit0 "$rc" "$CUR_TEST" || return
	assert_file_exists /tmp/rt33-global.log "$CUR_TEST" || return
	assert_file_exists /tmp/rt33-perpkg.log "$CUR_TEST" || return
	assert_file_exists "$MP_PREFIX/rt33h-installed" "$CUR_TEST" || return
	rm -f /tmp/rt33-global.log /tmp/rt33-perpkg.log
	t_pass
}
 
# a hook exiting nonzero vetoes the whole install: nothing gets staged
# or installed, and the failure names the hook.
test_hook_failure_vetoes() {
	t_begin "hook_failure_vetoes"
	reset_state
	printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
	mkport rt34h <<'EOF'
pkg_name="rt34h"
pkg_ver="1.0"
install:
	touch $MP_PREFIX/rt34h-installed
remove:
	rm -f $MP_PREFIX/rt34h-installed
EOF
	echo 'hook_pre_install=false' >> "$CONF"
	out=$(mp install rt34h 2>&1)
	rc=$?
	assert_exit_nonzero "$rc" "$CUR_TEST" || return
	assert_contains "$out" "hook failed" "$CUR_TEST" || return
	assert_file_absent "$MP_PREFIX/rt34h-installed" "$CUR_TEST" || return
	assert_file_absent "$WD/rt34h" "$CUR_TEST" || return
	t_pass
}
 
# a file-conflict install rejection fires the on_fail hook (best-effort
# alerting point) alongside the loud failure.
test_on_fail_hook_fires() {
	t_begin "on_fail_hook_fires"
	reset_state
	printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
	echo 'hook_on_fail=touch /tmp/rt35-onfail.log' >> "$CONF"
	mkport rt35a <<'EOF'
pkg_name="rt35a"
pkg_ver="1.0"
install:
	mkdir -p $MP_PREFIX/share/rt35collide
	echo A > $MP_PREFIX/share/rt35collide/same.txt
remove:
	rm -rf $MP_PREFIX/share/rt35collide
EOF
	mkport rt35b <<'EOF'
pkg_name="rt35b"
pkg_ver="1.0"
install:
	mkdir -p $MP_PREFIX/share/rt35collide
	echo B > $MP_PREFIX/share/rt35collide/same.txt
remove:
	rm -rf $MP_PREFIX/share/rt35collide
EOF
	rm -f /tmp/rt35-onfail.log
	mp install rt35a >/tmp/rt35.out 2>&1
	out=$(mp install rt35b 2>&1)
	rc=$?
	assert_exit_nonzero "$rc" "$CUR_TEST" || return
	assert_contains "$out" "conflicts with rt35a on installed files" "$CUR_TEST" || return
	assert_file_exists /tmp/rt35-onfail.log "$CUR_TEST" || return
	rm -f /tmp/rt35-onfail.log
	t_pass
}
 
# one hook-source scenario: a given phase fires from the given source
# (global config, per-package config, HOOKS_DIR file) and, for a
# "fails" case, vetoes the install.
hook_src_case() {
	# $1 name, $2 phase, $3 source (global/perpk/hdir), $4 fails (0/1)
	t_begin "$1"
	reset_state
	printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
	mkport "${1}p" <<EOF
pkg_name="${1}p"
pkg_ver="1.0"
build:
	:
install:
	touch \$MP_PREFIX/${1}p-installed
remove:
	rm -f \$MP_PREFIX/${1}p-installed
EOF
	case "$3" in
		global) printf 'hook_%s=touch /tmp/%s-global.log\n' "$2" "$1" >> "$CONF" ;;
		perpk)  printf '%sp:\n\thook_%s=touch /tmp/%s-perpk.log\n' "$1" "$2" "$1" >> "$CONF" ;;
		hdir)   mkdir -p "$WD/hooks/$2"
			printf '#!/bin/sh\ntouch /tmp/%s-hdir.log\n' "$1" > "$WD/hooks/$2/fire"
			chmod +x "$WD/hooks/$2/fire" ;;
	esac
	rm -f "/tmp/$1-global.log" "/tmp/$1-perpk.log" "/tmp/$1-hdir.log"
	if [ "$4" = "1" ]; then
		# a global failing hook runs FIRST (before the per-package or
		# directory one), so the later sources never fire at all.
		printf 'hook_%s=false\n' "$2" >> "$CONF"
	fi
	out=$(mp install "${1}p" 2>&1)
	rc=$?
	if [ "$4" = "1" ]; then
		assert_exit_nonzero "$rc" "$CUR_TEST" || return
		assert_contains "$out" "hook failed" "$CUR_TEST" || return
		assert_file_absent "/tmp/$1-global.log" "$CUR_TEST" || return
		assert_file_absent "/tmp/$1-perpk.log" "$CUR_TEST" || return
		assert_file_absent "/tmp/$1-hdir.log" "$CUR_TEST" || return
		t_pass
		return
	fi
	assert_exit0 "$rc" "$CUR_TEST" || return
	# pre_/post_remove hooks only exist in the remove lifecycle.
	if [ "$2" = "post_remove" ] || [ "$2" = "pre_remove" ]; then
		mp remove --force "${1}p" >>/tmp/"$1".out 2>&1
	fi
	case "$3" in
		global) assert_file_exists "/tmp/$1-global.log" "$CUR_TEST" || return ;;
		perpk)  assert_file_exists "/tmp/$1-perpk.log" "$CUR_TEST" || return ;;
		hdir)   assert_file_exists "/tmp/$1-hdir.log" "$CUR_TEST" || return ;;
	esac
	rm -f "/tmp/$1-global.log" "/tmp/$1-perpk.log" "/tmp/$1-hdir.log"
	t_pass
}
 
# HOOKS_<phase>=: a manual override layered on top of the IF_USE-
# computed hooks.conf baseline, same +/- delta convention as USE=/
# "mp use" -- global "-name" disables one hook without touching its
# file or hooks.conf, per-package "+name" forces one back on despite
# its own IF_USE, and a bare list is a complete, explicit override
# regardless of IF_USE.
test_hooks_config_override() {
	t_begin "hooks_config_override"
	reset_state
	printf 'GLOBAL_DEPS=" "\n' >> "$CONF"
	mkdir -p "$WD/hooks/rt50step"
	for n in h1 h2 h3; do
		printf '#!/bin/sh\necho %s >> $MP_PREFIX/rt50.log\n' "$n" > "$WD/hooks/rt50step/$n"
		chmod +x "$WD/hooks/rt50step/$n"
	done
	cat > "$WD/hooks/rt50step/hooks.conf" <<'EOF'
h3:
	IF_USE=rt50neverset
EOF
	mkport rt50p <<'EOF'
pkg_name="rt50p"
pkg_ver="1.0"
install:
	$MP_HOOK rt50step
	touch $MP_PREFIX/rt50p-installed
remove:
	rm -f $MP_PREFIX/rt50p-installed
EOF
 
	# baseline, no HOOKS_ override at all: h3's own IF_USE keeps it off.
	rm -f "$MP_PREFIX/rt50.log"
	mp install rt50p >/tmp/rt50.out 2>&1
	log=$(tr '\n' ',' < "$MP_PREFIX/rt50.log" 2>/dev/null)
	mp remove --force rt50p >/dev/null 2>&1
	assert_contains "$log" "h1," "$CUR_TEST (baseline h1)" || return
	assert_contains "$log" "h2," "$CUR_TEST (baseline h2)" || return
	assert_not_contains "$log" "h3" "$CUR_TEST (baseline h3 IF_USE-gated off)" || return
 
	# global delta: -h2 removes it from the baseline, h1 unaffected.
	echo 'HOOKS_rt50step=-h2' >> "$CONF"
	rm -f "$MP_PREFIX/rt50.log"
	mp install rt50p >/tmp/rt50.out 2>&1
	log=$(tr '\n' ',' < "$MP_PREFIX/rt50.log" 2>/dev/null)
	mp remove --force rt50p >/dev/null 2>&1
	assert_contains "$log" "h1," "$CUR_TEST (global delta keeps h1)" || return
	assert_not_contains "$log" "h2" "$CUR_TEST (global delta -h2)" || return
 
	# per-package delta wins over the still-present global line, and
	# +h3 forces it on despite its own IF_USE.
	cat >> "$CONF" <<'EOF'
rt50p:
	HOOKS_rt50step=+h3
EOF
	rm -f "$MP_PREFIX/rt50.log"
	mp install rt50p >/tmp/rt50.out 2>&1
	log=$(tr '\n' ',' < "$MP_PREFIX/rt50.log" 2>/dev/null)
	mp remove --force rt50p >/dev/null 2>&1
	assert_contains "$log" "h1," "$CUR_TEST (perpkg delta h1)" || return
	assert_contains "$log" "h2," "$CUR_TEST (perpkg delta h2)" || return
	assert_contains "$log" "h3," "$CUR_TEST (perpkg delta forces h3 on)" || return
 
	# a bare list (no +/-) is a complete, explicit override -- only h2,
	# even though h1 has no IF_USE condition at all.
	cat >> "$CONF" <<'EOF'
rt50p:
	HOOKS_rt50step=h2
EOF
	rm -f "$MP_PREFIX/rt50.log"
	mp install rt50p >/tmp/rt50.out 2>&1
	log=$(tr '\n' ',' < "$MP_PREFIX/rt50.log" 2>/dev/null)
	mp remove --force rt50p >/dev/null 2>&1
	assert_contains "$log" "h2," "$CUR_TEST (bare list keeps h2)" || return
	assert_not_contains "$log" "h1" "$CUR_TEST (bare list excludes h1)" || return
	assert_not_contains "$log" "h3" "$CUR_TEST (bare list excludes h3)" || return
 
	rm -rf "$WD/hooks/rt50step" "$MP_PREFIX/rt50.log"
	t_pass
}
 
run_hook_source_matrix() {
	hook_src_case hsrc_global_pre_install pre_install global 0
	hook_src_case hsrc_perpk_post_install post_install perpk 0
	hook_src_case hsrc_hdir_pre_build pre_build hdir 0
	hook_src_case hsrc_global_post_remove post_remove global 0
	hook_src_case hsrc_global_pre_install_fails pre_install global 1
	hook_src_case hsrc_perpk_post_install_fails post_install perpk 1
}
 
run_hooks_suite() {
	test_hooks_conf_pipeline
	test_custom_hook_reserved_name
	test_sysroot_hooks_isolation
	test_sysroot_mpxconf_isolation
	test_inline_config_hooks
	test_hook_failure_vetoes
	test_on_fail_hook_fires
	test_hooks_config_override
	run_hook_source_matrix
}
powered by btf.