summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--requirements.txt4
-rw-r--r--tooz/coordination.py3
-rw-r--r--tooz/drivers/etcd.py2
-rw-r--r--tooz/tests/__init__.py5
-rw-r--r--tooz/tests/drivers/test_file.py5
-rw-r--r--tooz/tests/test_coordination.py99
-rw-r--r--tooz/tests/test_etcd.py44
-rw-r--r--tooz/tests/test_memcache.py16
-rw-r--r--tooz/tests/test_mysql.py5
-rw-r--r--tooz/tests/test_postgresql.py5
-rw-r--r--tox.ini2
11 files changed, 124 insertions, 66 deletions
diff --git a/requirements.txt b/requirements.txt
index 9da24d1..0513da4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,7 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr>=1.6 # Apache-2.0
-stevedore>=1.10.0 # Apache-2.0
+stevedore>=1.16.0 # Apache-2.0
six>=1.9.0 # MIT
enum34;python_version=='2.7' or python_version=='2.6' or python_version=='3.3' # BSD
voluptuous>=0.8.9 # BSD License
@@ -10,6 +10,6 @@ msgpack-python>=0.4.0 # Apache-2.0
fasteners>=0.7 # Apache-2.0
retrying!=1.3.0,>=1.2.3 # Apache-2.0
futures>=3.0;python_version=='2.7' or python_version=='2.6' # BSD
-futurist>=0.11.0 # Apache-2.0
+futurist!=0.15.0,>=0.11.0 # Apache-2.0
oslo.utils>=3.15.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
diff --git a/tooz/coordination.py b/tooz/coordination.py
index 4307684..fdc80a0 100644
--- a/tooz/coordination.py
+++ b/tooz/coordination.py
@@ -322,6 +322,9 @@ class CoordinationDriver(object):
group_id in self._group_members):
del self._group_members[group_id]
+ if not self._hooks_leave_group[group_id]:
+ del self._hooks_leave_group[group_id]
+
@abc.abstractmethod
def watch_elected_as_leader(self, group_id, callback):
"""Call a function when member gets elected as leader.
diff --git a/tooz/drivers/etcd.py b/tooz/drivers/etcd.py
index 9d6531e..bdfa35c 100644
--- a/tooz/drivers/etcd.py
+++ b/tooz/drivers/etcd.py
@@ -142,7 +142,7 @@ class EtcdLock(locking.Lock):
try:
reply = self.client.get(
self._lock_url +
- "?wait=true&waitIndex=%d" % reply['index'],
+ "?wait=true&waitIndex=%d" % (reply['index'] + 1),
make_url=False,
timeout=watch.leftover() if watch else None)
except requests.exceptions.RequestException:
diff --git a/tooz/tests/__init__.py b/tooz/tests/__init__.py
index dde33f3..f7cd3b6 100644
--- a/tooz/tests/__init__.py
+++ b/tooz/tests/__init__.py
@@ -15,6 +15,7 @@
# under the License.
import functools
+import uuid
import six
from testtools import testcase
@@ -22,6 +23,10 @@ from testtools import testcase
import tooz
+def get_random_uuid():
+ return str(uuid.uuid4()).encode('ascii')
+
+
def _skip_decorator(func):
@functools.wraps(func)
def skip_if_not_implemented(*args, **kwargs):
diff --git a/tooz/tests/drivers/test_file.py b/tooz/tests/drivers/test_file.py
index 692e68b..c95eb66 100644
--- a/tooz/tests/drivers/test_file.py
+++ b/tooz/tests/drivers/test_file.py
@@ -15,16 +15,15 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
import mock
from testtools import testcase
from tooz import coordination
+from tooz import tests
class TestFileDriver(testcase.TestCase):
- _FAKE_MEMBER_ID = str(uuid.uuid4()).encode('ascii')
+ _FAKE_MEMBER_ID = tests.get_random_uuid()
def test_base_dir(self):
file_path = '/fake/file/path'
diff --git a/tooz/tests/test_coordination.py b/tooz/tests/test_coordination.py
index 5e22aeb..c23a790 100644
--- a/tooz/tests/test_coordination.py
+++ b/tooz/tests/test_coordination.py
@@ -17,7 +17,6 @@
import os
import threading
import time
-import uuid
from concurrent import futures
import fixtures
@@ -55,8 +54,8 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
if self.url is None:
self.skipTest("No URL set for this driver")
self.useFixture(fixtures.NestedTempfile())
- self.group_id = self._get_random_uuid()
- self.member_id = self._get_random_uuid()
+ self.group_id = tests.get_random_uuid()
+ self.member_id = tests.get_random_uuid()
self._coord = tooz.coordination.get_coordinator(self.url,
self.member_id)
self._coord.start()
@@ -88,8 +87,8 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertTrue(self.group_id in all_group_ids)
def test_get_lock_release_broken(self):
- name = self._get_random_uuid()
- memberid2 = self._get_random_uuid()
+ name = tests.get_random_uuid()
+ memberid2 = tests.get_random_uuid()
coord2 = tooz.coordination.get_coordinator(self.url,
memberid2)
coord2.start()
@@ -101,7 +100,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertTrue(lock2.acquire(blocking=False))
self.assertFalse(lock1.release())
# Assert lock is not accidentally broken now
- memberid3 = self._get_random_uuid()
+ memberid3 = tests.get_random_uuid()
coord3 = tooz.coordination.get_coordinator(self.url,
memberid3)
coord3.start()
@@ -115,7 +114,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
create_group.get)
def test_get_groups(self):
- groups_ids = [self._get_random_uuid() for _ in range(0, 5)]
+ groups_ids = [tests.get_random_uuid() for _ in range(0, 5)]
for group_id in groups_ids:
self._coord.create_group(group_id).get()
created_groups = self._coord.get_groups().get()
@@ -200,7 +199,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
leave_group.get)
def test_get_lock_twice_locked_one_released_two(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
self.assertTrue(lock1.acquire())
@@ -210,8 +209,8 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertFalse(lock2.release())
def test_get_members(self):
- group_id_test2 = self._get_random_uuid()
- member_id_test2 = self._get_random_uuid()
+ group_id_test2 = tests.get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -290,7 +289,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
def test_get_member_info_nonjoined_member(self):
self._coord.create_group(self.group_id).get()
- member_id = self._get_random_uuid()
+ member_id = tests.get_random_uuid()
member_info = self._coord.get_member_info(self.group_id,
member_id)
self.assertRaises(tooz.coordination.MemberNotJoined,
@@ -342,7 +341,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
heart.wait()
def test_disconnect_leave_group(self):
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -370,7 +369,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord = tooz.coordination.get_coordinator(url, self.member_id)
self._coord.start()
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(url, member_id_test2)
client2.start()
self._coord.create_group(self.group_id).get()
@@ -409,7 +408,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
return 42
def test_watch_group_join(self):
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -443,7 +442,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertIsNone(self.event)
def test_watch_leave_group(self):
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -494,7 +493,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.watch_join_group(self.group_id, self._set_event)
self._coord.watch_leave_group(self.group_id, self._set_event)
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -530,7 +529,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.watch_join_group(self.group_id, self._set_event)
self._coord.watch_leave_group(self.group_id, self._set_event)
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -576,7 +575,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.watch_elected_as_leader(self.group_id, self._set_event)
self._coord.run_watchers()
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -632,7 +631,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.watch_elected_as_leader(self.group_id, self._set_event)
self._coord.run_watchers()
- member_id_test2 = self._get_random_uuid()
+ member_id_test2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id_test2)
client2.start()
@@ -676,7 +675,8 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.watch_elected_as_leader(self.group_id, self._set_event)
# Ensure exactly one leader election hook exists
- self.assertEqual(1, len(self._coord._hooks_elected_leader))
+ self.assertEqual(1,
+ len(self._coord._hooks_elected_leader[self.group_id]))
# Unwatch, and ensure no leader election hooks exist
self._coord.unwatch_elected_as_leader(self.group_id, self._set_event)
@@ -694,6 +694,19 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.unwatch_join_group,
self.group_id, lambda x: None)
+ def test_unwatch_leave_group(self):
+ # Create a group and add a leave_group callback
+ self._coord.create_group(self.group_id).get()
+ self.assertEqual(0, len(self._coord._hooks_leave_group))
+ self._coord.watch_leave_group(self.group_id, self._set_event)
+
+ # Ensure exactly one leave group hook exists
+ self.assertEqual(1, len(self._coord._hooks_leave_group[self.group_id]))
+
+ # Unwatch, and ensure no leave group hooks exist
+ self._coord.unwatch_leave_group(self.group_id, self._set_event)
+ self.assertEqual(0, len(self._coord._hooks_leave_group))
+
def test_unwatch_leave_group_callback_not_found(self):
self._coord.create_group(self.group_id).get()
self.assertRaises(tooz.coordination.WatchCallbackNotFound,
@@ -701,14 +714,14 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.group_id, lambda x: None)
def test_get_lock(self):
- lock = self._coord.get_lock(self._get_random_uuid())
+ lock = self._coord.get_lock(tests.get_random_uuid())
self.assertTrue(lock.acquire())
self.assertTrue(lock.release())
with lock:
pass
def test_get_lock_concurrency_locking_same_lock(self):
- lock = self._coord.get_lock(self._get_random_uuid())
+ lock = self._coord.get_lock(tests.get_random_uuid())
graceful_ending = threading.Event()
@@ -729,13 +742,13 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
def _do_test_get_lock_concurrency_locking_two_lock(self, executor,
use_same_coord):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
with lock1:
with executor(max_workers=1) as e:
coord = self._coord if use_same_coord else None
f = e.submit(try_to_lock_job, name, coord, self.url,
- self._get_random_uuid())
+ tests.get_random_uuid())
self.assertFalse(f.result())
def test_get_lock_concurrency_locking_two_lock_process(self):
@@ -754,8 +767,8 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
# NOTE(sileht): some database based lock can have only
# one lock per connection, this test ensures acquiring a
# second lock doesn't release the first one.
- lock1 = self._coord.get_lock(self._get_random_uuid())
- lock2 = self._coord.get_lock(self._get_random_uuid())
+ lock1 = self._coord.get_lock(tests.get_random_uuid())
+ lock2 = self._coord.get_lock(tests.get_random_uuid())
graceful_ending = threading.Event()
thread_locked = threading.Event()
@@ -781,14 +794,14 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertTrue(graceful_ending.is_set())
def test_get_lock_twice_locked_twice(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
with lock1:
self.assertFalse(lock2.acquire(blocking=False))
def test_get_lock_context_fails(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
with mock.patch.object(lock2, 'acquire', return_value=False):
@@ -798,34 +811,34 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
lock2.__enter__)
def test_get_lock_context_check_value(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock = self._coord.get_lock(name)
with lock as returned_lock:
self.assertEqual(lock, returned_lock)
def test_lock_context_manager_acquire_no_argument(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
with lock1():
self.assertFalse(lock2.acquire(blocking=False))
def test_lock_context_manager_acquire_argument_return_value(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
blocking_value = 10.12
lock = self._coord.get_lock(name)
with lock(blocking_value) as returned_lock:
self.assertEqual(lock, returned_lock)
def test_lock_context_manager_acquire_argument_release_within(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
blocking_value = 10.12
lock = self._coord.get_lock(name)
with lock(blocking_value) as returned_lock:
self.assertTrue(returned_lock.release())
def test_lock_context_manager_acquire_argument(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
blocking_value = 10.12
lock = self._coord.get_lock(name)
with mock.patch.object(lock, 'acquire', wraps=True, autospec=True) as \
@@ -834,7 +847,7 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
mock_acquire.assert_called_once_with(blocking_value)
def test_lock_context_manager_acquire_argument_timeout(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
with lock1:
@@ -845,13 +858,13 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
pass
def test_get_lock_locked_twice(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock = self._coord.get_lock(name)
with lock:
self.assertFalse(lock.acquire(blocking=False))
def test_get_multiple_locks_with_same_coord(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
lock2 = self._coord.get_lock(name)
self.assertTrue(lock1.acquire())
@@ -860,19 +873,19 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self.assertTrue(lock1.release())
def test_ensure_acquire_release_return(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock1 = self._coord.get_lock(name)
self.assertTrue(lock1.acquire())
self.assertTrue(lock1.release())
self.assertFalse(lock1.release())
def test_get_lock_multiple_coords(self):
- member_id2 = self._get_random_uuid()
+ member_id2 = tests.get_random_uuid()
client2 = tooz.coordination.get_coordinator(self.url,
member_id2)
client2.start()
- lock_name = self._get_random_uuid()
+ lock_name = tests.get_random_uuid()
lock = self._coord.get_lock(lock_name)
self.assertTrue(lock.acquire())
@@ -889,16 +902,12 @@ class TestAPI(tests.TestCaseSkipNotImplemented):
self._coord.start()
def do_test_name_property(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock = self._coord.get_lock(name)
self.assertEqual(name, lock.name)
- @staticmethod
- def _get_random_uuid():
- return str(uuid.uuid4()).encode('ascii')
-
def test_acquire_twice_no_deadlock_releasing(self):
- name = self._get_random_uuid()
+ name = tests.get_random_uuid()
lock = self._coord.get_lock(name)
self.assertTrue(lock.acquire(blocking=False))
self.assertFalse(lock.acquire(blocking=False))
diff --git a/tooz/tests/test_etcd.py b/tooz/tests/test_etcd.py
new file mode 100644
index 0000000..bbc99e5
--- /dev/null
+++ b/tooz/tests/test_etcd.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2016 Red Hat, Inc.
+#
+# 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 mock
+from testtools import testcase
+
+import tooz.coordination
+
+
+class TestEtcd(testcase.TestCase):
+ FAKE_URL = "etcd://mocked-not-really-localhost:2379"
+ FAKE_MEMBER_ID = "mocked-not-really-member"
+
+ def setUp(self):
+ super(TestEtcd, self).setUp()
+ self._coord = tooz.coordination.get_coordinator(self.FAKE_URL,
+ self.FAKE_MEMBER_ID)
+
+ def test_multiple_locks_etcd_wait_index(self):
+ lock = self._coord.get_lock('mocked-not-really-random')
+
+ return_values = [
+ {'errorCode': {}, 'node': {}, 'index': 10},
+ {'errorCode': None, 'node': {}, 'index': 10}
+ ]
+ with mock.patch.object(lock.client, 'put', side_effect=return_values):
+ with mock.patch.object(lock.client, 'get') as mocked_get:
+ self.assertTrue(lock.acquire())
+ mocked_get.assert_called_once()
+ call = str(mocked_get.call_args)
+ self.assertIn("waitIndex=11", call)
diff --git a/tooz/tests/test_memcache.py b/tooz/tests/test_memcache.py
index 2b1b08c..787a96b 100644
--- a/tooz/tests/test_memcache.py
+++ b/tooz/tests/test_memcache.py
@@ -16,7 +16,6 @@
# under the License.
import socket
-import uuid
try:
from unittest import mock
@@ -26,6 +25,7 @@ except ImportError:
from testtools import testcase
from tooz import coordination
+from tooz import tests
class TestMemcacheDriverFailures(testcase.TestCase):
@@ -34,7 +34,7 @@ class TestMemcacheDriverFailures(testcase.TestCase):
@mock.patch('pymemcache.client.PooledClient')
def test_client_failure_start(self, mock_client_cls):
mock_client_cls.side_effect = socket.timeout('timed-out')
- member_id = str(uuid.uuid4()).encode('ascii')
+ member_id = tests.get_random_uuid()
coord = coordination.get_coordinator(self.FAKE_URL, member_id)
self.assertRaises(coordination.ToozConnectionError, coord.start)
@@ -42,29 +42,29 @@ class TestMemcacheDriverFailures(testcase.TestCase):
def test_client_failure_join(self, mock_client_cls):
mock_client = mock.MagicMock()
mock_client_cls.return_value = mock_client
- member_id = str(uuid.uuid4()).encode('ascii')
+ member_id = tests.get_random_uuid()
coord = coordination.get_coordinator(self.FAKE_URL, member_id)
coord.start()
mock_client.gets.side_effect = socket.timeout('timed-out')
- fut = coord.join_group(str(uuid.uuid4()).encode('ascii'))
+ fut = coord.join_group(tests.get_random_uuid())
self.assertRaises(coordination.ToozConnectionError, fut.get)
@mock.patch('pymemcache.client.PooledClient')
def test_client_failure_leave(self, mock_client_cls):
mock_client = mock.MagicMock()
mock_client_cls.return_value = mock_client
- member_id = str(uuid.uuid4()).encode('ascii')
+ member_id = tests.get_random_uuid()
coord = coordination.get_coordinator(self.FAKE_URL, member_id)
coord.start()
mock_client.gets.side_effect = socket.timeout('timed-out')
- fut = coord.leave_group(str(uuid.uuid4()).encode('ascii'))
+ fut = coord.leave_group(tests.get_random_uuid())
self.assertRaises(coordination.ToozConnectionError, fut.get)
@mock.patch('pymemcache.client.PooledClient')
def test_client_failure_heartbeat(self, mock_client_cls):
mock_client = mock.MagicMock()
mock_client_cls.return_value = mock_client
- member_id = str(uuid.uuid4()).encode('ascii')
+ member_id = tests.get_random_uuid()
coord = coordination.get_coordinator(self.FAKE_URL, member_id)
coord.start()
mock_client.set.side_effect = socket.timeout('timed-out')
@@ -77,7 +77,7 @@ class TestMemcacheDriverFailures(testcase.TestCase):
mock_run_watchers):
mock_client = mock.MagicMock()
mock_client_cls.return_value = mock_client
- member_id = str(uuid.uuid4()).encode('ascii')
+ member_id = tests.get_random_uuid()
coord = coordination.get_coordinator(self.FAKE_URL, member_id)
coord.start()
coord.run_watchers()
diff --git a/tooz/tests/test_mysql.py b/tooz/tests/test_mysql.py
index b8b3b5d..01cc93f 100644
--- a/tooz/tests/test_mysql.py
+++ b/tooz/tests/test_mysql.py
@@ -15,12 +15,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
from oslo_utils import encodeutils
from testtools import testcase
from tooz import coordination
+from tooz import tests
class TestMySQLDriver(testcase.TestCase):
@@ -37,7 +36,7 @@ class TestMySQLDriver(testcase.TestCase):
raise
coord = coordination.get_coordinator(url,
- str(uuid.uuid4()).encode('ascii'))
+ tests.get_random_uuid())
self.addCleanup(_safe_stop, coord)
return coord
diff --git a/tooz/tests/test_postgresql.py b/tooz/tests/test_postgresql.py
index 5dee9fc..24d86ea 100644
--- a/tooz/tests/test_postgresql.py
+++ b/tooz/tests/test_postgresql.py
@@ -14,8 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import uuid
-
try:
# Added in python 3.3+
from unittest import mock
@@ -27,6 +25,7 @@ import testtools
from testtools import testcase
from tooz import coordination
+from tooz import tests
# Handle the case gracefully where the driver is not installed.
try:
@@ -57,7 +56,7 @@ class TestPostgreSQLFailures(testcase.TestCase):
raise
coord = coordination.get_coordinator(self.FAKE_URL,
- str(uuid.uuid4()).encode('ascii'))
+ tests.get_random_uuid())
self.addCleanup(_safe_stop, coord)
return coord
diff --git a/tox.ini b/tox.ini
index 6e78135..6490e17 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,7 +5,7 @@ envlist = py27,py34,py27-zookeeper,py34-zookeeper,py27-redis,py34-redis,py27-sen
[testenv]
# We need to install a bit more than just `test' because those drivers have
# custom tests that we always run
-deps = .[test,zake,ipc,memcached,mysql]
+deps = .[test,zake,ipc,memcached,mysql,etcd]
py{27,34}-zookeeper: .[zookeeper]
py{27,34}-redis: .[redis]
py{27,34}-sentinel: .[redis]