From cf0484ad2e0ee80f8ae7d09961dd6fe2b62d9010 Mon Sep 17 00:00:00 2001 From: Vitalii Solodilov Date: Mon, 8 Jan 2018 21:17:36 +0400 Subject: [PATCH] Fixed integration of the unit tests with PosrgeSQL * Corrected the path to the mistral config file in a unit test * Minor improvement in the run_tests.sh script * Fixed unstable the `test_rerun_join_with_branch_errors` and test_rerun_on_join_task test. task3 id is properly passed now * Removed unused `insert_or_ignore` api and tests. This api broke the test in PostgreSQL case * Passed correct value to the filter in `test_filter_action_definitions_by_has_filter` test Change-Id: I2ce3d2e1be001d9c0c76ebe5293b2bf578a7160b Signed-off-by: Vitalii Solodilov --- mistral/db/v2/sqlalchemy/api.py | 55 --------- mistral/tests/unit/config.py | 2 +- .../tests/unit/db/v2/test_insert_or_ignore.py | 113 ------------------ .../unit/db/v2/test_sqlalchemy_db_api.py | 2 +- .../unit/engine/test_direct_workflow_rerun.py | 4 +- run_tests.sh | 20 +++- 6 files changed, 20 insertions(+), 176 deletions(-) delete mode 100644 mistral/tests/unit/db/v2/test_insert_or_ignore.py diff --git a/mistral/db/v2/sqlalchemy/api.py b/mistral/db/v2/sqlalchemy/api.py index 7d3907645..7a31dfe31 100644 --- a/mistral/db/v2/sqlalchemy/api.py +++ b/mistral/db/v2/sqlalchemy/api.py @@ -335,61 +335,6 @@ def append_string(insert, compiler, **kw): return s -@b.session_aware() -def insert_or_ignore(model_cls, values, session=None): - """Insert a new object into DB or ignore if it already exists. - - This method is based on ability of MySQL, PostgreSQL and SQLite - to check unique constraint violations and allow user to take a - conflict mitigation action. Hence, uniqueness of the object that's - being inserted should be considered only from this perspective. - - Note: This method hasn't been tested on databases other than MySQL, - PostgreSQL 9.5 or later, and SQLite. Therefore there's no guarantee - that it will work with them. - - :param model_cls: Model class. - :param values: Values of the new object. - """ - - model = model_cls() - - model.update(values) - - append = None - replace = None - - dialect = b.get_dialect_name() - - if dialect == 'sqlite': - replace = ('INSERT INTO', 'INSERT OR IGNORE INTO') - elif dialect == 'mysql': - append = 'ON DUPLICATE KEY UPDATE id=id' - elif dialect == 'postgres': - append = 'ON CONFLICT DO NOTHING' - else: - raise RuntimeError( - '"Insert or ignore" is supported only for dialects: sqlite,' - ' mysql and postgres. Actual dialect: %s' % dialect - ) - - insert = model.__table__.insert( - append_string=append, - replace_string=replace - ) - - # NOTE(rakhmerov): As it turned out the result proxy object - # returned by insert expression does not provide a valid - # count of updated rows in for all supported databases. - # For this reason we shouldn't return anything from this - # method. In order to check whether a new object was really - # inserted users should rely on different approaches. The - # simplest is just to insert an object with an explicitly - # set id and then check if object with such id exists in DB. - # Generated id must be unique to make it work. - session.execute(insert, model.to_dict()) - - # Workbook definitions. @b.session_aware() diff --git a/mistral/tests/unit/config.py b/mistral/tests/unit/config.py index d85dac1d8..761230503 100644 --- a/mistral/tests/unit/config.py +++ b/mistral/tests/unit/config.py @@ -19,7 +19,7 @@ from oslo_config import cfg def parse_args(): # Look for .mistral.conf in the project directory by default. - project_dir = '%s/../..' % os.path.dirname(__file__) + project_dir = '%s/../../..' % os.path.dirname(__file__) config_file = '%s/.mistral.conf' % os.path.realpath(project_dir) config_files = [config_file] if os.path.isfile(config_file) else None cfg.CONF(args=[], default_config_files=config_files) diff --git a/mistral/tests/unit/db/v2/test_insert_or_ignore.py b/mistral/tests/unit/db/v2/test_insert_or_ignore.py deleted file mode 100644 index 5ee4a054e..000000000 --- a/mistral/tests/unit/db/v2/test_insert_or_ignore.py +++ /dev/null @@ -1,113 +0,0 @@ -# Copyright 2015 - Mirantis, Inc. -# Copyright 2015 - StackStorm, Inc. -# -# 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 oslo_config import cfg - -from mistral.db.v2.sqlalchemy import api as db_api -from mistral.db.v2.sqlalchemy import models as db_models -from mistral.tests.unit import base as test_base - -WF_EX = { - 'id': '1', - 'spec': {}, - 'start_params': {'task': 'my_task1'}, - 'state': 'IDLE', - 'state_info': "Running...", - 'created_at': None, - 'updated_at': None, - 'context': None, - 'task_id': None, - 'trust_id': None, - 'description': None, - 'output': None -} - - -TASK_EX = { - 'workflow_execution_id': '1', - 'workflow_name': 'my_wf', - 'name': 'my_task1', - 'spec': None, - 'action_spec': None, - 'state': 'IDLE', - 'tags': ['deployment'], - 'in_context': None, - 'runtime_context': None, - 'created_at': None, - 'updated_at': None -} - - -class InsertOrIgnoreTest(test_base.DbTestCase): - def setUp(self): - super(InsertOrIgnoreTest, self).setUp() - - cfg.CONF.set_default('auth_enable', True, group='pecan') - - db_api.create_workflow_execution(WF_EX) - - self.addCleanup( - cfg.CONF.set_default, - 'auth_enable', - False, - group='pecan' - ) - - def test_insert_or_ignore_without_conflicts(self): - db_api.insert_or_ignore( - db_models.TaskExecution, - TASK_EX.copy() - ) - - task_execs = db_api.get_task_executions() - - self.assertEqual(1, len(task_execs)) - - task_ex = task_execs[0] - - self._assert_dict_contains_subset(TASK_EX, task_ex.to_dict()) - - def test_insert_or_ignore_with_conflicts(self): - # Insert the first object. - values = TASK_EX.copy() - - values['unique_key'] = 'key' - - db_api.insert_or_ignore(db_models.TaskExecution, values) - - task_execs = db_api.get_task_executions() - - self.assertEqual(1, len(task_execs)) - - task_ex = task_execs[0] - - self._assert_dict_contains_subset(TASK_EX, task_ex.to_dict()) - - # Insert the second object with the same unique key. - # We must not get exceptions and new object must not be saved. - values = TASK_EX.copy() - - values['unique_key'] = 'key' - - db_api.insert_or_ignore(db_models.TaskExecution, values) - - task_execs = db_api.get_task_executions() - - self.assertEqual(1, len(task_execs)) - - task_ex = task_execs[0] - - self._assert_dict_contains_subset(TASK_EX, task_ex.to_dict()) diff --git a/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py b/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py index 22ac61961..099800413 100644 --- a/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py +++ b/mistral/tests/unit/db/v2/test_sqlalchemy_db_api.py @@ -1130,7 +1130,7 @@ class ActionDefinitionTest(SQLAlchemyTest): self.assertEqual(1, len(fetched)) self.assertEqual(created3, fetched[0]) - f = filter_utils.create_or_update_filter('name', "Action", 'has') + f = filter_utils.create_or_update_filter('name', "action", 'has') fetched = db_api.get_action_definitions(**f) diff --git a/mistral/tests/unit/engine/test_direct_workflow_rerun.py b/mistral/tests/unit/engine/test_direct_workflow_rerun.py index fb1bba2e4..8fea35977 100644 --- a/mistral/tests/unit/engine/test_direct_workflow_rerun.py +++ b/mistral/tests/unit/engine/test_direct_workflow_rerun.py @@ -879,7 +879,7 @@ class DirectWorkflowRerunTest(base.EngineTestCase): self.assertIsNone(task_3_ex.state_info) task_3_action_exs = db_api.get_action_executions( - task_execution_id=task_execs[2].id + task_execution_id=task_3_ex.id ) self.assertEqual(2, len(task_3_action_exs)) @@ -1026,7 +1026,7 @@ class DirectWorkflowRerunTest(base.EngineTestCase): self.assertEqual(states.SUCCESS, task_3_ex.state) task_3_action_exs = db_api.get_action_executions( - task_execution_id=task_execs[2].id + task_execution_id=task_3_ex.id ) self.assertEqual(1, len(task_3_action_exs)) diff --git a/run_tests.sh b/run_tests.sh index a70805962..b06f412b9 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -140,15 +140,27 @@ function setup_db { dbname="mistral" username="mistral" password="m1stral" - sudo -u postgres psql -c "DROP DATABASE IF EXISTS $dbname;" - sudo -u postgres psql -c "DROP USER IF EXISTS $username;" - sudo -u postgres psql -c "CREATE USER $username WITH ENCRYPTED PASSWORD '$password';" - sudo -u postgres psql -c "CREATE DATABASE $dbname OWNER $username;" + + pg_command "SELECT pg_terminate_backend(pg_stat_activity.pid) + FROM pg_stat_activity + WHERE pg_stat_activity.datname = '$dbname' + AND pid <> pg_backend_pid();" + pg_command "DROP DATABASE IF EXISTS $dbname;" + pg_command "DROP USER IF EXISTS $username;" + pg_command "CREATE USER $username + WITH ENCRYPTED PASSWORD '$password';" + pg_command "CREATE DATABASE $dbname OWNER $username;" fi ;; esac } +function pg_command { + command=$1 + + sudo -u postgres psql -h localhost -c "${command}" +} + function setup_db_pylib { case ${db_type} in postgresql )