Passed
Pull Request — master (#62)
by Gleyberson
02:59
created

build.tests.test_main.TestMain.setUp()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
"""Test main."""
2
3
from unittest import TestCase
4
from unittest.mock import Mock
5
6
from pyof.utils import unpack
7
from pyof.v0x01.controller2switch.features_reply import \
8
    FeaturesReply as FReply_v0x01
9
from pyof.v0x01.controller2switch.stats_reply import StatsReply
10
from pyof.v0x04.controller2switch.features_reply import \
11
    FeaturesReply as FReply_v0x04
12
from pyof.v0x04.controller2switch.features_request import FeaturesRequest
13
from pyof.v0x04.controller2switch.multipart_reply import MultipartReply
14
from pyof.v0x04.symmetric.echo_request import EchoRequest
15
16
from kytos.core import Controller
17
from kytos.core.config import KytosConfig
18
from kytos.core.connection import Connection, ConnectionState
19
from kytos.core.events import KytosEvent
20
from kytos.core.interface import Interface
21
from kytos.core.switch import Switch
22
from napps.kytos.of_core.main import Main
23
from napps.kytos.of_core.utils import GenericHello
24
25
26
class TestMain(TestCase):
27
    """docstring for TestMain."""
28
29
    def setUp(self):
30
        """Execute steps before each tests.
31
32
        Set the server_name_url from kytos/of_core
33
        """
34
        self.server_name_url = 'http://localhost:8181/api/kytos/of_core'
35
        self.controller = self._get_controller_mock()
36
        self.napp = Main(self.controller)
37
        self.patched_events = []
38
39
    @staticmethod
40
    def _get_controller_mock():
41
        """Return a controller mock."""
42
        options = KytosConfig().options['daemon']
43
        controller = Controller(options)
44
        controller.log = Mock()
45
        return controller
46
47
    @staticmethod
48
    def _get_switch_mock(of_version, connection_state=ConnectionState.NEW,
49
                         dpid="00:00:00:00:00:00:00:01"):
50
        """Return a switch mock."""
51
        switch = Switch(dpid)
52
        address = Mock()
53
        port = Mock()
54
        socket = Mock()
55
        switch.connection = Connection(address, port, socket)
56
        switch.connection.protocol.unpack = unpack
57
        switch.connection.protocol.version = of_version
58
        switch.connection.state = connection_state
59
        return switch
60
61
    def _get_interface(self, interface_name, port, *args, **kwargs):
62
        """Return a interface mock."""
63
        switch1 = self._get_switch_mock(0x04)
64
        switch1.connection = Mock()
65
        iface1 = Interface(interface_name, port, switch1, *args, **kwargs)
66
        return iface1
67
68
    def test_get_event_listeners(self):
69
        """Verify all event listeners registered."""
70
        expected_events = [
71
            'kytos/of_core.v0x01.messages.in.ofpt_stats_reply',
72
            'kytos/of_core.v0x0[14].messages.in.ofpt_features_reply',
73
            'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply',
74
            'kytos/core.openflow.raw.in',
75
            'kytos/of_core.v0x0[14].messages.in.ofpt_echo_request',
76
            'kytos/of_core.v0x0[14].messages.out.ofpt_echo_reply',
77
            'kytos/of_core.v0x[0-9a-f]{2}.messages.in.hello_failed',
78
            'kytos/of_core.v0x0[14].messages.out.hello_failed',
79
        ]
80
81
        actual_events = self.napp.listeners()
82
        for _event in expected_events:
83
            self.assertIn(_event, actual_events, '%s' % _event)
84
85
    def test_execute(self):
86
        """Test 'execute' main method."""
87
        dpid_01 = "00:00:00:00:00:00:00:01"
88
        sw_01 = self._get_switch_mock(0x01, ConnectionState.ESTABLISHED,
89
                                      dpid_01)
90
        self.napp.controller.get_switch_or_create(dpid_01, sw_01.connection)
91
        dpid_02 = "00:00:00:00:00:00:00:02"
92
        sw_04 = self._get_switch_mock(0x04, ConnectionState.ESTABLISHED,
93
                                      dpid_02)
94
        self.napp.controller.get_switch_or_create(dpid_02, sw_04.connection)
95
        self.napp.execute()
96
97
    def test_handle_stats_reply(self):
98
        """Test handling stats reply message."""
99
        event_name = 'kytos/of_core.v0x01.messages.in.ofpt_stats_reply'
100
        switch = self._get_switch_mock(0x01)
101
        switch.connection = Mock()
102
103
        stats_data = b'\x01\x11\x00\x0c\x00\x00\x00\x01\x00\x01\x00\x01'
104
        stats_reply = StatsReply()
105
        stats_reply.unpack(stats_data[8:])
106
        stats_event = KytosEvent(name=event_name,
107
                                 content={'source': switch.connection,
108
                                          'message': stats_reply})
109
        self.napp.handle_stats_reply(stats_event)
110
111
        desc_stats_data = b'\x01\x11\x00\x0c\x00\x00\x00\x0e\x00\x00\x00\x00'
112
        desc_stats_reply = StatsReply()
113
        desc_stats_reply.unpack(desc_stats_data[8:])
114
        desc_stats_event = KytosEvent(name=event_name,
115
                                      content={'source': switch.connection,
116
                                               'message': desc_stats_reply})
117
        self.napp.handle_stats_reply(desc_stats_event)
118
119
    def test_handle_04_features_reply(self):
120
        """Test handling features reply message."""
121
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_features_reply'
122
        switch = self._get_switch_mock(0x04, ConnectionState.SETUP)
123
        switch.connection.protocol.state = 'waiting_features_reply'
124
125
        data = b'\x04\x06\x00\x20\x00\x00\x00\x00\x00\x00\x08\x60\x6e\x7f\x74'
126
        data += b'\xe7\x00\x00\x00\x00\xff\x63\x00\x00\x00\x00\x00\x4f\x00\x00'
127
        data += b'\x00\x00'
128
129
        features_reply = FReply_v0x04()
130
        features_reply.unpack(data)
131
132
        event = KytosEvent(name=event_name,
133
                           content={'source': switch.connection,
134
                                    'message': features_reply})
135
        self.napp.handle_features_reply(event)
136
137
    def test_handle_01_features_reply(self):
138
        """Test handling features reply message."""
139
        event_name = 'kytos/of_core.v0x01.messages.in.ofpt_features_reply'
140
        switch = self._get_switch_mock(0x01, ConnectionState.SETUP)
141
        switch.connection.protocol.state = 'waiting_features_reply'
142
143
        data = b'\x01\x06\x00\x80\x00\x00\x00\x00\x00\x00\x00\xff\x12\x34\x56'
144
        data += b'\x78\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\xa9\x00\x00'
145
        data += b'\x08\x43\x00\x07\xf2\x0b\xa4\xd0\x3f\x70\x50\x6f\x72\x74\x37'
146
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
147
        data += b'\x00\x00\x00\x10\x00\x00\x02\x88\x00\x00\x02\x80\x00\x00\x02'
148
        data += b'\x88\x00\x00\x02\x88\x00\x06\xf2\x0b\xa4\x7d\xf8\xea\x50\x6f'
149
        data += b'\x72\x74\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
150
        data += b'\x00\x00\x00\x00\x00\x00\x02\x00\x00\x02\x88\x00\x00\x02\x80'
151
        data += b'\x00\x00\x02\x88\x00\x00\x02\x88'
152
153
        features_reply = FReply_v0x01()
154
        features_reply.unpack(data[8:])
155
156
        event = KytosEvent(name=event_name,
157
                           content={'source': switch.connection,
158
                                    'message': features_reply})
159
        self.napp.handle_features_reply(event)
160
161
    def test_handle_features_request_sent(self):
162
        """Test handling features request sent message."""
163
        event_name = 'kytos/of_core.v0x01.messages.out.ofpt_features_request'
164
        switch = self._get_switch_mock(0x01)
165
        switch.connection.protocol.state = 'sending_features'
166
167
        data = b'\x04\x05\x00\x08\x00\x00\x00\x03'
168
        features_request = FeaturesRequest()
169
        features_request.unpack(data)
170
171
        event = KytosEvent(name=event_name,
172
                           content={'destination': switch.connection,
173
                                    'message': features_request})
174
        self.napp.handle_features_request_sent(event)
175
176
    def test_handle_echo_request(self):
177
        """Test handling echo request message."""
178
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_echo_request'
179
        switch = self._get_switch_mock(0x04)
180
181
        data = b'\x04\x02\x00\x0c\x00\x00\x00\x00\x68\x6f\x67\x65'
182
        echo_request = EchoRequest()
183
        echo_request.unpack(data)
184
185
        event = KytosEvent(name=event_name,
186
                           content={'source': switch.connection,
187
                                    'message': echo_request})
188
        self.napp.handle_echo_request(event)
189
190
    def test_handle_hello_raw_in(self):
191
        """Test handling hello raw in message."""
192
        event_name = 'kytos/core.openflow.raw.in'
193
        switch = self._get_switch_mock(0x04)
194
195
        data = b'\x04\x00\x00\x10\x00\x00\x00\x3e'
196
        data += b'\x00\x01\x00\x08\x00\x00\x00\x10'
197
        event = KytosEvent(name=event_name,
198
                           content={'source': switch.connection,
199
                                    'new_data': data})
200
        self.napp.handle_raw_in(event)
201
202
        data_exc = b'\x00\x00\x00\x08\xb8\xd1\xb1\x0c'
203
        event = KytosEvent(name=event_name,
204
                           content={'source': switch.connection,
205
                                    'new_data': data_exc})
206
        self.napp.handle_raw_in(event)
207
208
    def test_handle_port_status_raw_in(self):
209
        """Test handling port_status raw in message."""
210
        event_name = 'kytos/core.openflow.raw.in'
211
        switch = self._get_switch_mock(0x04, ConnectionState.ESTABLISHED)
212
        switch.connection.switch = self._get_switch_mock(0x04)
213
214
        data = b'\x04\x0c\x00\x50\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00'
215
        data += b'\x00\x00\x00\x00\x01\x00\x00\x00\x00\x62\x43\xe5\xdb\x35\x0a'
216
        data += b'\x00\x00\x73\x31\x2d\x65\x74\x68\x31\x00\x00\x00\x00\x00\x00'
217
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x08\x40'
218
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x98\x96'
219
        data += b'\x80\x00\x00\x00\x00'
220
221
        event = KytosEvent(name=event_name,
222
                           content={'source': switch.connection,
223
                                    'new_data': data})
224
        self.napp.handle_raw_in(event)
225
226
    def test_handle_packet_in_raw_in(self):
227
        """Test handling packet_in raw in message."""
228
        event_name = 'kytos/core.openflow.raw.in'
229
        switch = self._get_switch_mock(0x04, ConnectionState.ESTABLISHED)
230
        switch.connection.switch = self._get_switch_mock(0x04)
231
232
        data = b'\x04\x0a\x00\x94\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x01'
233
        data += b'\x01\x00\x01\x02\x03\x00\x00\x00\x00\x00\x01\x00\x50\x80\x00'
234
        data += b'\x00\x04\x00\x00\x00\x06\x80\x00\x0a\x02\x08\x06\x80\x00\x06'
235
        data += b'\x06\xff\xff\xff\xff\xff\xff\x80\x00\x08\x06\xf2\x0b\xa4\x7d'
236
        data += b'\xf8\xea\x80\x00\x2a\x02\x00\x01\x80\x00\x2c\x04\x0a\x00\x00'
237
        data += b'\x01\x80\x00\x2e\x04\x0a\x00\x00\x03\x80\x00\x30\x06\xf2\x0b'
238
        data += b'\xa4\x7d\xf8\xea\x80\x00\x32\x06\x00\x00\x00\x00\x00\x00\x00'
239
        data += b'\x00\xff\xff\xff\xff\xff\xff\xf2\x0b\xa4\x7d\xf8\xea\x08\x06'
240
        data += b'\x00\x01\x08\x00\x06\x04\x00\x01\xf2\x0b\xa4\x7d\xf8\xea\x0a'
241
        data += b'\x00\x00\x01\x00\x00\x00\x00\x00\x00\x0a\x00\x00\x03'
242
243
        event = KytosEvent(name=event_name,
244
                           content={'source': switch.connection,
245
                                    'new_data': data})
246
        self.napp.handle_raw_in(event)
247
248
    def test_handle_multipart_reply(self):
249
        """Test handling ofpt_multipart_reply."""
250
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply'
251
        switch = self._get_switch_mock(0x04, dpid='00:00:00:00:00:00:00:02')
252
        switch.connection.switch = self._get_switch_mock(0x04)
253
        self.napp.controller.get_switch_or_create(switch.dpid,
254
                                                  switch.connection)
255
256
        data = b'\x04\x13\x00\x68\xac\xc8\xdf\x58\x00\x01\x00\x00\x00\x00\x00'
257
        data += b'\x00\x00\x58\x00\x00\x00\x00\x00\x38\x25\xd9\x54\xc0\x03\xe8'
258
        data += b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00'
259
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12\x00\x00\x00\x00'
260
        data += b'\x00\x00\x02\xf4\x00\x01\x00\x10\x80\x00\x0a\x02\x88\xcc\x80'
261
        data += b'\x00\x0c\x02\x1e\xd7\x00\x04\x00\x18\x00\x00\x00\x00\x00\x00'
262
        data += b'\x00\x10\xff\xff\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x00'
263
264
        # pylint: disable=protected-access
265
        xid = self.napp._multipart_replies_xids[switch.dpid]
266
        # pylint: enable=protected-access
267
        multipart_reply = MultipartReply(xid=xid)
268
        multipart_reply.unpack(data[8:])
269
        stats_event = KytosEvent(name=event_name,
270
                                 content={'source': switch.connection,
271
                                          'message': multipart_reply})
272
273
        self.napp.handle_multipart_reply(stats_event)
274
275
        # test ofpmp_desc
276
        data = b'\x04\x12\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
277
        data += b'\x00'
278
        multipart_desc = MultipartReply()
279
        multipart_desc.unpack(data[8:])
280
        stats_desc_event = KytosEvent(name=event_name,
281
                                      content={'source': switch.connection,
282
                                               'message': multipart_desc})
283
284
        self.napp.handle_multipart_reply(stats_desc_event)
285
286
    def test_handle_port_desc_multipart_reply(self):
287
        """Test handling to ofpt_PORT_DESC."""
288
        event_name = 'kytos/of_core.v0x04.messages.in.ofpt_multipart_reply'
289
        switch = self._get_switch_mock(0x04)
290
        switch.connection.switch = self._get_switch_mock(0x04)
291
        data = b'\x04\x13\x00\x90\x00\x00\x00\x00\x00\x0d\x00\x00\x00\x00\x00'
292
        data += b'\x00\x00\x00\x00\x07\x00\x00\x00\x00\xf2\x0b\xa4\xd0\x3f\x70'
293
        data += b'\x00\x00\x50\x6f\x72\x74\x37\x00\x00\x00\x00\x00\x00\x00\x00'
294
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x28\x08'
295
        data += b'\x00\x00\x28\x00\x00\x00\x28\x08\x00\x00\x28\x08\x00\x00\x13'
296
        data += b'\x88\x00\x00\x13\x88\x00\x00\x00\x06\x00\x00\x00\x00\xf2\x0b'
297
        data += b'\xa4\x7d\xf8\xea\x00\x00\x50\x6f\x72\x74\x36\x00\x00\x00\x00'
298
        data += b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04'
299
        data += b'\x00\x00\x28\x08\x00\x00\x28\x00\x00\x00\x28\x08\x00\x00\x28'
300
        data += b'\x08\x00\x00\x13\x88\x00\x00\x13\x88'
301
302
        port_desc = MultipartReply()
303
        port_desc.unpack(data[8:])
304
        interface_1 = self._get_interface("interface1", 6)
305
        interface_2 = self._get_interface("interface2", 7)
306
        switch.connection.switch.interfaces = {6: interface_1, 7: interface_2}
307
308
        stats_event = KytosEvent(name=event_name,
309
                                 content={'source': switch.connection,
310
                                          'message': port_desc})
311
        self.napp.handle_multipart_reply(stats_event)
312
313
        # Send port_desc pack without interface
314
        switch = self._get_switch_mock(0x04)
315
        switch.connection.switch = self._get_switch_mock(0x04)
316
        stats_event = KytosEvent(name=event_name,
317
                                 content={'source': switch.connection,
318
                                          'message': port_desc})
319
320
        self.napp.handle_multipart_reply(stats_event)
321
322
    def test_pack_generic_hello(self):
323
        """Test packing a generic hello message."""
324
        data = b'\x04\x00\x00\x10\x00\x00\x00\x3e'
325
        data += b'\x00\x01\x00\x08\x00\x00\x00\x10'
326
        generic_hello = GenericHello(packet=data, versions=b'\x04')
327
        self.assertEqual(generic_hello.pack(), data)
328