def do_check_migration(config, cmd):
do_alembic_command(config, 'branches')
- validate_labels(config)
+ validate_revisions(config)
validate_heads_file(config)
_validate_single_revision_labels(script_dir, revision)
-def validate_labels(config):
+def validate_revisions(config):
script_dir = alembic_script.ScriptDirectory.from_config(config)
revisions = [v for v in script_dir.walk_revisions(base='base',
head='heads')]
+
+ branchpoints = []
for revision in revisions:
+ if revision.is_branch_point:
+ branchpoints.append(revision)
+
_validate_revision(script_dir, revision)
+ if len(branchpoints) > 1:
+ branchpoints = ', '.join(p.revision for p in branchpoints)
+ alembic_util.err(
+ _('Unexpected number of alembic branch points: %(branchpoints)s') %
+ {'branchpoints': branchpoints}
+ )
+
def _get_sorted_heads(script):
'''Get the list of heads for all branches, sorted.'''
from neutron.db.migration import autogen
from neutron.db.migration import cli
from neutron.tests import base
+from neutron.tests import tools
from neutron.tests.unit import testlib_api
class FakeRevision(object):
path = 'fakepath'
- def __init__(self, labels=None, down_revision=None):
+ def __init__(self, labels=None, down_revision=None, is_branch_point=False):
if not labels:
labels = set()
self.branch_labels = labels
self.down_revision = down_revision
+ self.is_branch_point = is_branch_point
+ self.revision = tools.get_random_string()
class MigrationEntrypointsMemento(fixtures.Fixture):
def _main_test_helper(self, argv, func_name, exp_kwargs=[{}]):
with mock.patch.object(sys, 'argv', argv),\
mock.patch.object(cli, 'run_sanity_checks'),\
- mock.patch.object(cli, 'validate_labels'):
+ mock.patch.object(cli, 'validate_revisions'):
cli.main()
self.do_alembic_cmd.assert_has_calls(
@mock.patch.object(cli, '_validate_revision')
@mock.patch('alembic.script.ScriptDirectory.walk_revisions')
- def test_validate_labels_walks_thru_all_revisions(
+ def test_validate_revisions_walks_thru_all_revisions(
self, walk_mock, validate_mock):
- revisions = [mock.Mock() for i in range(10)]
+ revisions = [FakeRevision() for i in range(10)]
walk_mock.return_value = revisions
- cli.validate_labels(self.configs[0])
+ cli.validate_revisions(self.configs[0])
validate_mock.assert_has_calls(
[mock.call(mock.ANY, revision) for revision in revisions]
)
+ @mock.patch.object(cli, '_validate_revision')
+ @mock.patch('alembic.script.ScriptDirectory.walk_revisions')
+ def test_validate_revisions_fails_on_multiple_branch_points(
+ self, walk_mock, validate_mock):
+
+ revisions = [FakeRevision(is_branch_point=True) for i in range(2)]
+ walk_mock.return_value = revisions
+ self.assertRaises(
+ SystemExit, cli.validate_revisions, self.configs[0])
+
@mock.patch.object(cli, '_use_separate_migration_branches')
@mock.patch.object(cli, '_get_version_branch_path')
def test_autogen_process_directives(
class TestSafetyChecks(base.BaseTestCase):
- def test_validate_labels(self, *mocks):
- cli.validate_labels(cli.get_neutron_config())
+ def test_validate_revisions(self, *mocks):
+ cli.validate_revisions(cli.get_neutron_config())
import copy
import random
-import string
import mock
from oslo_db import exception as obj_exc
from neutron.db import api as db_api
from neutron.objects import base
from neutron.tests import base as test_base
+from neutron.tests import tools
SQLALCHEMY_COMMIT = 'sqlalchemy.engine.Connection._commit_impl'
synthetic_fields = ['field2']
-def _random_string(n=10):
- return ''.join(random.choice(string.ascii_lowercase) for _ in range(n))
-
-
def _random_boolean():
return bool(random.getrandbits(1))
FIELD_TYPE_VALUE_GENERATOR_MAP = {
obj_fields.BooleanField: _random_boolean,
obj_fields.IntegerField: _random_integer,
- obj_fields.StringField: _random_string,
- obj_fields.UUIDField: _random_string,
+ obj_fields.StringField: tools.get_random_string,
+ obj_fields.UUIDField: tools.get_random_string,
obj_fields.ListOfObjectsField: lambda: []
}