#!/usr/bin/env atf-sh

. $(atf_get_srcdir)/test_env.sh
init_tests \
	lbu_usage \
	lbu_include_usage \
	lbu_inc_usage \
	lbu_add_usage \
	lbu_add_delete \
	lbu_commit_usage \
	lbu_ci_usage \
	lbu_exclude_usage \
	lbu_ex_usage \
	lbu_delete_usage \
	lbu_diff_usage \
	lbu_list_usage \
	lbu_ls_usage \
	lbu_list_backup_usage \
	lbu_lb_usage \
	lbu_package_usage \
	lbu_pkg_usage \
	lbu_revert_usage \
	lbu_status_usage \
	lbu_stat_usage \
	lbu_st_usage \
	lbu_package \
	lbu_package_encrypted \
	lbu_package_pre_post_hooks \
	lbu_commit \
	lbu_commit_backup \
	lbu_commit_delete_old \
	lbu_commit_dryrun \
	lbu_commit_encrypted \
	lbu_revert_basic \
	lbu_revert_file_not_found \
	lbu_revert_no_media \
	lbu_status_no_changes \
	lbu_status_added \
	lbu_status_deleted \
	lbu_status_updated \
	lbu_status_all_default \
	lbu_exclude_add \
	lbu_exclude_remove \
	lbu_exclude_existing \
	lbu_exclude_remove_nonexistent \
	lbu_exclude_list \
	lbu_include_list \
	lbu_list_basic \
	lbu_root_files \
	lbu_listbackup_basic \
	lbu_listbackup_no_media

lbu_usage_body() {
	test_usage lbu
}

lbu_include_usage_body() {
	test_usage "lbu include"
}

lbu_inc_usage_body() {
	test_usage "lbu inc"
}

lbu_add_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu include" \
		-e empty \
		lbu add -h
}

lbu_add_delete_body() {
	init_env
	mkdir -p root/.ssh
	atf_check -s exit:0 \
		-o match:"Adding root/.ssh to" \
		-e empty \
		lbu add -v root/.ssh

	atf_check -s exit:0 \
		-o match:"root/.ssh" \
		cat etc/apk/protected_paths.d/lbu.list

	atf_check -s exit:0 \
		-o match:"Removing root/.ssh from" \
		-e empty \
		lbu delete -v root/.ssh

	grep 'root/.ssh' etc/apk/protected_paths.d/lbu.list \
		|| atf_fail "root/.ssh was not removed"
}

lbu_commit_usage_body() {
	test_usage "lbu commit"
}

lbu_ci_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu commit" \
		-e empty \
		lbu ci -h
}

lbu_exclude_usage_body() {
	test_usage "lbu exclude"
}

lbu_ex_usage_body() {
	test_usage "lbu ex"
}

lbu_delete_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu exclude" \
		-e empty \
		lbu delete -h
}

lbu_diff_usage_body() {
	test_usage "lbu diff"
}

lbu_list_usage_body() {
	test_usage "lbu list"
}

lbu_ls_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu list" \
		-e empty \
		lbu ls -h
}

lbu_list_backup_usage_body() {
	test_usage "lbu list-backup"
}

lbu_lb_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu list-backup" \
		-e empty \
		lbu lb -h
}

lbu_package_usage_body() {
	test_usage "lbu package"
}

lbu_pkg_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu package" \
		-e empty \
		lbu pkg -h
}

lbu_revert_usage_body() {
	test_usage "lbu revert"
}

lbu_status_usage_body() {
	test_usage "lbu status"
}

lbu_stat_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu status" \
		-e empty \
		lbu stat -h
}

lbu_st_usage_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"usage: lbu status" \
		-e empty \
		lbu st -h
}

lbu_package_body() {
	init_env

	atf_check \
		lbu package

	atf_check \
		-o match:"etc/localtime" \
		-o match:"etc/hosts" \
		tar -ztf $(hostname).apkovl.tar.gz
}

get_sysconfdir() {
	sysconfdir=$(grep "^sysconfdir=" $(atf_get_srcdir)/../lbu \
		| cut -d= -f2-)
	if [ -z "$sysconfdir" ]; then
		atf_fail "sysconfdir is not set"
	fi
}

lbu_package_encrypted_body() {
	atf_require_prog openssl
	init_env
	get_sysconfdir
	mkdir -p "$PWD"/"$sysconfdir"
	(
		echo 'DEFAULT_CIPHER=aes-256-cbc'
		echo 'ENCRYPTION=$DEFAULT_CIPHER'
		echo 'PASSWORD=foobar'
	) > "$PWD/$sysconfdir/lbu.conf"

	atf_check \
		-e match:"WARNING" \
		lbu package

	if ! [ -e "$(hostname).apkovl.tar.gz.aes-256-cbc" ]; then
		atf_fail "ecrypted archive not created"
	fi
}

lbu_package_pre_post_hooks_body() {
	init_env
	get_sysconfdir

	mkdir -p "$PWD/$sysconfdir/pre-package.d" \
		"$PWD/$sysconfdir/post-package.d"
	cat >"$PWD/$sysconfdir/pre-package.d/foo.sh"<<-EOF
		#!/bin/sh
		echo \$0
	EOF
	chmod +x "$PWD/$sysconfdir/pre-package.d/foo.sh"
	ln -s ../pre-package.d/foo.sh  \
		"$PWD/$sysconfdir/post-package.d/foo.sh"

	atf_check \
		-e match:"pre-package" \
		-e match:"post-package" \
		lbu package
}

lbu_commit_body() {
	init_env
	mkdir -p backup

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit

	atf_check \
		-o match:"etc/localtime" \
		-o match:"etc/hosts" \
		tar -ztf "backup/$(hostname).apkovl.tar.gz"
}

lbu_commit_backup_body() {
	init_env
	mkdir -p backup

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit

	test -f "backup/$(hostname).apkovl.tar.gz" \
		|| atf_fail "archive not created on second commit"

	ls "backup/$(hostname)".[0-9]*.tar.gz >/dev/null 2>&1 \
		|| atf_fail "backup of previous archive not created"
}

lbu_commit_delete_old_body() {
	init_env
	mkdir -p backup

	touch backup/old.apkovl.tar.gz \
		backup/stale.apkovl.tar.gz

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -s not-exit:0 \
		-e match:"Please use -d to replace" \
		lbu commit

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit -d

	if [ -f "backup/old.apkovl.tar.gz" ] \
	   || [ -f "backup/stale.apkovl.tar.gz" ]; then
		atf_fail "old apkovl files were not removed with -d"
	fi

	test -f "backup/$(hostname).apkovl.tar.gz" \
		|| atf_fail "archive not created with -d"
}

lbu_commit_dryrun_body() {
	init_env
	mkdir -p backup

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit -n

	if ls backup/*.apkovl.tar.gz* >/dev/null 2>&1; then
		atf_fail "archive was created despite dryrun"
	fi
}

lbu_commit_encrypted_body() {
	atf_require_prog openssl
	init_env
	get_sysconfdir
	mkdir -p "$PWD/$sysconfdir"
	(
		echo 'DEFAULT_CIPHER=aes-256-cbc'
		echo 'ENCRYPTION=$DEFAULT_CIPHER'
		echo 'PASSWORD=foobar'
	) > "$PWD/$sysconfdir/lbu.conf"

	mkdir -p backup

	LBU_BACKUPDIR=backup BACKUP_LIMIT=1 \
		atf_check -o ignore -e ignore \
		lbu commit

	encfile="${PWD}/backup/$(hostname).apkovl.tar.gz.aes-256-cbc"
	if [ ! -f "$encfile" ]; then
		atf_fail "encrypted archive not created"
	fi
}

lbu_revert_basic_body() {
	init_env
	mkdir -p backup

	echo "current content" > "backup/$(hostname).apkovl.tar.gz"
	echo "revision content" > "backup/$(hostname).20250101000000.tar.gz"

	LBU_BACKUPDIR=backup \
		atf_check -s exit:0 \
		-o match:"Reverting" \
		-e empty \
		lbu revert -v "$(hostname).20250101000000.tar.gz"

	# Verify old current was backed up
	ls backup/"$(hostname)".[0-9]*.tar.gz >/dev/null 2>&1 \
		|| atf_fail "backup of current was not created"

	# Verify revision became new current
	atf_check \
		-o match:"revision content" \
		cat "backup/$(hostname).apkovl.tar.gz"

	# Verify revision file no longer exists
	if [ -f "backup/$(hostname).20250101000000.tar.gz" ]; then
		atf_fail "revision file was not removed"
	fi
}

lbu_revert_file_not_found_body() {
	init_env
	mkdir -p backup

	echo "current content" > "backup/$(hostname).apkovl.tar.gz"

	LBU_BACKUPDIR=backup \
		atf_check -s exit:1 \
		-o empty \
		-e match:"file not found" \
		lbu revert "nonexistent.tar.gz"

	# Verify current apkovl was not touched
	atf_check \
		-o match:"current content" \
		cat "backup/$(hostname).apkovl.tar.gz"
}

lbu_revert_no_media_body() {
	init_env
	atf_check -s exit:1 \
		-o empty \
		-e match:"usage.*revert" \
		lbu revert somefile
}

lbu_status_no_changes_body() {
	init_env
	mkdir -p backup committed/etc
	touch committed/etc/hosts
	touch committed/etc/localtime
	tar -czf "backup/$(hostname).apkovl.tar.gz" -C committed .

	LBU_BACKUPDIR=backup \
		atf_check -s exit:0 \
		-o empty \
		-e empty \
		lbu status
}

lbu_status_added_body() {
	init_env
	mkdir -p backup committed/etc
	echo "hosts content" > committed/etc/hosts
	tar -czf "backup/$(hostname).apkovl.tar.gz" -C committed .

	LBU_BACKUPDIR=backup \
		atf_check -s exit:0 \
		-o match:"^A etc/localtime" \
		-e empty \
		lbu status
}

lbu_status_deleted_body() {
	init_env
	mkdir -p backup committed/etc
	echo "hosts content" > committed/etc/hosts
	echo "localtime content" > committed/etc/localtime
	echo "extra content" > committed/etc/extra
	tar -czf "backup/$(hostname).apkovl.tar.gz" -C committed .

	LBU_BACKUPDIR=backup \
		atf_check -s exit:0 \
		-o match:"^D etc/extra" \
		-e empty \
		lbu status
}

lbu_status_updated_body() {
	init_env
	mkdir -p backup committed/etc
	echo "old hosts content" > committed/etc/hosts
	echo "localtime content" > committed/etc/localtime
	touch -t 202501010000 committed/etc/hosts
	tar -czf "backup/$(hostname).apkovl.tar.gz" -C committed .

	LBU_BACKUPDIR=backup \
		atf_check -s exit:0 \
		-o match:"^U etc/hosts" \
		-e empty \
		lbu status
}

lbu_status_all_default_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"^U etc/hosts" \
		-o match:"^U etc/localtime" \
		-e empty \
		lbu status -a
}

lbu_exclude_add_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"Adding etc/hosts to" \
		-e empty \
		lbu exclude -v etc/hosts

	atf_check -s exit:0 \
		-o match:"-etc/hosts" \
		cat etc/apk/protected_paths.d/lbu.list
}

lbu_exclude_remove_body() {
	init_env
	mkdir -p etc/apk/protected_paths.d
	echo "-etc/hosts" > etc/apk/protected_paths.d/lbu.list

	atf_check -s exit:0 \
		-o match:"Removing etc/hosts from" \
		-e empty \
		lbu exclude -r -v etc/hosts

	if grep -q 'etc/hosts' etc/apk/protected_paths.d/lbu.list; then
		atf_fail "etc/hosts was not removed from exclude list"
	fi
}

lbu_exclude_existing_body() {
	init_env
	mkdir -p etc/apk/protected_paths.d
	echo "-etc/hosts" > etc/apk/protected_paths.d/lbu.list

	atf_check -s exit:0 \
		-o match:"etc/hosts is already in" \
		-e empty \
		lbu exclude -v etc/hosts
}

lbu_exclude_remove_nonexistent_body() {
	init_env
	mkdir -p etc/apk/protected_paths.d
	: > etc/apk/protected_paths.d/lbu.list

	atf_check -s exit:0 \
		-o match:"etc/hosts is not in" \
		-e empty \
		lbu exclude -r -v etc/hosts
}

lbu_exclude_list_body() {
	init_env
	mkdir -p etc/apk/protected_paths.d
	cat > etc/apk/protected_paths.d/lbu.list <<-EOF
		+etc/hosts
		-etc/localtime
	EOF

	atf_check -s exit:0 \
		-o match:"Exclude files:" \
		-o match:"^etc/localtime" \
		-o not-match:"etc/hosts" \
		-e empty \
		lbu exclude -l -v
}

lbu_include_list_body() {
	init_env
	mkdir -p etc/apk/protected_paths.d
	cat > etc/apk/protected_paths.d/lbu.list <<-EOF
		+etc/hosts
		-etc/localtime
	EOF

	atf_check -s exit:0 \
		-o match:"Include files:" \
		-o match:"^etc/hosts" \
		-o not-match:"etc/localtime" \
		-e empty \
		lbu include -l -v
}

lbu_list_basic_body() {
	init_env
	atf_check -s exit:0 \
		-o match:"^etc/hosts" \
		-o match:"^etc/localtime" \
		-e empty \
		lbu list
}

lbu_root_files_body() {
	init_env
	touch foo.txt .gitignore
	mkdir targetdir
	ln -s targetdir linkdir

	atf_check -s exit:0 \
		-o ignore \
		-e empty \
		lbu add /foo.txt /.gitignore /linkdir

	atf_check -s exit:0 \
		-o match:"^foo.txt" \
		-o match:"^\\.gitignore" \
		-o match:"^linkdir" \
		-e empty \
		lbu list

	atf_check -s exit:0 \
		-o empty \
		-e empty \
		lbu package

	atf_check \
		-o match:"foo.txt" \
		-o match:"\\.gitignore" \
		-o match:"linkdir" \
		tar -ztf "$(hostname).apkovl.tar.gz"
}

lbu_listbackup_basic_body() {
	init_env
	mkdir -p backup
	touch backup/$(hostname).20200101000000.tar.gz
	touch backup/$(hostname).99991231235959.tar.gz

	LBU_BACKUPDIR=backup atf_check -s exit:0 \
		-o match:"^$(hostname).20200101000000.tar.gz" \
		-o match:"^$(hostname).99991231235959.tar.gz" \
		-e empty \
		lbu list-backup
}

lbu_listbackup_no_media_body() {
	init_env
	atf_check -s exit:1 \
		-o match:"usage:" \
		-e ignore \
		lbu list-backup
}
