diff --git a/manila/tests/test_migrations.conf b/manila/tests/test_migrations.conf deleted file mode 100644 index 774f149940..0000000000 --- a/manila/tests/test_migrations.conf +++ /dev/null @@ -1,9 +0,0 @@ -[DEFAULT] -# Set up any number of migration data stores you want, one -# The "name" used in the test is the config variable key. -#sqlite=sqlite:///test_migrations.db -sqlite=sqlite:// -#mysql=mysql://root:@localhost/test_migrations -#postgresql=postgresql://user:pass@localhost/test_migrations -[walk_style] -snake_walk=yes diff --git a/manila/tests/test_migrations.py b/manila/tests/test_migrations.py index 2a45b8041b..597a60fcab 100644 --- a/manila/tests/test_migrations.py +++ b/manila/tests/test_migrations.py @@ -16,186 +16,90 @@ # under the License. """ -Tests for database migrations. This test case reads the configuration -file test_migrations.conf for database connection settings -to use in the tests. For each connection found in the config file, -the test case runs a series of test cases to ensure that migrations work -properly both upgrading and downgrading, and that no data loss occurs -if possible. +Tests for database migrations. """ -import ConfigParser import os -import shutil -import tempfile from migrate.versioning import api as migration_api from migrate.versioning import repository +from oslo.db.sqlalchemy import test_base from oslo.db.sqlalchemy import test_migrations -import sqlalchemy -import testtools +from sqlalchemy.sql import text import manila.db.sqlalchemy.migrate_repo -from manila.openstack.common import log as logging -from manila import test - -LOG = logging.getLogger('manila.tests.test_migrations') -def _get_connect_string(backend, - user="openstack_citest", - passwd="openstack_citest", - database="openstack_citest"): - """ - Try to get a connection with a very specific set of values, if we get - these then we'll run the tests, otherwise they are skipped - """ - if backend == "postgres": - backend = "postgresql+psycopg2" - - return ("%(backend)s://%(user)s:%(passwd)s@localhost/%(database)s" - % locals()) - - -def _is_mysql_avail(**kwargs): - return _is_backend_avail('mysql', **kwargs) - - -def _is_backend_avail(backend, - user="openstack_citest", - passwd="openstack_citest", - database="openstack_citest"): - try: - if backend == "mysql": - connect_uri = _get_connect_string("mysql", user=user, - passwd=passwd, database=database) - elif backend == "postgres": - connect_uri = _get_connect_string("postgres", user=user, - passwd=passwd, database=database) - engine = sqlalchemy.create_engine(connect_uri) - connection = engine.connect() - except Exception: - # intentionally catch all to handle exceptions even if we don't - # have any backend code loaded. - return False - else: - connection.close() - engine.dispose() - return True - - -class TestMigrations(test.TestCase, - test_migrations.BaseMigrationTestCase, - test_migrations.WalkVersionsMixin): +class ManilaMigrationsCheckers(test_migrations.WalkVersionsMixin): """Test sqlalchemy-migrate migrations.""" - def __init__(self, *args, **kwargs): - super(TestMigrations, self).__init__(*args, **kwargs) + snake_walk = False + downgrade = False - self.DEFAULT_CONFIG_FILE = os.path.join(os.path.dirname(__file__), - 'test_migrations.conf') - # Test machines can set the MANILA_TEST_MIGRATIONS_CONF variable - # to override the location of the config file for migration testing - self.CONFIG_FILE_PATH = os.environ.get('MANILA_TEST_MIGRATIONS_CONF', - self.DEFAULT_CONFIG_FILE) - self.MIGRATE_FILE = manila.db.sqlalchemy.migrate_repo.__file__ - self.REPOSITORY = repository.Repository( - os.path.abspath(os.path.dirname(self.MIGRATE_FILE))) - self.migration_api = migration_api - self.INIT_VERSION = 000 + @property + def INIT_VERSION(self): + return 000 - def setUp(self): - if not os.environ.get("OSLO_LOCK_PATH"): - lock_dir = tempfile.mkdtemp() - os.environ["OSLO_LOCK_PATH"] = lock_dir - self.addCleanup(self._cleanup) + @property + def REPOSITORY(self): + migrate_file = manila.db.sqlalchemy.migrate_repo.__file__ + return repository.Repository( + os.path.abspath(os.path.dirname(migrate_file))) - self.snake_walk = False - if not self.test_databases: - super(TestMigrations, self).setUp() - cp = ConfigParser.RawConfigParser() - try: - cp.read(self.CONFIG_FILE_PATH) - self.snake_walk = cp.getboolean('walk_style', 'snake_walk') - except ConfigParser.ParsingError as e: - self.fail("Failed to read test_migrations.conf config " - "file. Got error: %s" % e) + @property + def migration_api(self): + return migration_api - def _cleanup(self): - shutil.rmtree(os.environ["OSLO_LOCK_PATH"], ignore_errors=True) - del os.environ["OSLO_LOCK_PATH"] + @property + def migrate_engine(self): + return self.engine def test_walk_versions(self): """ Walks all version scripts for each tested database, ensuring that there are no errors in the version scripts for each engine """ - for key, engine in self.engines.items(): - self._walk_versions(engine, self.snake_walk) + self._walk_versions(snake_walk=self.snake_walk, + downgrade=self.downgrade) - def test_mysql_connect_fail(self): - """ - Test that we can trigger a mysql connection failure and we fail - gracefully to ensure we don't break people without mysql - """ - if _is_mysql_avail(user="openstack_cifail"): - self.fail("Shouldn't have connected") - @testtools.skipUnless(test_migrations._have_mysql("openstack_citest", - "openstack_citest", - "openstack_citest"), - "mysql not available") +class TestManilaMigrationsMySQL(ManilaMigrationsCheckers, + test_base.MySQLOpportunisticTestCase): + """Run migration tests on MySQL backend.""" + def test_mysql_innodb(self): - """ - Test that table creation on mysql only builds InnoDB tables - """ - # add this to the global lists to make parent _reset_databases method - # work with it, it's removed automaticaly in parent tearDown method so - # no need to clean it up here. - connect_string = _get_connect_string('mysql') - engine = sqlalchemy.create_engine(connect_string) - self.engines["mysqlcitest"] = engine - self.test_databases["mysqlcitest"] = connect_string - - # build a fully populated mysql database with all the tables - self._reset_databases() - self._walk_versions(engine, False, False) - - uri = _get_connect_string('mysql', database="information_schema") - connection = sqlalchemy.create_engine(uri).connect() + """Test that table creation on mysql only builds InnoDB tables.""" + self._walk_versions(snake_walk=False, downgrade=False) # sanity check - total = connection.execute("SELECT count(*) " - "from information_schema.TABLES " - "where TABLE_SCHEMA='openstack_citest'") + sanity_check = """SELECT count(*) + FROM information_schema.tables + WHERE table_schema = :database;""" + total = self.engine.execute( + text(sanity_check), + database=self.engine.url.database) + self.assertTrue(total.scalar() > 0, "No tables found. Wrong schema?") - noninnodb = connection.execute("SELECT count(*) " - "from information_schema.TABLES " - "where TABLE_SCHEMA='openstack_citest' " - "and ENGINE!='InnoDB' " - "and TABLE_NAME!='migrate_version'") - count = noninnodb.scalar() + noninnodb_query = """ + SELECT count(*) + FROM information_schema.TABLES + WHERE table_schema = :database + AND engine != 'InnoDB' + AND table_name != 'migrate_version';""" + + count = self.engine.execute( + text(noninnodb_query), + database=self.engine.url.database + ).scalar() self.assertEqual(count, 0, "%d non InnoDB tables created" % count) - def test_postgresql_connect_fail(self): - """ - Test that we can trigger a postgres connection failure and we fail - gracefully to ensure we don't break people without postgres - """ - if _is_backend_avail('postgres', user="openstack_cifail"): - self.fail("Shouldn't have connected") - @testtools.skipUnless(_is_backend_avail('postgres'), - "postgresql not available") - def test_postgresql_opportunistically(self): - # add this to the global lists to make reset work with it, it's removed - # automatically in tearDown so no need to clean it up here. - connect_string = _get_connect_string("postgres") - engine = sqlalchemy.create_engine(connect_string) - self.engines["postgresqlcitest"] = engine - self.test_databases["postgresqlcitest"] = connect_string +class TestManilaMigrationsPostgreSQL( + ManilaMigrationsCheckers, test_base.PostgreSQLOpportunisticTestCase): + """Run migration tests on PostgreSQL backend.""" - # build a fully populated postgresql database with all the tables - self._reset_databases() - self._walk_versions(engine, False, False) + +class TestManilaMigrationsSQLite(ManilaMigrationsCheckers, + test_base.DbTestCase): + """Run migration tests on SQLite backend.""" diff --git a/tox.ini b/tox.ini index a5490f32cb..268858a962 100644 --- a/tox.ini +++ b/tox.ini @@ -5,6 +5,8 @@ envlist = py26,py27,pep8 [testenv] setenv = VIRTUAL_ENV={envdir} + # NOTE (viktors): Workaround for bug 1359982 + PYTHONHASHSEED=0 usedevelop = True install_command = pip install {opts} {packages} deps = -r{toxinidir}/requirements.txt