diff --git a/bindep.txt b/bindep.txt new file mode 100644 index 000000000..21ee1d88c --- /dev/null +++ b/bindep.txt @@ -0,0 +1,14 @@ +# This is a cross-platform list tracking distribution packages needed for install and tests; +# see https://docs.openstack.org/infra/bindep/ for additional information. + +mysql [platform:rpm !platform:redhat test] +mysql-client [platform:dpkg !platform:debian test] +mysql-devel [platform:rpm !platform:redhat test] +mysql-server [!platform:redhat !platform:debian test] +mariadb-devel [platform:rpm platform:redhat test] +mariadb-server [platform:rpm platform:redhat platform:debian test] +python3-all [platform:dpkg test] +python3-all-dev [platform:dpkg test] +python3 [platform:rpm test] +python3-devel [platform:rpm test] +sqlite-devel [platform:rpm test] diff --git a/test-requirements.txt b/test-requirements.txt index 4b261e60e..005f0704e 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -5,3 +5,6 @@ testscenarios>=0.5.0 # Apache-2.0/BSD testtools>=2.3.0 # MIT stestr>=2.0.0 # Apache-2.0 WebTest>=2.0.27 # MIT + +# Include drivers for opportunistic testing. +oslo.db[mysql]>=6.0.0 # Apache-2.0 diff --git a/tools/test-setup.sh b/tools/test-setup.sh new file mode 100755 index 000000000..ea98da30c --- /dev/null +++ b/tools/test-setup.sh @@ -0,0 +1,56 @@ +#!/bin/bash -xe + +# This script will be run by OpenStack CI before unit tests are run, +# it sets up the test system as needed. +# Developers should setup their test systems in a similar way. + +# This setup needs to be run as a user that can run sudo. + +# The root password for the MySQL database; pass it in via +# MYSQL_ROOT_PW. +DB_ROOT_PW=${MYSQL_ROOT_PW:-insecure_slave} + +# This user and its password are used by the tests, if you change it, +# your tests might fail. +DB_USER=openstack_citest +DB_PW=openstack_citest + +function is_rhel9 { + [ -f /usr/bin/dnf ] && \ + cat /etc/*release | grep -q -e "Red Hat" -e "CentOS" -e "CloudLinux" && \ + cat /etc/*release | grep -q 'release 9' +} + +function is_rhel10 { + [ -f /usr/bin/dnf ] && \ + cat /etc/*release | grep -q -e "Red Hat" -e "CentOS" -e "CloudLinux" && \ + cat /etc/*release | grep -q 'release 10' +} + +function set_conf_line { # file regex value + sudo sh -c "grep -q -e '$2' $1 && \ + sed -i 's|$2|$3|g' $1 || \ + echo '$3' >> $1" +} + +if is_rhel9 || is_rhel10; then + # mysql needs to be started on centos/rhel + sudo systemctl restart mariadb.service +fi + +sudo -H mysqladmin -u root password $DB_ROOT_PW + +# It's best practice to remove anonymous users from the database. If +# an anonymous user exists, then it matches first for connections and +# other connections from that host will not work. +sudo -H mysql -u root -p$DB_ROOT_PW -h localhost -e " + DELETE FROM mysql.user WHERE User=''; + FLUSH PRIVILEGES; + CREATE USER '$DB_USER'@'%' IDENTIFIED BY '$DB_PW'; + GRANT ALL PRIVILEGES ON *.* TO '$DB_USER'@'%' WITH GRANT OPTION;" + +# Now create our database. +mysql -u $DB_USER -p$DB_PW -h 127.0.0.1 -e " + SET default_storage_engine=MYISAM; + DROP DATABASE IF EXISTS openstack_citest; + CREATE DATABASE openstack_citest CHARACTER SET utf8;" diff --git a/watcher/tests/db/base.py b/watcher/tests/db/base.py index 4cf25eac0..196fc75c0 100644 --- a/watcher/tests/db/base.py +++ b/watcher/tests/db/base.py @@ -18,6 +18,7 @@ import fixtures from oslo_config import cfg from oslo_db.sqlalchemy import enginefacade +from oslo_db.sqlalchemy import test_fixtures from watcher.db import api as dbapi @@ -86,3 +87,18 @@ class DbTestCase(base.TestCase): engine.dispose() self.useFixture(_DB_CACHE) self._id_gen = utils.id_generator() + + +class MySQLDbTestCase(test_fixtures.OpportunisticDBTestMixin, base.TestCase): + + FIXTURE = test_fixtures.MySQLOpportunisticFixture + + def setUp(self): + conn_str = "mysql+pymysql://root:insecure_slave@127.0.0.1" + # to use mysql db + cfg.CONF.set_override("connection", conn_str, + group="database") + super().setUp() + self.engine = enginefacade.writer.get_engine() + self.dbapi = dbapi.get_instance() + migration.create_schema() diff --git a/watcher/tests/db/test_efficacy_indicator.py b/watcher/tests/db/test_efficacy_indicator.py index 171ea2d16..a0b55b53a 100644 --- a/watcher/tests/db/test_efficacy_indicator.py +++ b/watcher/tests/db/test_efficacy_indicator.py @@ -409,3 +409,55 @@ class DbEfficacyIndicatorTestCase(base.DbTestCase): self.assertRaises(exception.EfficacyIndicatorAlreadyExists, utils.create_test_efficacy_indicator, id=2, uuid=uuid) + + +class MySQLDbEfficacyIndicatorTestCase(base.MySQLDbTestCase): + + FAKE_OLDER_DATE = '2014-01-01T09:52:05.219414' + FAKE_OLD_DATE = '2015-01-01T09:52:05.219414' + FAKE_TODAY = '2016-02-24T09:52:05.219414' + + def setUp(self): + super(MySQLDbEfficacyIndicatorTestCase, self).setUp() + self.context.show_deleted = True + self._data_setup() + + def _data_setup(self): + self.audit_template_name = "Audit Template" + + self.goal = utils.create_test_goal( + id=1, uuid=w_utils.generate_uuid(), + name="GOAL_1", display_name='Goal 1') + self.strategy = utils.create_test_strategy( + id=1, uuid=w_utils.generate_uuid(), + name="STRATEGY_ID_1", display_name='My Strategy 1') + self.audit_template = utils.create_test_audit_template( + name=self.audit_template_name, id=1, uuid=None) + self.audit = utils.create_test_audit( + audit_template_id=self.audit_template.id, id=1, uuid=None) + self.action_plan = utils.create_test_action_plan( + audit_id=self.audit.id, id=1, uuid=None) + + with freezegun.freeze_time(self.FAKE_TODAY): + self.efficacy_indicator1 = utils.create_test_efficacy_indicator( + action_plan_id=self.action_plan.id, id=1, uuid=None, + name="efficacy_indicator1", description="Test Indicator 1", + value=0.01234567912345678) + with freezegun.freeze_time(self.FAKE_OLD_DATE): + self.efficacy_indicator2 = utils.create_test_efficacy_indicator( + action_plan_id=self.action_plan.id, id=2, uuid=None, + name="efficacy_indicator2", description="Test Indicator 2") + with freezegun.freeze_time(self.FAKE_OLDER_DATE): + self.efficacy_indicator3 = utils.create_test_efficacy_indicator( + action_plan_id=self.action_plan.id, id=3, uuid=None, + name="efficacy_indicator3", description="Test Indicator 3") + + def test_efficacy_indicator_value_decimals(self): + db_efficacy_indicator = self.dbapi.get_efficacy_indicator_by_id( + self.context, 1) + self.assertAlmostEqual(float(db_efficacy_indicator.value), + 0.00, places=2) + # FIXME: once the database bug is fixed check that the value is stored + # correctly + # self.assertAlmostEqual(float(db_efficacy_indicator.value), + # 0.01, places=2)