summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Page <james.page@ubuntu.com>2014-10-14 09:34:59 +0100
committerJames Page <james.page@ubuntu.com>2014-11-17 21:34:29 -0600
commit5aadc56b66c2d8504e9177b553359d2c01b367f4 (patch)
tree381cff050c5409ac9725c4d5dc6c77b8a93af9d9
parent10eb1202b37f896e1b7844d400e0defd926a7ab1 (diff)
downloadoslo-messaging-5aadc56b66c2d8504e9177b553359d2c01b367f4.tar.gz
Add basic tests for 0mq matchmakers
Basic unit tests for in-memory (localhost), ring and Redis based matchmakers. Redis tests are opportunitic based on a redis-server being installed and running. Test are currently skipped under py3 due to direct dependency on eventlet. Co-Authored-By: Kapil Thangavelu <kapil.thangavelu@canonical.com> Change-Id: I59c4d095033370ab94f645af0d50e2502530f816 Partial-bug: #1302941
-rw-r--r--test-requirements.txt3
-rw-r--r--tests/drivers/test_matchmaker.py69
-rw-r--r--tests/drivers/test_matchmaker_redis.py78
-rw-r--r--tests/drivers/test_matchmaker_ring.py73
4 files changed, 223 insertions, 0 deletions
diff --git a/test-requirements.txt b/test-requirements.txt
index dae910d..c609178 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -18,6 +18,9 @@ oslotest>=1.2.0 # Apache-2.0
# for test_qpid
qpid-python
+# for test_matchmaker_redis
+redis>=2.10.0
+
# when we can require tox>= 1.4, this can go into tox.ini:
# [testenv:cover]
# deps = {[testenv]deps} coverage
diff --git a/tests/drivers/test_matchmaker.py b/tests/drivers/test_matchmaker.py
new file mode 100644
index 0000000..0de2e6d
--- /dev/null
+++ b/tests/drivers/test_matchmaker.py
@@ -0,0 +1,69 @@
+# Copyright 2014 Canonical, Ltd.
+#
+# 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.
+
+import testtools
+
+from oslo.utils import importutils
+from tests import utils as test_utils
+
+# NOTE(jamespage) matchmaker tied directly to eventlet
+# which is not yet py3 compatible - skip if import fails
+matchmaker = (
+ importutils.try_import('oslo.messaging._drivers.matchmaker'))
+
+
+@testtools.skipIf(not matchmaker, "matchmaker/eventlet unavailable")
+class MatchmakerTest(test_utils.BaseTestCase):
+
+ def test_fanout_binding(self):
+ matcher = matchmaker.MatchMakerBase()
+ matcher.add_binding(
+ matchmaker.FanoutBinding(), matchmaker.DirectExchange())
+ self.assertEqual(matcher.queues('hello.world'), [])
+ self.assertEqual(
+ matcher.queues('fanout~fantasy.unicorn'),
+ [('fanout~fantasy.unicorn', 'unicorn')])
+ self.assertEqual(
+ matcher.queues('fanout~fantasy.pony'),
+ [('fanout~fantasy.pony', 'pony')])
+
+ def test_topic_binding(self):
+ matcher = matchmaker.MatchMakerBase()
+ matcher.add_binding(
+ matchmaker.TopicBinding(), matchmaker.StubExchange())
+ self.assertEqual(
+ matcher.queues('hello-world'), [('hello-world', None)])
+
+ def test_direct_binding(self):
+ matcher = matchmaker.MatchMakerBase()
+ matcher.add_binding(
+ matchmaker.DirectBinding(), matchmaker.StubExchange())
+ self.assertEqual(
+ matcher.queues('hello.server'), [('hello.server', None)])
+ self.assertEqual(matcher.queues('hello-world'), [])
+
+ def test_localhost_match(self):
+ matcher = matchmaker.MatchMakerLocalhost()
+ self.assertEqual(
+ matcher.queues('hello.server'), [('hello.server', 'server')])
+
+ # Gets remapped due to localhost exchange
+ # all bindings default to first match.
+ self.assertEqual(
+ matcher.queues('fanout~testing.server'),
+ [('fanout~testing.localhost', 'localhost')])
+
+ self.assertEqual(
+ matcher.queues('hello-world'),
+ [('hello-world.localhost', 'localhost')])
diff --git a/tests/drivers/test_matchmaker_redis.py b/tests/drivers/test_matchmaker_redis.py
new file mode 100644
index 0000000..1c20dab
--- /dev/null
+++ b/tests/drivers/test_matchmaker_redis.py
@@ -0,0 +1,78 @@
+# Copyright 2014 Canonical, Ltd.
+#
+# 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.
+
+import testtools
+
+from oslo.utils import importutils
+from tests import utils as test_utils
+
+redis = importutils.try_import('redis')
+matchmaker_redis = (
+ importutils.try_import('oslo.messaging._drivers.matchmaker_redis'))
+
+
+def redis_available():
+ '''Helper to see if local redis server is running'''
+ if not redis:
+ return False
+ try:
+ c = redis.StrictRedis(socket_timeout=1)
+ c.ping()
+ return True
+ except redis.exceptions.ConnectionError:
+ return False
+
+
+@testtools.skipIf(not matchmaker_redis, "matchmaker/eventlet unavailable")
+@testtools.skipIf(not redis_available(), "redis unavailable")
+class RedisMatchMakerTest(test_utils.BaseTestCase):
+
+ def setUp(self):
+ super(RedisMatchMakerTest, self).setUp()
+ self.ring_data = {
+ "conductor": ["controller1", "node1", "node2", "node3"],
+ "scheduler": ["controller1", "node1", "node2", "node3"],
+ "network": ["controller1", "node1", "node2", "node3"],
+ "cert": ["controller1"],
+ "console": ["controller1"],
+ "consoleauth": ["controller1"]}
+ self.matcher = matchmaker_redis.MatchMakerRedis()
+ self.populate()
+
+ def tearDown(self):
+ super(RedisMatchMakerTest, self).tearDown()
+ c = redis.StrictRedis()
+ c.flushdb()
+
+ def populate(self):
+ for k, hosts in self.ring_data.items():
+ for h in hosts:
+ self.matcher.register(k, h)
+
+ def test_direct(self):
+ self.assertEqual(
+ self.matcher.queues('cert.controller1'),
+ [('cert.controller1', 'controller1')])
+
+ def test_register(self):
+ self.matcher.register('cert', 'keymaster')
+ self.assertEqual(
+ sorted(self.matcher.redis.smembers('cert')),
+ ['cert.controller1', 'cert.keymaster'])
+
+ def test_unregister(self):
+ self.matcher.unregister('conductor', 'controller1')
+ self.assertEqual(
+ sorted(self.matcher.redis.smembers('conductor')),
+ ['conductor.node1', 'conductor.node2', 'conductor.node3'])
diff --git a/tests/drivers/test_matchmaker_ring.py b/tests/drivers/test_matchmaker_ring.py
new file mode 100644
index 0000000..c6d81e6
--- /dev/null
+++ b/tests/drivers/test_matchmaker_ring.py
@@ -0,0 +1,73 @@
+# Copyright 2014 Canonical, Ltd.
+#
+# 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.
+
+import testtools
+
+from oslo.utils import importutils
+from tests import utils as test_utils
+
+# NOTE(jamespage) matchmaker tied directly to eventlet
+# which is not yet py3 compatible - skip if import fails
+matchmaker_ring = (
+ importutils.try_import('oslo.messaging._drivers.matchmaker_ring'))
+
+
+@testtools.skipIf(not matchmaker_ring, "matchmaker/eventlet unavailable")
+class MatchmakerRingTest(test_utils.BaseTestCase):
+
+ def setUp(self):
+ super(MatchmakerRingTest, self).setUp()
+ self.ring_data = {
+ "conductor": ["controller1", "node1", "node2", "node3"],
+ "scheduler": ["controller1", "node1", "node2", "node3"],
+ "network": ["controller1", "node1", "node2", "node3"],
+ "cert": ["controller1"],
+ "console": ["controller1"],
+ "consoleauth": ["controller1"]}
+ self.matcher = matchmaker_ring.MatchMakerRing(self.ring_data)
+
+ def test_direct(self):
+ self.assertEqual(
+ self.matcher.queues('cert.controller1'),
+ [('cert.controller1', 'controller1')])
+ self.assertEqual(
+ self.matcher.queues('conductor.node1'),
+ [('conductor.node1', 'node1')])
+
+ def test_fanout(self):
+ self.assertEqual(
+ self.matcher.queues('fanout~conductor'),
+ [('fanout~conductor.controller1', 'controller1'),
+ ('fanout~conductor.node1', 'node1'),
+ ('fanout~conductor.node2', 'node2'),
+ ('fanout~conductor.node3', 'node3')])
+
+ def test_bare_topic(self):
+ # Round robins through the hosts on the topic
+ self.assertEqual(
+ self.matcher.queues('scheduler'),
+ [('scheduler.controller1', 'controller1')])
+ self.assertEqual(
+ self.matcher.queues('scheduler'),
+ [('scheduler.node1', 'node1')])
+ self.assertEqual(
+ self.matcher.queues('scheduler'),
+ [('scheduler.node2', 'node2')])
+ self.assertEqual(
+ self.matcher.queues('scheduler'),
+ [('scheduler.node3', 'node3')])
+ # Cycles loop
+ self.assertEqual(
+ self.matcher.queues('scheduler'),
+ [('scheduler.controller1', 'controller1')])