2015-01-23 10:55:19 -08:00
|
|
|
# Copyright 2012, 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.
|
|
|
|
|
2016-10-21 10:40:53 -04:00
|
|
|
import threading
|
2015-01-23 10:55:19 -08:00
|
|
|
import warnings
|
|
|
|
|
|
|
|
import mock
|
|
|
|
from oslotest import base as test_base
|
|
|
|
import six
|
|
|
|
|
|
|
|
from oslo_utils import eventletutils
|
|
|
|
|
|
|
|
|
|
|
|
class EventletUtilsTest(test_base.BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(EventletUtilsTest, self).setUp()
|
|
|
|
self._old_avail = eventletutils.EVENTLET_AVAILABLE
|
|
|
|
eventletutils.EVENTLET_AVAILABLE = True
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
super(EventletUtilsTest, self).tearDown()
|
|
|
|
eventletutils.EVENTLET_AVAILABLE = self._old_avail
|
|
|
|
|
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_warning_not_patched(self, mock_patcher):
|
|
|
|
mock_patcher.already_patched = True
|
|
|
|
mock_patcher.is_monkey_patched.return_value = False
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['os'])
|
|
|
|
self.assertEqual(1, len(capture))
|
|
|
|
w = capture[0]
|
|
|
|
self.assertEqual(RuntimeWarning, w.category)
|
|
|
|
self.assertIn('os', six.text_type(w.message))
|
|
|
|
|
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_warning_not_patched_none_provided(self, mock_patcher):
|
|
|
|
mock_patcher.already_patched = True
|
|
|
|
mock_patcher.is_monkey_patched.return_value = False
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched()
|
|
|
|
self.assertEqual(1, len(capture))
|
|
|
|
w = capture[0]
|
|
|
|
self.assertEqual(RuntimeWarning, w.category)
|
|
|
|
for m in eventletutils._ALL_PATCH:
|
|
|
|
self.assertIn(m, six.text_type(w.message))
|
|
|
|
|
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_warning_not_patched_all(self, mock_patcher):
|
|
|
|
mock_patcher.already_patched = True
|
|
|
|
mock_patcher.is_monkey_patched.return_value = False
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['all'])
|
|
|
|
self.assertEqual(1, len(capture))
|
|
|
|
w = capture[0]
|
|
|
|
self.assertEqual(RuntimeWarning, w.category)
|
|
|
|
for m in eventletutils._ALL_PATCH:
|
|
|
|
self.assertIn(m, six.text_type(w.message))
|
|
|
|
|
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_no_warning(self, mock_patcher):
|
|
|
|
mock_patcher.already_patched = True
|
|
|
|
mock_patcher.is_monkey_patched.return_value = True
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['os'])
|
|
|
|
self.assertEqual(0, len(capture))
|
|
|
|
|
2016-04-11 14:21:47 +03:00
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_eventlet_is_patched(self, mock_patcher):
|
|
|
|
mock_patcher.is_monkey_patched.return_value = True
|
|
|
|
self.assertTrue(eventletutils.is_monkey_patched('os'))
|
|
|
|
mock_patcher.is_monkey_patched.return_value = False
|
|
|
|
self.assertFalse(eventletutils.is_monkey_patched('os'))
|
|
|
|
|
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher", None)
|
|
|
|
def test_eventlet_no_patcher(self):
|
|
|
|
self.assertFalse(eventletutils.is_monkey_patched('os'))
|
|
|
|
|
2015-01-23 10:55:19 -08:00
|
|
|
@mock.patch("oslo_utils.eventletutils._patcher")
|
|
|
|
def test_partially_patched_warning(self, mock_patcher):
|
|
|
|
is_patched = set()
|
|
|
|
mock_patcher.already_patched = True
|
|
|
|
mock_patcher.is_monkey_patched.side_effect = lambda m: m in is_patched
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['os'])
|
|
|
|
self.assertEqual(1, len(capture))
|
|
|
|
is_patched.add('os')
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['os'])
|
|
|
|
self.assertEqual(0, len(capture))
|
|
|
|
is_patched.add('thread')
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['os', 'thread'])
|
|
|
|
self.assertEqual(0, len(capture))
|
|
|
|
with warnings.catch_warnings(record=True) as capture:
|
|
|
|
warnings.simplefilter("always")
|
|
|
|
eventletutils.warn_eventlet_not_patched(['all'])
|
|
|
|
self.assertEqual(1, len(capture))
|
|
|
|
w = capture[0]
|
|
|
|
self.assertEqual(RuntimeWarning, w.category)
|
|
|
|
for m in ['os', 'thread']:
|
|
|
|
self.assertNotIn(m, six.text_type(w.message))
|
|
|
|
|
|
|
|
def test_invalid_patch_check(self):
|
|
|
|
self.assertRaises(ValueError,
|
|
|
|
eventletutils.warn_eventlet_not_patched,
|
|
|
|
['blah.blah'])
|
2016-10-21 10:40:53 -04:00
|
|
|
|
2018-04-04 12:45:27 -04:00
|
|
|
@mock.patch('oslo_utils.eventletutils._eventlet')
|
|
|
|
def test_event_api_compat(self, mock_eventlet):
|
2016-11-07 09:41:10 -05:00
|
|
|
with mock.patch('oslo_utils.eventletutils.is_monkey_patched',
|
|
|
|
return_value=True):
|
|
|
|
e_event = eventletutils.Event()
|
2018-11-01 16:24:45 +00:00
|
|
|
self.assertIsInstance(e_event, eventletutils.EventletEvent)
|
2016-10-21 10:40:53 -04:00
|
|
|
|
|
|
|
t_event = eventletutils.Event()
|
|
|
|
if six.PY3:
|
|
|
|
t_event_cls = threading.Event
|
|
|
|
else:
|
|
|
|
t_event_cls = threading._Event
|
|
|
|
self.assertIsInstance(t_event, t_event_cls)
|
|
|
|
|
|
|
|
public_methods = [m for m in dir(t_event) if not m.startswith("_") and
|
|
|
|
callable(getattr(t_event, m))]
|
|
|
|
|
|
|
|
for method in public_methods:
|
|
|
|
self.assertTrue(hasattr(e_event, method))
|
2018-04-04 12:45:27 -04:00
|
|
|
|
|
|
|
# Ensure set() allows multiple invocations, same as in
|
|
|
|
# threading implementation. Must call reset on underlying
|
|
|
|
# Event before reusing it
|
|
|
|
e_event.set()
|
|
|
|
self.assertEqual(0, mock_eventlet.event.Event().reset.call_count)
|
|
|
|
e_event.set()
|
|
|
|
self.assertEqual(1, mock_eventlet.event.Event().reset.call_count)
|