Passed
Pull Request — master (#42)
by Gleyberson
02:04
created

TestMain.test_unpack_non_empty()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
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
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('kytos.core.buffers.KytosEventBuffer.put')
66
    @patch('napps.kytos.of_lldp.main.KytosEvent')
67
    @patch('napps.kytos.of_lldp.main.Main._build_lldp_flow_mod')
68
    def test_install_lldp_flow(self, *args):
69
        """Test install_lldp_flow method."""
70
        (mock_build_lldp_packet_out, mock_kytos_event, mock_buffer_put) = args
71
72
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
73
        event = get_kytos_event_mock(name='kytos/of_core.handshake.completed',
74
                                     content={'switch': switch})
75
76
        mock_build_lldp_packet_out.side_effect = ['flow_mod', None]
77
        mock_kytos_event.return_value = 'ofpt_flow_mod'
78
79
        self.napp.install_lldp_flow(event)
80
81
        switch.connection = None
82
83
        self.napp.install_lldp_flow(event)
84
85
        mock_buffer_put.assert_called_once_with('ofpt_flow_mod')
86
87
    @patch('kytos.core.buffers.KytosEventBuffer.put')
88
    @patch('napps.kytos.of_lldp.main.KytosEvent')
89
    @patch('kytos.core.controller.Controller.get_switch_by_dpid')
90
    @patch('napps.kytos.of_lldp.main.Main._unpack_non_empty')
91
    @patch('napps.kytos.of_lldp.main.UBInt32')
92
    @patch('napps.kytos.of_lldp.main.DPID')
93
    @patch('napps.kytos.of_lldp.main.LLDP')
94
    @patch('napps.kytos.of_lldp.main.Ethernet')
95
    def test_notify_uplink_detected(self, *args):
96
        """Test notify_uplink_detected method."""
97
        (mock_ethernet, mock_lldp, mock_dpid, mock_ubint32,
98
         mock_unpack_non_empty, mock_get_switch_by_dpid, mock_kytos_event,
99
         mock_buffer_put) = args
100
101
        switch = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
102
        message = MagicMock()
103
        message.in_port = 1
104
        message.data = 'data'
105
        event = get_kytos_event_mock(name='kytos/of_core.v0x0[14].messages.in.'
106
                                          'ofpt_packet_in',
107
                                     content={'source': switch.connection,
108
                                              'message': message})
109
110
        ethernet = MagicMock()
111
        ethernet.ether_type = 0x88CC
112
        ethernet.data = 'eth_data'
113
        lldp = MagicMock()
114
        lldp.chassis_id.sub_value = 'chassis_id'
115
        lldp.port_id.sub_value = 'port_id'
116
        dpid = MagicMock()
117
        dpid.value = "00:00:00:00:00:00:00:02"
118
        port_b = MagicMock()
119
120
        mock_unpack_non_empty.side_effect = [ethernet, lldp, dpid, port_b]
121
        mock_get_switch_by_dpid.return_value = get_switch_mock(dpid.value,
122
                                                               0x04)
123
        mock_kytos_event.return_value = 'nni'
124
125
        self.napp.notify_uplink_detected(event)
126
127
        calls = [call(mock_ethernet, message.data),
128
                 call(mock_lldp, ethernet.data),
129
                 call(mock_dpid, lldp.chassis_id.sub_value),
130
                 call(mock_ubint32, lldp.port_id.sub_value)]
131
        mock_unpack_non_empty.assert_has_calls(calls)
132
        mock_buffer_put.assert_called_with('nni')
133
134
    @patch('napps.kytos.of_lldp.main.PO13')
135
    @patch('napps.kytos.of_lldp.main.PO10')
136
    @patch('napps.kytos.of_lldp.main.AO13')
137
    @patch('napps.kytos.of_lldp.main.AO10')
138
    def test_build_lldp_packet_out(self, *args):
139
        """Test _build_lldp_packet_out method."""
140
        (mock_ao10, mock_ao13, mock_po10, mock_po13) = args
141
142
        ao10 = MagicMock()
143
        ao13 = MagicMock()
144
        po10 = MagicMock()
145
        po10.actions = []
146
        po13 = MagicMock()
147
        po13.actions = []
148
149
        mock_ao10.return_value = ao10
150
        mock_ao13.return_value = ao13
151
        mock_po10.return_value = po10
152
        mock_po13.return_value = po13
153
154
        packet_out10 = self.napp._build_lldp_packet_out(0x01, 1, 'data1')
155
        packet_out13 = self.napp._build_lldp_packet_out(0x04, 2, 'data2')
156
        packet_out14 = self.napp._build_lldp_packet_out(0x05, 3, 'data3')
157
158
        self.assertEqual(packet_out10.data, 'data1')
159
        self.assertEqual(packet_out10.actions, [ao10])
160
        self.assertEqual(packet_out10.actions[0].port, 1)
161
162
        self.assertEqual(packet_out13.data, 'data2')
163
        self.assertEqual(packet_out13.actions, [ao13])
164
        self.assertEqual(packet_out13.actions[0].port, 2)
165
166
        self.assertIsNone(packet_out14)
167
168
    @patch('napps.kytos.of_lldp.main.InstructionApplyAction')
169
    @patch('napps.kytos.of_lldp.main.OxmTLV')
170
    @patch('napps.kytos.of_lldp.main.FM13')
171
    @patch('napps.kytos.of_lldp.main.FM10')
172
    @patch('napps.kytos.of_lldp.main.AO13')
173
    @patch('napps.kytos.of_lldp.main.AO10')
174
    def test_build_lldp_flow_mod(self, *args):
175
        """Test _build_lldp_flow_mod method."""
176
        (mock_ao10, mock_ao13, mock_fm10, mock_fm13, mock_oxm_tlv,
177
         mock_instruction) = args
178
179
        ao10 = MagicMock()
180
        fm10 = MagicMock()
181
        fm10.actions = []
182
        ao13 = MagicMock()
183
        fm13 = MagicMock()
184
        fm13.match.oxm_match_fields = []
185
        fm13.instructions = []
186
        instruction = MagicMock()
187
        instruction.actions = []
188
189
        match_lldp = MagicMock()
190
        match_lldp.oxm_field = 5
191
        match_lldp.oxm_value = 'ether_type'
192
193
        match_vlan = MagicMock()
194
        match_vlan.oxm_field = 6
195
        match_vlan.oxm_value = 'vlan_value'
196
197
        oxm_tlvs = [match_lldp, match_vlan]
198
199
        mock_ao10.return_value = ao10
200
        mock_fm10.return_value = fm10
201
        mock_ao13.return_value = ao13
202
        mock_fm13.return_value = fm13
203
        mock_instruction.return_value = instruction
204
        mock_oxm_tlv.side_effect = oxm_tlvs
205
206
        flow_mod10 = self.napp._build_lldp_flow_mod(0x01)
207
        flow_mod13 = self.napp._build_lldp_flow_mod(0x04)
208
        flow_mod14 = self.napp._build_lldp_flow_mod(0x05)
209
210
        self.assertEqual(flow_mod10.command, 0)
211
        self.assertEqual(flow_mod10.priority, 1000)
212
        self.assertEqual(flow_mod10.match.dl_type, 0x88CC)
213
        self.assertEqual(flow_mod10.match.dl_vlan, 3799)
214
        self.assertEqual(flow_mod10.actions, [ao10])
215
216
        self.assertEqual(flow_mod13.command, 0)
217
        self.assertEqual(flow_mod13.priority, 1000)
218
        self.assertEqual(flow_mod13.match.oxm_match_fields, oxm_tlvs)
219
        self.assertEqual(flow_mod13.instructions[0], instruction)
220
        self.assertEqual(flow_mod13.instructions[0].actions, [ao13])
221
222
        self.assertIsNone(flow_mod14)
223
224
    def test_unpack_non_empty(self):
225
        """Test _unpack_non_empty method."""
226
        desired_class = MagicMock()
227
        data = MagicMock()
228
        data.value = 'data'
229
230
        obj = self.napp._unpack_non_empty(desired_class, data)
231
232
        obj.unpack.assert_called_with('data')
233
234
    def test_get_data(self):
235
        """Test _get_data method."""
236
        req = MagicMock()
237
        interfaces = ['00:00:00:00:00:00:00:01:1', '00:00:00:00:00:00:00:01:2']
238
        req.get_json.return_value = {'interfaces': interfaces}
239
240
        data = self.napp._get_data(req)
241
242
        self.assertEqual(data, interfaces)
243
244
    def test_get_interfaces(self):
245
        """Test _get_interfaces method."""
246
        expected_interfaces = self.get_topology_interfaces()
247
248
        interfaces = self.napp._get_interfaces()
249
250
        self.assertEqual(interfaces, expected_interfaces)
251
252
    def test_get_interfaces_dict(self):
253
        """Test _get_interfaces_dict method."""
254
        interfaces = self.napp._get_interfaces()
255
        expected_interfaces = {inter.id: inter for inter in interfaces}
256
257
        interfaces_dict = self.napp._get_interfaces_dict(interfaces)
258
259
        self.assertEqual(interfaces_dict, expected_interfaces)
260
261
    def test_get_lldp_interfaces(self):
262
        """Test _get_lldp_interfaces method."""
263
        lldp_interfaces = self.napp._get_lldp_interfaces()
264
265
        expected_interfaces = ['00:00:00:00:00:00:00:01:1',
266
                               '00:00:00:00:00:00:00:01:2',
267
                               '00:00:00:00:00:00:00:02:1',
268
                               '00:00:00:00:00:00:00:02:2',
269
                               '00:00:00:00:00:00:00:03:1',
270
                               '00:00:00:00:00:00:00:03:2']
271
272
        self.assertEqual(lldp_interfaces, expected_interfaces)
273
274
    def test_rest_get_lldp_interfaces(self):
275
        """Test get_lldp_interfaces method."""
276
        api = get_test_client(self.napp.controller, self.napp)
277
        url = f'{self.server_name_url}/v1/interfaces'
278
        response = api.open(url, method='GET')
279
280
        expected_data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
281
                                        '00:00:00:00:00:00:00:01:2',
282
                                        '00:00:00:00:00:00:00:02:1',
283
                                        '00:00:00:00:00:00:00:02:2',
284
                                        '00:00:00:00:00:00:00:03:1',
285
                                        '00:00:00:00:00:00:00:03:2']}
286
        self.assertEqual(response.json, expected_data)
287
        self.assertEqual(response.status_code, 200)
288
289
    def test_enable_disable_lldp_200(self):
290
        """Test 200 response for enable_lldp and disable_lldp methods."""
291
        data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
292
                               '00:00:00:00:00:00:00:01:2',
293
                               '00:00:00:00:00:00:00:02:1',
294
                               '00:00:00:00:00:00:00:02:2',
295
                               '00:00:00:00:00:00:00:03:1',
296
                               '00:00:00:00:00:00:00:03:2']}
297
298
        api = get_test_client(self.napp.controller, self.napp)
299
300
        url = f'{self.server_name_url}/v1/interfaces/disable'
301
        disable_response = api.open(url, method='POST', json=data)
302
303
        url = f'{self.server_name_url}/v1/interfaces/enable'
304
        enable_response = api.open(url, method='POST', json=data)
305
306
        self.assertEqual(disable_response.status_code, 200)
307
        self.assertEqual(enable_response.status_code, 200)
308
309
    def test_enable_disable_lldp_404(self):
310
        """Test 404 response for enable_lldp and disable_lldp methods."""
311
        data = {"interfaces": []}
312
313
        self.napp.controller.switches = {}
314
        api = get_test_client(self.napp.controller, self.napp)
315
316
        url = f'{self.server_name_url}/v1/interfaces/disable'
317
        disable_response = api.open(url, method='POST', json=data)
318
319
        url = f'{self.server_name_url}/v1/interfaces/enable'
320
        enable_response = api.open(url, method='POST', json=data)
321
322
        self.assertEqual(disable_response.status_code, 404)
323
        self.assertEqual(enable_response.status_code, 404)
324
325
    def test_enable_disable_lldp_400(self):
326
        """Test 400 response for enable_lldp and disable_lldp methods."""
327
        data = {"interfaces": ['00:00:00:00:00:00:00:01:1',
328
                               '00:00:00:00:00:00:00:01:2',
329
                               '00:00:00:00:00:00:00:02:1',
330
                               '00:00:00:00:00:00:00:02:2',
331
                               '00:00:00:00:00:00:00:03:1',
332
                               '00:00:00:00:00:00:00:03:2',
333
                               '00:00:00:00:00:00:00:04:1']}
334
335
        api = get_test_client(self.napp.controller, self.napp)
336
337
        url = f'{self.server_name_url}/v1/interfaces/disable'
338
        disable_response = api.open(url, method='POST', json=data)
339
340
        url = f'{self.server_name_url}/v1/interfaces/enable'
341
        enable_response = api.open(url, method='POST', json=data)
342
343
        self.assertEqual(disable_response.status_code, 400)
344
        self.assertEqual(enable_response.status_code, 400)
345