Files
subunit2sql/subunit2sql/tests/migrations/test_model_sync.py
Masayuki Igawa 5557641fea Fix lock range, again
This commit fixes lock range. We should get a lock before connecting to
a database.

Change-Id: Iecca74db980d3660248ad9dba6ddccd656f439bd
2016-04-07 10:59:00 -04:00

135 lines
5.1 KiB
Python

# Copyright (c) 2015 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.
import mock
from oslo_db.sqlalchemy import test_migrations
import sqlalchemy
import testscenarios
from subunit2sql.db import models
from subunit2sql.tests import base
from subunit2sql.tests import db_test_utils
from subunit2sql.tests import subunit2sql_fixtures as fixtures
load_tests = testscenarios.load_tests_apply_scenarios
class TestModelsMigrations(test_migrations.ModelsMigrationsSync,
base.TestCase):
"""Test for checking of equality models state and migrations.
Output is a list that contains information about differences between db and
models. Output example::
[('add_table',
Table('bat', MetaData(bind=None),
Column('info', String(), table=<bat>), schema=None)),
('remove_table',
Table(u'bar', MetaData(bind=None),
Column(u'data', VARCHAR(), table=<bar>), schema=None)),
('add_column',
None,
'foo',
Column('data', Integer(), table=<foo>)),
('remove_column',
None,
'foo',
Column(u'old_data', VARCHAR(), table=None)),
[('modify_nullable',
None,
'foo',
u'x',
{'existing_server_default': None,
'existing_type': INTEGER()},
True,
False)]]
* ``remove_*`` means that there is extra table/column/constraint in db;
* ``add_*`` means that it is missing in db;
* ``modify_*`` means that on column in db is set wrong
type/nullable/server_default. Element contains information:
- what should be modified,
- schema,
- table,
- column,
- existing correct column parameters,
- right value,
- wrong value.
"""
scenarios = [
('mysql', {'dialect': 'mysql'}),
('postgresql', {'dialect': 'postgres'}),
('sqlite', {'dialect': 'sqlite'})
]
# NOTE(mtreinish): Mock out db attr because oslo.db tries to assert
# control of how the opportunistic db is setup. But, since subunit2sql's
# tests already do this, just let oslo.db think it's doing the operations
db = mock.MagicMock()
def setUp(self):
super(TestModelsMigrations, self).setUp()
self.useFixture(fixtures.LockFixture(self.dialect))
if not db_test_utils.is_backend_avail(self.dialect):
raise self.skipTest('%s is not available' % self.dialect)
if self.dialect == 'sqlite':
raise self.skipException('sqlite skipped because of model sync '
'issue with BigInteger vs Integer')
if self.dialect == 'mysql':
self.useFixture(fixtures.MySQLConfFixture())
elif self.dialect == 'postgres':
self.useFixture(fixtures.PostgresConfFixture())
connect_string = db_test_utils.get_connect_string(self.dialect)
self.engine = sqlalchemy.create_engine(connect_string)
def get_engine(self):
return self.engine
def get_metadata(self):
return models.BASE.metadata
def db_sync(self, engine):
db_test_utils.run_migration('head', engine)
def include_object(self, object_, name, type_, reflected, compare_to):
if type_ == 'table' and name == 'alembic_version':
return False
return super(TestModelsMigrations, self).include_object(
object_, name, type_, reflected, compare_to)
def filter_metadata_diff(self, diff):
return filter(self.remove_unrelated_errors, diff)
def remove_unrelated_errors(self, element):
insp = sqlalchemy.engine.reflection.Inspector.from_engine(
self.get_engine())
dialect = self.get_engine().dialect.name
if isinstance(element, tuple):
if dialect == 'mysql' and element[0] == 'remove_index':
table_name = element[1].table.name
for fk in insp.get_foreign_keys(table_name):
if fk['name'] == element[1].name:
return False
cols = [c.name for c in element[1].expressions]
for col in cols:
if col in insp.get_pk_constraint(
table_name)['constrained_columns']:
return False
else:
for modified, _, table, column, _, _, new in element:
if modified == 'modify_default' and dialect == 'mysql':
constrained = insp.get_pk_constraint(table)
if column in constrained['constrained_columns']:
return False
return True