launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06745
[Merge] lp:~allenap/maas/use-rabbit-fixture into lp:maas
Gavin Panella has proposed merging lp:~allenap/maas/use-rabbit-fixture into lp:maas.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~allenap/maas/use-rabbit-fixture/+merge/97932
--
https://code.launchpad.net/~allenap/maas/use-rabbit-fixture/+merge/97932
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/maas/use-rabbit-fixture into lp:maas.
=== modified file 'src/maasserver/tests/__init__.py'
--- src/maasserver/tests/__init__.py 2012-01-23 12:42:42 +0000
+++ src/maasserver/tests/__init__.py 2012-03-16 17:23:36 +0000
@@ -1,18 +0,0 @@
-# Copyright 2012 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-from __future__ import (
- print_function,
- unicode_literals,
- )
-
-__metaclass__ = type
-__all__ = []
-
-from os.path import dirname
-
-from django.utils.unittest import TestLoader
-
-
-def suite():
- return TestLoader().discover(dirname(__file__))
=== modified file 'src/maasserver/tests/test_views.py'
--- src/maasserver/tests/test_views.py 2012-03-16 16:16:11 +0000
+++ src/maasserver/tests/test_views.py 2012-03-16 17:23:36 +0000
@@ -43,6 +43,7 @@
get_yui_location,
proxy_to_longpoll,
)
+from maastesting.rabbit import uses_rabbit
def get_prefixed_form_data(prefix, data):
@@ -237,6 +238,7 @@
self.patch(views, 'messaging', get_messaging())
self.assertEqual({}, get_longpoll_context())
+ @uses_rabbit
def test_get_longpoll_context(self):
longpoll = factory.getRandomString()
self.patch(settings, 'LONGPOLL_PATH', longpoll)
=== modified file 'src/maastesting/rabbit.py'
--- src/maastesting/rabbit.py 2012-01-24 12:44:48 +0000
+++ src/maastesting/rabbit.py 2012-03-16 17:23:36 +0000
@@ -10,56 +10,87 @@
__metaclass__ = type
__all__ = [
- "RabbitServerResource",
+ "get_rabbit",
+ "RabbitServerSettings",
+ "start_rabbit",
+ "stop_rabbit",
+ "use_rabbit",
+ "uses_rabbit",
]
+from functools import wraps
+
+from fixtures import Fixture
from rabbitfixture.server import RabbitServer
-from testresources import TestResource
-
-
-class RabbitServerResource(TestResource):
- """A `TestResource` that wraps a `RabbitServer`.
-
- :ivar server: A `RabbitServer`.
- """
-
- def __init__(self, config=None):
- """See `TestResource.__init__`.
-
- :param config: An optional instance of
- `rabbitfixture.server.RabbitServerResources`.
- """
- super(RabbitServerResource, self).__init__()
- self.server = RabbitServer(config)
-
- def clean(self, resource):
- """See `TestResource.clean`."""
- resource.cleanUp()
-
- def make(self, dependency_resources):
- """See `TestResource.make`."""
- self.server.setUp()
- return self.server
-
- def isDirty(self):
- """See `TestResource.isDirty`.
-
- Always returns ``True`` because it's difficult to figure out if an
- `RabbitMQ` server has been used, and it will be very quick to reset
- once we have the management plugin.
-
- Also, somewhat confusingly, `testresources` uses `self._dirty` to
- figure out whether or not to recreate the resource in `self.reset`.
- That's only set by calling `self.dirtied`, which is fiddly from a
- test. For now we assume that it doesn't matter if it's dirty or not;
- tests need to ensure they're using uniquely named queues and/or
- exchanges, or explicity purge things during set-up.
- """
- return True
-
- def reset(self, old_resource, result=None):
- """See `TestResource.reset`."""
- # XXX: GavinPanella 2011-01-20 bug=???: When it becomes possible to
- # install rabbitmq-management on Precise this could be changed to
- # properly reset the running server.
- return super(RabbitServerResource, self).reset(old_resource, result)
+from testtools.monkey import MonkeyPatcher
+
+
+class RabbitServerSettings(Fixture):
+ """
+ This patches the active Django settings to point the application at the
+ ephemeral RabbitMQ server specified by the given configuration.
+ """
+
+ def __init__(self, config):
+ super(RabbitServerSettings, self).__init__()
+ self.config = config
+
+ def setUp(self):
+ super(RabbitServerSettings, self).setUp()
+ from django.conf import settings
+ patcher = MonkeyPatcher()
+ patcher.add_patch(
+ settings, "RABBITMQ_HOST", "%s:%d" % (
+ self.config.hostname, self.config.port))
+ patcher.add_patch(settings, "RABBITMQ_USERID", "guest")
+ patcher.add_patch(settings, "RABBITMQ_PASSWORD", "guest")
+ patcher.add_patch(settings, "RABBITMQ_VIRTUAL_HOST", "/")
+ patcher.add_patch(settings, "RABBITMQ_PUBLISH", True)
+ self.addCleanup(patcher.restore)
+ patcher.patch()
+
+
+# See {start,stop,get}_rabbit().
+rabbit = None
+
+
+def start_rabbit():
+ """Start a shared :class:`RabbitServer`."""
+ global rabbit
+ if rabbit is None:
+ rabbit = RabbitServer()
+ rabbit.setUp()
+
+
+def stop_rabbit():
+ """Stop a shared :class:`RabbitServer`, if any."""
+ global rabbit
+ if rabbit is not None:
+ rabbit.cleanUp()
+ rabbit = None
+
+
+def get_rabbit():
+ """Start and return a shared :class:`RabbitServer`."""
+ global rabbit
+ start_rabbit()
+ return rabbit
+
+
+def use_rabbit(test):
+ """Ensure that a :class:`RabbitServer` is started, and Django's setting
+ updated to point to it, and that Django's settings are returned to their
+ original values at the end.
+ """
+ config = get_rabbit().config
+ fixture = RabbitServerSettings(config)
+ test.useFixture(fixture)
+
+
+def uses_rabbit(func):
+ """Decorate a test function with `use_rabbit`."""
+ @wraps(func)
+ def wrapper(self):
+ use_rabbit(self)
+ return func(self)
+ return wrapper
=== modified file 'src/maastesting/tests/test_rabbit.py'
--- src/maastesting/tests/test_rabbit.py 2012-03-13 05:34:38 +0000
+++ src/maastesting/tests/test_rabbit.py 2012-03-16 17:23:36 +0000
@@ -11,50 +11,27 @@
__metaclass__ = type
__all__ = []
-from maastesting.rabbit import RabbitServerResource
+from random import randint
+
+from django.conf import settings
+from maastesting.factory import factory
+from maastesting.rabbit import RabbitServerSettings
from maastesting.testcase import TestCase
-from rabbitfixture.server import RabbitServer
-
-
-class TestRabbitServerResourceBasics(TestCase):
-
- def test_cycle(self):
- """
- A RabbitMQ server can be successfully brought up and shut-down.
- """
- resource = RabbitServerResource()
- server = resource.make({})
- try:
- self.assertIs(resource.server, server)
- self.assertIsInstance(server, RabbitServer)
- finally:
- resource.clean(server)
-
- def test_reset(self):
- """
- Resetting a RabbitMQ server resource when it has not explicitly been
- marked as dirty - via `RabbitServerResource.dirtied` - is a no-op; the
- same server is returned.
- """
- resource = RabbitServerResource()
- server = resource.make({})
- try:
- server2 = resource.reset(server)
- self.assertIs(server, server2)
- finally:
- resource.clean(server)
-
-
-class TestRabbitServerResource(TestCase):
-
- resources = [
- ("rabbit", RabbitServerResource()),
- ]
-
- def test_one(self):
- """The `self.rabbit` resource is made available here."""
- self.assertIsInstance(self.rabbit, RabbitServer)
-
- def test_two(self):
- """The `self.rabbit resource is also made available here."""
- self.assertIsInstance(self.rabbit, RabbitServer)
+from rabbitfixture.server import RabbitServerResources
+
+
+class TestRabbitServerSettings(TestCase):
+
+ def test_patch(self):
+ config = RabbitServerResources(
+ hostname=factory.getRandomString(),
+ port=randint(1025, 2**16))
+ self.useFixture(config)
+ self.useFixture(RabbitServerSettings(config))
+ self.assertEqual(
+ "%s:%d" % (config.hostname, config.port),
+ settings.RABBITMQ_HOST)
+ self.assertEqual("guest", settings.RABBITMQ_PASSWORD)
+ self.assertEqual("guest", settings.RABBITMQ_USERID)
+ self.assertEqual("/", settings.RABBITMQ_VIRTUAL_HOST)
+ self.assertTrue(settings.RABBITMQ_PUBLISH)
=== modified file 'src/metadataserver/tests/__init__.py'
--- src/metadataserver/tests/__init__.py 2012-02-14 14:34:29 +0000
+++ src/metadataserver/tests/__init__.py 2012-03-16 17:23:36 +0000
@@ -0,0 +1,17 @@
+# Copyright 2005-2011 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for `metadataserver`."""
+
+from __future__ import (
+ print_function,
+ unicode_literals,
+ )
+
+__metaclass__ = type
+__all__ = []
+
+from maastesting.rabbit import stop_rabbit
+
+
+tearDown = stop_rabbit
=== modified file 'src/metadataserver/tests/test_api.py'
--- src/metadataserver/tests/test_api.py 2012-03-13 05:34:38 +0000
+++ src/metadataserver/tests/test_api.py 2012-03-16 17:23:36 +0000
@@ -19,6 +19,7 @@
from maasserver.exceptions import Unauthorized
from maasserver.testing.factory import factory
from maasserver.testing.oauthclient import OAuthAuthenticatedClient
+from maastesting.rabbit import uses_rabbit
from maastesting.testcase import TestCase
from metadataserver.api import (
check_version,
@@ -94,6 +95,7 @@
def test_extract_oauth_key_rejects_auth_without_oauth_key(self):
self.assertRaises(Unauthorized, extract_oauth_key, '')
+ @uses_rabbit
def test_get_node_for_request_finds_node(self):
node = factory.make_node()
token = NodeKey.objects.get_token_for_node(node)
@@ -137,10 +139,12 @@
def test_no_anonymous_access(self):
self.assertEqual(httplib.UNAUTHORIZED, self.get('/').status_code)
+ @uses_rabbit
def test_metadata_index_shows_latest(self):
client = self.make_node_client()
self.assertIn('latest', self.get('/', client).content)
+ @uses_rabbit
def test_metadata_index_shows_only_known_versions(self):
client = self.make_node_client()
for item in self.get('/', client).content.splitlines():
@@ -148,16 +152,19 @@
# The test is that we get here without exception.
pass
+ @uses_rabbit
def test_version_index_shows_meta_data(self):
client = self.make_node_client()
items = self.get('/latest/', client).content.splitlines()
self.assertIn('meta-data', items)
+ @uses_rabbit
def test_version_index_does_not_show_user_data_if_not_available(self):
client = self.make_node_client()
items = self.get('/latest/', client).content.splitlines()
self.assertNotIn('user-data', items)
+ @uses_rabbit
def test_version_index_shows_user_data_if_available(self):
node = factory.make_node()
NodeUserData.objects.set_user_data(node, b"User data for node")
@@ -165,6 +172,7 @@
items = self.get('/latest/', client).content.splitlines()
self.assertIn('user-data', items)
+ @uses_rabbit
def test_meta_data_view_lists_fields(self):
client = self.make_node_client()
response = self.get('/latest/meta-data/', client)
@@ -172,12 +180,14 @@
self.assertItemsEqual(
MetaDataHandler.fields, response.content.split())
+ @uses_rabbit
def test_meta_data_view_is_sorted(self):
client = self.make_node_client()
response = self.get('/latest/meta-data/', client)
attributes = response.content.split()
self.assertEqual(sorted(attributes), attributes)
+ @uses_rabbit
def test_meta_data_unknown_item_is_not_found(self):
client = self.make_node_client()
response = self.get('/latest/meta-data/UNKNOWN-ITEM-HA-HA-HA', client)
@@ -188,6 +198,7 @@
producers = map(handler.get_attribute_producer, handler.fields)
self.assertNotIn(None, producers)
+ @uses_rabbit
def test_meta_data_local_hostname_returns_hostname(self):
hostname = factory.getRandomString()
client = self.make_node_client(factory.make_node(hostname=hostname))
@@ -197,6 +208,7 @@
(response.status_code, response.content.decode('ascii')))
self.assertIn('text/plain', response['Content-Type'])
+ @uses_rabbit
def test_meta_data_instance_id_returns_system_id(self):
node = factory.make_node()
client = self.make_node_client(node)
@@ -206,6 +218,7 @@
(response.status_code, response.content.decode('ascii')))
self.assertIn('text/plain', response['Content-Type'])
+ @uses_rabbit
def test_user_data_view_returns_binary_data(self):
data = b"\x00\xff\xff\xfe\xff"
node = factory.make_node()
@@ -217,6 +230,7 @@
self.assertEqual(
(httplib.OK, data), (response.status_code, response.content))
+ @uses_rabbit
def test_user_data_for_node_without_user_data_returns_not_found(self):
response = self.get('/latest/user-data', self.make_node_client())
self.assertEqual(httplib.NOT_FOUND, response.status_code)
=== modified file 'src/metadataserver/tests/test_models.py'
--- src/metadataserver/tests/test_models.py 2012-03-13 05:34:38 +0000
+++ src/metadataserver/tests/test_models.py 2012-03-16 17:23:36 +0000
@@ -12,6 +12,7 @@
__all__ = []
from maasserver.testing.factory import factory
+from maastesting.rabbit import use_rabbit
from maastesting.testcase import TestCase
from metadataserver.models import (
NodeKey,
@@ -22,6 +23,10 @@
class TestNodeKeyManager(TestCase):
"""Test NodeKeyManager."""
+ def setUp(self):
+ super(TestNodeKeyManager, self).setUp()
+ use_rabbit(self)
+
def test_get_token_for_node_registers_node_key(self):
node = factory.make_node()
token = NodeKey.objects.get_token_for_node(node)
@@ -68,6 +73,10 @@
class TestNodeUserDataManager(TestCase):
"""Test NodeUserDataManager."""
+ def setUp(self):
+ super(TestNodeUserDataManager, self).setUp()
+ use_rabbit(self)
+
def test_set_user_data_creates_new_nodeuserdata_if_needed(self):
node = factory.make_node()
data = b'foo'
=== modified file 'src/provisioningserver/testing/amqpclient.py'
--- src/provisioningserver/testing/amqpclient.py 2012-03-15 13:58:32 +0000
+++ src/provisioningserver/testing/amqpclient.py 2012-03-16 17:23:36 +0000
@@ -67,12 +67,12 @@
http://readthedocs.org/docs/nose/en/latest/writing_tests.html
"""
- from provisioningserver import tests
- return tests.get_rabbit()
+ from maastesting import rabbit
+ return rabbit.get_rabbit()
@skip(
"RabbitMQ is not yet a required component "
- "of a running MAAS installation.")
+ "of a running MAAS pserv instance.")
def setUp(self):
"""
At each run, we delete the test vhost and recreate it, to be sure to be
=== modified file 'src/provisioningserver/tests/__init__.py'
--- src/provisioningserver/tests/__init__.py 2012-02-15 14:23:44 +0000
+++ src/provisioningserver/tests/__init__.py 2012-03-16 17:23:36 +0000
@@ -9,28 +9,9 @@
)
__metaclass__ = type
-__all__ = [
- "get_rabbit",
- ]
-
-from rabbitfixture.server import RabbitServer
-
-# Set get_rabbit() and tearDown().
-rabbit = None
-
-
-def get_rabbit():
- """Return a running `RabbitServer` fixture."""
- global rabbit
- if rabbit is None:
- rabbit = RabbitServer()
- rabbit.setUp()
- return rabbit
-
-
-def tearDown():
- """Package-level fixture hook, recognized by nose."""
- global rabbit
- if rabbit is not None:
- rabbit.cleanUp()
- rabbit = None
+__all__ = []
+
+from maastesting.rabbit import stop_rabbit
+
+
+tearDown = stop_rabbit