build.tests.unit.test_main   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 356
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 251
dl 0
loc 356
rs 10
c 0
b 0
f 0
wmc 21

19 Methods

Rating   Name   Duplication   Size   Complexity  
B TestMain.test_notify_uplink_detected() 0 46 1
A TestMain.test_build_lldp_packet_out() 0 33 1
A TestMain.get_topology_interfaces() 0 6 2
A TestMain.test_execute() 0 27 1
A TestMain.setUp() 0 14 2
A TestMain.test_handle_lldp_flows() 0 18 1
A TestMain.test_get_time() 0 8 1
A TestMain.test_get_interfaces() 0 7 1
A TestMain.test_get_interfaces_dict() 0 8 1
A TestMain.test_enable_disable_lldp_404() 0 15 1
A TestMain.test_set_time_400() 0 9 1
A TestMain.test_rest_get_lldp_interfaces() 0 14 1
A TestMain.test_unpack_non_empty() 0 9 1
A TestMain.test_enable_disable_lldp_400() 0 20 1
A TestMain.test_set_time() 0 11 1
A TestMain.test_enable_disable_lldp_200() 0 19 1
A TestMain.test_build_lldp_flow() 0 38 1
A TestMain.test_get_data() 0 9 1
A TestMain.test_get_lldp_interfaces() 0 12 1
1
"""Test Main methods."""
2
from unittest import TestCase
3
from unittest.mock import MagicMock, call, patch
4
5
from kytos.lib.helpers import (get_controller_mock, get_kytos_event_mock,
6
                               get_switch_mock, get_test_client)
7
8
from tests.helpers import get_topology_mock
9
10
11
# pylint: disable=protected-access
12
class TestMain(TestCase):
13
    """Tests for the Main class."""
14
15
    def setUp(self):
16
        """Execute steps before each tests."""
17
        self.server_name_url = 'http://127.0.0.1:8181/api/kytos/of_lldp'
18
19
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
20
        # pylint: disable=bad-option-value, import-outside-toplevel
21
        from napps.kytos.of_lldp.main import Main
22
        self.addCleanup(patch.stopall)
23
24
        self.topology = get_topology_mock()
25
        controller = get_controller_mock()
26
        controller.switches = self.topology.switches
27
28
        self.napp = Main(controller)
29
30
    def get_topology_interfaces(self):
31
        """Return interfaces present in topology."""
32
        interfaces = []
33
        for switch in list(self.topology.switches.values()):
34
            interfaces += list(switch.interfaces.values())
35
        return interfaces
36
37
    @patch('kytos.core.buffers.KytosEventBuffer.put')
38
    @patch('napps.kytos.of_lldp.main.Main._build_lldp_packet_out')
39
    @patch('napps.kytos.of_lldp.main.KytosEvent')
40
    @patch('napps.kytos.of_lldp.main.VLAN')
41
    @patch('napps.kytos.of_lldp.main.Ethernet')
42
    @patch('napps.kytos.of_lldp.main.DPID')
43
    @patch('napps.kytos.of_lldp.main.LLDP')
44
    def test_execute(self, *args):
45
        """Test execute method."""
46
        (_, _, mock_ethernet, _, mock_kytos_event, mock_build_lldp_packet_out,
47
         mock_buffer_put) = args
48
49
        ethernet = MagicMock()
50
        ethernet.pack.return_value = 'pack'
51
        interfaces = self.get_topology_interfaces()
52
        po_args = [(interface.switch.connection.protocol.version,
53
                    interface.port_number, 'pack') for interface in interfaces]
54
55
        mock_ethernet.return_value = ethernet
56
        mock_kytos_event.side_effect = po_args
57
58
        self.napp.execute()
59
60
        mock_build_lldp_packet_out.assert_has_calls([call(*(arg))
61
                                                     for arg in po_args])
62
        mock_buffer_put.assert_has_calls([call(arg)
63
                                          for arg in po_args])
64
65
    @patch('requests.delete')
66
    @patch('requests.post')
67
    def test_handle_lldp_flows(self, mock_post, mock_delete):
68
        """Test handle_lldp_flow method."""
69
        dpid = "00:00:00:00:00:00:00:01"
70
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
71
        self.napp.controller.switches = {dpid: switch}
72
        event_post = get_kytos_event_mock(name='kytos/topology.switch.enabled',
73
                                          content={'dpid': dpid})
74
75
        event_del = get_kytos_event_mock(name='kytos/topology.switch.disabled',
76
                                         content={'dpid': dpid})
77
78
        self.napp.handle_lldp_flows(event_post)
79
        mock_post.assert_called()
80
81
        self.napp.handle_lldp_flows(event_del)
82
        mock_delete.assert_called()
83
84
    @patch('kytos.core.buffers.KytosEventBuffer.put')
85
    @patch('napps.kytos.of_lldp.main.KytosEvent')
86
    @patch('kytos.core.controller.Controller.get_switch_by_dpid')
87
    @patch('napps.kytos.of_lldp.main.Main._unpack_non_empty')
88
    @patch('napps.kytos.of_lldp.main.UBInt32')
89
    @patch('napps.kytos.of_lldp.main.DPID')
90
    @patch('napps.kytos.of_lldp.main.LLDP')
91
    @patch('napps.kytos.of_lldp.main.Ethernet')
92
    def test_notify_uplink_detected(self, *args):
93
        """Test notify_uplink_detected method."""
94
        (mock_ethernet, mock_lldp, mock_dpid, mock_ubint32,
95
         mock_unpack_non_empty, mock_get_switch_by_dpid, mock_kytos_event,
96
         mock_buffer_put) = args
97
98
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
99
        message = MagicMock()
100
        message.in_port = 1
101
        message.data = 'data'
102
        event = get_kytos_event_mock(name='kytos/of_core.v0x0[14].messages.in.'
103
                                          'ofpt_packet_in',
104
                                     content={'source': switch.connection,
105
                                              'message': message})
106
107
        ethernet = MagicMock()
108
        ethernet.ether_type = 0x88CC
109
        ethernet.data = 'eth_data'
110
        lldp = MagicMock()
111
        lldp.chassis_id.sub_value = 'chassis_id'
112
        lldp.port_id.sub_value = 'port_id'
113
        dpid = MagicMock()
114
        dpid.value = "00:00:00:00:00:00:00:02"
115
        port_b = MagicMock()
116
117
        mock_unpack_non_empty.side_effect = [ethernet, lldp, dpid, port_b]
118
        mock_get_switch_by_dpid.return_value = get_switch_mock(dpid.value,
119
                                                               0x04)
120
        mock_kytos_event.return_value = 'nni'
121
122
        self.napp.notify_uplink_detected(event)
123
124
        calls = [call(mock_ethernet, message.data),
125
                 call(mock_lldp, ethernet.data),
126
                 call(mock_dpid, lldp.chassis_id.sub_value),
127
                 call(mock_ubint32, lldp.port_id.sub_value)]
128
        mock_unpack_non_empty.assert_has_calls(calls)
129
        mock_buffer_put.assert_called_with('nni')
130
131
    @patch('napps.kytos.of_lldp.main.PO13')
132
    @patch('napps.kytos.of_lldp.main.PO10')
133
    @patch('napps.kytos.of_lldp.main.AO13')
134
    @patch('napps.kytos.of_lldp.main.AO10')
135
    def test_build_lldp_packet_out(self, *args):
136
        """Test _build_lldp_packet_out method."""
137
        (mock_ao10, mock_ao13, mock_po10, mock_po13) = args
138
139
        ao10 = MagicMock()
140
        ao13 = MagicMock()
141
        po10 = MagicMock()
142
        po10.actions = []
143
        po13 = MagicMock()
144
        po13.actions = []
145
146
        mock_ao10.return_value = ao10
147
        mock_ao13.return_value = ao13
148
        mock_po10.return_value = po10
149
        mock_po13.return_value = po13
150
151
        packet_out10 = self.napp._build_lldp_packet_out(0x01, 1, 'data1')
152
        packet_out13 = self.napp._build_lldp_packet_out(0x04, 2, 'data2')
153
        packet_out14 = self.napp._build_lldp_packet_out(0x05, 3, 'data3')
154
155
        self.assertEqual(packet_out10.data, 'data1')
156
        self.assertEqual(packet_out10.actions, [ao10])
157
        self.assertEqual(packet_out10.actions[0].port, 1)
158
159
        self.assertEqual(packet_out13.data, 'data2')
160
        self.assertEqual(packet_out13.actions, [ao13])
161
        self.assertEqual(packet_out13.actions[0].port, 2)
162
163
        self.assertIsNone(packet_out14)
164
165
    @patch('napps.kytos.of_lldp.main.settings')
166
    @patch('napps.kytos.of_lldp.main.EtherType')
167
    @patch('napps.kytos.of_lldp.main.Port13')
168
    @patch('napps.kytos.of_lldp.main.Port10')
169
    def test_build_lldp_flow(self, *args):
170
        """Test _build_lldp_flow method."""
171
        (mock_v0x01_port, mock_v0x04_port, mock_ethertype,
172
         mock_settings) = args
173
        self.napp.vlan_id = None
174
        mock_v0x01_port.OFPP_CONTROLLER = 123
175
        mock_v0x04_port.OFPP_CONTROLLER = 1234
176
177
        mock_ethertype.LLDP = 10
178
        mock_settings.FLOW_VLAN_VID = None
179
        mock_settings.FLOW_PRIORITY = 1500
180
        mock_settings.TABLE_ID = 0
181
182
        flow = {}
183
        match = {}
184
        flow['priority'] = 1500
185
        flow['table_id'] = 0
186
        match['dl_type'] = 10
187
188
        flow['match'] = match
189
        expected_flow_v0x01 = flow.copy()
190
        expected_flow_v0x04 = flow.copy()
191
192
        expected_flow_v0x01['actions'] = [{'action_type': 'output',
193
                                           'port': 123}]
194
195
        expected_flow_v0x04['actions'] = [{'action_type': 'output',
196
                                           'port': 1234}]
197
198
        flow_mod10 = self.napp._build_lldp_flow(0x01)
199
        flow_mod13 = self.napp._build_lldp_flow(0x04)
200
201
        self.assertDictEqual(flow_mod10, expected_flow_v0x01)
202
        self.assertDictEqual(flow_mod13, expected_flow_v0x04)
203
204
    def test_unpack_non_empty(self):
205
        """Test _unpack_non_empty method."""
206
        desired_class = MagicMock()
207
        data = MagicMock()
208
        data.value = 'data'
209
210
        obj = self.napp._unpack_non_empty(desired_class, data)
211
212
        obj.unpack.assert_called_with('data')
213
214
    def test_get_data(self):
215
        """Test _get_data method."""
216
        req = MagicMock()
217
        interfaces = ['00:00:00:00:00:00:00:01:1', '00:00:00:00:00:00:00:01:2']
218
        req.get_json.return_value = {'interfaces': interfaces}
219
220
        data = self.napp._get_data(req)
221
222
        self.assertEqual(data, interfaces)
223
224
    def test_get_interfaces(self):
225
        """Test _get_interfaces method."""
226
        expected_interfaces = self.get_topology_interfaces()
227
228
        interfaces = self.napp._get_interfaces()
229
230
        self.assertEqual(interfaces, expected_interfaces)
231
232
    def test_get_interfaces_dict(self):
233
        """Test _get_interfaces_dict method."""
234
        interfaces = self.napp._get_interfaces()
235
        expected_interfaces = {inter.id: inter for inter in interfaces}
236
237
        interfaces_dict = self.napp._get_interfaces_dict(interfaces)
238
239
        self.assertEqual(interfaces_dict, expected_interfaces)
240
241
    def test_get_lldp_interfaces(self):
242
        """Test _get_lldp_interfaces method."""
243
        lldp_interfaces = self.napp._get_lldp_interfaces()
244
245
        expected_interfaces = ['00:00:00:00:00:00:00:01:1',
246
                               '00:00:00:00:00:00:00:01:2',
247
                               '00:00:00:00:00:00:00:02:1',
248
                               '00:00:00:00:00:00:00:02:2',
249
                               '00:00:00:00:00:00:00:03:1',
250
                               '00:00:00:00:00:00:00:03:2']
251
252
        self.assertEqual(lldp_interfaces, expected_interfaces)
253
254
    def test_rest_get_lldp_interfaces(self):
255
        """Test get_lldp_interfaces method."""
256
        api = get_test_client(self.napp.controller, self.napp)
257
        url = f'{self.server_name_url}/v1/interfaces'
258
        response = api.open(url, method='GET')
259
260
        expected_data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
261
                                        '00:00:00:00:00:00:00:01:2',
262
                                        '00:00:00:00:00:00:00:02:1',
263
                                        '00:00:00:00:00:00:00:02:2',
264
                                        '00:00:00:00:00:00:00:03:1',
265
                                        '00:00:00:00:00:00:00:03:2']}
266
        self.assertEqual(response.json, expected_data)
267
        self.assertEqual(response.status_code, 200)
268
269
    def test_enable_disable_lldp_200(self):
270
        """Test 200 response for enable_lldp and disable_lldp methods."""
271
        data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
272
                               '00:00:00:00:00:00:00:01:2',
273
                               '00:00:00:00:00:00:00:02:1',
274
                               '00:00:00:00:00:00:00:02:2',
275
                               '00:00:00:00:00:00:00:03:1',
276
                               '00:00:00:00:00:00:00:03:2']}
277
278
        api = get_test_client(self.napp.controller, self.napp)
279
280
        url = f'{self.server_name_url}/v1/interfaces/disable'
281
        disable_response = api.open(url, method='POST', json=data)
282
283
        url = f'{self.server_name_url}/v1/interfaces/enable'
284
        enable_response = api.open(url, method='POST', json=data)
285
286
        self.assertEqual(disable_response.status_code, 200)
287
        self.assertEqual(enable_response.status_code, 200)
288
289
    def test_enable_disable_lldp_404(self):
290
        """Test 404 response for enable_lldp and disable_lldp methods."""
291
        data = {"interfaces": []}
292
293
        self.napp.controller.switches = {}
294
        api = get_test_client(self.napp.controller, self.napp)
295
296
        url = f'{self.server_name_url}/v1/interfaces/disable'
297
        disable_response = api.open(url, method='POST', json=data)
298
299
        url = f'{self.server_name_url}/v1/interfaces/enable'
300
        enable_response = api.open(url, method='POST', json=data)
301
302
        self.assertEqual(disable_response.status_code, 404)
303
        self.assertEqual(enable_response.status_code, 404)
304
305
    def test_enable_disable_lldp_400(self):
306
        """Test 400 response for enable_lldp and disable_lldp methods."""
307
        data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
308
                               '00:00:00:00:00:00:00:01:2',
309
                               '00:00:00:00:00:00:00:02:1',
310
                               '00:00:00:00:00:00:00:02:2',
311
                               '00:00:00:00:00:00:00:03:1',
312
                               '00:00:00:00:00:00:00:03:2',
313
                               '00:00:00:00:00:00:00:04:1']}
314
315
        api = get_test_client(self.napp.controller, self.napp)
316
317
        url = f'{self.server_name_url}/v1/interfaces/disable'
318
        disable_response = api.open(url, method='POST', json=data)
319
320
        url = f'{self.server_name_url}/v1/interfaces/enable'
321
        enable_response = api.open(url, method='POST', json=data)
322
323
        self.assertEqual(disable_response.status_code, 400)
324
        self.assertEqual(enable_response.status_code, 400)
325
326
    def test_get_time(self):
327
        """Test get polling time."""
328
        api = get_test_client(self.napp.controller, self.napp)
329
330
        url = f'{self.server_name_url}/v1/polling_time'
331
        response = api.open(url, method='GET')
332
333
        self.assertEqual(response.status_code, 200)
334
335
    def test_set_time(self):
336
        """Test update polling time."""
337
        data = {"polling_time": 5}
338
339
        api = get_test_client(self.napp.controller, self.napp)
340
341
        url = f'{self.server_name_url}/v1/polling_time'
342
        response = api.open(url, method='POST', json=data)
343
344
        self.assertEqual(response.status_code, 200)
345
        self.assertEqual(self.napp.polling_time, data['polling_time'])
346
347
    def test_set_time_400(self):
348
        """Test fail case the update polling time."""
349
        api = get_test_client(self.napp.controller, self.napp)
350
351
        url = f'{self.server_name_url}/v1/polling_time'
352
353
        data = {'polling_time': 'A'}
354
        response = api.open(url, method='POST', json=data)
355
        self.assertEqual(response.status_code, 400)
356