build.tests.integration.test_main   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 407
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 21
eloc 323
dl 0
loc 407
rs 10
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A TestMain.test_handle_packet_in_raw_in() 0 26 1
A TestMain.test_handle_features_request_sent() 0 18 1
A TestMain.test_handle_01_features_reply() 0 33 2
A TestMain.test_handle_hello_raw_in() 0 21 2
A TestMain.test_pack_generic_hello() 0 6 1
A TestMain.test_handle_stats_reply() 0 33 1
A TestMain.setUp() 0 13 2
A TestMain.test_handle_echo_request() 0 18 1
A TestMain.test_handle_port_status_raw_in() 0 22 1
B TestMain.test_handle_multipart_reply() 0 55 1
A TestMain.test_execute() 0 23 2
A TestMain.test_get_event_listeners() 0 16 2
A TestMain.test_handle_04_features_reply() 0 35 2
B TestMain.test_handle_port_desc_multipart_reply() 0 50 2
1
"""Integration test main."""
2
3
from unittest import TestCase
4
from unittest.mock import patch
5
6
from pyof.v0x01.controller2switch.features_reply import \
7
    FeaturesReply as FReply_v0x01
8
from pyof.v0x01.controller2switch.stats_reply import StatsReply
9
from pyof.v0x04.controller2switch.features_reply import \
10
    FeaturesReply as FReply_v0x04
11
from pyof.v0x04.controller2switch.features_request import FeaturesRequest
12
from pyof.v0x04.controller2switch.multipart_reply import MultipartReply
13
from pyof.v0x04.symmetric.echo_request import EchoRequest
14
15
from kytos.core.connection import ConnectionState
16
from kytos.core.events import KytosEvent
17
from napps.kytos.of_core.utils import GenericHello
18
from tests.helpers import (get_connection_mock, get_controller_mock,
19
                           get_interface_mock, get_switch_mock)
20
21
22
class TestMain(TestCase):
23
    """Class to Integration test kytos/of_core main."""
24
25
    def setUp(self):
26
        """Execute steps before each tests.
27
        Set the server_name_url from kytos/of_core
28
        """
29
        self.server_name_url = 'http://localhost:8181/api/kytos/of_core'
30
31
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
32
        # pylint: disable=import-outside-toplevel
33
        from napps.kytos.of_core.main import Main
34
        self.addCleanup(patch.stopall)
35
36
        self.napp = Main(get_controller_mock())
37
        self.patched_events = []
38
39
    def test_get_event_listeners(self):
40
        """Verify all event listeners registered."""
41
        expected_events = [
42
            'kytos/of_core.v0x01.messages.in.ofpt_stats_reply',
43
            'kytos/of_core.v0x0[14].messages.in.ofpt_features_reply',
44
            'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply',
45
            'kytos/core.openflow.raw.in',
46
            'kytos/of_core.v0x0[14].messages.in.ofpt_echo_request',
47
            'kytos/of_core.v0x0[14].messages.out.ofpt_echo_reply',
48
            'kytos/of_core.v0x[0-9a-f]{2}.messages.in.hello_failed',
49
            'kytos/of_core.v0x0[14].messages.out.hello_failed',
50
        ]
51
52
        actual_events = self.napp.listeners()
53
        for _event in expected_events:
54
            self.assertIn(_event, actual_events, '%s' % _event)
55
56
    def test_execute(self):
57
        """Test 'execute' main method."""
58
        dpid_01 = "00:00:00:00:00:00:00:01"
59
        dpid_02 = "00:00:00:00:00:00:00:02"
60
        sw_01 = get_switch_mock()
61
        sw_01.connection = get_connection_mock(
62
            0x01, get_switch_mock(dpid_02), ConnectionState.ESTABLISHED)
63
        sw_04 = get_switch_mock(dpid_02)
64
        sw_04.connection = get_connection_mock(
65
            0x04, get_switch_mock(dpid_01), ConnectionState.ESTABLISHED)
66
67
        self.napp.controller.get_switch_or_create(dpid_01, sw_01.connection)
68
        self.napp.controller.get_switch_or_create(dpid_02, sw_04.connection)
69
        self.napp.execute()
70
        expected = [
71
            'kytos/of_core.v0x01.messages.out.ofpt_stats_request',
72
            'kytos/of_core.v0x01.messages.out.ofpt_echo_request',
73
            'kytos/of_core.v0x04.messages.out.ofpt_multipart_request',
74
            'kytos/of_core.v0x04.messages.out.ofpt_echo_request'
75
        ]
76
        for message in expected:
77
            of_event = self.napp.controller.buffers.msg_out.get()
78
            self.assertEqual(of_event.name, message)
79
80
    def test_handle_stats_reply(self):
81
        """Test handling stats reply message."""
82
        event_name = 'kytos/of_core.v0x01.messages.in.ofpt_stats_reply'
83
        switch = get_switch_mock()
84
        switch.connection = get_connection_mock(
85
            0x01, get_switch_mock("00:00:00:00:00:00:00:02"))
86
87
        stats_data = b'\x01\x11\x00\x0c\x00\x00\x00\x01\x00\x01\x00\x01'
88
        stats_reply = StatsReply()
89
        stats_reply.unpack(stats_data[8:])
90
        stats_event = KytosEvent(name=event_name,
91
                                 content={'source': switch.connection,
92
                                          'message': stats_reply})
93
        self.napp.handle_stats_reply(stats_event)
94
95
        desc_stats_data = b'\x01\x11\x00\x0c\x00\x00\x00\x0e\x00\x00\x00\x00'
96
        desc_stats_reply = StatsReply()
97
        desc_stats_reply.unpack(desc_stats_data[8:])
98
        desc_stats_event = KytosEvent(name=event_name,
99
                                      content={'source': switch.connection,
100
                                               'message': desc_stats_reply})
101
        self.napp.handle_stats_reply(desc_stats_event)
102
103
        self.assertEqual(desc_stats_reply.body.mfr_desc.value,
104
                         switch.connection.switch.description["manufacturer"])
105
        self.assertEqual(desc_stats_reply.body.hw_desc.value,
106
                         switch.connection.switch.description["hardware"])
107
        self.assertEqual(desc_stats_reply.body.sw_desc.value,
108
                         switch.connection.switch.description["software"])
109
        self.assertEqual(desc_stats_reply.body.serial_num.value,
110
                         switch.connection.switch.description["serial"])
111
        self.assertEqual(desc_stats_reply.body.dp_desc.value,
112
                         switch.connection.switch.description["data_path"])
113
114
    def test_handle_04_features_reply(self):
115
        """Test handling features reply message."""
116
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_features_reply'
117
        switch = get_switch_mock()
118
        switch.connection = get_connection_mock(
119
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"),
120
            ConnectionState.SETUP)
121
        switch.connection.protocol.state = 'waiting_features_reply'
122
123
        data = b'\x04\x06\x00\x20\x00\x00\x00\x00\x00\x00\x08\x60\x6e\x7f\x74'
124
        data += b'\xe7\x00\x00\x00\x00\xff\x63\x00\x00\x00\x00\x00\x4f\x00\x00'
125
        data += b'\x00\x00'
126
127
        features_reply = FReply_v0x04()
128
        features_reply.unpack(data[8:])
129
130
        event = KytosEvent(name=event_name,
131
                           content={'source': switch.connection,
132
                                    'message': features_reply})
133
        self.napp.handle_features_reply(event)
134
        target_switch = '00:00:08:60:6e:7f:74:e7'
135
        of_event_01 = self.napp.controller.buffers.app.get()
136
        of_event_02 = self.napp.controller.buffers.app.get()
137
        self.assertEqual("kytos/core.switch.new", of_event_01.name)
138
        self.assertEqual(target_switch, of_event_01.content["switch"].dpid)
139
        self.assertEqual("kytos/of_core.handshake.completed", of_event_02.name)
140
        self.assertEqual(target_switch, of_event_02.content["switch"].dpid)
141
        expected = [
142
            'kytos/of_core.v0x04.messages.out.ofpt_multipart_request',
143
            'kytos/of_core.v0x04.messages.out.ofpt_multipart_request',
144
            'kytos/of_core.v0x04.messages.out.ofpt_set_config'
145
        ]
146
        for message in expected:
147
            of_event = self.napp.controller.buffers.msg_out.get()
148
            self.assertEqual(of_event.name, message)
149
150
    def test_handle_01_features_reply(self):
151
        """Test handling features reply message."""
152
        event_name = 'kytos/of_core.v0x01.messages.in.ofpt_features_reply'
153
        switch = get_switch_mock()
154
        switch.connection = get_connection_mock(
155
            0x01, get_switch_mock("00:00:00:00:00:00:00:02"),
156
            ConnectionState.SETUP)
157
        switch.connection.protocol.state = 'waiting_features_reply'
158
159
        data = b'\x01\x06\x00\x80\x00\x00\x00\x00\x00\x00\x00\xff\x12\x34\x56'
160
        data += b'\x78\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\xa9\x00\x00'
161
        data += b'\x08\x43\x00\x07\xf2\x0b\xa4\xd0\x3f\x70\x50\x6f\x72\x74\x37'
162
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
163
        data += b'\x00\x00\x00\x10\x00\x00\x02\x88\x00\x00\x02\x80\x00\x00\x02'
164
        data += b'\x88\x00\x00\x02\x88\x00\x06\xf2\x0b\xa4\x7d\xf8\xea\x50\x6f'
165
        data += b'\x72\x74\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
166
        data += b'\x00\x00\x00\x00\x00\x00\x02\x00\x00\x02\x88\x00\x00\x02\x80'
167
        data += b'\x00\x00\x02\x88\x00\x00\x02\x88'
168
169
        features_reply = FReply_v0x01()
170
        features_reply.unpack(data[8:])
171
172
        event = KytosEvent(name=event_name,
173
                           content={'source': switch.connection,
174
                                    'message': features_reply})
175
        self.napp.handle_features_reply(event)
176
        expected = [
177
            'kytos/of_core.v0x01.messages.out.ofpt_stats_request',
178
            'kytos/of_core.v0x01.messages.out.ofpt_set_config'
179
        ]
180
        for message in expected:
181
            of_event = self.napp.controller.buffers.msg_out.get()
182
            self.assertEqual(of_event.name, message)
183
184
    def test_handle_features_request_sent(self):
185
        """Test handling features request sent message."""
186
        event_name = 'kytos/of_core.v0x01.messages.out.ofpt_features_request'
187
        switch = get_switch_mock()
188
        switch.connection = get_connection_mock(
189
            0x01, get_switch_mock("00:00:00:00:00:00:00:02"))
190
        switch.connection.protocol.state = 'sending_features'
191
192
        data = b'\x04\x05\x00\x08\x00\x00\x00\x03'
193
        features_request = FeaturesRequest()
194
        features_request.unpack(data)
195
196
        event = KytosEvent(name=event_name,
197
                           content={'destination': switch.connection,
198
                                    'message': features_request})
199
        self.napp.handle_features_request_sent(event)
200
        self.assertEqual(event.destination.protocol.state,
201
                         'waiting_features_reply')
202
203
    def test_handle_echo_request(self):
204
        """Test handling echo request message."""
205
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_echo_request'
206
        switch = get_switch_mock()
207
        switch.connection = get_connection_mock(
208
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"))
209
210
        data = b'\x04\x02\x00\x0c\x00\x00\x00\x00\x68\x6f\x67\x65'
211
        echo_request = EchoRequest()
212
        echo_request.unpack(data)
213
214
        event = KytosEvent(name=event_name,
215
                           content={'source': switch.connection,
216
                                    'message': echo_request})
217
        self.napp.handle_echo_request(event)
218
        of_event = self.napp.controller.buffers.msg_out.get()
219
        self.assertEqual(of_event.name,
220
                         'kytos/of_core.v0x04.messages.out.ofpt_echo_reply')
221
222
    def test_handle_hello_raw_in(self):
223
        """Test handling hello raw in message."""
224
        event_name = 'kytos/core.openflow.raw.in'
225
        switch = get_switch_mock()
226
        switch.connection = get_connection_mock(
227
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"))
228
229
        data = b'\x04\x00\x00\x10\x00\x00\x00\x3e'
230
        data += b'\x00\x01\x00\x08\x00\x00\x00\x10'
231
        event = KytosEvent(name=event_name,
232
                           content={'source': switch.connection,
233
                                    'new_data': data})
234
        self.napp.handle_raw_in(event)
235
236
        expected = [
237
            'kytos/of_core.v0x04.messages.out.ofpt_hello',
238
            'kytos/of_core.v0x04.messages.out.ofpt_features_request'
239
        ]
240
        for message in expected:
241
            of_event = self.napp.controller.buffers.msg_out.get()
242
            self.assertEqual(of_event.name, message)
243
244
    def test_handle_port_status_raw_in(self):
245
        """Test handling port_status raw in message."""
246
        event_name = 'kytos/core.openflow.raw.in'
247
        switch = get_switch_mock()
248
        switch.connection = get_connection_mock(
249
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"),
250
            ConnectionState.ESTABLISHED)
251
252
        data = b'\x04\x0c\x00\x50\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00'
253
        data += b'\x00\x00\x00\x00\x01\x00\x00\x00\x00\x62\x43\xe5\xdb\x35\x0a'
254
        data += b'\x00\x00\x73\x31\x2d\x65\x74\x68\x31\x00\x00\x00\x00\x00\x00'
255
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x08\x40'
256
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x96'
257
        data += b'\x80\x00\x00\x00\x00'
258
259
        event = KytosEvent(name=event_name,
260
                           content={'source': switch.connection,
261
                                    'new_data': data})
262
        self.napp.handle_raw_in(event)
263
        of_event = self.napp.controller.buffers.msg_in.get()
264
        self.assertEqual(of_event.name,
265
                         'kytos/of_core.v0x04.messages.in.ofpt_port_status')
266
267
    def test_handle_packet_in_raw_in(self):
268
        """Test handling packet_in raw in message."""
269
        event_name = 'kytos/core.openflow.raw.in'
270
        switch = get_switch_mock()
271
        switch.connection = get_connection_mock(
272
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"),
273
            ConnectionState.ESTABLISHED)
274
275
        data = b'\x04\x0a\x00\x94\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x01'
276
        data += b'\x01\x00\x01\x02\x03\x00\x00\x00\x00\x00\x01\x00\x50\x80\x00'
277
        data += b'\x00\x04\x00\x00\x00\x06\x80\x00\x0a\x02\x08\x06\x80\x00\x06'
278
        data += b'\x06\xff\xff\xff\xff\xff\xff\x80\x00\x08\x06\xf2\x0b\xa4\x7d'
279
        data += b'\xf8\xea\x80\x00\x2a\x02\x00\x01\x80\x00\x2c\x04\x0a\x00\x00'
280
        data += b'\x01\x80\x00\x2e\x04\x0a\x00\x00\x03\x80\x00\x30\x06\xf2\x0b'
281
        data += b'\xa4\x7d\xf8\xea\x80\x00\x32\x06\x00\x00\x00\x00\x00\x00\x00'
282
        data += b'\x00\xff\xff\xff\xff\xff\xff\xf2\x0b\xa4\x7d\xf8\xea\x08\x06'
283
        data += b'\x00\x01\x08\x00\x06\x04\x00\x01\xf2\x0b\xa4\x7d\xf8\xea\x0a'
284
        data += b'\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x03'
285
286
        event = KytosEvent(name=event_name,
287
                           content={'source': switch.connection,
288
                                    'new_data': data})
289
        self.napp.handle_raw_in(event)
290
        of_event = self.napp.controller.buffers.msg_in.get()
291
        self.assertEqual(of_event.name,
292
                         'kytos/of_core.v0x04.messages.in.ofpt_packet_in')
293
294
    def test_handle_multipart_reply(self):
295
        """Test handling ofpt_multipart_reply."""
296
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply'
297
        switch = get_switch_mock("00:00:00:00:00:00:00:02")
298
        switch.connection = get_connection_mock(
299
            0x04, get_switch_mock("00:00:00:00:00:00:00:01"),
300
            ConnectionState.ESTABLISHED)
301
302
        self.napp.controller.get_switch_or_create(switch.dpid,
303
                                                  switch.connection)
304
305
        data = b'\x04\x13\x00\x68\xac\xc8\xdf\x58\x00\x01\x00\x00\x00\x00\x00'
306
        data += b'\x00\x00\x58\x00\x00\x00\x00\x00\x38\x25\xd9\x54\xc0\x03\xe8'
307
        data += b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00'
308
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00'
309
        data += b'\x00\x00\x02\xf4\x00\x01\x00\x10\x80\x00\x0a\x02\x88\xcc\x80'
310
        data += b'\x00\x0c\x02\x1e\xd7\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00'
311
        data += b'\x00\x10\xff\xff\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x00'
312
313
        # pylint: disable=protected-access
314
        xid = self.napp._multipart_replies_xids[switch.dpid]
315
        # pylint: enable=protected-access
316
        multipart_reply = MultipartReply(xid=xid)
317
        multipart_reply.unpack(data[8:])
318
        stats_event = KytosEvent(name=event_name,
319
                                 content={'source': switch.connection,
320
                                          'message': multipart_reply})
321
322
        self.napp.handle_multipart_reply(stats_event)
323
324
        # test ofpmp_desc
325
        data = b'\x04\x12\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
326
        data += b'\x00'
327
        multipart_desc = MultipartReply()
328
        multipart_desc.unpack(data[8:])
329
        stats_desc_event = KytosEvent(name=event_name,
330
                                      content={'source': switch.connection,
331
                                               'message': multipart_desc})
332
333
        target_switch = switch.connection.switch
334
        self.napp.handle_multipart_reply(stats_desc_event)
335
        # pylint: disable=protected-access
336
        self.assertNotIn(xid, self.napp._multipart_replies_xids)
337
        # pylint: enable=protected-access
338
        self.assertGreater(len(target_switch.flows), 0)
339
        self.assertEqual(multipart_desc.body.mfr_desc.value,
340
                         target_switch.description["manufacturer"])
341
        self.assertEqual(multipart_desc.body.hw_desc.value,
342
                         target_switch.description["hardware"])
343
        self.assertEqual(multipart_desc.body.sw_desc.value,
344
                         target_switch.description["software"])
345
        self.assertEqual(multipart_desc.body.serial_num.value,
346
                         target_switch.description["serial"])
347
        self.assertEqual(multipart_desc.body.dp_desc.value,
348
                         target_switch.description["data_path"])
349
350
    def test_handle_port_desc_multipart_reply(self):
351
        """Test handling to ofpt_PORT_DESC."""
352
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply'
353
        switch = get_switch_mock()
354
        switch.connection = get_connection_mock(
355
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"))
356
357
        data = b'\x04\x13\x00\x90\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x00\x00'
358
        data += b'\x00\x00\x00\x00\x07\x00\x00\x00\x00\xf2\x0b\xa4\xd0\x3f\x70'
359
        data += b'\x00\x00\x50\x6f\x72\x74\x37\x00\x00\x00\x00\x00\x00\x00\x00'
360
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x28\x08'
361
        data += b'\x00\x00\x28\x00\x00\x00\x28\x08\x00\x00\x28\x08\x00\x00\x13'
362
        data += b'\x88\x00\x00\x13\x88\x00\x00\x00\x06\x00\x00\x00\x00\xf2\x0b'
363
        data += b'\xa4\x7d\xf8\xea\x00\x00\x50\x6f\x72\x74\x36\x00\x00\x00\x00'
364
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04'
365
        data += b'\x00\x00\x28\x08\x00\x00\x28\x00\x00\x00\x28\x08\x00\x00\x28'
366
        data += b'\x08\x00\x00\x13\x88\x00\x00\x13\x88'
367
368
        port_desc = MultipartReply()
369
        port_desc.unpack(data[8:])
370
        interface_1 = get_interface_mock("interface1", 6)
371
        interface_2 = get_interface_mock("interface2", 7)
372
        switch.connection.switch.interfaces = {6: interface_1, 7: interface_2}
373
374
        stats_event = KytosEvent(name=event_name,
375
                                 content={'source': switch.connection,
376
                                          'message': port_desc})
377
        self.napp.handle_multipart_reply(stats_event)
378
379
        # Send port_desc pack without interface
380
        switch = get_switch_mock()
381
        switch.connection = get_connection_mock(
382
            0x04, get_switch_mock("00:00:00:00:00:00:00:02"))
383
        stats_event = KytosEvent(name=event_name,
384
                                 content={'source': switch.connection,
385
                                          'message': port_desc})
386
387
        self.napp.handle_multipart_reply(stats_event)
388
389
        expected_event = 'kytos/of_core.switch.port.created'
390
        expected_dpid = '00:00:00:00:00:00:00:02'
391
        for _ in range(0, 2):
392
            of_event_01 = self.napp.controller.buffers.app.get()
393
            of_event_02 = self.napp.controller.buffers.app.get()
394
            self.assertEqual(of_event_01.name, expected_event)
395
            self.assertEqual(of_event_01.content['switch'], expected_dpid)
396
            self.assertEqual(of_event_01.content['port'], 7)
397
            self.assertEqual(of_event_02.name, expected_event)
398
            self.assertEqual(of_event_02.content['switch'], expected_dpid)
399
            self.assertEqual(of_event_02.content['port'], 6)
400
401
    def test_pack_generic_hello(self):
402
        """Test packing a generic hello message."""
403
        data = b'\x04\x00\x00\x10\x00\x00\x00\x3e'
404
        data += b'\x00\x01\x00\x08\x00\x00\x00\x10'
405
        generic_hello = GenericHello(packet=data, versions=b'\x04')
406
        self.assertEqual(generic_hello.pack(), data)
407