#!/bin/bash set -o errexit # ---------------UPDATE ME-------------------------------# # Increment me any time the environment should be rebuilt. # This includes dependncy changes, directory renames, etc. # Simple integer secuence: 1, 2, 3... environment_version=3 #--------------------------------------------------------# function usage { echo "Usage: $0 [OPTION]..." echo "Run Horizon's test suite(s)" echo "" echo " -V, --virtual-env Always use virtualenv. Install automatically" echo " if not present" echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local" echo " environment" echo " -c, --coverage Generate reports using Coverage" echo " -f, --force Force a clean re-build of the virtual" echo " environment. Useful when dependencies have" echo " been added." echo " -p, --pep8 Just run pep8" echo " -t, --tabs Check for tab characters in files." echo " -y, --pylint Just run pylint" echo " -q, --quiet Run non-interactively. (Relatively) quiet." echo " --with-selenium Run unit tests including Selenium tests" echo " --runserver Run the Django development server for" echo " openstack-dashboard in the virtual" echo " environment." echo " --docs Just build the documentation" echo " --backup-environment Make a backup of the environment on exit" echo " --restore-environment Restore the environment before running" echo " --destroy-environment DEstroy the environment and exit" echo " -h, --help Print this usage message" echo "" echo "Note: with no options specified, the script will try to run the tests in" echo " a virtual environment, If no virtualenv is found, the script will ask" echo " if you would like to create one. If you prefer to run tests NOT in a" echo " virtual environment, simply pass the -N option." exit } # DEFAULTS FOR RUN_TESTS.SH # venv=openstack-dashboard/.dashboard-venv django_with_venv=openstack-dashboard/tools/with_venv.sh dashboard_with_venv=tools/with_venv.sh always_venv=0 never_venv=0 force=0 with_coverage=0 selenium=0 testargs="" django_wrapper="" dashboard_wrapper="" just_pep8=0 just_pylint=0 just_docs=0 just_tabs=0 runserver=0 quiet=0 backup_env=0 restore_env=0 destroy=0 # Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default" [ "$JOB_NAME" ] || JOB_NAME="default" function process_option { case "$1" in -h|--help) usage;; -V|--virtual-env) always_venv=1; never_venv=0;; -N|--no-virtual-env) always_venv=0; never_venv=1;; -p|--pep8) just_pep8=1;; -y|--pylint) just_pylint=1;; -f|--force) force=1;; -t|--tabs) just_tabs=1;; -q|--quiet) quiet=1;; -c|--coverage) with_coverage=1;; --with-selenium) selenium=1;; --docs) just_docs=1;; --runserver) runserver=1;; --backup-environment) backup_env=1;; --restore-environment) restore_env=1;; --destroy-environment) destroy=1;; *) testargs="$testargs $1" esac } function run_server { echo "Starting Django development server..." ${django_wrapper} python openstack-dashboard/dashboard/manage.py runserver echo "Server stopped." } function run_pylint { echo "Running pylint ..." PYLINT_INCLUDE="openstack-dashboard/dashboard horizon/horizon" ${django_wrapper} pylint --rcfile=.pylintrc -f parseable $PYLINT_INCLUDE > pylint.txt || true CODE=$? grep Global -A2 pylint.txt if [ $CODE -lt 32 ] then echo "Completed successfully." exit 0 else echo "Completed with problems." exit $CODE fi } function run_pep8 { echo "Running pep8 ..." rm -f pep8.txt PEP8_EXCLUDE=vcsversion.py PEP8_OPTIONS="--exclude=$PEP8_EXCLUDE --repeat" PEP8_INCLUDE="openstack-dashboard/dashboard horizon/horizon" echo "${django_wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE > pep8.txt" ${django_wrapper} pep8 $PEP8_OPTIONS $PEP8_INCLUDE > pep8.txt || true PEP8_COUNT=`wc -l pep8.txt | awk '{ print $1 }'` if [ $PEP8_COUNT -ge 1 ]; then echo "PEP8 violations found ($PEP8_COUNT):" cat pep8.txt echo "Please fix all PEP8 violations before committing." else echo "No violations found. Good job!" fi } function run_sphinx { echo "Building sphinx..." echo "export DJANGO_SETTINGS_MODULE=dashboard.settings" export DJANGO_SETTINGS_MODULE=dashboard.settings echo "${django_wrapper} sphinx-build -b html docs/source docs/build/html" ${django_wrapper} sphinx-build -b html docs/source docs/build/html echo "Build complete." } function tab_check { TAB_VIOLATIONS=`find horizon/horizon openstack-dashboard/dashboard -type f -regex ".*\.\(css\|js\|py\|html\)" -print0 | xargs -0 awk '/\t/' | wc -l` if [ $TAB_VIOLATIONS -gt 0 ]; then echo "TABS! $TAB_VIOLATIONS of them! Oh no!" HORIZON_FILES=`find horizon/horizon openstack-dashboard/dashboard -type f -regex ".*\.\(css\|js\|py|\html\)"` for TABBED_FILE in $HORIZON_FILES do TAB_COUNT=`awk '/\t/' $TABBED_FILE | wc -l` if [ $TAB_COUNT -gt 0 ]; then echo "$TABBED_FILE: $TAB_COUNT" fi done fi return $TAB_VIOLATIONS; } function destroy_buildout { echo "Removing buildout files..." rm -rf horizon/bin rm -rf horizon/eggs rm -rf horizon/parts rm -rf horizon/develop-eggs rm -rf horizon/horizon.egg-info echo "Buildout files removed." } function destroy_venv { echo "Cleaning virtualenv..." destroy_buildout echo "Removing virtualenv..." rm -rf openstack-dashboard/.dashboard-venv echo "Virtualenv removed." rm -f .environment_version echo "Environment cleaned." } function environment_check { echo "Checking environment." if [ -f .environment_version ]; then ENV_VERS=`cat .environment_version` if [ $ENV_VERS -eq $environment_version ]; then if [ -e ${venv} ]; then # If the environment exists and is up-to-date then set our variables django_wrapper="${django_with_venv}" dashboard_wrapper="${dashboard_with_venv}" echo "Environment is up to date." return 0 fi fi fi if [ $quiet -eq 1 ]; then install_venv else if [ ! -e ${venv} ]; then echo -e "Environment not found. Install? (Y/n) \c" else echo -e "Your environment appears to be out of date. Update? (Y/n) \c" fi read update_env if [ "x$update_env" = "xY" -o "x$update_env" = "x" -o "x$update_env" = "xy" ]; then # Buildout doesn't play nice with upgrading everytime; kill it to be safe destroy_buildout install_venv fi fi } function sanity_check { # Anything that should be determined prior to running the tests, server, etc. if [ ! -e ${venv} ]; then echo "Virtualenv not found at openstack-dashboard/.dashboard-venv. Did install_venv.py succeed?" exit 1 fi if [ ! -f horizon/bin/test ]; then echo "Error: Test script not found at horizon/bin/test. Did buildout succeed?" exit 1 fi if [ ! -f horizon/bin/coverage ]; then echo "Error: Coverage script not found at horizon/bin/coverage. Did buildout succeed?" exit 1 fi if [ ! -f horizon/bin/seleniumrc ]; then echo "Error: Selenium script not found at horizon/bin/seleniumrc. Did buildout succeed?" exit 1 fi } function backup_environment { if [ $backup_env -eq 1 ]; then echo "Backing up environment \"$JOB_NAME\"..." if [ ! -e ${venv} ]; then echo "Environment not installed. Cannot back up." return 0 fi if [ -d /tmp/.horizon_environment/$JOB_NAME ]; then mv /tmp/.horizon_environment/$JOB_NAME /tmp/.horizon_environment/$JOB_NAME.old rm -rf /tmp/.horizon_environment/$JOB_NAME fi mkdir -p /tmp/.horizon_environment/$JOB_NAME cp -r openstack-dashboard/.dashboard-venv /tmp/.horizon_environment/$JOB_NAME/ cp -r horizon/bin /tmp/.horizon_environment/$JOB_NAME/ cp -r horizon/eggs /tmp/.horizon_environment/$JOB_NAME/ cp -r horizon/parts /tmp/.horizon_environment/$JOB_NAME/ cp -r horizon/develop-eggs /tmp/.horizon_environment/$JOB_NAME/ cp -r horizon/horizon.egg-info /tmp/.horizon_environment/$JOB_NAME/ cp .environment_version /tmp/.horizon_environment/$JOB_NAME/ # Remove the backup now that we've completed successfully rm -rf /tmp/.horizon_environment/$JOB_NAME.old echo "Backup completed" fi } function restore_environment { if [ $restore_env -eq 1 ]; then echo "Restoring environment from backup..." if [ ! -d /tmp/.horizon_environment/$JOB_NAME ]; then echo "No backup to restore from." return 0 fi destroy_buildout cp -r /tmp/.horizon_environment/$JOB_NAME/.dashboard-venv openstack-dashboard/ cp -r /tmp/.horizon_environment/$JOB_NAME/bin horizon/ cp -r /tmp/.horizon_environment/$JOB_NAME/eggs horizon/ cp -r /tmp/.horizon_environment/$JOB_NAME/parts horizon/ cp -r /tmp/.horizon_environment/$JOB_NAME/develop-eggs horizon/ cp -r /tmp/.horizon_environment/$JOB_NAME/horizon.egg-info horizon/ cp -r /tmp/.horizon_environment/$JOB_NAME/.environment_version ./ echo "Environment restored successfully." fi } function install_venv { # Install openstack-dashboard with install_venv.py export PIP_DOWNLOAD_CACHE=/tmp/.pip_download_cache export PIP_USE_MIRRORS=true cd openstack-dashboard python tools/install_venv.py cd .. # Install horizon with buildout if [ ! -d /tmp/.buildout_cache ]; then mkdir -p /tmp/.buildout_cache fi cd horizon python bootstrap.py bin/buildout cd .. django_wrapper="${django_with_venv}" dashboard_wrapper="${dashboard_with_venv}" # Make sure it worked and record the environment version sanity_check chmod -R 754 openstack-dashboard/.dashboard-venv echo $environment_version > .environment_version } function wait_for_selenium { # Selenium can sometimes take several seconds to start. STARTED=`grep -irn "Started SocketListener on 0.0.0.0:4444" .selenium_log` if [ $? -eq 0 ]; then echo "Selenium server started." return 0 fi echo -n "." sleep 1 wait_for_selenium } function stop_selenium { if [ $selenium -eq 1 ]; then echo "Stopping Selenium server..." SELENIUM_JOB=`ps -elf | grep "seleniumrc" | grep -v grep` if [ $? -eq 0 ]; then kill `echo "${SELENIUM_JOB}" | awk '{print $4}'` echo "Selenium process stopped." else echo "No selenium process running." fi rm -f .selenium_log fi } function run_tests { sanity_check if [ $selenium -eq 1 ]; then stop_selenium echo "Starting Selenium server..." rm -f .selenium_log ${django_wrapper} horizon/bin/seleniumrc > .selenium_log & wait_for_selenium fi echo "Running Horizon application tests" ${django_wrapper} coverage erase ${django_wrapper} coverage run horizon/bin/test # get results of the Horizon tests OPENSTACK_RESULT=$? echo "Running openstack-dashboard (Django project) tests" cd openstack-dashboard if [ -f local/local_settings.py ]; then cp local/local_settings.py local/local_settings.py.bak fi cp local/local_settings.py.example local/local_settings.py if [ $selenium -eq 1 ]; then ${dashboard_wrapper} coverage run dashboard/manage.py test --with-selenium --with-cherrypyliveserver else ${dashboard_wrapper} coverage run dashboard/manage.py test fi # get results of the openstack-dashboard tests DASHBOARD_RESULT=$? if [ -f local/local_settings.py.bak ]; then cp local/local_settings.py.bak local/local_settings.py rm local/local_settings.py.bak fi cd .. if [ $with_coverage -eq 1 ]; then echo "Generating coverage reports" ${django_wrapper} coverage combine ${django_wrapper} coverage xml -i --omit='/usr*,setup.py,*egg*' ${django_wrapper} coverage html -i --omit='/usr*,setup.py,*egg*' -d reports fi stop_selenium if [ $(($OPENSTACK_RESULT || $DASHBOARD_RESULT)) -eq 0 ]; then echo "Tests completed successfully." else echo "Tests failed." fi exit $(($OPENSTACK_RESULT || $DASHBOARD_RESULT)) } # ---------PREPARE THE ENVIRONMENT------------ # # PROCESS ARGUMENTS, OVERRIDE DEFAULTS for arg in "$@"; do process_option $arg done # If destroy is set, just blow it away and exit. if [ $destroy -eq 1 ]; then destroy_venv exit 0 fi # Ignore all of this if the -N flag was set if [ $never_venv -eq 0 ]; then # Restore previous environment if desired if [ $restore_env -eq 1 ]; then restore_environment fi # Remove the virtual environment if --force used if [ $force -eq 1 ]; then destroy_venv fi # Then check if it's up-to-date environment_check # Create a backup of the up-to-date environment if desired if [ $backup_env -eq 1 ]; then backup_environment fi fi # ---------EXERCISE THE CODE------------ # # Build the docs if [ $just_docs -eq 1 ]; then run_sphinx exit $? fi # PEP8 if [ $just_pep8 -eq 1 ]; then run_pep8 exit $? fi # Pylint if [ $just_pylint -eq 1 ]; then run_pylint exit $? fi # Tab checker if [ $just_tabs -eq 1 ]; then tab_check exit $? fi # Django development server if [ $runserver -eq 1 ]; then run_server exit $? fi # Full test suite run_tests || exit