Merge "Fixes handling of arrays in XML to JSON conversion"
diff --git a/run_tempest.sh b/run_tempest.sh
new file mode 100755
index 0000000..be9b38a
--- /dev/null
+++ b/run_tempest.sh
@@ -0,0 +1,158 @@
+#!/usr/bin/env bash
+
+function usage {
+ echo "Usage: $0 [OPTION]..."
+ echo "Run Tempest test suite"
+ echo ""
+ echo " -V, --virtual-env Always use virtualenv. Install automatically if not present"
+ echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment"
+ echo " -n, --no-site-packages Isolate the virtualenv from the global Python environment"
+ echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
+ echo " -u, --update Update the virtual environment with any newer package versions"
+ echo " -s, --smoke Only run smoke tests"
+ echo " -t, --serial Run testr serially"
+ echo " -C, --config Config file location"
+ echo " -h, --help Print this usage message"
+ echo " -d, --debug Debug this script -- set -o xtrace"
+ echo " -l, --logging Enable logging"
+ echo " -L, --logging-config Logging config file location. Default is etc/logging.conf"
+ echo " -- [TESTROPTIONS] After the first '--' you can pass arbitrary arguments to testr "
+}
+
+testrargs=""
+venv=.venv
+with_venv=tools/with_venv.sh
+serial=0
+always_venv=0
+never_venv=0
+no_site_packages=0
+force=0
+wrapper=""
+config_file=""
+update=0
+logging=0
+logging_config=etc/logging.conf
+
+if ! options=$(getopt -o VNnfusthdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,help,debug,config:,logging,logging-config: -- "$@")
+then
+ # parse error
+ usage
+ exit 1
+fi
+
+eval set -- $options
+first_uu=yes
+while [ $# -gt 0 ]; do
+ case "$1" in
+ -h|--help) usage; exit;;
+ -V|--virtual-env) always_venv=1; never_venv=0;;
+ -N|--no-virtual-env) always_venv=0; never_venv=1;;
+ -n|--no-site-packages) no_site_packages=1;;
+ -f|--force) force=1;;
+ -u|--update) update=1;;
+ -d|--debug) set -o xtrace;;
+ -C|--config) config_file=$2; shift;;
+ -s|--smoke) testrargs+="smoke"; noseargs+="--attr=type=smoke";;
+ -t|--serial) serial=1;;
+ -l|--logging) logging=1;;
+ -L|--logging-config) logging_config=$2; shift;;
+ --) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no ;;
+ *) testrargs="$testrargs $1"; noseargs+=" $1" ;;
+ esac
+ shift
+done
+
+if [ -n "$config_file" ]; then
+ config_file=`readlink -f "$config_file"`
+ export TEMPEST_CONFIG_DIR=`dirname "$config_file"`
+ export TEMPEST_CONFIG=`basename "$config_file"`
+fi
+
+if [ $logging -eq 1 ]; then
+ if [ ! -f "$logging_config" ]; then
+ echo "No such logging config file: $logging_config"
+ exit 1
+ fi
+ logging_config=`readlink -f "$logging_config"`
+ export TEMPEST_LOG_CONFIG_DIR=`dirname "$logging_config"`
+ export TEMPEST_LOG_CONFIG=`basename "$logging_config"`
+fi
+
+cd `dirname "$0"`
+
+if [ $no_site_packages -eq 1 ]; then
+ installvenvopts="--no-site-packages"
+fi
+
+function testr_init {
+ if [ ! -d .testrepository ]; then
+ ${wrapper} testr init
+ fi
+}
+
+function run_tests {
+ testr_init
+ ${wrapper} find . -type f -name "*.pyc" -delete
+ export OS_TEST_PATH=./tempest/test_discover
+ if [ $serial -eq 1 ]; then
+ ${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ else
+ ${wrapper} testr run --parallel --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
+ fi
+}
+
+function run_tests_nose {
+ export NOSE_WITH_OPENSTACK=1
+ export NOSE_OPENSTACK_COLOR=1
+ export NOSE_OPENSTACK_RED=15.00
+ export NOSE_OPENSTACK_YELLOW=3.00
+ export NOSE_OPENSTACK_SHOW_ELAPSED=1
+ export NOSE_OPENSTACK_STDOUT=1
+ export TEMPEST_PY26_NOSE_COMPAT=1
+ if [[ "x$noseargs" =~ "tempest" ]]; then
+ noseargs="$testrargs"
+ else
+ noseargs="$noseargs tempest"
+ fi
+ ${wrapper} nosetests $noseargs
+}
+
+if [ $never_venv -eq 0 ]
+then
+ # Remove the virtual environment if --force used
+ if [ $force -eq 1 ]; then
+ echo "Cleaning virtualenv..."
+ rm -rf ${venv}
+ fi
+ if [ $update -eq 1 ]; then
+ echo "Updating virtualenv..."
+ python tools/install_venv.py $installvenvopts
+ fi
+ if [ -e ${venv} ]; then
+ wrapper="${with_venv}"
+ else
+ if [ $always_venv -eq 1 ]; then
+ # Automatically install the virtualenv
+ python tools/install_venv.py $installvenvopts
+ wrapper="${with_venv}"
+ else
+ echo -e "No virtual environment found...create one? (Y/n) \c"
+ read use_ve
+ if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
+ # Install the virtualenv and run the test suite in it
+ python tools/install_venv.py $installvenvopts
+ wrapper=${with_venv}
+ fi
+ fi
+ fi
+fi
+
+py_version=`${wrapper} python --version 2>&1`
+if [[ $py_version =~ "2.6" ]] ; then
+ run_tests_nose
+else
+ run_tests
+fi
+retval=$?
+
+exit $retval
diff --git a/run_tests.sh b/run_tests.sh
index 3c9c051..9dc8d7b 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -2,21 +2,17 @@
function usage {
echo "Usage: $0 [OPTION]..."
- echo "Run Tempest test suite"
+ echo "Run Tempest unit tests"
echo ""
echo " -V, --virtual-env Always use virtualenv. Install automatically if not present"
echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment"
echo " -n, --no-site-packages Isolate the virtualenv from the global Python environment"
echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
echo " -u, --update Update the virtual environment with any newer package versions"
- echo " -s, --smoke Only run smoke tests"
echo " -t, --serial Run testr serially"
- echo " -C, --config Config file location"
echo " -p, --pep8 Just run pep8"
echo " -h, --help Print this usage message"
echo " -d, --debug Debug this script -- set -o xtrace"
- echo " -l, --logging Enable logging"
- echo " -L, --logging-config Logging config file location. Default is etc/logging.conf"
echo " -- [TESTROPTIONS] After the first '--' you can pass arbitrary arguments to testr "
}
@@ -32,10 +28,8 @@
wrapper=""
config_file=""
update=0
-logging=0
-logging_config=etc/logging.conf
-if ! options=$(getopt -o VNnfustphdC:lL: -l virtual-env,no-virtual-env,no-site-packages,force,update,smoke,serial,pep8,help,debug,config:,logging,logging-config: -- "$@")
+if ! options=$(getopt -o VNnfutphd -l virtual-env,no-virtual-env,no-site-packages,force,update,serial,pep8,help,debug -- "$@")
then
# parse error
usage
@@ -53,33 +47,14 @@
-f|--force) force=1;;
-u|--update) update=1;;
-d|--debug) set -o xtrace;;
- -C|--config) config_file=$2; shift;;
-p|--pep8) let just_pep8=1;;
- -s|--smoke) testrargs+="smoke"; noseargs+="--attr=type=smoke";;
-t|--serial) serial=1;;
- -l|--logging) logging=1;;
- -L|--logging-config) logging_config=$2; shift;;
--) [ "yes" == "$first_uu" ] || testrargs="$testrargs $1"; first_uu=no ;;
*) testrargs="$testrargs $1"; noseargs+=" $1" ;;
esac
shift
done
-if [ -n "$config_file" ]; then
- config_file=`readlink -f "$config_file"`
- export TEMPEST_CONFIG_DIR=`dirname "$config_file"`
- export TEMPEST_CONFIG=`basename "$config_file"`
-fi
-
-if [ $logging -eq 1 ]; then
- if [ ! -f "$logging_config" ]; then
- echo "No such logging config file: $logging_config"
- exit 1
- fi
- logging_config=`readlink -f "$logging_config"`
- export TEMPEST_LOG_CONFIG_DIR=`dirname "$logging_config"`
- export TEMPEST_LOG_CONFIG=`basename "$logging_config"`
-fi
cd `dirname "$0"`
@@ -96,6 +71,7 @@
function run_tests {
testr_init
${wrapper} find . -type f -name "*.pyc" -delete
+ export OS_TEST_PATH=./tempest/tests
if [ $serial -eq 1 ]; then
${wrapper} testr run --subunit $testrargs | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py
else
@@ -103,22 +79,6 @@
fi
}
-function run_tests_nose {
- export NOSE_WITH_OPENSTACK=1
- export NOSE_OPENSTACK_COLOR=1
- export NOSE_OPENSTACK_RED=15.00
- export NOSE_OPENSTACK_YELLOW=3.00
- export NOSE_OPENSTACK_SHOW_ELAPSED=1
- export NOSE_OPENSTACK_STDOUT=1
- export TEMPEST_PY26_NOSE_COMPAT=1
- if [[ "x$noseargs" =~ "tempest" ]]; then
- noseargs="$testrargs"
- else
- noseargs="$noseargs tempest"
- fi
- ${wrapper} nosetests $noseargs
-}
-
function run_pep8 {
echo "Running flake8 ..."
if [ $never_venv -eq 1 ]; then
@@ -163,12 +123,7 @@
exit
fi
-py_version=`${wrapper} python --version 2>&1`
-if [[ $py_version =~ "2.6" ]] ; then
- run_tests_nose
-else
- run_tests
-fi
+run_tests
retval=$?
if [ -z "$testrargs" ]; then
diff --git a/tempest/api/compute/servers/test_instance_actions.py b/tempest/api/compute/servers/test_instance_actions.py
index 5019003..5058211 100644
--- a/tempest/api/compute/servers/test_instance_actions.py
+++ b/tempest/api/compute/servers/test_instance_actions.py
@@ -16,8 +16,7 @@
# under the License.
from tempest.api.compute import base
-from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class InstanceActionsTestJSON(base.BaseV2ComputeTest):
@@ -31,7 +30,7 @@
cls.request_id = resp['x-compute-request-id']
cls.server_id = server['id']
- @attr(type='gate')
+ @test.attr(type='gate')
def test_list_instance_actions(self):
# List actions of the provided server
resp, body = self.client.reboot(self.server_id, 'HARD')
@@ -43,7 +42,7 @@
self.assertTrue(any([i for i in body if i['action'] == 'create']))
self.assertTrue(any([i for i in body if i['action'] == 'reboot']))
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_instance_action(self):
# Get the action details of the provided server
resp, body = self.client.get_instance_action(self.server_id,
@@ -52,18 +51,6 @@
self.assertEqual(self.server_id, body['instance_uuid'])
self.assertEqual('create', body['action'])
- @attr(type=['negative', 'gate'])
- def test_list_instance_actions_invalid_server(self):
- # List actions of the invalid server id
- self.assertRaises(exceptions.NotFound,
- self.client.list_instance_actions, 'server-999')
-
- @attr(type=['negative', 'gate'])
- def test_get_instance_action_invalid_request(self):
- # Get the action details of the provided server with invalid request
- self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
- self.server_id, '999')
-
class InstanceActionsTestXML(InstanceActionsTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
new file mode 100644
index 0000000..68f2dcb
--- /dev/null
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -0,0 +1,50 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NEC Corporation
+# All Rights Reserved.
+#
+# 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.
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import exceptions
+from tempest import test
+
+
+class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(InstanceActionsNegativeTestJSON, cls).setUpClass()
+ cls.client = cls.servers_client
+ resp, server = cls.create_test_server(wait_until='ACTIVE')
+ cls.server_id = server['id']
+
+ @test.attr(type=['negative', 'gate'])
+ def test_list_instance_actions_non_existent_server(self):
+ # List actions of the non-existent server id
+ non_existent_server_id = data_utils.rand_uuid()
+ self.assertRaises(exceptions.NotFound,
+ self.client.list_instance_actions,
+ non_existent_server_id)
+
+ @test.attr(type=['negative', 'gate'])
+ def test_get_instance_action_invalid_request(self):
+ # Get the action details of the provided server with invalid request
+ self.assertRaises(exceptions.NotFound, self.client.get_instance_action,
+ self.server_id, '999')
+
+
+class InstanceActionsNegativeTestXML(InstanceActionsNegativeTestJSON):
+ _interface = 'xml'
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index e7cb806..47d8cca 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -101,6 +101,7 @@
The containers should be visible from the container_client given.
Will not throw any error if the containers don't exist.
+ Will not check that object and container deletions succeed.
:param containers: list of container names to remove
:param container_client: if None, use cls.container_client, this means
diff --git a/tempest/api/object_storage/test_object_expiry.py b/tempest/api/object_storage/test_object_expiry.py
index 4958f70..9c2834d 100644
--- a/tempest/api/object_storage/test_object_expiry.py
+++ b/tempest/api/object_storage/test_object_expiry.py
@@ -21,7 +21,6 @@
from tempest.common.utils import data_utils
from tempest import exceptions
from tempest.test import attr
-from tempest.test import skip_because
class ObjectExpiryTest(base.BaseObjectTest):
@@ -33,31 +32,20 @@
@classmethod
def tearDownClass(cls):
- """The test script fails in tear down class
- as the container contains expired objects (LP bug 1069849).
- But delete action for the expired object is raising
- NotFound exception and also non empty container cannot be deleted.
- """
cls.delete_containers([cls.container_name])
super(ObjectExpiryTest, cls).tearDownClass()
- @skip_because(bug="1069849")
- @attr(type='gate')
- def test_get_object_after_expiry_time(self):
- # TODO(harika-vakadi): similar test case has to be created for
- # "X-Delete-At", after this test case works.
-
+ def _test_object_expiry(self, metadata):
# create object
object_name = data_utils.rand_name(name='TestObject')
- data = data_utils.arbitrary_string()
resp, _ = self.object_client.create_object(self.container_name,
- object_name, data)
- # update object metadata with expiry time of 3 seconds
- metadata = {'X-Delete-After': '3'}
+ object_name, '')
+ # update object metadata
resp, _ = \
self.object_client.update_object_metadata(self.container_name,
object_name, metadata,
metadata_prefix='')
+ # verify object metadata
resp, _ = \
self.object_client.list_object_metadata(self.container_name,
object_name)
@@ -69,10 +57,20 @@
self.assertEqual(resp['status'], '200')
self.assertHeaders(resp, 'Object', 'GET')
self.assertIn('x-delete-at', resp)
- # check data
- self.assertEqual(body, data)
+
# sleep for over 5 seconds, so that object expires
time.sleep(5)
+
# object should not be there anymore
self.assertRaises(exceptions.NotFound, self.object_client.get_object,
self.container_name, object_name)
+
+ @attr(type='gate')
+ def test_get_object_after_expiry_time(self):
+ metadata = {'X-Delete-After': '3'}
+ self._test_object_expiry(metadata)
+
+ @attr(type='gate')
+ def test_get_object_at_expiry_time(self):
+ metadata = {'X-Delete-At': str(int(time.time()) + 3)}
+ self._test_object_expiry(metadata)
diff --git a/tempest/api/telemetry/__init__.py b/tempest/api/telemetry/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tempest/api/telemetry/__init__.py
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
new file mode 100644
index 0000000..1f661a6
--- /dev/null
+++ b/tempest/api/telemetry/base.py
@@ -0,0 +1,27 @@
+# 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.
+
+from tempest import config
+import tempest.test
+
+CONF = config.CONF
+
+
+class BaseTelemetryTest(tempest.test.BaseTestCase):
+
+ """Base test case class for all Telemetry API tests."""
+
+ @classmethod
+ def setUpClass(cls):
+ super(BaseTelemetryTest, cls).setUpClass()
+ if not CONF.service_available.ceilometer:
+ raise cls.skipException("Ceilometer support is required")
diff --git a/tempest/cli/simple_read_only/test_ceilometer.py b/tempest/cli/simple_read_only/test_ceilometer.py
index 8bdd633..b762b47 100644
--- a/tempest/cli/simple_read_only/test_ceilometer.py
+++ b/tempest/cli/simple_read_only/test_ceilometer.py
@@ -15,17 +15,16 @@
# License for the specific language governing permissions and limitations
# under the License.
-from oslo.config import cfg
-
-import tempest.cli
+from tempest import cli
+from tempest import config
from tempest.openstack.common import log as logging
-CONF = cfg.CONF
+CONF = config.CONF
LOG = logging.getLogger(__name__)
-class SimpleReadOnlyCeilometerClientTest(tempest.cli.ClientTestBase):
+class SimpleReadOnlyCeilometerClientTest(cli.ClientTestBase):
"""Basic, read-only tests for Ceilometer CLI client.
Checks return values and output of read-only commands.
diff --git a/tempest/cli/simple_read_only/test_neutron.py b/tempest/cli/simple_read_only/test_neutron.py
index 61ffc25..34c6fd9 100644
--- a/tempest/cli/simple_read_only/test_neutron.py
+++ b/tempest/cli/simple_read_only/test_neutron.py
@@ -18,18 +18,17 @@
import re
import subprocess
-from oslo.config import cfg
-
-import tempest.cli
+from tempest import cli
+from tempest import config
from tempest.openstack.common import log as logging
from tempest import test
-CONF = cfg.CONF
+CONF = config.CONF
LOG = logging.getLogger(__name__)
-class SimpleReadOnlyNeutronClientTest(tempest.cli.ClientTestBase):
+class SimpleReadOnlyNeutronClientTest(cli.ClientTestBase):
"""Basic, read-only tests for Neutron CLI client.
Checks return values and output of read-only commands.
@@ -89,7 +88,7 @@
def _test_neutron_lbaas_command(self, command):
try:
self.neutron(command)
- except tempest.cli.CommandFailed as e:
+ except cli.CommandFailed as e:
if '404 Not Found' not in e.stderr:
self.fail('%s: Unexpected failure.' % command)
@@ -156,7 +155,7 @@
'router-show', 'agent-update', 'help'))
self.assertFalse(wanted_commands - commands)
- # Optional arguments:
+ # Optional arguments:
@test.attr(type='smoke')
def test_neutron_version(self):
diff --git a/tempest/stress/etc/ssh_floating.json b/tempest/stress/etc/ssh_floating.json
index 0cb6776..e03fd4f 100644
--- a/tempest/stress/etc/ssh_floating.json
+++ b/tempest/stress/etc/ssh_floating.json
@@ -8,7 +8,7 @@
"new_floating": true,
"verify": ["check_icmp_echo", "check_port_ssh"],
"check_timeout": 120,
- "check_inerval": 1,
+ "check_interval": 1,
"wait_after_vm_create": true,
"wait_for_disassociate": true,
"reboot": false}