#!/bin/sh

# testsuite - run tests in our test environment
#
# Copyright (C) 2013 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA

set -e

# get the script name
script="`basename "$0"`"

# redirect stderr to stdout to have readable logs
exec 2>&1

# stop any running daemons that might interfere
echo "$script: stopping services..."
service slapd stop || true
service nslcd stop || true
service pynslcd stop || true
service nscd stop || true
service unscd stop || true

# temporary file to keep nslcd debug output
nslcd_debug_log=`mktemp -t nslcd.debug.log.XXXXXX`

if [ "$(aa-enabled 2> /dev/null)" = "Yes" ]; then
  apparmor_enabled="true"
else
  apparmor_enabled="false"
fi

_apparmor_check() {
	# allow command to fail if running on Ubuntu-armhf (due to LP: #2008393)
	"$@" && return 0
	_ret=$?

	if [ "$(dpkg-vendor --query Vendor)-$(dpkg --print-architecture)" = "Ubuntu-armhf" ]; then
		echo "WARNING: failed to perform apparmor command: $*" >&2
		echo "On armhf and Ubuntu DEP8 infrastructure, this is not a fatal error." >&2
		echo "See LP: #2008393 for details." >&2
		return 0
	fi

	echo "apparmor command failed: $*" >&2
	exit $_ret
}


# Clean up on exit
cleanup() {
  echo "$script: cleaning up..."
  service nslcd stop || true
  service pynslcd stop || true
  if [ "$apparmor_enabled" = true ]; then
    echo "$script: restoring apparmor config for slapd..."
    rm /etc/apparmor.d/local/usr.sbin.slapd
    [ -f $tmpslapd/apparmor.bak ] && mv $tmpslapd/apparmor.bak /etc/apparmor.d/local/usr.sbin.slapd
    _apparmor_check apparmor_parser -W -T -r /etc/apparmor.d/usr.sbin.slapd
  fi
  [ -n "$tmpslapd" ] && tests/setup_slapd.sh "$tmpslapd" clean
  echo "$script: restoring configuration..."
  if [ -n "$bkdir" ]
  then
    cp -p "$bkdir"/nsswitch.conf /etc/nsswitch.conf
    cp -p "$bkdir"/nslcd.conf  /etc/nslcd.conf
    rm -rf "$bkdir"
  fi
  if [ -n "$nslcd_debug_log" ]
  then
    rm -f "$nslcd_debug_log"
  fi
}
trap cleanup EXIT

# make backup of some files
echo "$script: making backup of old configuration..."
bkdir=`mktemp -d -t backups.XXXXXX`
cp -p /etc/nsswitch.conf "$bkdir"/
cp -p /etc/nslcd.conf "$bkdir"/

# configure nsswitch.conf
echo "$script: configuring /etc/nsswitch.conf..."
tests/testenv.sh nss_enable \
  passwd group shadow hosts networks protocols services ethers rpc netgroup aliases

# configure PAM?

# set up test environment
echo "$script: setting up test slapd..."
tmpslapd=`mktemp -d -t slapd.XXXXXX`
tests/setup_slapd.sh "$tmpslapd" setup
# if apparmor is used, allow access to test directory
if [ "$apparmor_enabled" = true ]; then
  # this directory is like /etc/slapd
  echo "$script: backing up and replacing apparmor config for slapd..."
  [ -f /etc/apparmor.d/local/usr.sbin.slapd ] && mv /etc/apparmor.d/local/usr.sbin.slapd $tmpslapd/apparmor.bak
  echo "$tmpslapd/** kwr," >> /etc/apparmor.d/local/usr.sbin.slapd
  _apparmor_check apparmor_parser -W -T -r /etc/apparmor.d/usr.sbin.slapd
fi
# configure and start slapd
tests/setup_slapd.sh "$tmpslapd" start

# set up nslcd.conf
echo "$script: setting up nslcd.conf..."
cat tests/nslcd-test.conf > /etc/nslcd.conf

# start nslcd (or pynslcd)
[ -x /usr/sbin/nslcd ] && daemon="nslcd" || true
[ -x /usr/sbin/pynslcd ] && daemon="pynslcd" || true
if [ -z "$daemon" ]
then
  echo "$script: neither nslcd nor pynslcd found..."
  exit 1
fi
echo "$script: starting $daemon..."
/usr/sbin/$daemon -d > "$nslcd_debug_log" 2>&1 &

# allow for a second to have nslcd up and running
sleep 1

# see if anything failed
fail=""

# see if test environment is in order
echo "$script: check test environment..."
tests/testenv.sh check || fail="fail"
tests/testenv.sh check_nss \
  passwd group shadow hosts networks protocols services ethers rpc netgroup aliases || fail="fail"

# dump nslcd debug output on failure
if [ -n "$fail" ]
then
  echo "$script: FAIL"
  echo "$script: $daemon debug output:"
  service $daemon stop || true
  cat "$nslcd_debug_log"
  exit 1
fi

# run the NSS tests
echo "$script: running NSS tests..."
tests/test_nsscmds.sh || fail="fail"

# run the PAM tests
echo "$script: running PAM tests..."
tests/test_pamcmds.sh || fail="fail"

# dump nslcd debug output on failure
if [ -n "$fail" ]
then
  echo "$script: FAIL"
  echo "$script: $daemon debug output:"
  service $daemon stop || true
  cat "$nslcd_debug_log"
  exit 1
else
  echo "$script: all tests passed!"
  exit 0
fi
