docker: Enable reruning tests without bringing down setup

Add flag "--retest" which uses the existing docker setup to run the
tests again while changing the external environment, or after making
changes to the tests.

Change-Id: I47ee54c76db97f6da9955cc18a3a6ef765371eba
diff --git a/test/docker/lib_options.sh b/test/docker/lib_options.sh
new file mode 100755
index 0000000..87c77cd
--- /dev/null
+++ b/test/docker/lib_options.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+options_prefix() { # array_name option_name
+    local array_name=$1
+    local array_elements_name=$array_name[@]
+    local option=$2
+    local items=("${!array_elements_name}")
+    local item
+    eval "$array_name=()"
+    for item in "${items[@]}"; do
+        eval "$array_name"'+=("$option" "$item")'
+    done
+}
diff --git a/test/docker/run.sh b/test/docker/run.sh
index 7d493ff..681b05b 100755
--- a/test/docker/run.sh
+++ b/test/docker/run.sh
@@ -2,6 +2,8 @@
 
 readlink -f / &> /dev/null || readlink() { greadlink "$@" ; } # for MacOS
 MYDIR=$(dirname -- "$(readlink -f -- "$0")")
+MYPROG=$(basename -- "$0")
+source "$MYDIR/lib_options.sh"
 ARTIFACTS=$MYDIR/gerrit/artifacts
 
 die() { echo -e "\nERROR: $@" ; kill $$ ; exit 1 ; } # error_message
@@ -20,11 +22,9 @@
 }
 
 usage() { # [error_message]
-    local prog=$(basename -- "$0")
-
     cat <<-EOF
 Usage:
-    $prog [--task-plugin-jar|-t <FILE_PATH>] [--gerrit-war|-g <FILE_PATH>]
+    $MYPROG [--task-plugin-jar|-t <FILE_PATH>] [--gerrit-war|-g <FILE_PATH>]
 
     This tool runs the plugin functional tests in a Docker environment built
     from the gerritcodereview/gerrit base Docker image.
@@ -61,6 +61,13 @@
         '/task/test/docker/run_tests/start.sh'
 }
 
+retest() {
+    docker-compose "${COMPOSE_ARGS[@]}" exec -T --user=gerrit_admin \
+        run_tests task/test/docker/run_tests/start.sh retest
+    RESULT=$?
+    cleanup
+}
+
 get_run_test_container() {
     docker-compose "${COMPOSE_ARGS[@]}" ps | grep run_tests | awk '{ print $1 }'
 }
@@ -73,6 +80,10 @@
         echo "To exec into runtests container, use following command:"
         echo "docker exec -it $(get_run_test_container) /bin/bash"
         echo ""
+        options_prefix "COMPOSE_ARGS" "--compose-arg"
+        echo "Use command below to re run tests after making changes to test scripts"
+        echo " $MYDIR/$MYPROG --retest --preserve ${COMPOSE_ARGS[@]}"
+        echo ""
         echo "Run the following command to bring down the setup:"
         echo "docker-compose ${COMPOSE_ARGS[@]} down -v --rmi local"
     else
@@ -81,16 +92,23 @@
 }
 
 PRESERVE="false"
+RETEST="false"
+COMPOSE_ARGS=()
 while (( "$#" )) ; do
     case "$1" in
         --help|-h)                usage ;;
         --gerrit-war|-g)          shift ; GERRIT_WAR=$1 ;;
         --task-plugin-jar|-t)     shift ; TASK_PLUGIN_JAR=$1 ;;
         --preserve)               PRESERVE="true" ;;
+        --retest)                 RETEST="true" ;;
+        --compose-arg)            shift ; COMPOSE_ARGS+=("$1") ;;
         *)                        usage "invalid argument $1" ;;
     esac
     shift
 done
+
+[ "$RETEST" = "true" ] && { retest ; exit "$RESULT" ; }
+
 PROJECT_NAME="task_$$"
 COMPOSE_YAML="$MYDIR/docker-compose.yaml"
 COMPOSE_ARGS=(--project-name "$PROJECT_NAME" -f "$COMPOSE_YAML")
diff --git a/test/docker/run_tests/start.sh b/test/docker/run_tests/start.sh
index 9b40537..ac185d8 100755
--- a/test/docker/run_tests/start.sh
+++ b/test/docker/run_tests/start.sh
@@ -3,6 +3,11 @@
 USER_RUN_TESTS_DIR="$USER_HOME"/"$RUN_TESTS_DIR"
 cp -r /task "$USER_HOME"/
 
+if [ "$1" = "retest" ] ; then
+    cd "$USER_RUN_TESTS_DIR"/../../ && ./check_task_statuses.sh "$GERRIT_HOST"
+    exit $?
+fi
+
 ./"$USER_RUN_TESTS_DIR"/wait-for-it.sh "$GERRIT_HOST":29418 -t 60 -- echo "gerrit is up"
 
 echo "Creating a default user account ..."