#!/bin/sh
# Start a private shairport-sync instance using the dummy output backend and
# check that it serves RTSP, exposes its D-Bus and MPRIS interfaces and
# creates the metadata pipe. Nothing here touches the installed service.
#
# usage: instance classic|airplay2
set -eu

service_type="$1"
case "$service_type" in
classic) expected_protocol="AirPlay" ;;
airplay2) expected_protocol="AirPlay 2" ;;
*)
	echo "usage: $0 classic|airplay2" >&2
	exit 2
	;;
esac

# Re-exec under a private session bus so the D-Bus names do not clash with
# an installed service on the system bus.
if [ -z "${SPS_TEST_IN_SESSION:-}" ]; then
	SPS_TEST_IN_SESSION=1 exec dbus-run-session -- "$0" "$@"
fi

tests_dir="$(cd "$(dirname "$0")" && pwd)"
tmp="${AUTOPKGTEST_TMP:-$(mktemp -d)}"
port="${SPS_TEST_PORT:-25000}"
name="autopkgtest-$$"
conf="$tmp/shairport-sync.conf"
log="$tmp/shairport-sync.log"
pipe="$tmp/metadata"
info="$tmp/info.plist"

cat >"$conf" <<CONF
general = {
	name = "$name";
	output_backend = "dummy";
	port = $port;
	service_type = "$service_type";
	dbus_service_bus = "session";
	mpris_service_bus = "session";
};
metadata = {
	enabled = "yes";
	include_cover_art = "no";
	pipe_name = "$pipe";
};
CONF

fail() {
	echo "FAIL: $*" >&2
	echo "--- shairport-sync log ---" >&2
	cat "$log" >&2
	exit 1
}

get_property() { # get_property DEST OBJECT INTERFACE PROPERTY
	dbus-send --session --print-reply=literal --dest="$1" "$2" \
		org.freedesktop.DBus.Properties.Get "string:$3" "string:$4" |
		sed 's/^ *variant *//'
}

name_has_owner() {
	dbus-send --session --print-reply=literal \
		--dest=org.freedesktop.DBus /org/freedesktop/DBus \
		org.freedesktop.DBus.NameHasOwner "string:$1" 2>/dev/null |
		grep -q 'boolean true'
}

shairport-sync -c "$conf" -v >"$log" 2>&1 &
pid=$!
trap 'kill "$pid" 2>/dev/null || true' EXIT

echo "waiting for RTSP on port $port and the D-Bus names..."
i=0
while :; do
	kill -0 "$pid" 2>/dev/null || fail "shairport-sync exited prematurely"
	if "$tests_dir/rtsp-request" "$port" OPTIONS '*' >"$tmp/options" 2>/dev/null &&
		name_has_owner org.gnome.ShairportSync &&
		name_has_owner org.mpris.MediaPlayer2.ShairportSync; then
		break
	fi
	i=$((i + 1))
	[ "$i" -lt 100 ] || fail "timed out waiting for shairport-sync to come up"
	sleep 0.2
done

echo "checking RTSP OPTIONS..."
cat "$tmp/options"
grep -q '^Public:.*OPTIONS' "$tmp/options" || fail "OPTIONS response lacks a Public: header"

echo "checking RTSP GET /info..."
"$tests_dir/rtsp-request" "$port" GET /info "$info" || fail "GET /info did not succeed"
[ "$(head -c 8 "$info")" = "bplist00" ] || fail "GET /info did not return a binary plist"

echo "checking D-Bus properties..."
protocol="$(get_property org.gnome.ShairportSync /org/gnome/ShairportSync org.gnome.ShairportSync Protocol)"
echo "Protocol: $protocol"
[ "$protocol" = "$expected_protocol" ] || fail "expected protocol '$expected_protocol'"

service_name="$(get_property org.gnome.ShairportSync /org/gnome/ShairportSync org.gnome.ShairportSync ServiceName)"
echo "ServiceName: $service_name"
[ "$service_name" = "$name" ] || fail "expected service name '$name'"

version_string="$(get_property org.gnome.ShairportSync /org/gnome/ShairportSync org.gnome.ShairportSync VersionString)"
echo "VersionString: $version_string"
[ "$version_string" = "$(shairport-sync -V)" ] || fail "VersionString does not match shairport-sync -V"

echo "checking MPRIS..."
identity="$(get_property org.mpris.MediaPlayer2.ShairportSync /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2 Identity)"
echo "Identity: $identity"
[ "$identity" = "Shairport Sync" ] || fail "unexpected MPRIS identity"

echo "checking metadata pipe..."
[ -p "$pipe" ] || fail "metadata pipe $pipe was not created"

echo "stopping..."
kill -TERM "$pid"
trap - EXIT
status=0
wait "$pid" || status=$?
[ "$status" -eq 0 ] || fail "shairport-sync exited with status $status on SIGTERM"
! grep -q 'fatal error' "$log" || fail "fatal error logged"
echo "OK"
