#!/bin/sh
set -e

TESTDIR="$(readlink -f "$(dirname "$0")")"
. "$TESTDIR/framework"

setupenvironment
configarchitecture 'amd64'

# Test that documented commands show command-specific help
# (Usage line mentions the command, no "Most used commands:" list)
check_command_help() {
	local cmd="$1"
	testsuccess apt "$cmd" --help
	cp -f rootdir/tmp/testsuccess.output "${cmd}-help.output"
	# Must have a Usage line mentioning the command name
	testsuccess grep "^Usage: apt \[options\] ${cmd}" "${cmd}-help.output"
	# Must NOT fall back to the generic command listing
	testfailure grep "Most used commands:" "${cmd}-help.output"
	# Both supported help syntaxes must produce identical output
	testsuccess apt help "$cmd"
	cp -f rootdir/tmp/testsuccess.output "${cmd}-help-command.output"
	testsuccess cmp "${cmd}-help.output" "${cmd}-help-command.output"
}

msggroup "Checking per-command help for documented commands"
for cmd in list search show install reinstall remove purge autoremove \
	   update upgrade full-upgrade satisfy why \
	   edit-sources modernize-sources; do
	check_command_help "$cmd"
done
msggroup

msggroup "Checking combined why and why-not help"
testsuccess apt why-not --help
cp -f rootdir/tmp/testsuccess.output why-not-help.output
testsuccess grep "^Usage: apt \[options\] why <package>" why-not-help.output
testsuccess grep "^       apt \[options\] why-not <package>" why-not-help.output
testfailure grep "Most used commands:" why-not-help.output

testsuccess apt help why-not
cp -f rootdir/tmp/testsuccess.output why-not-help-command.output
testsuccess cmp why-not-help.output why-not-help-command.output
msggroup

# Test that install/reinstall/remove/purge show the correct command name
# in the Usage line (they share a help function)
msggroup "Checking shared help shows correct command name"
for cmd in install reinstall remove purge; do
	testsuccess apt "$cmd" --help
	cp -f rootdir/tmp/testsuccess.output "${cmd}-shared-help.output"
	testsuccess grep "^Usage: apt \[options\] ${cmd} <package(s)>" "${cmd}-shared-help.output"
done
msggroup

# Commands without additional prose still receive command-specific option help.
check_options_only_help() {
	local cmd="$1"
	testsuccess apt "$cmd" --help
	cp -f rootdir/tmp/testsuccess.output "${cmd}-options-only-help.output"
	testfailure grep "Most used commands:" "${cmd}-options-only-help.output"
	testsuccess grep -Fx "Global options:" "${cmd}-options-only-help.output"

	testsuccess apt help "$cmd"
	cp -f rootdir/tmp/testsuccess.output "${cmd}-options-only-help-command.output"
	testsuccess cmp "${cmd}-options-only-help.output" \
		"${cmd}-options-only-help-command.output"
}

msggroup "Checking option help for commands without additional prose"
for cmd in moo; do
	check_options_only_help "$cmd"
done
msggroup

msggroup "Checking canonical alias help"
testsuccess apt info --help
cp -f rootdir/tmp/testsuccess.output info-canonical-help.output
testsuccess grep "^Usage: apt \[options\] show " \
	info-canonical-help.output

testsuccess apt dist-clean --help
cp -f rootdir/tmp/testsuccess.output dist-clean-canonical-help.output
testsuccess grep "^Usage: apt \[options\] distclean$" \
        dist-clean-canonical-help.output
testsuccess apt help dist-clean
cp -f rootdir/tmp/testsuccess.output dist-clean-canonical-help-command.output
testsuccess cmp dist-clean-canonical-help.output \
        dist-clean-canonical-help-command.output

testsuccess apt auto-clean --help
cp -f rootdir/tmp/testsuccess.output auto-clean-canonical-help.output
testsuccess grep "^Usage: apt \[options\] autoclean$" \
        auto-clean-canonical-help.output
testsuccess apt help auto-clean
cp -f rootdir/tmp/testsuccess.output auto-clean-canonical-help-command.output
testsuccess cmp auto-clean-canonical-help.output \
        auto-clean-canonical-help-command.output

testsuccess apt dist-upgrade --help
cp -f rootdir/tmp/testsuccess.output dist-upgrade-canonical-help.output
testsuccess grep "^Usage: apt \[options\] full-upgrade " \
	dist-upgrade-canonical-help.output
msggroup

# Test that apt --help (no command) still shows the generic help
msggroup "Checking generic apt --help"
testsuccess apt --help
cp -f rootdir/tmp/testsuccess.output apt-generic-help.output
testsuccess grep "^Usage: apt \[options\] command" apt-generic-help.output
testsuccess grep "Most used commands:" apt-generic-help.output
testsuccess grep "^  list - " apt-generic-help.output
testsuccess grep "^  install - " apt-generic-help.output
# Generic help should have the verbose footer and Super Cow
testsuccess grep "Super Cow Powers" apt-generic-help.output
testsuccessequal 'Source configuration options:
Global options:' grep -E '^[^[:space:]].* options:$' apt-generic-help.output
msggroup

# History commands receive per-command help.
msggroup "Checking per-command help for history commands"
for cmd in history-list history-info history-redo history-undo history-rollback; do
        check_command_help "$cmd"
done
msggroup

msggroup "Checking per-command help for apt-cache compatibility commands"
for cmd in showsrc depends rdepends policy; do
        check_command_help "$cmd"
done
msggroup

msggroup "Checking per-command help for apt-get compatibility commands"
for cmd in source build-dep download changelog; do
        check_command_help "$cmd"
done
msggroup

msggroup "Checking per-command help for package-cache maintenance commands"
for cmd in clean distclean autoclean; do
        check_command_help "$cmd"
done
msggroup

# Check the complete section sequence, including commands with multiple groups.
check_option_groups() {
	local cmd="$1"
	local expected="$2"
	testsuccess apt "$cmd" --help
	cp -f rootdir/tmp/testsuccess.output "${cmd}-groups.output"
	testsuccessequal "$expected" grep -E '^[^[:space:]].* options:$' "${cmd}-groups.output"
	testfailure grep -E '^(Options|Common options):$' "${cmd}-groups.output"
}

msggroup "Checking named option groups"
check_option_groups list 'List options:
Source configuration options:
Global options:'
check_option_groups search 'Search options:
Cache options:
Global options:'
check_option_groups show 'Package information options:
Source configuration options:
Global options:'
for cmd in install reinstall remove purge autoremove full-upgrade; do
	check_option_groups "$cmd" 'Package management options:
Simulation options:
Common package management options:
Global options:'
done
check_option_groups upgrade 'Package management options:
Upgrade options:
Simulation options:
Common package management options:
Global options:'
check_option_groups update 'Update options:
Common package management options:
Global options:'
check_option_groups satisfy 'Dependency resolution options:
Simulation options:
Common package management options:
Global options:'
check_option_groups build-dep 'Dependency resolution options:
Build dependency options:
Simulation options:
Common package management options:
Global options:'
# policy matches a declaration with an empty group: do not print an empty heading.
check_option_groups policy 'Cache options:
Global options:'
check_option_groups clean 'Simulation options:
Common package management options:
Global options:'
msggroup

# A heading alone is insufficient: verify that options belong to that section.
option_group_body() {
	awk -v heading="$1" '
		$0 == heading { printing = 1; next }
		printing && /^$/ { exit }
		printing { print }
	' "$2"
}

msggroup "Checking options within their named groups"
option_group_body 'Simulation options:' install-groups.output > simulation-group.output
testsuccess grep -F -- '-s, --simulate' simulation-group.output
testfailure grep -E -- '--(fix-broken|yes|help|just-print|recon|dry-run|no-act)([[:space:]]|$)' simulation-group.output
option_group_body 'Package management options:' install-groups.output > management-group.output
testsuccess grep -F -- '-f, --fix-broken' management-group.output
testfailure grep -F -- '--simulate' management-group.output
option_group_body 'Common package management options:' install-groups.output > common-group.output
testsuccess grep -F -- '-y, --yes' common-group.output
testsuccess grep -F -- '-m, --fix-missing' common-group.output
option_group_body 'Cache options:' search-groups.output > cache-group.output
testsuccess grep -F -- '-g, --generate' cache-group.output
option_group_body 'Global options:' list-groups.output > global-group.output
testsuccess grep -F -- '-h, --help' global-group.output
testfailure grep -E -- '--(config-file|option|silent)([[:space:]]|$)' list-groups.output
testfailure grep -E -- '--(upgradable|default-release)([[:space:]]|$)' list-groups.output
msggroup

msggroup "Checking declarative option formatting"
testsuccess apt list --help
cp -f rootdir/tmp/testsuccess.output list-option-formatting.output
testsuccess grep -F -- "-u, --upgradeable" list-option-formatting.output
testsuccess grep -F -- "--target-release <value>" list-option-formatting.output
testsuccess grep -F -- "--snapshot <value>" list-option-formatting.output

testsuccess apt satisfy --help
cp -f rootdir/tmp/testsuccess.output satisfy-option-formatting.output
testsuccess grep -F -- "--host-architecture <value>" satisfy-option-formatting.output
testsuccess grep -F -- "--solver <value>" satisfy-option-formatting.output
msggroup

msggroup "Checking common options in per-command help"
testsuccess apt list --help
cp -f rootdir/tmp/testsuccess.output list-common-options.output
testsuccess grep -Fx "Global options:" list-common-options.output
testsuccess grep -F -- "--with-source <value>" list-common-options.output
testsuccess grep -F -- "-h, --help" list-common-options.output

# install and search are inherited from apt-get and apt-cache respectively
testsuccess apt install --help
cp -f rootdir/tmp/testsuccess.output install-common-options.output
testsuccess grep -F -- "-y, --yes" install-common-options.output
testsuccess grep -F -- "-m, --fix-missing" install-common-options.output

testsuccess apt search --help
cp -f rootdir/tmp/testsuccess.output search-common-options.output
testsuccess grep -F -- "-g, --generate" search-common-options.output

testsuccess apt showsrc --help
cp -f rootdir/tmp/testsuccess.output showsrc-common-options.output
testsuccess grep -F -- "--only-source" showsrc-common-options.output

testsuccess apt depends --help
cp -f rootdir/tmp/testsuccess.output depends-common-options.output
testsuccess grep -F -- "--installed" depends-common-options.output

testsuccess apt source --help
cp -f rootdir/tmp/testsuccess.output source-common-options.output
testsuccess grep -F -- "--dsc-only" source-common-options.output

testsuccess apt build-dep --help
cp -f rootdir/tmp/testsuccess.output build-dep-common-options.output
testsuccess grep -F -- "--arch-only" build-dep-common-options.output

testsuccess apt clean --help
cp -f rootdir/tmp/testsuccess.output clean-common-options.output
testsuccess grep -F -- "--simulate" clean-common-options.output
msggroup

# Commands without command-specific options should only show common groups.
msggroup "Checking commands without command-specific option groups"
for cmd in why why-not edit-sources modernize-sources; do
	check_option_groups "$cmd" 'Source configuration options:
Global options:'
done
msggroup

# Test that per-command help does NOT include Super Cow Powers
# and uses the shortened footer instead of the verbose one
msggroup "Checking footer and Super Cow in per-command help"
testsuccess apt list --help
cp -f rootdir/tmp/testsuccess.output list-footer-help.output
# Shortened footer present
testsuccess grep "See apt(8), apt.conf(5), sources.list(5)" list-footer-help.output
# Verbose footer absent
testfailure grep "^Configuration options and syntax" list-footer-help.output
# Super Cow absent in per-command help
testfailure grep "Super Cow Powers" list-footer-help.output
msggroup
