#!/usr/bin/env bash
# Copyright 2026 Nadeŭka <me+oss@nadevko.cc>
# Distributed under the terms of the GNU General Public License v2
EAPI=8
source "$(dirname -- "${BASH_SOURCE[0]}")/.test.sh" "$@" || exit 1

inherit egetent

# @FUNCTION: check
# @USAGE: [-d <desc>] [-s] [-r <root_opt>] [-e <VAR=val>] [-x <ret>] [-m <err>] -- <args...>
# @INTERNAL
# @DESCRIPTION:
# Compares egetent execution against system getent or explicit expected exit/stderr values.
check() {
	local desc='' sorted=0 exp_ret='' exp_err='' env_var='' root_opt='--root /'

	while (( $# )); do
		case $1 in
			--) shift; break ;;
			-d) desc=$2; shift 2 ;;
			-s) sorted=1; shift ;;
			-r) root_opt=$2; shift 2 ;;
			-e) env_var=$2; shift 2 ;;
			-x) exp_ret=$2; shift 2 ;;
			-m) exp_err=$2; shift 2 ;;
			*)  die "unknown test option: $1" ;;
		esac
	done

	if [[ -z ${desc} ]]; then
		desc=${*:-<no arguments>}
		[[ ${root_opt} == '--root /' ]] || desc+=" (${root_opt})"
		[[ -z ${env_var} ]] || desc+=" (${env_var})"
		(( sorted )) && desc+=' (sorted)'
	fi

	tbegin "${desc}"

	[[ -z ${env_var} ]] || local "${env_var}"

	local -a cmd=( egetent ${root_opt} )

	if [[ -n ${exp_ret} ]]; then
		t "${cmd[@]}" "$@"
		assert_eq "${exp_ret}" "${CMD_RES[ret]}" 'Exit code'
		[[ ${CMD_RES[err]} == *"${exp_err}"* ]] ||
			TEST_DIFFS+="  Stderr mismatch: expected to contain ${exp_err@Q}, got ${CMD_RES[err]@Q}"$'\n'
	else
		t getent "$@"
		local orig_ret=${CMD_RES[ret]} orig_out=${CMD_RES[out]} orig_err=${CMD_RES[err]}
		t "${cmd[@]}" "$@"

		if (( sorted )); then
			orig_out=$(sort -u <<< "${orig_out}")
			CMD_RES[out]=$(sort -u <<< "${CMD_RES[out]}")
		fi

		assert_eq "${orig_ret}" "${CMD_RES[ret]}" 'Exit code'
		assert_diff "${orig_out}" "${CMD_RES[out]}" 'Stdout'
		assert_diff "${orig_err}" "${CMD_RES[err]}" 'Stderr'
	fi

	tend
}

# @FUNCTION: checks
# @USAGE: <database> <key_or_keys>...
# @INTERNAL
# @DESCRIPTION:
# Runs check for multiple keys or space-separated key combinations under a single database.
checks() {
	local db=$1 k
	shift
	for k; do check -- "${db}" ${k}; done
}

einfo "Starting egetent.eclass test suite"

check -d 'missing database argument' --
check -- unknown_database_xyz

check -- -s
check -- --service
check -x 64 -m "option requires an argument -- 'R'" -- -R
check -x 64 -m "option '--root' requires an argument" -- --root

# enumeration
for db in ethers netgroup initgroups; do check -- "${db}"; done
for db in passwd group protocols networks rpc services; do
	[[ -r /etc/${db} ]] && check -- "${db}"
done
if [[ -r /etc/hosts ]]; then
	for db in hosts ahosts ahostsv4 ahostsv6; do check -s -- "${db}"; done
fi
for db in shadow gshadow; do
	[[ -r /etc/${db} ]] && check -- "${db}"
done
[[ -r /etc/aliases.db || -r /etc/mail/aliases.db ]] && check -- aliases

# lookup by key
checks passwd root 0 'root nobody' non_existent_user_12345 'root non_existent_user_12345'
checks group root 0 'root bin daemon' non_existent_group_12345 'root non_existent_group_12345'
grep -q '^video:' /etc/group 2>/dev/null && checks group video

[[ -r /etc/shadow ]] && checks shadow root non_existent_user_12345 'root non_existent_user_12345'
[[ -r /etc/gshadow ]] && checks gshadow root non_existent_group_12345 'root non_existent_group_12345'

checks protocols tcp 6 IP-ENCAP 'hip shim6' divert non_existent_proto
[[ -r /etc/networks ]] && checks networks loopback 127.0.0.0 'loopback 127.0.0.0' non_existent_net
checks services http 80 http/tcp 80/tcp asp http/udp 'ssh smtp' non_existent_svc_12345

if [[ -r /etc/rpc ]]; then
	checks rpc portmapper 100000 'portmapper 100000' non_existent_rpc_12345
	grep -q '^amd' /etc/rpc 2>/dev/null && checks rpc amd
fi

checks hosts 127.0.0.1 ::1 localhost non_existent_host_12345 'localhost ::1'

checks initgroups root
id nobody &>/dev/null && checks initgroups nobody
checks initgroups non_existent_user_12345 'root non_existent_user_12345'

if [[ -r /etc/aliases || -r /etc/mail/aliases ]]; then
	IFS=: read -r first_alias _ < <(getent aliases 2>/dev/null)
	[[ -z ${first_alias} ]] || check -- aliases "${first_alias}"
	check -- aliases non_existent_alias_12345
fi

checks ethers non_existent_ether_host_12345
checks netgroup non_existent_netgroup_12345

checks ahosts 127.0.0.1 '127.0.0.1 localhost'
checks ahostsv4 localhost
checks ahostsv6 localhost

# options
check -r '--root /' -- passwd root
check -r '--root=/' -- passwd root
check -r '-R /' -- passwd root
check -e 'ROOT=/' -r '-R /' -- passwd root

check -- -s files passwd root
check -- --service=files passwd root
check -- -s passwd:files passwd root
check -- --service=passwd:files passwd root
check -- -s group:files group root
check -- -s files group root
check -- -i hosts localhost
check -- --no-idn hosts localhost
check -- -A ahosts 127.0.0.1
check -- --no-addrconfig ahosts 127.0.0.1

texit
