Add functional test framework and some basic tests

hpgit lacks of functional tests that ensure it works as expected and
that can be used to automate code verifications.
Functional tests will help to improve hpgit software quality.

JIRA: CICD-1089
Change-Id: Id9764b93c504da3fcc8d8c56415120536388a432
This commit is contained in:
Davide Guerri 2014-01-02 16:51:19 +00:00
parent fd3524e1b7
commit 8e066904b5
10 changed files with 516 additions and 0 deletions

1
functional-tests/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test-*-*

View File

@ -0,0 +1,24 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
source $BASE_DIR/libs/utils.lib
function test_version_output() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
git-hp --version >/dev/null 2>&1
return $?
}
TESTS="test_version_output"
for test in $TESTS; do
$test && log INFO "$TEST_NAME::$test() passed." || \
log ERROR "$TEST_NAME::$test() failed!"
done

View File

@ -0,0 +1,25 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
source $BASE_DIR/libs/utils.lib
function test_help_output() {
local com="$1"
log DEBUG "Starting $TEST_NAME::$FUNCNAME command $com"
help1=$(git-hp${com:+ }${com} --help)
help2=$(git-hp${com:+ }${com} -h)
help3=$(git-hp help${com:+ }${com})
[ -z "$help1" -o -z "$help2" -o -z "$help3" -o \
"$help1" != "$help2" -o "$help2" != "$help3" ] && return 1 || return 0
}
for com in "" "import-upstream" ; do
test_help_output $com && log INFO "test_help_output::${com:-null} passed." || \
log ERROR "test_help_output::${com:-null} failed!"
done

View File

@ -0,0 +1,55 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
source $BASE_DIR/libs/utils.lib
REPO_NAME="empty-repo"
UPSTREAM_REPO=$(git rev-parse --show-toplevel)
TEST_BASE_REF="2c4bf67b5c416adfb162d9ca1fb4b0bf353fbb2a"
CHERRY_PICKS="19b89746d08fa224bb8aba12106dbc330cb5d019 \
5d4fbe79037c3b2516216258a907d3a02f0b205c"
TEST_REBASE_REF="fd3524e1b7353cda228b6fb73c3a2d34a4fee4de"
function test_no_local_changes() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
prepare_for_hpgit $TEST_DIR $REPO_NAME $UPSTREAM_REPO $TEST_BASE_REF \
$TEST_NAME
pushd $TEST_DIR/$REPO_NAME >/dev/null
log DEBUG "Cherry picking upstream commits"
for cp in $CHERRY_PICKS; do
log DEBUG "Cherry picking commit $cp"
git cherry-pick $cp >/dev/null || return 1
done
git push -u origin master --quiet >/dev/null || return 1
git checkout master --quiet || return 1
log DEBUG "Rebasing local patches onto upstream version $TEST_REBASE_REF"
git branch import/$TEST_NAME-new $TEST_REBASE_REF --quiet || return 1
local result="$(git-hp import-upstream import/$TEST_NAME-new)"
echo "$result" | grep "There are no local changes to be applied!" >/dev/null
if [ "$?" -ne 0 ]; then
popd >/dev/null
return 1
fi
popd >/dev/null
}
TESTS="test_no_local_changes"
for test in $TESTS; do
$test && log INFO "$TEST_NAME::$test() passed." || \
log ERROR "$TEST_NAME::$test() failed!"
done

View File

@ -0,0 +1,76 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
source $BASE_DIR/libs/utils.lib
REPO_NAME="empty-repo"
UPSTREAM_REPO=$(git rev-parse --show-toplevel)
TEST_BASE_REF="2c4bf67b5c416adfb162d9ca1fb4b0bf353fbb2a"
CHERRY_PICKS="19b89746d08fa224bb8aba12106dbc330cb5d019 \
5d4fbe79037c3b2516216258a907d3a02f0b205c"
TEST_REBASE_REF="fd3524e1b7353cda228b6fb73c3a2d34a4fee4de"
SUCCESS_SHA1="b8aee554fd9e22c05cfd8c20f6c19d26320fc293 ?-"
function test_simple_rebase() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
prepare_for_hpgit $TEST_DIR $REPO_NAME $UPSTREAM_REPO $TEST_BASE_REF \
$TEST_NAME
pushd $TEST_DIR/$REPO_NAME >/dev/null
log DEBUG "Creating a local patch"
cat <<EOP | patch -tsp1 || return 1
diff --git a/setup.py b/setup.py
index 170ec46..251e1dd 100644
--- a/setup.py
+++ b/setup.py
@@ -28,6 +28,8 @@ setup(
version=version.version,
author="Darragh Bailey",
author_email="dbailey@hp.com",
+ maintainer="Davide Guerri",
+ maintainer_email="davide.guerri@hp.com",
description=("Tool supporting HPCloud git workflows."),
license="Proprietary",
keywords="git hpcloud workflow",
EOP
git commit -a -m "Add maintainer info" --quiet || return 1
git push -u origin master --quiet >/dev/null || return 1
log DEBUG "Cherry picking upstream commits"
for cp in $CHERRY_PICKS; do
log DEBUG "Cherry picking commit $cp"
git cherry-pick $cp >/dev/null || return 1
done
git push --quiet || return 1
git checkout master --quiet || return 1
log DEBUG "Rebasing local patches onto upstream version $TEST_REBASE_REF"
git branch import/$TEST_NAME-new $TEST_REBASE_REF --quiet || return 1
git-hp import-upstream import/$TEST_NAME-new >/dev/null || return 1
local test_sha1="$(git log --pretty=format:"%s"|sort | shasum -p -)"
if [ "$test_sha1" != "$SUCCESS_SHA1" ]
then
popd >/dev/null
return 1
fi
popd >/dev/null
}
TESTS="test_simple_rebase"
for test in $TESTS; do
$test && log INFO "$TEST_NAME::$test() passed." || \
log ERROR "$TEST_NAME::$test() failed!"
done

View File

@ -0,0 +1,71 @@
# How to run
Just run
run_tests.sh
That script will install a virtual env with hpgit (from the current repo clone)
and will run every script which name match the following regex:
([0-9]{3})-test_(.+).sh
Order of execution is given by $1 and test name by $2.
It's also possible to run single tests creating a test directory and running
BASE_TEST_DIR=<your base test dir> 0xx-test_<your test name>.sh
But that will need a git-hp executable in yout path.
# Creating more tests
Simply copy
sample-test_name_here.sh
giving it a name that matches the aforementioned regexp.
Then edit the file definig a function that performs the actual test
function test_name1() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
return 0
}
Leave rest of the code as it is.
## Reference of global variables/functions available in this framework
logging.lib
-----------
set_verbority() Set verbosity level. Available verbosities are:
"ERROR WARNING INFO DEBUG"
log() Print the given string, with a decoration, if current
verbosity level is less or equal to the one passed as
an argument.
utils.lib
-----------
TEST_DIR Testing directory. Objects pertaining a test should be
created under that directory.
TEST_NAME The name of current test. Extracted from the test filename.
prepare_for_hpgit() Using the current hpgit repo, create an initial
configuration useful for testing hp-git. After invoking it
a "$TEST_DIR/$REPO_NAME"
## Environment variable used by the test framework
VERBOSITY Set tests verbosity. Valid verbosities are:
"ERROR WARNING INFO DEBUG"
LEAVE_DIR If equals to "yes", testing framework won't remove testing
directory. Useful for debugging and to inspect tests
results.

View File

@ -0,0 +1,87 @@
# Utility functions/macros for logging
_VERBOSITY="INFO"
_VERBOSITIES="ERROR WARNING INFO DEBUG"
function list_contains() {
if [ $# -ne 2 ]; then
_log "FATAL" "Invalid number of argument! \
(${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]}::list_contains())"
exit 127
fi
local list=$1
local obj=$2
for word in $list; do
[ "$word" == "$obj" ] && return 0
done
return 1
}
function set_verbority() {
if [ $# -ne 1 ]; then
_log "FATAL" "Invalid number of argument! \
(${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]}::set_verbority())"
exit 127
fi
local verb=$1
if list_contains "$_VERBOSITIES" "$1"; then
_VERBOSITY=$verb
else
_log "FATAL" "Invalid verbosity level specified: '$1'"
exit 127
fi
}
# Return 0 if current VERBISITY is greater equal than the argument
function check_verbosity() {
if [ $# -ne 1 ]; then
_log "FATAL" "Invalid number of argument! \
(${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]}::check_verbosity())"
exit 127
fi
local verb=$1
for verbosity in $_VERBOSITIES; do
if [ "$verbosity" == "$verb" ]; then
return 0
elif [ "$_VERBOSITY" == "$verbosity" ]; then
return 1
fi
done
return 1
}
function _log() {
local level=$1
shift
local messages=$@
printf "[%-7s] %s\n" "$level" "$messages"
}
function log() {
if [ $# -ne 2 ]; then
_log "FATAL" "Invalid number of argument! \
(${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]}::log())"
exit 127
fi
local level=$1
shift
local messages=$@
list_contains "$_VERBOSITIES" "$level"
if [ $? -ne 0 ]; then
_log "FATAL" "Invalid verbosity level specified: '$1'"
exit 127
fi
if check_verbosity $level; then
_log "$level" "$messages"
fi
}

View File

@ -0,0 +1,61 @@
# Utility functions/macros
if [ -z "$BASE_TEST_DIR" ]; then
log ERROR "Please define BASE_TEST_DIR variable"
exit 1
fi
TEST_NAME=$(basename $0 | cut -d_ -f2- | cut -d'.' -f 1)
TEST_DIR="$BASE_TEST_DIR/test-dir_$TEST_NAME"
function _clean_up() {
if [ -z "$LEAVE_DIR" ]; then
log DEBUG "Removing test directory"
rm -rf $TEST_DIR
fi
}
VERBOSITY=${VERBOSITY:-INFO}
set_verbority $VERBOSITY
mkdir -p "$TEST_DIR"
# Define an handler for clean_up
trap "_clean_up; exit 0" EXIT
function prepare_for_hpgit() {
local TEST_DIR="$1"
local REPO_NAME="$2"
local UPSTREAM_REPO="$3"
local TEST_BASE_REF="$4"
local TEST_NAME="$5"
log DEBUG "Creating bare repo '$REPO_NAME.bare'"
rm -rf $TEST_DIR/$REPO_NAME.bare >/dev/null 2>&1
mkdir $TEST_DIR/$REPO_NAME.bare
pushd $TEST_DIR/$REPO_NAME.bare >/dev/null
git init --bare --quiet || return 1
popd >/dev/null
log DEBUG "Cloning repo $REPO_NAME"
rm -rf $TEST_DIR/$REPO_NAME >/dev/null 2>&1
mkdir $TEST_DIR/$REPO_NAME
pushd $TEST_DIR/$REPO_NAME >/dev/null
git init --quiet || return 1
git config push.default simple --quiet || return 1
git remote add origin $TEST_DIR/$REPO_NAME.bare || return 1
log DEBUG "Fetching upstream testing version"
git remote add upstream $UPSTREAM_REPO || return 1
git fetch --all --quiet >/dev/null || return 1
git for-each-ref refs/remotes/upstream --format "%(refname:short)" | \
sed -e 's:\(upstream/\(.*\)\)$:\1\:refs/heads/upstream/\2:' | \
xargs git push --quiet --tags origin || return 1
log DEBUG "Creating a new branch from version $TEST_BASE_REF"
git checkout -b import/$TEST_NAME $TEST_BASE_REF --quiet || return 1
git checkout -b master --quiet || return 1
popd >/dev/null
}

87
functional-tests/run_tests.sh Executable file
View File

@ -0,0 +1,87 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
INSTALL_DIR=$(dirname $BASE_DIR)
TIME_STAMP=$(date +%Y%m%d%H%M%S)
export BASE_TEST_DIR=$(mktemp -d $BASE_DIR/test-$TIME_STAMP-XXXX)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
export VERBOSITY="${VERBOSITY:-INFO}"
set_verbority $VERBOSITY
if [ -n "$LEAVE_DIR" -a "$LEAVE_DIR" == "yes" ]; then
export LEAVE_DIR="yes"
else
unset LEAVE_DIR
fi
function check_app() {
if [ $# -ne 1 ]; then
log ERROR "Invalid number of argument! \
(${BASH_SOURCE[1]##*/} ${BASH_LINENO[0]}::check_app())"
exit 127
fi
local app=$1
if [ ! -x $(which $app) ]; then
log ERROR "App '$app' not found"
exit 127
fi
return 0
}
function _clean_up() {
log DEBUG "Cleaning up"
# Deactivate virtualenv
log DEBUG "Deactivate virtualenv"
deactivate >/dev/null 2>&1
if [ -z "$LEAVE_DIR" ]; then
log DEBUG "Removing base test directory"
rm -rf $BASE_TEST_DIR
fi
}
# Define an handler for clean_up
trap "_clean_up; exit 0" EXIT
# ----- Start
log DEBUG "Initializing testbed"
check_app virtualenv
log DEBUG "Creating virtualenv for hpgit"
rm -rf $BASE_TEST_DIR/virtualenv >/dev/null 2>&1
virtualenv $BASE_TEST_DIR/virtualenv >/dev/null 2>&1
if [ $? -ne 0 ]; then
log ERROR "Virtualenv creation failed"
exit 1
fi
log DEBUG "Activating virtualenv for hpgit"
source $BASE_TEST_DIR/virtualenv/bin/activate
if [ $? -ne 0 ]; then
log ERROR "Virtualenv activation failed"
exit 1
fi
log DEBUG "Installing hpgit"
easy_install -q $INSTALL_DIR >/dev/null 2>&1
if [ $? -ne 0 ]; then
log ERROR "hp git installation failed!"
exit 1
fi
for test in $(ls [[:digit:]][[:digit:]][[:digit:]]-test*); do
$BASE_DIR/$test
done

View File

@ -0,0 +1,29 @@
#!/bin/bash
BASE_DIR=$(cd $(dirname $0); pwd -P)
# Include and run common test functions and initializations
source $BASE_DIR/libs/logging.lib
source $BASE_DIR/libs/utils.lib
function test_name1() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
return 0
}
function test_name2() {
log DEBUG "Starting $TEST_NAME::$FUNCNAME"
return 0
}
TESTS="test_name1 test_name2"
for test in $TESTS; do
$test && log INFO "$TEST_NAME::$test() passed." || \
log ERROR "$TEST_NAME::$test() failed!"
done