Use fakes instead of mocks for data objects
We hit a nasty infinite recursion issue because we were passing mock's to obj_to_dict which was setting the mock's attributes as attributes of the returned Bunch objects. Really though, we should just not be turning mock objects into Bunch's. Change-Id: I91a69a87082b30e16545c45ef8705ef4e929d5ca
This commit is contained in:
parent
a89dbfadf0
commit
3328cc77da
59
shade/tests/fakes.py
Normal file
59
shade/tests/fakes.py
Normal file
@ -0,0 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.V
|
||||
|
||||
"""
|
||||
fakes
|
||||
----------------------------------
|
||||
|
||||
Fakes used for testing
|
||||
"""
|
||||
|
||||
|
||||
class FakeFlavor(object):
|
||||
def __init__(self, id, name):
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
||||
|
||||
class FakeImage(object):
|
||||
def __init__(self, id, name, status):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.status = status
|
||||
|
||||
|
||||
class FakeProject(object):
|
||||
def __init__(self, id):
|
||||
self.id = id
|
||||
|
||||
|
||||
class FakeServer(object):
|
||||
def __init__(self, id, name, status):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.status = status
|
||||
|
||||
|
||||
class FakeUser(object):
|
||||
def __init__(self, id, email, name):
|
||||
self.id = id
|
||||
self.email = email
|
||||
self.name = name
|
||||
|
||||
|
||||
class FakeVolume(object):
|
||||
def __init__(self, id, status, display_name):
|
||||
self.id = id
|
||||
self.status = status
|
||||
self.display_name = display_name
|
@ -19,6 +19,7 @@ import yaml
|
||||
|
||||
import shade
|
||||
from shade import meta
|
||||
from shade.tests import fakes
|
||||
from shade.tests.unit import base
|
||||
|
||||
|
||||
@ -67,82 +68,68 @@ class TestMemoryCache(base.TestCase):
|
||||
|
||||
@mock.patch('shade.OpenStackCloud.keystone_client')
|
||||
def test_project_cache(self, keystone_mock):
|
||||
mock_project = mock.MagicMock()
|
||||
mock_project.id = 'project_a'
|
||||
keystone_mock.projects.list.return_value = [mock_project]
|
||||
self.assertEqual({'project_a': mock_project}, self.cloud.project_cache)
|
||||
mock_project_b = mock.MagicMock()
|
||||
mock_project_b.id = 'project_b'
|
||||
keystone_mock.projects.list.return_value = [mock_project,
|
||||
mock_project_b]
|
||||
project = fakes.FakeProject('project_a')
|
||||
keystone_mock.projects.list.return_value = [project]
|
||||
self.assertEqual({'project_a': project}, self.cloud.project_cache)
|
||||
project_b = fakes.FakeProject('project_b')
|
||||
keystone_mock.projects.list.return_value = [project,
|
||||
project_b]
|
||||
self.assertEqual(
|
||||
{'project_a': mock_project}, self.cloud.project_cache)
|
||||
{'project_a': project}, self.cloud.project_cache)
|
||||
self.cloud.get_project_cache.invalidate(self.cloud)
|
||||
self.assertEqual(
|
||||
{'project_a': mock_project,
|
||||
'project_b': mock_project_b}, self.cloud.project_cache)
|
||||
{'project_a': project,
|
||||
'project_b': project_b}, self.cloud.project_cache)
|
||||
|
||||
@mock.patch('shade.OpenStackCloud.cinder_client')
|
||||
def test_list_volumes(self, cinder_mock):
|
||||
mock_volume = mock.MagicMock()
|
||||
mock_volume.id = 'volume1'
|
||||
mock_volume.status = 'available'
|
||||
mock_volume.display_name = 'Volume 1 Display Name'
|
||||
mock_volume_dict = meta.obj_to_dict(mock_volume)
|
||||
cinder_mock.volumes.list.return_value = [mock_volume]
|
||||
self.assertEqual([mock_volume_dict], self.cloud.list_volumes())
|
||||
mock_volume2 = mock.MagicMock()
|
||||
mock_volume2.id = 'volume2'
|
||||
mock_volume2.status = 'available'
|
||||
mock_volume2.display_name = 'Volume 2 Display Name'
|
||||
mock_volume2_dict = meta.obj_to_dict(mock_volume2)
|
||||
cinder_mock.volumes.list.return_value = [mock_volume, mock_volume2]
|
||||
self.assertEqual([mock_volume_dict], self.cloud.list_volumes())
|
||||
fake_volume = fakes.FakeVolume('volume1', 'available',
|
||||
'Volume 1 Display Name')
|
||||
fake_volume_dict = meta.obj_to_dict(fake_volume)
|
||||
cinder_mock.volumes.list.return_value = [fake_volume]
|
||||
self.assertEqual([fake_volume_dict], self.cloud.list_volumes())
|
||||
fake_volume2 = fakes.FakeVolume('volume2', 'available',
|
||||
'Volume 2 Display Name')
|
||||
fake_volume2_dict = meta.obj_to_dict(fake_volume2)
|
||||
cinder_mock.volumes.list.return_value = [fake_volume, fake_volume2]
|
||||
self.assertEqual([fake_volume_dict], self.cloud.list_volumes())
|
||||
self.cloud.list_volumes.invalidate(self.cloud)
|
||||
self.assertEqual([mock_volume_dict, mock_volume2_dict],
|
||||
self.assertEqual([fake_volume_dict, fake_volume2_dict],
|
||||
self.cloud.list_volumes())
|
||||
|
||||
@mock.patch('shade.OpenStackCloud.cinder_client')
|
||||
def test_list_volumes_creating_invalidates(self, cinder_mock):
|
||||
mock_volume = mock.MagicMock()
|
||||
mock_volume.id = 'volume1'
|
||||
mock_volume.status = 'creating'
|
||||
mock_volume.display_name = 'Volume 1 Display Name'
|
||||
mock_volume_dict = meta.obj_to_dict(mock_volume)
|
||||
cinder_mock.volumes.list.return_value = [mock_volume]
|
||||
self.assertEqual([mock_volume_dict], self.cloud.list_volumes())
|
||||
mock_volume2 = mock.MagicMock()
|
||||
mock_volume2.id = 'volume2'
|
||||
mock_volume2.status = 'available'
|
||||
mock_volume2.display_name = 'Volume 2 Display Name'
|
||||
mock_volume2_dict = meta.obj_to_dict(mock_volume2)
|
||||
cinder_mock.volumes.list.return_value = [mock_volume, mock_volume2]
|
||||
self.assertEqual([mock_volume_dict, mock_volume2_dict],
|
||||
fake_volume = fakes.FakeVolume('volume1', 'creating',
|
||||
'Volume 1 Display Name')
|
||||
fake_volume_dict = meta.obj_to_dict(fake_volume)
|
||||
cinder_mock.volumes.list.return_value = [fake_volume]
|
||||
self.assertEqual([fake_volume_dict], self.cloud.list_volumes())
|
||||
fake_volume2 = fakes.FakeVolume('volume2', 'available',
|
||||
'Volume 2 Display Name')
|
||||
fake_volume2_dict = meta.obj_to_dict(fake_volume2)
|
||||
cinder_mock.volumes.list.return_value = [fake_volume, fake_volume2]
|
||||
self.assertEqual([fake_volume_dict, fake_volume2_dict],
|
||||
self.cloud.list_volumes())
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'cinder_client')
|
||||
def test_create_volume_invalidates(self, cinder_mock):
|
||||
mock_volb4 = mock.MagicMock()
|
||||
mock_volb4.id = 'volume1'
|
||||
mock_volb4.status = 'available'
|
||||
mock_volb4.display_name = 'Volume 1 Display Name'
|
||||
mock_volb4_dict = meta.obj_to_dict(mock_volb4)
|
||||
cinder_mock.volumes.list.return_value = [mock_volb4]
|
||||
self.assertEqual([mock_volb4_dict], self.cloud.list_volumes())
|
||||
fake_volb4 = fakes.FakeVolume('volume1', 'available',
|
||||
'Volume 1 Display Name')
|
||||
fake_volb4_dict = meta.obj_to_dict(fake_volb4)
|
||||
cinder_mock.volumes.list.return_value = [fake_volb4]
|
||||
self.assertEqual([fake_volb4_dict], self.cloud.list_volumes())
|
||||
volume = dict(display_name='junk_vol',
|
||||
size=1,
|
||||
display_description='test junk volume')
|
||||
mock_vol = mock.Mock()
|
||||
mock_vol.status = 'creating'
|
||||
mock_vol.id = '12345'
|
||||
mock_vol_dict = meta.obj_to_dict(mock_vol)
|
||||
cinder_mock.volumes.create.return_value = mock_vol
|
||||
cinder_mock.volumes.list.return_value = [mock_volb4, mock_vol]
|
||||
fake_vol = fakes.FakeVolume('12345', 'creating', '')
|
||||
fake_vol_dict = meta.obj_to_dict(fake_vol)
|
||||
cinder_mock.volumes.create.return_value = fake_vol
|
||||
cinder_mock.volumes.list.return_value = [fake_volb4, fake_vol]
|
||||
|
||||
def creating_available():
|
||||
def now_available():
|
||||
mock_vol.status = 'available'
|
||||
mock_vol_dict['status'] = 'available'
|
||||
fake_vol.status = 'available'
|
||||
fake_vol_dict['status'] = 'available'
|
||||
return mock.DEFAULT
|
||||
cinder_mock.volumes.list.side_effect = now_available
|
||||
return mock.DEFAULT
|
||||
@ -153,40 +140,36 @@ class TestMemoryCache(base.TestCase):
|
||||
# If cache was not invalidated, we would not see our own volume here
|
||||
# because the first volume was available and thus would already be
|
||||
# cached.
|
||||
self.assertEqual([mock_volb4_dict, mock_vol_dict],
|
||||
self.assertEqual([fake_volb4_dict, fake_vol_dict],
|
||||
self.cloud.list_volumes())
|
||||
|
||||
# And now delete and check same thing since list is cached as all
|
||||
# available
|
||||
mock_vol.status = 'deleting'
|
||||
mock_vol_dict = meta.obj_to_dict(mock_vol)
|
||||
fake_vol.status = 'deleting'
|
||||
fake_vol_dict = meta.obj_to_dict(fake_vol)
|
||||
|
||||
def deleting_gone():
|
||||
def now_gone():
|
||||
cinder_mock.volumes.list.return_value = [mock_volb4]
|
||||
cinder_mock.volumes.list.return_value = [fake_volb4]
|
||||
return mock.DEFAULT
|
||||
cinder_mock.volumes.list.side_effect = now_gone
|
||||
return mock.DEFAULT
|
||||
cinder_mock.volumes.list.return_value = [mock_volb4, mock_vol]
|
||||
cinder_mock.volumes.list.return_value = [fake_volb4, fake_vol]
|
||||
cinder_mock.volumes.list.side_effect = deleting_gone
|
||||
cinder_mock.volumes.delete.return_value = mock_vol_dict
|
||||
cinder_mock.volumes.delete.return_value = fake_vol_dict
|
||||
self.cloud.delete_volume('12345')
|
||||
self.assertEqual([mock_volb4_dict], self.cloud.list_volumes())
|
||||
self.assertEqual([fake_volb4_dict], self.cloud.list_volumes())
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'keystone_client')
|
||||
def test_get_user_cache(self, keystone_mock):
|
||||
mock_user = mock.MagicMock()
|
||||
mock_user.id = '999'
|
||||
keystone_mock.users.list.return_value = [mock_user]
|
||||
self.assertEqual({'999': mock_user}, self.cloud.get_user_cache())
|
||||
fake_user = fakes.FakeUser('999', '', '')
|
||||
keystone_mock.users.list.return_value = [fake_user]
|
||||
self.assertEqual({'999': fake_user}, self.cloud.get_user_cache())
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'keystone_client')
|
||||
def test_modify_user_invalidates_cache(self, keystone_mock):
|
||||
class User(object):
|
||||
id = 'abc123'
|
||||
email = 'abc123@domain.test'
|
||||
name = 'abc123 name'
|
||||
fake_user = User()
|
||||
fake_user = fakes.FakeUser('abc123', 'abc123@domain.test',
|
||||
'abc123 name')
|
||||
# first cache an empty list
|
||||
keystone_mock.users.list.return_value = []
|
||||
self.assertEqual({}, self.cloud.get_user_cache())
|
||||
@ -201,8 +184,8 @@ class TestMemoryCache(base.TestCase):
|
||||
# Cache should have been invalidated
|
||||
self.assertEqual({'abc123': fake_user}, self.cloud.get_user_cache())
|
||||
# Update and check to see if it is updated
|
||||
fake_user2 = User()
|
||||
fake_user2.email = 'abc123-changed@domain.test'
|
||||
fake_user2 = fakes.FakeUser('abc123', 'abc123 name',
|
||||
'abc123-changed@domain.test')
|
||||
keystone_mock.users.update.return_value = fake_user2
|
||||
keystone_mock.users.list.return_value = [fake_user2]
|
||||
self.cloud.update_user('abc123', email='abc123-changed@domain.test')
|
||||
@ -220,10 +203,7 @@ class TestMemoryCache(base.TestCase):
|
||||
nova_mock.flavors.list.return_value = []
|
||||
self.assertEqual([], self.cloud.list_flavors())
|
||||
|
||||
class Flavor(object):
|
||||
id = '555'
|
||||
name = 'vanilla'
|
||||
fake_flavor = Flavor()
|
||||
fake_flavor = fakes.FakeFlavor('555', 'vanilla')
|
||||
fake_flavor_dict = meta.obj_to_dict(fake_flavor)
|
||||
nova_mock.flavors.list.return_value = [fake_flavor]
|
||||
self.cloud.list_flavors.invalidate(self.cloud)
|
||||
@ -234,11 +214,7 @@ class TestMemoryCache(base.TestCase):
|
||||
glance_mock.images.list.return_value = []
|
||||
self.assertEqual([], self.cloud.list_images())
|
||||
|
||||
class Image(object):
|
||||
id = '22'
|
||||
name = '22 name'
|
||||
status = 'success'
|
||||
fake_image = Image()
|
||||
fake_image = fakes.FakeImage('22', '22 name', 'success')
|
||||
fake_image_dict = meta.obj_to_dict(fake_image)
|
||||
glance_mock.images.list.return_value = [fake_image]
|
||||
self.cloud.list_images.invalidate(self.cloud)
|
||||
@ -246,20 +222,11 @@ class TestMemoryCache(base.TestCase):
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'glance_client')
|
||||
def test_list_images_ignores_unsteady_status(self, glance_mock):
|
||||
class Image(object):
|
||||
id = None
|
||||
name = None
|
||||
status = None
|
||||
steady_image = Image()
|
||||
steady_image.id = '68'
|
||||
steady_image.name = 'Jagr'
|
||||
steady_image.status = 'active'
|
||||
steady_image = fakes.FakeImage('68', 'Jagr', 'active')
|
||||
steady_image_dict = meta.obj_to_dict(steady_image)
|
||||
for status in ('queued', 'saving', 'pending_delete'):
|
||||
active_image = Image()
|
||||
active_image.id = self.getUniqueString()
|
||||
active_image.name = self.getUniqueString()
|
||||
active_image.status = status
|
||||
active_image = fakes.FakeImage(self.getUniqueString(),
|
||||
self.getUniqueString(), status)
|
||||
glance_mock.images.list.return_value = [active_image]
|
||||
active_image_dict = meta.obj_to_dict(active_image)
|
||||
self.assertEqual([active_image_dict],
|
||||
@ -271,20 +238,11 @@ class TestMemoryCache(base.TestCase):
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'glance_client')
|
||||
def test_list_images_caches_steady_status(self, glance_mock):
|
||||
class Image(object):
|
||||
id = None
|
||||
name = None
|
||||
status = None
|
||||
steady_image = Image()
|
||||
steady_image.id = '91'
|
||||
steady_image.name = 'Federov'
|
||||
steady_image.status = 'active'
|
||||
steady_image = fakes.FakeImage('91', 'Federov', 'active')
|
||||
first_image = None
|
||||
for status in ('active', 'deleted', 'killed'):
|
||||
active_image = Image()
|
||||
active_image.id = self.getUniqueString()
|
||||
active_image.name = self.getUniqueString()
|
||||
active_image.status = status
|
||||
active_image = fakes.FakeImage(self.getUniqueString(),
|
||||
self.getUniqueString(), status)
|
||||
active_image_dict = meta.obj_to_dict(active_image)
|
||||
if not first_image:
|
||||
first_image = active_image_dict
|
||||
@ -309,11 +267,7 @@ class TestMemoryCache(base.TestCase):
|
||||
glance_mock.images.list.return_value = []
|
||||
self.assertEqual([], self.cloud.list_images())
|
||||
|
||||
class Image(object):
|
||||
id = '42'
|
||||
name = '42 name'
|
||||
status = 'success'
|
||||
fake_image = Image()
|
||||
fake_image = fakes.FakeImage('42', '42 name', 'success')
|
||||
glance_mock.images.create.return_value = fake_image
|
||||
glance_mock.images.list.return_value = [fake_image]
|
||||
self._call_create_image('42 name')
|
||||
|
@ -22,7 +22,7 @@ Tests for the `create_server` command.
|
||||
from mock import patch, Mock
|
||||
from shade import OpenStackCloud
|
||||
from shade.exc import (OpenStackCloudException, OpenStackCloudTimeout)
|
||||
from shade.tests import base
|
||||
from shade.tests import base, fakes
|
||||
|
||||
|
||||
class TestCreateServer(base.TestCase):
|
||||
@ -109,14 +109,14 @@ class TestCreateServer(base.TestCase):
|
||||
novaclient create call returns the server instance.
|
||||
"""
|
||||
with patch("shade.OpenStackCloud"):
|
||||
mock_server = Mock(status="BUILD")
|
||||
fake_server = fakes.FakeServer('', '', 'BUILD')
|
||||
config = {
|
||||
"servers.create.return_value": mock_server,
|
||||
"servers.get.return_value": mock_server
|
||||
"servers.create.return_value": fake_server,
|
||||
"servers.get.return_value": fake_server
|
||||
}
|
||||
OpenStackCloud.nova_client = Mock(**config)
|
||||
self.assertEqual(
|
||||
self.client.create_server(), mock_server)
|
||||
self.client.create_server(), fake_server)
|
||||
|
||||
def test_create_server_wait(self):
|
||||
"""
|
||||
@ -124,15 +124,16 @@ class TestCreateServer(base.TestCase):
|
||||
its status changes to "ACTIVE".
|
||||
"""
|
||||
with patch("shade.OpenStackCloud"):
|
||||
mock_server = Mock(status="ACTIVE")
|
||||
fake_server = fakes.FakeServer('', '', 'ACTIVE')
|
||||
config = {
|
||||
"servers.create.return_value": Mock(status="BUILD"),
|
||||
"servers.create.return_value": fakes.FakeServer('', '',
|
||||
'ACTIVE'),
|
||||
"servers.get.side_effect": [
|
||||
Mock(status="BUILD"), mock_server]
|
||||
Mock(status="BUILD"), fake_server]
|
||||
}
|
||||
OpenStackCloud.nova_client = Mock(**config)
|
||||
with patch.object(OpenStackCloud, "add_ips_to_server",
|
||||
return_value=mock_server):
|
||||
return_value=fake_server):
|
||||
self.assertEqual(
|
||||
self.client.create_server(wait=True),
|
||||
mock_server)
|
||||
fake_server)
|
||||
|
@ -23,6 +23,7 @@ import mock
|
||||
from novaclient import exceptions as nova_exc
|
||||
|
||||
from shade import OpenStackCloud
|
||||
from shade.tests import fakes
|
||||
from shade.tests.unit import base
|
||||
|
||||
|
||||
@ -37,9 +38,7 @@ class TestDeleteServer(base.TestCase):
|
||||
"""
|
||||
Test that novaclient server delete is called when wait=False
|
||||
"""
|
||||
server = mock.MagicMock(id='1234',
|
||||
status='ACTIVE')
|
||||
server.name = 'daffy'
|
||||
server = fakes.FakeServer('1234', 'daffy', 'ACTIVE')
|
||||
nova_mock.servers.list.return_value = [server]
|
||||
self.cloud.delete_server('daffy', wait=False)
|
||||
nova_mock.servers.delete.assert_called_with(server=server.id)
|
||||
@ -63,9 +62,7 @@ class TestDeleteServer(base.TestCase):
|
||||
"""
|
||||
Test that delete_server waits for NotFound from novaclient
|
||||
"""
|
||||
server = mock.MagicMock(id='9999',
|
||||
status='ACTIVE')
|
||||
server.name = 'wily'
|
||||
server = fakes.FakeServer('9999', 'wily', 'ACTIVE')
|
||||
nova_mock.servers.list.return_value = [server]
|
||||
|
||||
def _delete_wily(*args, **kwargs):
|
||||
|
Loading…
Reference in New Issue
Block a user