nova/nova/tests/unit/test_fake_notifier.py
Matthew Booth c333e7e12e Raise error on timeout in wait_for_versioned_notifications
fake_notifier.wait_for_versioned_notifications previously returned
None if it timed out. This is counter-intuitive, and several callers
were failing to check its return. Every one of these represents a race
as it means we can continue past a barrier without its condition
having been met.

This change makes it default to safe by raising an exception if it
times out. Note that it's possible this may subsequently result in new
non-deterministic errors in functional. I would consider this a
feature, as these were previously hidden. They should be addressed
individually.

This change highlights several deterministically incorrect uses of
wait_for_versioned_notifications which were previously always silently
timing out. These are all fixed.

We also increase the default timeout from 1 to 10 seconds as we seem
to hit the 1 second timeout in practise, e.g.:

  http://logs.openstack.org/46/578846/14/check/nova-tox-functional/8a444c1/job-output.txt.gz

Change-Id: I017d1a31139c9300642dd706eadc265f7c954ca8
2018-09-29 00:29:49 +01:00

85 lines
3.1 KiB
Python

# Copyright 2018 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 functools
from nova import context
from nova import exception_wrapper
from nova import rpc
from nova import test
from nova.tests.unit import fake_notifier
class FakeVersionedNotifierTestCase(test.NoDBTestCase):
def setUp(self):
super(FakeVersionedNotifierTestCase, self).setUp()
fake_notifier.stub_notifier(self)
self.addCleanup(fake_notifier.reset)
self.context = context.RequestContext()
_get_notifier = functools.partial(rpc.get_notifier, 'compute')
@exception_wrapper.wrap_exception(get_notifier=_get_notifier,
binary='nova-compute')
def _raise_exception(self, context):
raise test.TestingException
def _generate_exception_notification(self):
self.assertRaises(test.TestingException, self._raise_exception,
self.context)
def test_wait_for_versioned_notifications(self):
# Wait for a single notification which we emitted first
self._generate_exception_notification()
notifications = fake_notifier.wait_for_versioned_notifications(
'compute.exception')
self.assertEqual(1, len(notifications))
def test_wait_for_versioned_notifications_fail(self):
# Wait for a single notification which is never sent
self.assertRaises(
AssertionError,
fake_notifier.wait_for_versioned_notifications,
'compute.exception', timeout=0.1)
def test_wait_for_versioned_notifications_n(self):
# Wait for 2 notifications which we emitted first
self._generate_exception_notification()
self._generate_exception_notification()
notifications = fake_notifier.wait_for_versioned_notifications(
'compute.exception', 2)
self.assertEqual(2, len(notifications))
def test_wait_for_versioned_notifications_n_fail(self):
# Wait for 2 notifications when we only emitted one
self._generate_exception_notification()
self.assertRaises(
AssertionError,
fake_notifier.wait_for_versioned_notifications,
'compute.exception', 2, timeout=0.1)
def test_wait_for_versioned_notifications_too_many(self):
# Wait for a single notification when there are 2 in the queue
self._generate_exception_notification()
self._generate_exception_notification()
notifications = fake_notifier.wait_for_versioned_notifications(
'compute.exception')
self.assertEqual(2, len(notifications))