diff --git a/.stestr.conf b/.stestr.conf index 7e7d325..ec410bf 100644 --- a/.stestr.conf +++ b/.stestr.conf @@ -1,4 +1,4 @@ [DEFAULT] -test_path=./os_refresh_config/tests +test_path=${OS_TEST_PATH:-./os_refresh_config/tests/unit} top_dir=./ diff --git a/os_refresh_config/os_refresh_config.py b/os_refresh_config/os_refresh_config.py old mode 100755 new mode 100644 index 260e086..9aabea5 --- a/os_refresh_config/os_refresh_config.py +++ b/os_refresh_config/os_refresh_config.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python3 # Copyright 2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # @@ -159,7 +158,3 @@ def main(argv=sys.argv): log.debug('No dir for phase %s' % phase) return exit(lock) - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/os_refresh_config/tests/functional/__init__.py b/os_refresh_config/tests/functional/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/os_refresh_config/tests/test_cmd.py b/os_refresh_config/tests/functional/test_cmd.py similarity index 96% rename from os_refresh_config/tests/test_cmd.py rename to os_refresh_config/tests/functional/test_cmd.py index 49038a8..a409130 100644 --- a/os_refresh_config/tests/test_cmd.py +++ b/os_refresh_config/tests/functional/test_cmd.py @@ -17,16 +17,11 @@ import time import fixtures import testtools -script_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - '../os_refresh_config.py') - class TestCmd(testtools.TestCase): def setUp(self): super(TestCmd, self).setUp() - self.assertTrue(os.path.exists(script_path)) self.useFixture(fixtures.NestedTempfile()) self.base_dir = self.useFixture(fixtures.TempDir()) self.lockdir = self.useFixture(fixtures.TempDir()) @@ -49,8 +44,7 @@ class TestCmd(testtools.TestCase): 'PATH': os.environ.get('PATH') } cmd_args = [ - script_path, - '--lockfile', self.lockfile + 'os-refresh-config', '--lockfile', self.lockfile ] if args: cmd_args.extend(args) diff --git a/os_refresh_config/tests/unit/__init__.py b/os_refresh_config/tests/unit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/os_refresh_config/tests/test_main.py b/os_refresh_config/tests/unit/test_main.py similarity index 100% rename from os_refresh_config/tests/test_main.py rename to os_refresh_config/tests/unit/test_main.py diff --git a/os_refresh_config/tests/test_os_refresh_config.py b/os_refresh_config/tests/unit/test_os_refresh_config.py similarity index 100% rename from os_refresh_config/tests/test_os_refresh_config.py rename to os_refresh_config/tests/unit/test_os_refresh_config.py diff --git a/requirements.txt b/requirements.txt index f749343..415555e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ pbr!=2.1.0,>=2.0.0 # Apache-2.0 -dib-utils>=0.0.8 # Apache-2.0 psutil>=3.2.2 # BSD diff --git a/setup.cfg b/setup.cfg index 19551a5..6e8c87c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,8 @@ classifier = [files] packages = os_refresh_config +scripts = + tools/dib-run-parts [entry_points] console_scripts = diff --git a/tools/dib-run-parts b/tools/dib-run-parts new file mode 100755 index 0000000..0f81be1 --- /dev/null +++ b/tools/dib-run-parts @@ -0,0 +1,144 @@ +#!/bin/bash +# Inspired by Debian and RedHat run-parts but portable and specific to di-b. +# +# Copyright 2012 Hewlett-Packard Development Company, L.P. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +allowed_regex=${RUN_PARTS_REGEX:-"^[0-9A-Za-z_-]+$"} +show_list= + +set -ue +set -o pipefail + +name=$(basename $0) + +usage() { + echo "Usage: $name [OPTION] scripts_directory" + echo "Option:" + echo " --list print names of all valid files" + echo + echo "Examples:" + echo " dib-run-parts --list /opt/stack/os-config-refresh/configure.d/" + echo " dib-run-parts /opt/stack/os-config-refresh/configure.d/" + exit 1 +} >&2 + + +output_prefix() { + printf "%s %s " "${name}" "$(date)" >&2 +} + +output () { + output_prefix + echo $* >&2 +} + +output_printf () { + local FORMAT="$1" + shift + output_prefix + printf "${FORMAT}" $@ >&2 +} + +# source the environment files from environment.d +# arg : target_dir +source_environment() { + + local dir=$target_dir/../environment.d + local env_files + local xtrace + + if [ -d ${dir} ] ; then + env_files=$(find ${dir} -maxdepth 1 -xtype f | \ + grep -E "/[0-9A-Za-z_\.-]+$" | \ + LANG=C sort -n) + for env_file in $env_files ; do + output "Sourcing environment file ${env_file}" + # Set tracing as we import these environment files; it's + # nice to see the definitions in the logs + xtrace=$(set +o | grep xtrace) + set -o xtrace + source $env_file + $xtrace + done + fi +} + +if [ $# -lt 1 ] ; then + usage +fi + +if [ "$1" == "--list" ] ; then + show_list="1" + shift +fi + +target_dir="${1:-}" + +if ! [ -d "$target_dir" ] ; then + output "Scripts directory [$target_dir] must exist and be a directory" + usage +fi + +# We specifically only want to sort *by the numbers*. +# Lexical sorting is not guaranteed, and identical numbers may be +# parallelized later +# Note: -maxdepth 1 ensures only files in the target directory (but not +# subdirectories) are run, which is the way run-parts behaves. +targets=$(find $target_dir -maxdepth 1 -xtype f -executable -printf '%f\n' | grep -E "$allowed_regex" | LANG=C sort -n || echo "") + +if [ "$show_list" == "1" ] ; then + for target in $targets ; do + echo "${target_dir}/${target}" + done + exit 0 +fi + +PROFILE_DIR=$(mktemp -d --tmpdir profiledir.XXXXXX) + +# note, run this in a sub-shell so we don't pollute our +# own environment with source_environment +( + source_environment + + for target in $targets ; do + output "Running $target_dir/$target" + target_tag=${target//\//_} + date +%s.%N > $PROFILE_DIR/start_$target_tag + $target_dir/$target + target_tag=${target//\//_} + date +%s.%N > $PROFILE_DIR/stop_$target_tag + output "$target completed" + done +) + +output "----------------------- PROFILING -----------------------" +output "" +output "Target: $(basename $target_dir)" +output "" +output_printf "%-40s %9s\n" Script Seconds +output_printf "%-40s %9s\n" --------------------------------------- ---------- +output "" +pushd $PROFILE_DIR > /dev/null +for target in $(find . -name 'start_*' -printf '%f\n' | env LC_ALL=C sort -n) ; do + stop_file=stop_${target##start_} + start_seconds=$(cat $target) + stop_seconds=$(cat $stop_file) + duration=$(echo - | awk "{ print $stop_seconds - $start_seconds }") + LC_NUMERIC=C LC_ALL=C output_printf "%-40s %10.3f\n" ${target##start_} $duration +done +popd > /dev/null +rm -rf $PROFILE_DIR +output "" +output "--------------------- END PROFILING ---------------------" diff --git a/tools/tests/run_tests.sh b/tools/tests/run_tests.sh new file mode 100755 index 0000000..24f9146 --- /dev/null +++ b/tools/tests/run_tests.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Runs all test cases in this directory +# + +set -ue +set -o pipefail + +TESTS_BASE_DIR=$(cd $(dirname "$0") && pwd) + +for tc in ${TESTS_BASE_DIR}/tc??.sh; do + echo "--- Running ${tc} ---" + ${tc} +done + +echo "--- TESTS COMPLETE ---" diff --git a/tools/tests/tc01.sh b/tools/tests/tc01.sh new file mode 100755 index 0000000..c040d52 --- /dev/null +++ b/tools/tests/tc01.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Runs dib-run-parts on an empty directory. +# + +set -ue +set -o pipefail +set -x + +TESTS_BASE_DIR=$(cd $(dirname "$0") && pwd) + +DRP_BIN=${TESTS_BASE_DIR}/../dib-run-parts + +TEST_EXEC_DIR=${TESTS_BASE_DIR}/tc01/td + +mkdir -p ${TEST_EXEC_DIR} +rval=0 + +RES=$(${DRP_BIN} --list ${TEST_EXEC_DIR}) +if test $? -ne 0; then + echo "*** FAILED: --list of empty dir failed" + rval=1 +fi +if test -n "${RES}"; then + echo "*** FAILED: --list of empty dir not empty" + rval=1 +fi + +RES=$(${DRP_BIN} ${TEST_EXEC_DIR} 2>/dev/null) +if test $? -ne 0; then + echo "*** FAILED: dib-run-parts on empty dir failed" + rval=1 +fi +if test -n "${RES}"; then + echo "*** FAILED: dib-run-parts on empty dir not empty" + rval=1 +fi + +exit ${rval} diff --git a/tools/tests/tc02.sh b/tools/tests/tc02.sh new file mode 100755 index 0000000..795af8a --- /dev/null +++ b/tools/tests/tc02.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# Runs dib-run-parts on directory containing some scripts. +# + +set -ue +set -o pipefail +set -x + +TESTS_BASE_DIR=$(cd $(dirname "$0") && pwd) + +DRP_BIN=${TESTS_BASE_DIR}/../dib-run-parts + +TEST_EXEC_DIR=${TESTS_BASE_DIR}/tc02/td + +rval=0 + +RES=$(${DRP_BIN} --list ${TEST_EXEC_DIR}) +if test $? -ne 0; then + echo "*** FAILED: --list failed" + rval=1 +fi + +EXPECTED="${TESTS_BASE_DIR}/tc02/td/call_me_1 +${TESTS_BASE_DIR}/tc02/td/call_me_2" + +if test "${EXPECTED}" != "${RES}"; then + echo "*** FAILED: --list returns incorrect result" + rval=1 +fi + +RES=$(${DRP_BIN} ${TEST_EXEC_DIR} 2>/dev/null) +if test $? -ne 0; then + echo "*** FAILED: dib-run-parts on empty dir failed" + rval=1 +fi + +EXPECTED="call_me_1 called +call_me_2 called" + +if test "${EXPECTED}" != "${RES}"; then + echo "*** FAILED: dib-run-parts returns incorrect result" + rval=1 +fi + +exit ${rval} diff --git a/tools/tests/tc02/td/call_me_1 b/tools/tests/tc02/td/call_me_1 new file mode 100755 index 0000000..4e3b6a0 --- /dev/null +++ b/tools/tests/tc02/td/call_me_1 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "call_me_1 called" diff --git a/tools/tests/tc02/td/call_me_2 b/tools/tests/tc02/td/call_me_2 new file mode 100755 index 0000000..d96423d --- /dev/null +++ b/tools/tests/tc02/td/call_me_2 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "call_me_2 called" diff --git a/tools/tests/tc03.sh b/tools/tests/tc03.sh new file mode 100755 index 0000000..996fe9f --- /dev/null +++ b/tools/tests/tc03.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Runs dib-run-parts on directory containing some scripts +# and using the environment directory. +# + +set -ue +set -o pipefail +set -x + +TESTS_BASE_DIR=$(dirname $0) + +DRP_BIN=${TESTS_BASE_DIR}/../dib-run-parts + +TEST_EXEC_DIR=${TESTS_BASE_DIR}/tc03/td + +rval=0 + +RES=$(${DRP_BIN} ${TEST_EXEC_DIR} 2>/dev/null) +if test $? -ne 0; then + echo "*** FAILED: dib-run-parts failed" + rval=1 +fi + +EXPECTED="call_me_1 called [Some thing] +call_me_2 called [Other thing]" + +if test "${EXPECTED}" != "${RES}"; then + echo "*** FAILED: dib-run-parts returns incorrect result" + rval=1 +fi + +exit ${rval} diff --git a/tools/tests/tc03/environment.d/set_var.bash b/tools/tests/tc03/environment.d/set_var.bash new file mode 100644 index 0000000..d9dc4ac --- /dev/null +++ b/tools/tests/tc03/environment.d/set_var.bash @@ -0,0 +1,5 @@ +#!/bin/bash + +export CM1="Some thing" +export CM2="Other thing" + diff --git a/tools/tests/tc03/td/call_me_1 b/tools/tests/tc03/td/call_me_1 new file mode 100755 index 0000000..11a4850 --- /dev/null +++ b/tools/tests/tc03/td/call_me_1 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "call_me_1 called [${CM1}]" diff --git a/tools/tests/tc03/td/call_me_2 b/tools/tests/tc03/td/call_me_2 new file mode 100755 index 0000000..db5dec8 --- /dev/null +++ b/tools/tests/tc03/td/call_me_2 @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "call_me_2 called [${CM2}]" diff --git a/tox.ini b/tox.ini index 461d023..9e6d358 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] minversion = 3.1.0 -skipsdist = True envlist = py3,pep8 +skipsdist = false skip_missing_interpreters = true # this allows tox to infer the base python from the environment name # and override any basepython configured in this file @@ -9,7 +9,6 @@ ignore_basepython_conflict=true [testenv] basepython = python3 -usedevelop = True deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt @@ -35,6 +34,15 @@ commands = [testenv:venv] commands = {posargs} +[testenv:functional] +setenv = + OS_TEST_PATH=os_refresh_config/tests/functional +commands = + stestr run --slowest {posargs} + {toxinidir}/tools/tests/run_tests.sh {posargs} +allowlist_externals = + {toxinidir}/tools/tests/run_tests.sh + [flake8] ignore = E125 exclude = .venv,.tox,dist,doc,*.egg diff --git a/zuul.d/layout.yaml b/zuul.d/layout.yaml index 7d1cedf..0ee2dd8 100644 --- a/zuul.d/layout.yaml +++ b/zuul.d/layout.yaml @@ -3,3 +3,9 @@ - check-requirements - openstack-cover-jobs - openstack-python3-jobs + check: + jobs: + - openstack-tox-functional + gate: + jobs: + - openstack-tox-functional