dragonflow/dragonflow/tests/unit/test_df_local_controller.py

209 lines
8.1 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 oslo_config import cfg
from dragonflow.controller import df_local_controller
from dragonflow.db import db_store
from dragonflow.db import field_types as df_fields
from dragonflow.db import model_framework
from dragonflow.db.models import core
from dragonflow.db.models import mixins
from dragonflow.switch.drivers.ovs import os_ken_base_app
from dragonflow.tests.common import utils
from dragonflow.tests.unit import test_app_base
@model_framework.construct_nb_db_model
class _Model(model_framework.ModelBase, mixins.BasicEvents, mixins.Version):
table_name = 'some_table'
@model_framework.construct_nb_db_model
class _ModelNoEvents(model_framework.ModelBase, mixins.Version):
table_name = 'another_table'
class DfLocalControllerTestCase(test_app_base.DFAppTestBase):
apps_list = ["l2"]
@mock.patch.object(os_ken_base_app.OsKenDFAdapter,
'notify_switch_sync_finished')
def test_switch_sync_finished(self, mock_notify):
self.controller.switch_sync_finished()
mock_notify.assert_called_once()
@mock.patch.object(os_ken_base_app.OsKenDFAdapter,
'notify_switch_sync_started')
def test_switch_sync_started(self, mock_notify):
self.controller.switch_sync_started()
mock_notify.assert_called_once()
@mock.patch.object(df_local_controller.DfLocalController,
'delete_model_object')
@mock.patch.object(db_store.DbStore, 'get_all')
@mock.patch.object(db_store.DbStore, 'delete')
def test_delete_chassis(self, mock_db_store_delete,
mock_get_ports, mock_controller_delete):
lport_id = 'fake_lport_id'
chassis = core.Chassis(id='fake_chassis_id')
lport = mock.Mock()
lport.id = lport_id
mock_get_ports.return_value = [lport]
self.controller.delete(chassis)
mock_controller_delete.assert_called_once_with(lport)
mock_db_store_delete.assert_called_once_with(chassis)
@utils.with_nb_objects(test_app_base.fake_chassis1)
def test_register_chassis(self):
cfg.CONF.set_override('external_host_ip',
'172.24.4.100',
group='df')
self.controller.register_chassis()
expected_chassis = core.Chassis(
id=self.controller.chassis_name,
ip=self.controller.ip,
external_host_ip="172.24.4.100",
tunnel_types=self.controller.tunnel_types,
)
self.assertIn(expected_chassis, self.controller.db_store)
self.nb_api.update.assert_called_once_with(
expected_chassis,
skip_send_event=True,
)
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'update')
def test_update_model_object_created_called(self, update, get_one):
obj = _Model(id='foo', version=1)
obj.emit_created = mock.Mock()
get_one.return_value = None
self.controller.update_model_object(obj)
update.assert_called_once_with(obj)
obj.emit_created.assert_called_once()
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'update')
def test_update_model_object_updated_called(self, update, get_one):
obj = _Model(id='foo', version=2)
obj.emit_updated = mock.Mock()
old_obj = _Model(id='foo', version=1)
get_one.return_value = old_obj
self.controller.update_model_object(obj)
update.assert_called_once_with(obj)
obj.emit_updated.assert_called_once_with(old_obj)
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'update')
def test_update_model_object_updated_called_no_events(self, update,
get_one):
obj = _ModelNoEvents(id='foo', version=2)
old_obj = _ModelNoEvents(id='foo', version=1)
get_one.return_value = old_obj
self.controller.update_model_object(obj)
update.assert_called_once_with(obj)
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'update')
def test_update_model_object_not_called(self, update, get_one):
obj = _Model(id='foo', version=1)
obj.emit_updated = mock.Mock()
old_obj = _Model(id='foo', version=1)
get_one.return_value = old_obj
self.controller.update_model_object(obj)
update.assert_not_called()
obj.emit_updated.assert_not_called()
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'update')
def test_update_model_object_not_called_no_events(self, update, get_one):
obj = _ModelNoEvents(id='foo', version=1)
old_obj = _ModelNoEvents(id='foo', version=1)
get_one.return_value = old_obj
self.controller.update_model_object(obj)
update.assert_not_called()
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'delete')
def test_delete_model_object_called(self, delete, get_one):
obj = _Model(id='foo', version=1)
obj.emit_deleted = mock.MagicMock()
get_one.return_value = obj
self.controller.delete_model_object(obj)
delete.assert_called_once()
obj.emit_deleted.assert_called_once()
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'delete')
def test_delete_model_object_called_no_events(self, delete, get_one):
obj = _ModelNoEvents(id='foo', version=1)
get_one.return_value = obj
self.controller.delete_model_object(obj)
delete.assert_called_once()
@mock.patch.object(db_store.DbStore, 'get_one')
@mock.patch.object(db_store.DbStore, 'delete')
def test_delete_model_object_not_called(self, delete, get_one):
get_one.return_value = None
self.controller.delete_model_object(None)
delete.assert_not_called()
def test_iter_references_deep(self):
@model_framework.register_model
@model_framework.construct_nb_db_model
class LocalReffedModel(model_framework.ModelBase):
table_name = 'LocalReffedModel'
pass
@model_framework.register_model
@model_framework.construct_nb_db_model
class LocalReffingModel(model_framework.ModelBase):
table_name = 'LocalReffingModel'
ref1 = df_fields.ReferenceField(LocalReffedModel)
@model_framework.register_model
@model_framework.construct_nb_db_model
class LocalListReffingModel(model_framework.ModelBase):
table_name = 'LocalListReffingModel'
ref2 = df_fields.ReferenceListField(LocalReffingModel)
models = {}
nb_api_mocker = mock.patch.object(self.controller, 'nb_api')
nb_api = nb_api_mocker.start()
self.addCleanup(nb_api_mocker.stop)
nb_api.get = lambda m: models[m.id]
models['3'] = LocalReffedModel(id='3')
ref1 = LocalReffingModel(id='2', ref1='3')
models['2'] = ref1
models['5'] = LocalReffedModel(id='5')
ref2 = LocalReffingModel(id='4', ref1='5')
models['4'] = ref2
model = LocalListReffingModel(id='1', ref2=[ref1, ref2])
models['1'] = model
references = [inst.id for inst in
self.controller.iter_model_references_deep(model)]
self.assertItemsEqual(['2', '3', '4', '5'], references)
self.assertLess(references.index('2'), references.index('3'))
self.assertLess(references.index('4'), references.index('5'))