Passed
Push — master ( 75d007...4d9626 )
by Humberto
01:10 queued 12s
created

build.tests.integration.test_main   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 384
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 304
dl 0
loc 384
rs 10
c 0
b 0
f 0
wmc 20

14 Methods

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