#!/bin/sh

# please always adjust the length of file to be 1000 lines
#
# This file is auto generated, do not modify it or your changes
# might be lost.
#
# shell test suite v0.6 for kdb command


#
# VARIABLES
#

NEWLINE='
'

# variables to count up errors and tests
nbError=0
nbTest=0
nbSkip=0

# the script itself
scriptName=`basename "$0"`

MOUNTPOINT="/tests/script"

NAMESPACES="user system"

USER_ROOT="user/tests/script"
SYSTEM_ROOT="system/tests/script"

ROOTS="$USER_ROOT $SYSTEM_ROOT"

IS_INSTALLED=YES
if [ "x$IS_INSTALLED" = "xYES" ]
then
	DATADIR="/usr/share/elektra/test_data/shell"
else
	DATADIR="/chakra/desktop/elektra/src/libelektra-0.8.24/tests/shell/shell"
fi

USER="`id -un`"
GROUP="`id -gn`"

SYSTEM_FOLDER=/etc/kdb
if [ -n "$HOME" ]
then
	USER_FOLDER=$HOME/.config
else
	USER_FOLDER=/home/$USER/.config
fi
PLUGINS=`echo "base64;boolean;c;camel;ccode;conditionals;constants;counter;crypto_gcrypt;crypto_openssl;csvstorage;curlget;date;dbus;desktop;dini;directoryvalue;dpkg;dump;enum;error;fcrypt;filecheck;fstab;glob;hexcode;hexnumber;hidden;hosts;iconv;ini;ipaddr;journald;keytometa;line;lineendings;list;logchange;mathcheck;mini;multifile;network;ni;noresolver;null;path;profile;range;regexstore;rename;required;resolver_fm_b_b;resolver_fm_hb_b;resolver_fm_hp_b;resolver_fm_hpu_b;resolver_fm_pb_b;resolver_fm_ub_x;resolver_fm_uhb_xb;resolver_fm_xb_x;resolver_fm_xhp_x;resolver_fm_xp_x;shell;simpleini;spec;struct;sync;syslog;timeofday;tracer;type;uname;validation;wresolver;xmltool" | tr ';' ' '`
ADDED_PLUGINS_WITHOUT_ONLY_SHARED=`echo "base64;boolean;c;camel;ccode;conditionals;constants;counter;crypto_gcrypt;crypto_openssl;csvstorage;curlget;date;dbus;desktop;dini;directoryvalue;dpkg;dump;enum;error;fcrypt;filecheck;fstab;glob;hexcode;hexnumber;hidden;hosts;iconv;ini;ipaddr;journald;keytometa;line;lineendings;list;logchange;mathcheck;mini;multifile;network;ni;noresolver;null;path;profile;range;regexstore;rename;required;resolver_fm_b_b;resolver_fm_hb_b;resolver_fm_hp_b;resolver_fm_hpu_b;resolver_fm_pb_b;resolver_fm_ub_x;resolver_fm_uhb_xb;resolver_fm_xb_x;resolver_fm_xhp_x;resolver_fm_xp_x;shell;simpleini;spec;struct;sync;syslog;timeofday;tracer;type;uname;validation;wresolver;xmltool" | tr ';' ' '`
PLUGINS_NEWLINES=`echo "base64;boolean;c;camel;ccode;conditionals;constants;counter;crypto_gcrypt;crypto_openssl;csvstorage;curlget;date;dbus;desktop;dini;directoryvalue;dpkg;dump;enum;error;fcrypt;filecheck;fstab;glob;hexcode;hexnumber;hidden;hosts;iconv;ini;ipaddr;journald;keytometa;line;lineendings;list;logchange;mathcheck;mini;multifile;network;ni;noresolver;null;path;profile;range;regexstore;rename;required;resolver_fm_b_b;resolver_fm_hb_b;resolver_fm_hp_b;resolver_fm_hpu_b;resolver_fm_pb_b;resolver_fm_ub_x;resolver_fm_uhb_xb;resolver_fm_xb_x;resolver_fm_xhp_x;resolver_fm_xp_x;shell;simpleini;spec;struct;sync;syslog;timeofday;tracer;type;uname;validation;wresolver;xmltool" | tr ';' '\n'`

DATE=`date "+%b %d %H:%M"`

KDB_DEFAULT_STORAGE="dump"
KDB_DEFAULT_RESOLVER="resolver_fm_hpu_b"

KDB_GETENV=`kdb elektrify-getenv getenv KDB 2> /dev/null`

if [ "${KDB_GETENV}" ]
then
	KDB=${KDB_GETENV};
fi

# ensure ruby plugin finds Ruby bindings without installation
# (require both the src and the build dir)
export RUBYLIB="/chakra/desktop/elektra/src/libelektra-0.8.24/src/bindings/swig/ruby:/chakra/desktop/elektra/src/libelektra-0.8.24/build/src/bindings/swig/ruby"
export SAVE=0 # some Rubies do not accept RUBYLIB if SAVE is not 0

#
# HELPER
#

# POSIX way to test if string contains substring
contains() {
    string="$1"
    substring="$2"
    test "${string#*$substring}" != "$string"
}

#
# ASSERTIONS
#

#succeed if the previous command was successful
succeed_if ()
{
	if [ $? != "0" ]
	then
		nbError=$(( $nbError + 1 ))
		echo error: $*
	fi
	nbTest=$(( $nbTest + 1 ))
}

#fails and exits the program if the previous command failed
exit_if_fail ()
{
	if [ $? != "0" ]
	then
		if command -v cleanup > /dev/null
		then
			echo "fatal: $*"
			cleanup
		else
			echo "fatal (no cleanup necessary): $*"
		fi
		exit 1
	fi
	nbTest=$(( $nbTest + 1 ))
}

end_script()
{
	if command -v cleanup > /dev/null
	then
		cleanup
	fi

	printf "$scriptName RESULTS: $nbTest test(s) done"
	if [ $nbSkip -ne 0 ]
	then
		printf " $nbSkip skipped"
	fi
	echo " $nbError error(s)."
	exit "$nbError"
}


#
# COMMON CHECKS
#
KDB_VERSION="0.8.24"
SO_VERSION="4"

check_version()
{
	echo "Check if script tests the correct version"

	if [ "x`kdb elektrify-getenv getenv CHECK_VERSION 2> /dev/null`" = "xNO" ]
	then
		return 0
	fi

	#if no kdb elektrify-getenv getenv is installed:
	if [ "x$CHECK_VERSION" = "xNO" ]
	then
		return 0
	fi

	REAL_KDB_VERSION="`"$KDB" get system/elektra/version/constants/KDB_VERSION 2> /dev/null`"
	[ "x$REAL_KDB_VERSION" = "x$KDB_VERSION" ]
	exit_if_fail "Script was not compiled ($KDB_VERSION) with this elektra version ($REAL_KDB_VERSION): KDB_VERSION mismatch for kdb-tool ($KDB), use CHECK_VERSION=NO to disable"

	REAL_SO_VERSION="`"$KDB" get system/elektra/version/constants/SO_VERSION 2> /dev/null`"
	[ "x$REAL_SO_VERSION" = "x$SO_VERSION" ]
	exit_if_fail "Script was not compiled ($SO_VERSION) with this elektra version ($REAL_SO_VERSION): SO_VERSION mismatch for kdb-tool ($KDB), use CHECK_VERSION=NO to disable"
}

check_remaining_files()
{
	USER_REMAINING="`find $USER_FOLDER -maxdepth 1 -name $1'*' -print -quit`"
	test -z "$USER_REMAINING"
	exit_if_fail "files $USER_REMAINING in $USER_FOLDER would be removed during tests, so test is aborted"

	SYSTEM_REMAINING="`find $SYSTEM_FOLDER -maxdepth 1 -name $1'*' -print -quit`"
	test -z "$SYSTEM_REMAINING"
	exit_if_fail "files $SYSTEM_REMAINING in $SYSTEM_FOLDER would be removed during tests, so test is aborted"
}

check_set_rm()
{
	"$KDB" set "$1" "$2" 1>/dev/null
	succeed_if "could not set $1 with $2"

	[ "x`"$KDB" get "$1" 2> /dev/null`" = "x$2" ]
	succeed_if "cant get $1 (expected $2)"

	"$KDB" rm "$1" 1>/dev/null
	succeed_if "could not rm $1 (having value $2)"

	[ "x`"$KDB" sget $1 defvalue 2> /dev/null`" = "xdefvalue" ]
	succeed_if "Value still there after remove"
}


check_set_mv_rm()
{
	"$KDB" set "$1" "$3" 1>/dev/null
	succeed_if "could not set $1 with $3"

	[ "x`"$KDB" get "$1" 2> /dev/null`" = "x$3" ]
	succeed_if "cant get $1 (expected $3)"

	"$KDB" mv "$1" "$2" 1>/dev/null
	succeed_if "could not mv $1 to $2"

	[ "x`"$KDB" sget $1 defvalue 2> /dev/null`" = "xdefvalue" ]
	succeed_if "Value still there after move"

	[ "x`"$KDB" get "$2" 2> /dev/null`" = "x$3" ]
	succeed_if "cant get $2 (expected $3)"

	"$KDB" rm "$2" 1>/dev/null
	succeed_if "could not rm $2 (having value $3)"

	[ "x`"$KDB" sget $2 defvalue 2> /dev/null`" = "xdefvalue" ]
	succeed_if "Value still there after remove"
}



#
# COMMON UTILITIES
#


is_not_rw_storage()
{
	test ! "x`"$KDB" info $PLUGIN provides 2>/dev/null`" = "xstorage" \
	-o "x$PLUGIN" = "xhosts" \
	-o "x$PLUGIN" = "xfstab" \
	-o "x$PLUGIN" = "xline" \
	-o "x$PLUGIN" = "xuname" \
	-o "x$PLUGIN" = "xconstants" \
	-o "x$PLUGIN" = "xaugeas" \
	-o "x$PLUGIN" = "xcsvstorage" \
	-o "x$PLUGIN" = "xdpkg" \
	-o "x$PLUGIN" = "xregexstore" \
	-o "x$PLUGIN" = "xpasswd" \
	-o "x$PLUGIN" = "xsimplespeclang" \
	-o "x$PLUGIN" = "xmozprefs" \
	-o "x$PLUGIN" = "xfile" \
	-o "x$PLUGIN" = "xruby"
}

is_plugin_available()
{
	for PLUGIN in $PLUGINS
	do
		if [ "x$1" = "x$PLUGIN" ]
		then
			return 0
		fi
	done
	return 1
}

mktempdir_elektra()
{
	mktemp -d 2>/dev/null || mktemp -d -t 'libelektra-test'
}

mktempfile_elektra()
{
	mktemp -t elektraenv.XXXXXXXXX 2>/dev/null || mktemp -t 'elektraenv'
}

replace_newline_return () {
	awk '{if (NR>1) {printf("%s⏎", line);} line=$0;} END { printf("%s\n", line); }'
}

printerr () {
	>&2 printf "$@"
}

#
# EXPORT FUNCTIONS
#


check_failed()
{
	EXPORTS=$1
	TESTNAME=$2
	CONFIGNAME=$3

	echo "$TESTNAME did not leave $CONFIGNAME config in the same state at is was before!"
	echo "This means the test itself is flawed or the KDB was externally modified while the tests were running!"
	echo "You can inspect the original $CONFIGNAME config in $EXPORTS/$CONFIGNAME.export.dump"
	echo "compared to situation now in $EXPORTS/$CONFIGNAME.check.dump"
	echo
	echo "Other important recovery files are also in the directory $EXPORTS"
	echo "Please remove the $EXPORTS directory yourself after you fixed the situation, I cannot do it for you"
	exit 1
}

export_config()
{
	EXPORTS=$1

	if [ ! -d "$EXPORTS" ]
	then
		echo "Failed to create directory “$EXPORTS”"
		exit 1
	fi

	SPECEXPORT="$EXPORTS/spec.export.dump"
	DIREXPORT="$EXPORTS/dir.export.dump"
	USEREXPORT="$EXPORTS/user.export.dump"
	SYSTEMEXPORT="$EXPORTS/system.export.dump"
	MOUNTEXPORT="$EXPORTS/mount.export.dump"

	"$KDB" export spec dump > "$SPECEXPORT"
	exit_if_fail "Could not export spec config"

	"$KDB" export dir dump > "$DIREXPORT"
	exit_if_fail "Could not export dir config"

	"$KDB" export user dump > "$USEREXPORT"
	exit_if_fail "Could not export user config"

	"$KDB" export system --without-elektra dump > "$SYSTEMEXPORT"
	exit_if_fail "Could not export system config"

	"$KDB" export system/elektra/mountpoints dump > "$MOUNTEXPORT"
	exit_if_fail "Could not export mount config"
}

export_check()
{
	EXPORTS=$1
	TESTNAME=$2
	IMPORTCONFIG=$3

	SPECEXPORT="$EXPORTS/spec.export.dump"
	SPECCHECK="$EXPORTS/spec.check.dump"

	DIREXPORT="$EXPORTS/dir.export.dump"
	DIRCHECK="$EXPORTS/dir.check.dump"

	USEREXPORT="$EXPORTS/user.export.dump"
	USERCHECK="$EXPORTS/user.check.dump"

	SYSTEMEXPORT="$EXPORTS/system.export.dump"
	SYSTEMCHECK="$EXPORTS/system.check.dump"

	MOUNTEXPORT="$EXPORTS/mount.export.dump"
	MOUNTCHECK="$EXPORTS/mount.check.dump"

	"$KDB" export spec dump > "$SPECCHECK"
	exit_if_fail "Could not export spec config"

	"$KDB" export dir dump > "$DIRCHECK"
	exit_if_fail "Could not export dir config"

	"$KDB" export user dump > "$USERCHECK"
	exit_if_fail "Could not export user config"

	"$KDB" export system --without-elektra dump > "$SYSTEMCHECK"
	exit_if_fail "Could not export system config"

	"$KDB" export system/elektra/mountpoints dump > "$MOUNTCHECK"
	exit_if_fail "Could not export mount config"

	if [ "$IMPORTCONFIG" = 'true' ]; then
		"$KDB" import spec dump < "$SPECEXPORT"
		exit_if_fail "Could not import spec config"

		"$KDB" import dir dump < "$DIREXPORT"
		exit_if_fail "Could not import dir config"

		"$KDB" import user dump < "$USEREXPORT"
		exit_if_fail "Could not import user config"

		"$KDB" import system --without-elektra dump < "$SYSTEMEXPORT"
		exit_if_fail "Could not import system config"

		"$KDB" import system/elektra/mountpoints dump < "$MOUNTEXPORT"
		exit_if_fail "Could not import mount config"
	fi

	diff "$SPECEXPORT" "$SPECCHECK"
	if [ $? != "0" ]
	then
		check_failed "$EXPORTS" "$TESTNAME" spec
	fi

	diff "$DIREXPORT" "$DIRCHECK"
	if [ $? != "0" ]
	then
		check_failed "$EXPORTS" "$TESTNAME" dir
	fi

	diff "$USEREXPORT" "$USERCHECK"
	if [ $? != "0" ]
	then
		check_failed "$EXPORTS" "$TESTNAME" user
	fi

	diff "$SYSTEMEXPORT" "$SYSTEMCHECK"
	if [ $? != "0" ]
	then
		check_failed "$EXPORTS" "$TESTNAME" system
	fi

	diff "$MOUNTEXPORT" "$MOUNTCHECK"
	if [ $? != "0" ]
	then
		check_failed "$EXPORTS" "$TESTNAME" mount
	fi
}

















































































































































































































































































































































































































































































































































































































# empty lines up to 1000 so that line numbers in the resulting scripts are more useful
if [ -z "$KDB" ]; then KDB=kdb; fi

echo
echo ELEKTRA CHECK RESOLVER
echo

#set tmp path (mainly for macOS compatibility)
TMPPATH=`cd /tmp; pwd -P`

#checks if resolver can be mounted and also partly checks if it resolves
#correctly (more tests welcome).

check_version

if is_plugin_available dump && is_plugin_available sync
then
	echo "dump and sync available"
else
	echo "dump or sync not available, skipping tests"
	nbSkip=$(( $nbSkip + 100 ))
	exit 0
fi

#enable with care: might remove more (empty) directories than it created
#root access required, writes into various paths (they are listed,
#even if WRITE_TO_SYSTEM is deactivated)
#WRITE_TO_SYSTEM=YES
WRITE_TO_SYSTEM=NO

ROOT_MOUNTPOINT=/test/script

#method that does all the checking
check_resolver()
{
	if [ "$1" = "user" ]
	then
		PLUGIN=`echo "$PLUGINS_NEWLINES" | grep -m 1 "resolver_.*_$2.*_.*"`
	else
		PLUGIN=`echo "$PLUGINS_NEWLINES" | grep -m 1 "resolver_.*_.*_$2.*"`
	fi

	if [ "$2" = "w" ]
	then
		if is_plugin_available wresolver
		then
			PLUGIN=wresolver
		else
			PLUGIN=""
		fi
	fi

	if [ -z "$PLUGIN" ]
	then
		nbSkip=$(( $nbSkip + 1 ))
		echo "skipping test because plugin variant $2 is missing, for $2 with $3"
		return
	fi

	MOUNTPOINT=$1$ROOT_MOUNTPOINT

	"$KDB" mount --resolver $PLUGIN $3 $MOUNTPOINT dump 1>/dev/null
	succeed_if "could not mount root using: "$KDB" mount --resolver $PLUGIN $3 $MOUNTPOINT dump"

	FILE=`"$KDB" file -N $1 -n $ROOT_MOUNTPOINT 2> /dev/null`
	echo "For $1 $2 $3 we got $FILE"
	[ "x$FILE"  = "x$4" ]
	succeed_if "resolving of $MOUNTPOINT did not yield $4 but $FILE"

	if [ "x$WRITE_TO_SYSTEM" = "xYES" ]; then
		KEY=$ROOT_MOUNTPOINT/key
		"$KDB" set -N $1 $KEY value
		succeed_if "could not set $KEY"

		echo "remove $FILE and its directories"
		rm $FILE
		succeed_if "could not remove $FILE"

		dirname $FILE
		rmdir -p --ignore-fail-on-non-empty `dirname $FILE`
	fi

	"$KDB" umount $MOUNTPOINT >/dev/null
	succeed_if "could not umount $MOUNTPOINT"
}


# need HOME to work
unset USER

# HOME on buildserver wrong...
#check_resolver system b '~/FOO' ~/FOO
#check_resolver system b '~/x' ~/x
#check_resolver system b '~/x/y' ~/x/y
#check_resolver system b '~//x' ~//x
#check_resolver system b '~/' ~/
#check_resolver system b '~' ~/
#
#check_resolver spec b '~/x' ~/x
#check_resolver spec b '~/x/y' ~/x/y
#check_resolver spec b '~//x' ~//x
#check_resolver spec b '~/' ~/
#check_resolver spec b '~' ~/

unset HOME
unset USER

if echo "resolver_fm_hpu_b" | grep "resolver_.*_.*_x.*"
then
	echo "skipping tests where XDG_CONFIG_DIRS is manipulated, because default resolver itself would use those paths"
	nbSkip=$(( $nbSkip + 10 ))
else

unset XDG_CONFIG_DIRS
unset XDG_CONFIG_HOME

check_resolver system x app/config_file /etc/xdg/app/config_file

export XDG_CONFIG_DIRS="/xdg_dir"

check_resolver system x app/config_file /xdg_dir/app/config_file

export XDG_CONFIG_DIRS="/xdg_dir1:/xdg_dir2:/xdg_dir3"

check_resolver system x app/config_file /xdg_dir3/app/config_file

unset XDG_CONFIG_DIRS
export XDG_CONFIG_HOME="/xdg_dir1"

check_resolver system x app/config_file /etc/xdg/app/config_file
check_resolver user x app/config_file /xdg_dir1/app/config_file

export XDG_CONFIG_HOME="broken"
check_resolver system x app/config_file /etc/xdg/app/config_file
export XDG_CONFIG_HOME="(broken)"
check_resolver system x app/config_file /etc/xdg/app/config_file
export XDG_CONFIG_HOME="(even):(more):(broken):"
check_resolver system x app/config_file /etc/xdg/app/config_file
export XDG_CONFIG_HOME=""
check_resolver system x app/config_file /etc/xdg/app/config_file
unset XDG_CONFIG_HOME
check_resolver system x app/config_file /etc/xdg/app/config_file

OD=`pwd`
cd $TMPPATH # hopefully no .dir is in $TMPPATH
check_resolver dir x /a $TMPPATH/a
check_resolver dir x /a/b $TMPPATH/a/b
check_resolver dir x a $TMPPATH/.dir/a
check_resolver dir x a/b $TMPPATH/.dir/a/b
cd "$OD"

fi # end of XDG tests







export ALLUSERSPROFILE="/C"
check_resolver spec w /app/config_file /C/app/config_file
check_resolver spec w app/config_file /C/usr/share/elektra/specification/app/config_file
check_resolver system w /app/config_file /C/app/config_file
check_resolver system w app/config_file /C/etc/kdb/app/config_file
unset ALLUSERSPROFILE

export HOME="/D"
check_resolver user w /app/config_file /D//app/config_file
check_resolver user w app/config_file /D/app/config_file #.config not impl
unset HOME

OD=`pwd`
cd $TMPPATH # hopefully no .dir is in $TMPPATH
check_resolver dir w /a $TMPPATH//a
check_resolver dir w /a/b $TMPPATH//a/b
check_resolver dir w a $TMPPATH/a #.dir not impl
check_resolver dir w a/b $TMPPATH/a/b #.dir not impl
cd "$OD"








check_resolver system b x /etc/kdb/x
check_resolver system b x/a /etc/kdb/x/a
check_resolver system b /a /a
check_resolver system b /a/b/c /a/b/c

check_resolver spec b x /usr/share/elektra/specification/x
check_resolver spec b x/a /usr/share/elektra/specification/x/a
check_resolver spec b /x /x
check_resolver spec b /x/a /x/a

check_resolver user b x /home/.config/x
check_resolver user b x/a /home/.config/x/a
check_resolver user b /a /home/a

# empty env must have no influence
export HOME=""
export USER=""

check_resolver system b x /etc/kdb/x
check_resolver system b x/a /etc/kdb/x/a
check_resolver system b /a /a
check_resolver system b /a/b/c /a/b/c

check_resolver user b x /home/.config/x
check_resolver user b x/a /home/.config/x/a
check_resolver user b /a /home/a

OD=`pwd`
cd $TMPPATH # hopefully no .dir is in $TMPPATH
check_resolver dir b /a $TMPPATH/a
check_resolver dir b /a/b $TMPPATH/a/b
check_resolver dir b a $TMPPATH/.dir/a
check_resolver dir b a/b $TMPPATH/.dir/a/b

T="`cd $(mktempdir_elektra); pwd -P`"

cleanup()
{
	rm -rf "$T"
}

cd $T
check_resolver dir b /a $T/a
check_resolver dir b /a/b $T/a/b
check_resolver dir b a $T/.dir/a
check_resolver dir b a/b $T/.dir/a/b

mkdir $T/sub
cd $T/sub
touch $T/a
check_resolver dir b /a $T/a
check_resolver dir b /a/b $T/sub/a/b
rm $T/a

mkdir $T/.dir
touch $T/.dir/a
check_resolver dir b a $T/.dir/a
check_resolver dir b a/b $T/sub/.dir/a/b
rm $T/.dir/a

cd $OD

unset HOME
unset USER

export HOME=/nowhere/below

check_resolver user h x $HOME/.config/x

unset HOME
export USER=markus/somewhere/test

check_resolver user u abc /home/$USER/.config/abc

end_script resolver
