a03b141a95
Brief summary of the modifications: * Use six for compatibility with both Python 2 and 3; * Replace UserDict.DictMixin with collections.MutableMapping; * Fix relative imports; * Use test-requirements.txt for requirements that are common to both Python 2 and 3, and test-requirements-py{2,3}.txt for version-specific requirements; * Miscellaneous fixes. * Use a specific test_db_py3.cfg file for Python 3, that only runs tests on sqlite. Thanks to Victor Stinner who co-wrote this patch. Change-Id: Ia6dc536c39d274924c21fd5bb619e8e5721e04c4 Co-Authored-By: Victor Stinner <victor.stinner@enovance.com>
206 lines
6.6 KiB
Python
206 lines
6.6 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import shutil
|
|
|
|
import six
|
|
|
|
from migrate import exceptions
|
|
from migrate.versioning.schema import *
|
|
from migrate.versioning import script, schemadiff
|
|
|
|
from sqlalchemy import *
|
|
|
|
from migrate.tests import fixture
|
|
|
|
|
|
class TestControlledSchema(fixture.Pathed, fixture.DB):
|
|
# Transactions break postgres in this test; we'll clean up after ourselves
|
|
level = fixture.DB.CONNECT
|
|
|
|
def setUp(self):
|
|
super(TestControlledSchema, self).setUp()
|
|
self.path_repos = self.temp_usable_dir + '/repo/'
|
|
self.repos = Repository.create(self.path_repos, 'repo_name')
|
|
|
|
def _setup(self, url):
|
|
self.setUp()
|
|
super(TestControlledSchema, self)._setup(url)
|
|
self.cleanup()
|
|
|
|
def _teardown(self):
|
|
super(TestControlledSchema, self)._teardown()
|
|
self.cleanup()
|
|
self.tearDown()
|
|
|
|
def cleanup(self):
|
|
# drop existing version table if necessary
|
|
try:
|
|
ControlledSchema(self.engine, self.repos).drop()
|
|
except:
|
|
# No table to drop; that's fine, be silent
|
|
pass
|
|
|
|
def tearDown(self):
|
|
self.cleanup()
|
|
super(TestControlledSchema, self).tearDown()
|
|
|
|
@fixture.usedb()
|
|
def test_version_control(self):
|
|
"""Establish version control on a particular database"""
|
|
# Establish version control on this database
|
|
dbcontrol = ControlledSchema.create(self.engine, self.repos)
|
|
|
|
# Trying to create another DB this way fails: table exists
|
|
self.assertRaises(exceptions.DatabaseAlreadyControlledError,
|
|
ControlledSchema.create, self.engine, self.repos)
|
|
|
|
# We can load a controlled DB this way, too
|
|
dbcontrol0 = ControlledSchema(self.engine, self.repos)
|
|
self.assertEqual(dbcontrol, dbcontrol0)
|
|
|
|
# We can also use a repository path, instead of a repository
|
|
dbcontrol0 = ControlledSchema(self.engine, self.repos.path)
|
|
self.assertEqual(dbcontrol, dbcontrol0)
|
|
|
|
# We don't have to use the same connection
|
|
engine = create_engine(self.url)
|
|
dbcontrol0 = ControlledSchema(engine, self.repos.path)
|
|
self.assertEqual(dbcontrol, dbcontrol0)
|
|
|
|
# Clean up:
|
|
dbcontrol.drop()
|
|
|
|
# Attempting to drop vc from a db without it should fail
|
|
self.assertRaises(exceptions.DatabaseNotControlledError, dbcontrol.drop)
|
|
|
|
# No table defined should raise error
|
|
self.assertRaises(exceptions.DatabaseNotControlledError,
|
|
ControlledSchema, self.engine, self.repos)
|
|
|
|
@fixture.usedb()
|
|
def test_version_control_specified(self):
|
|
"""Establish version control with a specified version"""
|
|
# Establish version control on this database
|
|
version = 0
|
|
dbcontrol = ControlledSchema.create(self.engine, self.repos, version)
|
|
self.assertEqual(dbcontrol.version, version)
|
|
|
|
# Correct when we load it, too
|
|
dbcontrol = ControlledSchema(self.engine, self.repos)
|
|
self.assertEqual(dbcontrol.version, version)
|
|
|
|
dbcontrol.drop()
|
|
|
|
# Now try it with a nonzero value
|
|
version = 10
|
|
for i in range(version):
|
|
self.repos.create_script('')
|
|
self.assertEqual(self.repos.latest, version)
|
|
|
|
# Test with some mid-range value
|
|
dbcontrol = ControlledSchema.create(self.engine,self.repos, 5)
|
|
self.assertEqual(dbcontrol.version, 5)
|
|
dbcontrol.drop()
|
|
|
|
# Test with max value
|
|
dbcontrol = ControlledSchema.create(self.engine, self.repos, version)
|
|
self.assertEqual(dbcontrol.version, version)
|
|
dbcontrol.drop()
|
|
|
|
@fixture.usedb()
|
|
def test_version_control_invalid(self):
|
|
"""Try to establish version control with an invalid version"""
|
|
versions = ('Thirteen', '-1', -1, '' , 13)
|
|
# A fresh repository doesn't go up to version 13 yet
|
|
for version in versions:
|
|
#self.assertRaises(ControlledSchema.InvalidVersionError,
|
|
# Can't have custom errors with assertRaises...
|
|
try:
|
|
ControlledSchema.create(self.engine, self.repos, version)
|
|
self.assertTrue(False, repr(version))
|
|
except exceptions.InvalidVersionError:
|
|
pass
|
|
|
|
@fixture.usedb()
|
|
def test_changeset(self):
|
|
"""Create changeset from controlled schema"""
|
|
dbschema = ControlledSchema.create(self.engine, self.repos)
|
|
|
|
# empty schema doesn't have changesets
|
|
cs = dbschema.changeset()
|
|
self.assertEqual(cs, {})
|
|
|
|
for i in range(5):
|
|
self.repos.create_script('')
|
|
self.assertEqual(self.repos.latest, 5)
|
|
|
|
cs = dbschema.changeset(5)
|
|
self.assertEqual(len(cs), 5)
|
|
|
|
# cleanup
|
|
dbschema.drop()
|
|
|
|
@fixture.usedb()
|
|
def test_upgrade_runchange(self):
|
|
dbschema = ControlledSchema.create(self.engine, self.repos)
|
|
|
|
for i in range(10):
|
|
self.repos.create_script('')
|
|
|
|
self.assertEqual(self.repos.latest, 10)
|
|
|
|
dbschema.upgrade(10)
|
|
|
|
self.assertRaises(ValueError, dbschema.upgrade, 'a')
|
|
self.assertRaises(exceptions.InvalidVersionError, dbschema.runchange, 20, '', 1)
|
|
|
|
# TODO: test for table version in db
|
|
|
|
# cleanup
|
|
dbschema.drop()
|
|
|
|
@fixture.usedb()
|
|
def test_create_model(self):
|
|
"""Test workflow to generate create_model"""
|
|
model = ControlledSchema.create_model(self.engine, self.repos, declarative=False)
|
|
self.assertTrue(isinstance(model, six.string_types))
|
|
|
|
model = ControlledSchema.create_model(self.engine, self.repos.path, declarative=True)
|
|
self.assertTrue(isinstance(model, six.string_types))
|
|
|
|
@fixture.usedb()
|
|
def test_compare_model_to_db(self):
|
|
meta = self.construct_model()
|
|
|
|
diff = ControlledSchema.compare_model_to_db(self.engine, meta, self.repos)
|
|
self.assertTrue(isinstance(diff, schemadiff.SchemaDiff))
|
|
|
|
diff = ControlledSchema.compare_model_to_db(self.engine, meta, self.repos.path)
|
|
self.assertTrue(isinstance(diff, schemadiff.SchemaDiff))
|
|
meta.drop_all(self.engine)
|
|
|
|
@fixture.usedb()
|
|
def test_update_db_from_model(self):
|
|
dbschema = ControlledSchema.create(self.engine, self.repos)
|
|
|
|
meta = self.construct_model()
|
|
|
|
dbschema.update_db_from_model(meta)
|
|
|
|
# TODO: test for table version in db
|
|
|
|
# cleanup
|
|
dbschema.drop()
|
|
meta.drop_all(self.engine)
|
|
|
|
def construct_model(self):
|
|
meta = MetaData()
|
|
|
|
user = Table('temp_model_schema', meta, Column('id', Integer), Column('user', String(245)))
|
|
|
|
return meta
|
|
|
|
# TODO: test how are tables populated in db
|