107 lines
4.2 KiB
Python
107 lines
4.2 KiB
Python
# 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 os_ken.ofproto import ofproto_v1_3
|
|
from os_ken.ofproto import ofproto_v1_3_parser
|
|
|
|
from neutron.plugins.ml2.drivers.openvswitch.agent.openflow.native \
|
|
import ofswitch
|
|
from neutron.tests import base
|
|
|
|
|
|
class FakeReply(object):
|
|
def __init__(self, type):
|
|
self.type = type
|
|
|
|
|
|
class TestBundledOpenFlowBridge(base.BaseTestCase):
|
|
def setUp(self):
|
|
super(TestBundledOpenFlowBridge, self).setUp()
|
|
br = mock.Mock(spec=['install_instructions', 'foo'])
|
|
br._get_dp = lambda: (mock.Mock(), ofproto_v1_3, ofproto_v1_3_parser)
|
|
br.active_bundles = set()
|
|
self.br = ofswitch.BundledOpenFlowBridge(br, False, False)
|
|
|
|
def test_method_calls(self):
|
|
self.br.install_instructions(dummy_arg=1)
|
|
self.br.br.install_instructions.assert_called_once_with(dummy_arg=1)
|
|
|
|
def test_illegal_method_calls(self):
|
|
# With python3, this can be written as "with assertRaises..."
|
|
try:
|
|
self.br.uninstall_foo()
|
|
self.fail("Expected an exception")
|
|
except Exception as e:
|
|
self.assertIsInstance(e, AttributeError)
|
|
try:
|
|
self.br.foo()
|
|
self.fail("Expected an exception")
|
|
except Exception as e:
|
|
self.assertIsInstance(e, AttributeError)
|
|
|
|
def test_normal_bundle_context(self):
|
|
self.assertIsNone(self.br.active_bundle)
|
|
self.br.br._send_msg = mock.Mock(side_effect=[
|
|
FakeReply(ofproto_v1_3.ONF_BCT_OPEN_REPLY),
|
|
FakeReply(ofproto_v1_3.ONF_BCT_COMMIT_REPLY)])
|
|
with self.br:
|
|
self.assertIsNotNone(self.br.active_bundle)
|
|
# Do nothing
|
|
# Assert that the active bundle is gone
|
|
self.assertIsNone(self.br.active_bundle)
|
|
|
|
def test_aborted_bundle_context(self):
|
|
self.assertIsNone(self.br.active_bundle)
|
|
self.br.br._send_msg = mock.Mock(side_effect=[
|
|
FakeReply(ofproto_v1_3.ONF_BCT_OPEN_REPLY),
|
|
FakeReply(ofproto_v1_3.ONF_BCT_DISCARD_REPLY)])
|
|
try:
|
|
with self.br:
|
|
self.assertIsNotNone(self.br.active_bundle)
|
|
raise Exception()
|
|
except Exception:
|
|
pass
|
|
# Assert that the active bundle is gone
|
|
self.assertIsNone(self.br.active_bundle)
|
|
self.assertEqual(2, len(self.br.br._send_msg.mock_calls))
|
|
args, kwargs = self.br.br._send_msg.call_args_list[0]
|
|
self.assertEqual(ofproto_v1_3.ONF_BCT_OPEN_REQUEST,
|
|
args[0].type)
|
|
args, kwargs = self.br.br._send_msg.call_args_list[1]
|
|
self.assertEqual(ofproto_v1_3.ONF_BCT_DISCARD_REQUEST,
|
|
args[0].type)
|
|
|
|
def test_bundle_context_with_error(self):
|
|
self.assertIsNone(self.br.active_bundle)
|
|
self.br.br._send_msg = mock.Mock(side_effect=[
|
|
FakeReply(ofproto_v1_3.ONF_BCT_OPEN_REPLY),
|
|
RuntimeError])
|
|
try:
|
|
with self.br:
|
|
saved_bundle_id = self.br.active_bundle
|
|
self.assertIsNotNone(self.br.active_bundle)
|
|
self.fail("Expected an exception")
|
|
except RuntimeError:
|
|
pass
|
|
# Assert that the active bundle is gone
|
|
self.assertIsNone(self.br.active_bundle)
|
|
self.assertIn(saved_bundle_id, self.br.br.active_bundles)
|
|
|
|
self.assertEqual(2, len(self.br.br._send_msg.mock_calls))
|
|
args, kwargs = self.br.br._send_msg.call_args_list[0]
|
|
self.assertEqual(ofproto_v1_3.ONF_BCT_OPEN_REQUEST,
|
|
args[0].type)
|
|
args, kwargs = self.br.br._send_msg.call_args_list[1]
|
|
self.assertEqual(ofproto_v1_3.ONF_BCT_COMMIT_REQUEST,
|
|
args[0].type)
|