diff --git a/functional-tests/.gitignore b/functional-tests/.gitignore new file mode 100644 index 0000000..c7bae14 --- /dev/null +++ b/functional-tests/.gitignore @@ -0,0 +1 @@ +test-*-* \ No newline at end of file diff --git a/functional-tests/010-test_version_check.sh b/functional-tests/010-test_version_check.sh new file mode 100755 index 0000000..1971e31 --- /dev/null +++ b/functional-tests/010-test_version_check.sh @@ -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 diff --git a/functional-tests/020-test_help.sh b/functional-tests/020-test_help.sh new file mode 100755 index 0000000..dfa95cc --- /dev/null +++ b/functional-tests/020-test_help.sh @@ -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 diff --git a/functional-tests/030-test_no_local_changes.sh b/functional-tests/030-test_no_local_changes.sh new file mode 100755 index 0000000..d5006a8 --- /dev/null +++ b/functional-tests/030-test_no_local_changes.sh @@ -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 diff --git a/functional-tests/040-test_simple_rebase.sh b/functional-tests/040-test_simple_rebase.sh new file mode 100755 index 0000000..ae54169 --- /dev/null +++ b/functional-tests/040-test_simple_rebase.sh @@ -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 </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 diff --git a/functional-tests/README.md b/functional-tests/README.md new file mode 100644 index 0000000..ba28b8e --- /dev/null +++ b/functional-tests/README.md @@ -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= 0xx-test_.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. \ No newline at end of file diff --git a/functional-tests/libs/logging.lib b/functional-tests/libs/logging.lib new file mode 100644 index 0000000..35bb332 --- /dev/null +++ b/functional-tests/libs/logging.lib @@ -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 +} diff --git a/functional-tests/libs/utils.lib b/functional-tests/libs/utils.lib new file mode 100644 index 0000000..c859733 --- /dev/null +++ b/functional-tests/libs/utils.lib @@ -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 +} + diff --git a/functional-tests/run_tests.sh b/functional-tests/run_tests.sh new file mode 100755 index 0000000..24556c5 --- /dev/null +++ b/functional-tests/run_tests.sh @@ -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 diff --git a/functional-tests/sample-test_name_here.sh b/functional-tests/sample-test_name_here.sh new file mode 100755 index 0000000..e2ebca4 --- /dev/null +++ b/functional-tests/sample-test_name_here.sh @@ -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