Restore sqlalchemy unit tests

Bring back the sqlalchemy unittests and fix all the bugs required to
make the tests pass.

Closes-bug: #1490450
Change-Id: Ibfa1a3ff372ce3e4a98a532798113013d3c1dec1
This commit is contained in:
Flavio Percoco 2015-08-31 11:11:37 +02:00
parent 96b191d402
commit 47b8453d8b
8 changed files with 76 additions and 44 deletions

View File

@ -76,7 +76,7 @@ class CatalogueController(base.CatalogueBase):
self._conn.execute(stmt)
except sa.exc.IntegrityError:
self.update(project, queue, pool)
self._update(project, queue, pool)
def delete(self, project, queue):
stmt = sa.sql.delete(tables.Catalogue).where(
@ -84,6 +84,12 @@ class CatalogueController(base.CatalogueBase):
)
self._conn.execute(stmt)
def _update(self, project, queue, pool):
stmt = sa.sql.update(tables.Catalogue).where(
_match(project, queue)
).values(pool=pool)
self._conn.execute(stmt)
def update(self, project, queue, pool=None):
if pool is None:
return
@ -91,10 +97,7 @@ class CatalogueController(base.CatalogueBase):
if not self.exists(project, queue):
raise errors.QueueNotMapped(queue, project)
stmt = sa.sql.update(tables.Catalogue).where(
_match(project, queue)
).values(pool=pool)
self._conn.execute(stmt)
self._update(project, queue, pool)
def drop_all(self):
stmt = sa.sql.expression.delete(tables.Catalogue)

View File

@ -86,11 +86,22 @@ class PoolsController(base.PoolsBase):
return _normalize(pool, detailed)
def _ensure_group_exists(self, name):
try:
stmt = sa.sql.expression.insert(tables.PoolGroup).values(name=name)
self._conn.execute(stmt)
return True
except sa.exc.IntegrityError:
return False
# TODO(cpp-cabrera): rename to upsert
@utils.raises_conn_error
def _create(self, name, weight, uri, group=None, options=None):
opts = None if options is None else utils.json_encode(options)
if group is not None:
self._ensure_group_exists(group)
try:
stmt = sa.sql.expression.insert(tables.Pools).values(
name=name, weight=weight, uri=uri, group=group, options=opts
@ -143,6 +154,8 @@ class PoolsController(base.PoolsBase):
def _drop_all(self):
stmt = sa.sql.expression.delete(tables.Pools)
self._conn.execute(stmt)
stmt = sa.sql.expression.delete(tables.PoolGroup)
self._conn.execute(stmt)
def _normalize(pool, detailed=False):

View File

@ -58,15 +58,17 @@ class QueueController(storage.Queue):
if project is None:
project = ''
try:
sel = sa.sql.select([tables.Queues.c.metadata], sa.and_(
tables.Queues.c.project == project,
tables.Queues.c.name == name
))
return utils.json_decode(self.driver.run(sel).fetchone()[0])
except utils.NoResult:
sel = sa.sql.select([tables.Queues.c.metadata], sa.and_(
tables.Queues.c.project == project,
tables.Queues.c.name == name
))
queue = self.driver.run(sel).fetchone()
if queue is None:
raise errors.QueueDoesNotExist(name, project)
return utils.json_decode(queue[0])
def _get(self, name, project=None):
try:
return self.get_metadata(name, project)

View File

@ -28,19 +28,25 @@ Queues = sa.Table('Queues', metadata,
)
PoolGroup = sa.Table('PoolGroup', metadata,
sa.Column('name', sa.String(64), primary_key=True))
Pools = sa.Table('Pools', metadata,
sa.Column('name', sa.String(64), primary_key=True),
sa.Column('group', sa.String(64),
unique=True, nullable=True),
sa.Column('group', sa.ForeignKey('PoolGroup.name',
ondelete='CASCADE'),
nullable=True),
sa.Column('uri', sa.String(255),
unique=True, nullable=False),
sa.Column('weight', sa.INTEGER, nullable=False),
sa.Column('options', sa.BINARY))
Flavors = sa.Table('Flavors', metadata,
sa.Column('name', sa.String(64), primary_key=True),
sa.Column('project', sa.String(64)),
sa.Column('pool', sa.ForeignKey('Pools.group',
sa.Column('pool', sa.ForeignKey('PoolGroup.name',
ondelete='CASCADE'),
nullable=False),
sa.Column('capabilities', sa.BINARY))

View File

@ -5,7 +5,8 @@ admin_mode = False
[drivers]
transport = wsgi
message_store = sqlalchemy
message_store = mongodb
management_store = sqlalchemy
[drivers:transport:wsgi]
bind = 0.0.0.0

View File

@ -173,7 +173,7 @@ def pool_entry(controller, project, queue, pool):
@contextlib.contextmanager
def pool_entries(controller, count):
def pool_entries(controller, pool_ctrl, count):
"""Context manager to create several catalogue entries for testing.
The entries are automatically deleted when the context manager
@ -190,12 +190,14 @@ def pool_entries(controller, count):
for i in range(count)]
for p, q, s in spec:
pool_ctrl.create(s, 100, s)
controller.insert(p, q, s)
yield spec
for p, q, _ in spec:
for p, q, s in spec:
controller.delete(p, q)
pool_ctrl.delete(s)
def requires_mongodb(test_case):

View File

@ -1258,8 +1258,15 @@ class CatalogueControllerTest(ControllerBaseTest):
def setUp(self):
super(CatalogueControllerTest, self).setUp()
self.controller = self.driver.catalogue_controller
self.queue = six.text_type(uuid.uuid1())
self.project = six.text_type(uuid.uuid1())
self.pool_ctrl = self.driver.pools_controller
self.queue = six.text_type(uuid.uuid4())
self.project = six.text_type(uuid.uuid4())
self.pool = str(uuid.uuid1())
self.pool_group = str(uuid.uuid1())
self.pool_ctrl.create(self.pool, 100, 'localhost',
group=self.pool_group, options={})
self.addCleanup(self.pool_ctrl.delete, self.pool)
def tearDown(self):
self.controller.drop_all()
@ -1287,13 +1294,14 @@ class CatalogueControllerTest(ControllerBaseTest):
self.fail('There should be no entries at this time')
# create a listing, check its length
with helpers.pool_entries(self.controller, 10) as expect:
with helpers.pool_entries(self.controller,
self.pool_ctrl, 10) as expect:
project = expect[0][0]
xs = list(self.controller.list(project))
self.assertEqual(len(xs), 10)
# create, check existence, delete
with helpers.pool_entry(self.controller, project, queue, u'a'):
with helpers.pool_entry(self.controller, project, queue, self.pool):
self.assertTrue(self.controller.exists(project, queue))
# verify it no longer exists
@ -1303,7 +1311,8 @@ class CatalogueControllerTest(ControllerBaseTest):
self.assertEqual(len(list(self.controller.list(project))), 0)
def test_list(self):
with helpers.pool_entries(self.controller, 10) as expect:
with helpers.pool_entries(self.controller,
self.pool_ctrl, 10) as expect:
values = zip(self.controller.list(u'_'), expect)
for e, x in values:
p, q, s = x
@ -1311,12 +1320,18 @@ class CatalogueControllerTest(ControllerBaseTest):
self._check_value(e, xqueue=q, xproject=p, xpool=s)
def test_update(self):
p2 = u'b'
self.pool_ctrl.create(p2, 100, '127.0.0.1',
group=self.pool_group,
options={})
self.addCleanup(self.pool_ctrl.delete, p2)
with helpers.pool_entry(self.controller, self.project,
self.queue, u'a') as expect:
self.queue, self.pool) as expect:
p, q, s = expect
self.controller.update(p, q, pool=u'b')
self.controller.update(p, q, pool=p2)
entry = self.controller.get(p, q)
self._check_value(entry, xqueue=q, xproject=p, xpool=u'b')
self._check_value(entry, xqueue=q, xproject=p, xpool=p2)
def test_update_raises_when_entry_does_not_exist(self):
e = self.assertRaises(errors.QueueNotMapped,
@ -1327,7 +1342,7 @@ class CatalogueControllerTest(ControllerBaseTest):
def test_get(self):
with helpers.pool_entry(self.controller,
self.project,
self.queue, u'a') as expect:
self.queue, self.pool) as expect:
p, q, s = expect
e = self.controller.get(p, q)
self._check_value(e, xqueue=q, xproject=p, xpool=s)
@ -1350,7 +1365,7 @@ class CatalogueControllerTest(ControllerBaseTest):
def test_exists(self):
with helpers.pool_entry(self.controller,
self.project,
self.queue, u'a') as expect:
self.queue, self.pool) as expect:
p, q, _ = expect
self.assertTrue(self.controller.exists(p, q))
self.assertFalse(self.controller.exists('nada', 'not_here'))

View File

@ -21,35 +21,25 @@ from zaqar import tests as testing
from zaqar.tests.unit.storage import base
# NOTE(flaper87): We'll need this after splitting queues
# from the data driver
class SqlalchemyQueueTests(base.QueueControllerTest):
driver_class = sqlalchemy.ControlDriver
config_file = 'wsgi_sqlalchemy.conf'
controller_class = controllers.QueueController
control_driver_class = sqlalchemy.ControlDriver
class SqlalchemyPoolsTest(base.PoolsControllerTest):
config_file = 'wsgi_sqlalchemy.conf'
driver_class = sqlalchemy.ControlDriver
controller_class = controllers.PoolsController
def setUp(self):
super(SqlalchemyPoolsTest, self).setUp()
self.load_conf('wsgi_sqlalchemy.conf')
def tearDown(self):
super(SqlalchemyPoolsTest, self).tearDown()
control_driver_class = sqlalchemy.ControlDriver
class SqlalchemyCatalogueTest(base.CatalogueControllerTest):
config_file = 'wsgi_sqlalchemy.conf'
driver_class = sqlalchemy.ControlDriver
controller_class = controllers.CatalogueController
def setUp(self):
super(SqlalchemyCatalogueTest, self).setUp()
self.load_conf('wsgi_sqlalchemy.conf')
def tearDown(self):
super(SqlalchemyCatalogueTest, self).tearDown()
control_driver_class = sqlalchemy.ControlDriver
class MsgidTests(testing.TestBase):