diff options
| author | Boris Pavlovic <boris@pavlovic.me> | 2013-05-22 16:57:47 +0400 |
|---|---|---|
| committer | Boris Pavlovic <boris@pavlovic.me> | 2013-05-24 14:57:27 +0400 |
| commit | 7238438ef218d79a31acb07ea004fca8c2e78798 (patch) | |
| tree | 6424423d6c16a18004601ad62bfc87f6a97b72f9 | |
| parent | 05be719ec76adf60a151b56d695c59fd832cb22b (diff) | |
| download | nova-7238438ef218d79a31acb07ea004fca8c2e78798.tar.gz nova-7238438ef218d79a31acb07ea004fca8c2e78798.tar.xz nova-7238438ef218d79a31acb07ea004fca8c2e78798.zip | |
Fix tests for sqlalchemy utils
This fix tests to be able to run it with postgresql and mysql.
Some tests should be run only on sqlite
Method create_shadow_tables raises different exception in different
backends (when we try to create duplicate table):
In postgresql it is ProgrammingError
In sqlite and mysql it is OperationalError
So create new Exception that will be raised in both cases.
bp db-common-migration-and-utils
Change-Id: I11be23106bc01bd3c72dad30edfb31a17177bb34
| -rw-r--r-- | nova/db/sqlalchemy/utils.py | 18 | ||||
| -rw-r--r-- | nova/exception.py | 4 | ||||
| -rw-r--r-- | nova/tests/test_migration_utils.py | 154 |
3 files changed, 92 insertions, 84 deletions
diff --git a/nova/db/sqlalchemy/utils.py b/nova/db/sqlalchemy/utils.py index f0eece661..84a24b94f 100644 --- a/nova/db/sqlalchemy/utils.py +++ b/nova/db/sqlalchemy/utils.py @@ -16,12 +16,18 @@ # under the License. from migrate.changeset import UniqueConstraint +from sqlalchemy import Column from sqlalchemy.engine import reflection +from sqlalchemy.exc import OperationalError +from sqlalchemy.exc import ProgrammingError from sqlalchemy.ext.compiler import compiles from sqlalchemy import func -from sqlalchemy import MetaData, Table, Column, Index -from sqlalchemy.sql.expression import UpdateBase, literal_column +from sqlalchemy import Index +from sqlalchemy import MetaData +from sqlalchemy.sql.expression import literal_column +from sqlalchemy.sql.expression import UpdateBase from sqlalchemy.sql import select +from sqlalchemy import Table from sqlalchemy.types import NullType from nova.db.sqlalchemy import api as db @@ -256,11 +262,15 @@ def create_shadow_table(migrate_engine, table_name=None, table=None, else: columns.append(column.copy()) - shadow_table = Table(db._SHADOW_TABLE_PREFIX + table.name, meta, *columns, + shadow_table_name = db._SHADOW_TABLE_PREFIX + table.name + shadow_table = Table(shadow_table_name, meta, *columns, mysql_engine='InnoDB') try: shadow_table.create() + except (OperationalError, ProgrammingError): + LOG.info(repr(shadow_table)) + LOG.exception(_('Exception while creating table.')) + raise exception.ShadowTableExists(name=shadow_table_name) except Exception: LOG.info(repr(shadow_table)) LOG.exception(_('Exception while creating table.')) - raise diff --git a/nova/exception.py b/nova/exception.py index dfa31941a..a763fbcb6 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1203,6 +1203,10 @@ class RescheduledException(NovaException): "%(reason)s") +class ShadowTableExists(NovaException): + message = _("Shadow table with name %(name)s already exists.") + + class InstanceFaultRollback(NovaException): def __init__(self, inner_exception=None): message = _("Instance rollback performed due to: %s") diff --git a/nova/tests/test_migration_utils.py b/nova/tests/test_migration_utils.py index d6e1ee568..5155dba8f 100644 --- a/nova/tests/test_migration_utils.py +++ b/nova/tests/test_migration_utils.py @@ -19,7 +19,6 @@ from migrate.changeset import UniqueConstraint from sqlalchemy import Integer, DateTime, String from sqlalchemy import MetaData, Table, Column from sqlalchemy.exc import NoSuchTableError -from sqlalchemy.exc import OperationalError from sqlalchemy.exc import SAWarning from sqlalchemy.sql import select from sqlalchemy.types import UserDefinedType @@ -92,54 +91,51 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): {'id': 3, 'a': 1, 'foo': 30} ] - for key, engine in self.engines.items(): - meta = MetaData() - meta.bind = engine - test_table = Table(table_name, meta, - Column('id', Integer, primary_key=True, - nullable=False), - Column('a', Integer), - Column('foo', CustomType, default=0), - UniqueConstraint('a', name='uniq_a'), - UniqueConstraint('foo', name=uc_name)) - test_table.create() - - engine.execute(test_table.insert(), values) - if key == "sqlite": - warnings.simplefilter("ignore", SAWarning) - # NOTE(boris-42): Missing info about column `foo` that has - # unsupported type CustomType. - self.assertRaises(exception.NovaException, - utils.drop_unique_constraint, - engine, table_name, uc_name, 'foo') - - # NOTE(boris-42): Wrong type of foo instance. it should be - # instance of sqlalchemy.Column. - self.assertRaises(exception.NovaException, - utils.drop_unique_constraint, - engine, table_name, uc_name, 'foo', - foo=Integer()) - - foo = Column('foo', CustomType, default=0) - utils.drop_unique_constraint(engine, table_name, uc_name, 'foo', - foo=foo) - - s = test_table.select().order_by(test_table.c.id) - rows = engine.execute(s).fetchall() + engine = self.engines['sqlite'] + meta = MetaData(bind=engine) - for i in xrange(0, len(values)): - v = values[i] - self.assertEqual((v['id'], v['a'], v['foo']), rows[i]) + test_table = Table(table_name, meta, + Column('id', Integer, primary_key=True, + nullable=False), + Column('a', Integer), + Column('foo', CustomType, default=0), + UniqueConstraint('a', name='uniq_a'), + UniqueConstraint('foo', name=uc_name)) + test_table.create() - # NOTE(boris-42): Update data about Table from DB. - meta = MetaData() - meta.bind = engine - test_table = Table(table_name, meta, autoload=True) - constraints = filter(lambda c: c.name == uc_name, - test_table.constraints) - self.assertEqual(len(constraints), 0) - self.assertEqual(len(test_table.constraints), 1) - test_table.drop() + engine.execute(test_table.insert(), values) + warnings.simplefilter("ignore", SAWarning) + # NOTE(boris-42): Missing info about column `foo` that has + # unsupported type CustomType. + self.assertRaises(exception.NovaException, + utils.drop_unique_constraint, + engine, table_name, uc_name, 'foo') + + # NOTE(boris-42): Wrong type of foo instance. it should be + # instance of sqlalchemy.Column. + self.assertRaises(exception.NovaException, + utils.drop_unique_constraint, + engine, table_name, uc_name, 'foo', foo=Integer()) + + foo = Column('foo', CustomType, default=0) + utils.drop_unique_constraint(engine, table_name, uc_name, 'foo', + foo=foo) + + s = test_table.select().order_by(test_table.c.id) + rows = engine.execute(s).fetchall() + + for i in xrange(0, len(values)): + v = values[i] + self.assertEqual((v['id'], v['a'], v['foo']), rows[i]) + + # NOTE(boris-42): Update data about Table from DB. + meta = MetaData(bind=engine) + test_table = Table(table_name, meta, autoload=True) + constraints = filter(lambda c: c.name == uc_name, + test_table.constraints) + self.assertEqual(len(constraints), 0) + self.assertEqual(len(test_table.constraints), 1) + test_table.drop() def _populate_db_for_drop_duplicate_entries(self, engine, meta, table_name): @@ -160,7 +156,7 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): nullable=False), Column('a', Integer), Column('b', Integer), - Column('c', String), + Column('c', String(255)), Column('deleted', Integer, default=0), Column('deleted_at', DateTime), Column('updated_at', DateTime)) @@ -296,22 +292,21 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): def test_check_shadow_table_with_unsupported_type(self): table_name = 'abc' - for key, engine in self.engines.items(): - meta = MetaData() - meta.bind = engine - - table = Table(table_name, meta, - Column('id', Integer, primary_key=True), - Column('a', Integer), - Column('c', CustomType)) - table.create() - - shadow_table = Table(db._SHADOW_TABLE_PREFIX + table_name, meta, - Column('id', Integer, primary_key=True), - Column('a', Integer), - Column('c', CustomType)) - shadow_table.create() - self.assertTrue(utils.check_shadow_table(engine, table_name)) + engine = self.engines['sqlite'] + meta = MetaData(bind=engine) + + table = Table(table_name, meta, + Column('id', Integer, primary_key=True), + Column('a', Integer), + Column('c', CustomType)) + table.create() + + shadow_table = Table(db._SHADOW_TABLE_PREFIX + table_name, meta, + Column('id', Integer, primary_key=True), + Column('a', Integer), + Column('c', CustomType)) + shadow_table.create() + self.assertTrue(utils.check_shadow_table(engine, table_name)) def test_create_shadow_table_by_table_instance(self): table_name = 'abc' @@ -342,21 +337,20 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): def test_create_shadow_table_not_supported_type(self): table_name = 'abc' - for key, engine in self.engines.items(): - meta = MetaData() - meta.bind = engine - - table = Table(table_name, meta, - Column('id', Integer, primary_key=True), - Column('a', CustomType)) - table.create() - self.assertRaises(exception.NovaException, - utils.create_shadow_table, - engine, table_name=table_name) - - utils.create_shadow_table(engine, table_name=table_name, - a=Column('a', CustomType())) - self.assertTrue(utils.check_shadow_table(engine, table_name)) + engine = self.engines['sqlite'] + meta = MetaData() + meta.bind = engine + table = Table(table_name, meta, + Column('id', Integer, primary_key=True), + Column('a', CustomType)) + table.create() + self.assertRaises(exception.NovaException, + utils.create_shadow_table, + engine, table_name=table_name) + + utils.create_shadow_table(engine, table_name=table_name, + a=Column('a', CustomType())) + self.assertTrue(utils.check_shadow_table(engine, table_name)) def test_create_shadow_both_table_and_table_name_are_none(self): for key, engine in self.engines.items(): @@ -388,6 +382,6 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): Column('a', Integer)) table.create() utils.create_shadow_table(engine, table_name=table_name) - self.assertRaises(OperationalError, + self.assertRaises(exception.ShadowTableExists, utils.create_shadow_table, engine, table_name=table_name) |
