Passed
Push — master ( 5db727...2bc5c8 )
by Humberto
01:20 queued 11s
created

build.tests.integration.test_main   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 220
dl 0
loc 282
rs 10
c 0
b 0
f 0
wmc 17

13 Methods

Rating   Name   Duplication   Size   Complexity  
A TestMain.init_napp() 0 11 2
B TestMain.test_verify_api_urls() 0 41 1
A FakeBox.__init__() 0 8 1
A TestMain.test_handle_new_switch() 0 10 1
A TestMain.test_handle_connection_lost() 0 10 1
A TestMain.test_save_metadata_on_store() 0 10 1
A TestMain.setUp() 0 7 1
A TestMain.test_handle_interface_created() 0 10 1
A TestMain.get_app_test_client() 0 5 1
A TestMain.get_napp_urls() 0 24 4
A TestMain.test_get_switches_dict() 0 6 1
A TestMain.test_get_event_listeners() 0 15 1
A TestMain.test_handle_interface_deleted() 0 10 1
1
"""Module to test the main napp file."""
2
from unittest import TestCase
3
from unittest.mock import Mock, patch
4
5
from kytos.core.events import KytosEvent
6
from tests.integration.helpers import (get_controller_mock, get_interface_mock,
7
                                       get_switch_mock)
8
9
LINK_DATA = {
10
    "active": False,
11
    "enabled": True,
12
    "endpoint_a": {
13
        "id": "00:00:00:00:00:00:00:01:1",
14
        "link": "26927949-df3c-4c25-874b-3da30d8ae983",
15
        "mac": "26:fb:42:20:b8:b1",
16
        "name": "s1-eth1",
17
        "nni": False,
18
        "port_number": 1,
19
        "speed": "10 Gbps",
20
        "switch": "00:00:00:00:00:00:00:01",
21
        "type": "interface",
22
        "uni": True
23
    },
24
    "endpoint_b": {
25
        "id": "00:00:00:00:00:00:00:01:1",
26
        "link": "26927949-df3c-4c25-874b-3da30d8ae983",
27
        "mac": "26:fb:42:20:b8:b1",
28
        "name": "s1-eth1",
29
        "nni": False,
30
        "port_number": 1,
31
        "speed": "10 Gbps",
32
        "switch": "00:00:00:00:00:00:00:01",
33
        "type": "interface",
34
        "uni": True
35
    }
36
}
37
38
SWITCH_DATA = {
39
    "id": "00:00:00:00:00:00:00:01",
40
    "name": "my-beautiful-switch",
41
    "serial": "string",
42
    "software": "Version 2.3.4",
43
    "ofp_version": "0x01",
44
    "connection": "127.0.0.1:49330",
45
    "data_path": "string",
46
    "manufacturer": "Unkown Manufactor",
47
    "hardware": "Hardware version 2.0",
48
    "type": "switch",
49
    "active": True,
50
    "enabled": False,
51
    "dpid": "00:00:00:00:00:00:00:01",
52
    "metadata": {},
53
    "interfaces": {
54
        "additionalProp1": {
55
            "id": "00:00:00:00:00:00:00:01:1",
56
            "link": "26927949-df3c-4c25-874b-3da30d8ae983",
57
            "mac": "26:fb:42:20:b8:b1",
58
            "name": "s1-eth1",
59
            "nni": False,
60
            "port_number": 1,
61
            "speed": "10 Gbps",
62
            "switch": "00:00:00:00:00:00:00:01",
63
            "type": "interface",
64
            "uni": True
65
        },
66
        "additionalProp2": {
67
            "id": "00:00:00:00:00:00:00:01:1",
68
            "link": "26927949-df3c-4c25-874b-3da30d8ae983",
69
            "mac": "26:fb:42:20:b8:b1",
70
            "name": "s1-eth1",
71
            "nni": False,
72
            "port_number": 1,
73
            "speed": "10 Gbps",
74
            "switch": "00:00:00:00:00:00:00:01",
75
            "type": "interface",
76
            "uni": True
77
        },
78
        "additionalProp3": {
79
            "id": "00:00:00:00:00:00:00:01:1",
80
            "link": "26927949-df3c-4c25-874b-3da30d8ae983",
81
            "mac": "26:fb:42:20:b8:b1",
82
            "name": "s1-eth1",
83
            "nni": False,
84
            "port_number": 1,
85
            "speed": "10 Gbps",
86
            "switch": "00:00:00:00:00:00:00:01",
87
            "type": "interface",
88
            "uni": True
89
        }
90
    }
91
}
92
93
94
class FakeBox:
95
    """Simulate a Storehouse Box."""
96
97
    def __init__(self, data):
98
        """Initizalize default values to FakeBox."""
99
        self.data = data
100
        self.namespace = None
101
        self.name = None
102
        self.box_id = None
103
        self.created_at = None
104
        self.owner = None
105
106
107
# pylint: disable=bad-option-value
108
class TestMain(TestCase):
109
    """Test the Main class."""
110
111
    def setUp(self):
112
        """Execute steps before each tests.
113
114
        Set the server_name_url from kytos/topology
115
        """
116
        self.server_name_url = 'http://localhost:8181/api/kytos/topology'
117
        self.init_napp()
118
119
    @patch('napps.kytos.topology.main.Main.verify_storehouse')
120
    def init_napp(self, mock_verify_storehouse=None):
121
        """Initialize a Topology NApp instance."""
122
        mock_verify_storehouse.return_value = None
123
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
124
        from napps.kytos.topology.main import Main
125
        self.addCleanup(patch.stopall)
126
        self.napp = Main(get_controller_mock())
127
        self.napp.store_items = {
128
            "links": FakeBox(LINK_DATA),
129
            "switches": FakeBox(SWITCH_DATA)
130
        }
131
132
    def test_get_switches_dict(self):
133
        """Basic test for switch listing."""
134
        # pylint: disable=protected-access
135
        switches = self.napp._get_switches_dict()
136
        assert isinstance(switches['switches'], dict)
137
        assert switches['switches'] == {}
138
139
    def test_get_event_listeners(self):
140
        """Verify all event listeners registered."""
141
        expected_events = ['kytos/core.shutdown',
142
                           'kytos/core.shutdown.kytos/topology',
143
                           '.*.interface.is.nni',
144
                           '.*.connection.lost',
145
                           '.*.switch.interface.created',
146
                           '.*.switch.interface.deleted',
147
                           '.*.switch.interface.link_down',
148
                           '.*.switch.interface.link_up',
149
                           '.*.switch.(new|reconnected)',
150
                           '.*.switch.port.created',
151
                           'kytos/topology.*.metadata.*']
152
        actual_events = self.napp.listeners()
153
        self.assertEqual(expected_events, actual_events)
154
155
    def test_verify_api_urls(self):
156
        """Verify all APIs registered."""
157
        expected_urls = [
158
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/interfaces'),
159
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/switches'),
160
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/links'),
161
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/'),
162
         ({'key': '[key]', 'interface_id': '[interface_id]'},
163
          {'OPTIONS', 'DELETE'},
164
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata/<key>'),
165
         ({'interface_id': '[interface_id]'}, {'POST', 'OPTIONS'},
166
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata'),
167
         ({'interface_id': '[interface_id]'}, {'GET', 'OPTIONS', 'HEAD'},
168
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata'),
169
         ({'interface_id': '[interface_id]'}, {'POST', 'OPTIONS'},
170
          '/api/kytos/topology/v3/interfaces/<interface_id>/disable'),
171
         ({'interface_id': '[interface_id]'}, {'POST', 'OPTIONS'},
172
          '/api/kytos/topology/v3/interfaces/<interface_id>/enable'),
173
         ({'dpid': '[dpid]', 'key': '[key]'}, {'OPTIONS', 'DELETE'},
174
          '/api/kytos/topology/v3/switches/<dpid>/metadata/<key>'),
175
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
176
          '/api/kytos/topology/v3/switches/<dpid>/metadata'),
177
         ({'dpid': '[dpid]'}, {'GET', 'OPTIONS', 'HEAD'},
178
          '/api/kytos/topology/v3/switches/<dpid>/metadata'),
179
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
180
          '/api/kytos/topology/v3/switches/<dpid>/disable'),
181
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
182
          '/api/kytos/topology/v3/switches/<dpid>/enable'),
183
         ({'link_id': '[link_id]', 'key': '[key]'}, {'OPTIONS', 'DELETE'},
184
          '/api/kytos/topology/v3/links/<link_id>/metadata/<key>'),
185
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
186
          '/api/kytos/topology/v3/links/<link_id>/metadata'),
187
         ({'link_id': '[link_id]'}, {'GET', 'OPTIONS', 'HEAD'},
188
          '/api/kytos/topology/v3/links/<link_id>/metadata'),
189
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
190
          '/api/kytos/topology/v3/links/<link_id>/disable'),
191
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
192
          '/api/kytos/topology/v3/links/<link_id>/enable')]
193
194
        urls = self.get_napp_urls(self.napp)
195
        self.assertEqual(expected_urls, urls)
196
197
    @staticmethod
198
    def get_napp_urls(napp):
199
        """Return the kytos/topology urls.
200
201
        The urls will be like:
202
203
        urls = [
204
            (options, methods, url)
205
        ]
206
207
        """
208
        controller = napp.controller
209
        controller.api_server.register_napp_endpoints(napp)
210
211
        urls = []
212
        for rule in controller.api_server.app.url_map.iter_rules():
213
            options = {}
214
            for arg in rule.arguments:
215
                options[arg] = "[{0}]".format(arg)
216
217
            if f'{napp.username}/{napp.name}' in str(rule):
218
                urls.append((options, rule.methods, f'{str(rule)}'))
219
220
        return urls
221
222
    @staticmethod
223
    def get_app_test_client(napp):
224
        """Return a flask api test client."""
225
        napp.controller.api_server.register_napp_endpoints(napp)
226
        return napp.controller.api_server.app.test_client()
227
228
    def test_save_metadata_on_store(self):
229
        """Test save metadata on store."""
230
        event_name = 'kytos.storehouse.update'
231
        switch = get_switch_mock(0x04)
232
        event = KytosEvent(name=event_name,
233
                           content={'switch': switch})
234
        self.napp.save_metadata_on_store(event)
235
        event_response = self.napp.controller.buffers.app.get()
236
        self.assertEqual(event_response.name,
237
                         'kytos.storehouse.update')
238
239
    def test_handle_new_switch(self):
240
        """Test handle new switch."""
241
        event_name = '.*.switch.(new|reconnected)'
242
        switch = get_switch_mock(0x04)
243
        event = KytosEvent(name=event_name,
244
                           content={'switch': switch})
245
        self.napp.handle_new_switch(event)
246
        event_response = self.napp.controller.buffers.app.get()
247
        self.assertEqual(event_response.name,
248
                         'kytos/topology.updated')
249
250
    def test_handle_interface_created(self):
251
        """Test handle interface created."""
252
        event_name = '.*.switch.interface.created'
253
        interface = get_interface_mock("interface1", 7)
254
        stats_event = KytosEvent(name=event_name,
255
                                 content={'interface': interface})
256
        self.napp.handle_interface_created(stats_event)
257
        event_response = self.napp.controller.buffers.app.get()
258
        self.assertEqual(event_response.name,
259
                         'kytos/topology.updated')
260
261
    def test_handle_interface_deleted(self):
262
        """Test handle interface deleted."""
263
        event_name = '.*.switch.interface.deleted'
264
        interface = get_interface_mock("interface1", 7)
265
        stats_event = KytosEvent(name=event_name,
266
                                 content={'interface': interface})
267
        self.napp.handle_interface_deleted(stats_event)
268
        event_response = self.napp.controller.buffers.app.get()
269
        self.assertEqual(event_response.name,
270
                         'kytos/topology.updated')
271
272
    def test_handle_connection_lost(self):
273
        """Test handle connection lost."""
274
        event_name = '.*.connection.lost'
275
        source = Mock()
276
        stats_event = KytosEvent(name=event_name,
277
                                 content={'source': source})
278
        self.napp.handle_connection_lost(stats_event)
279
        event_response = self.napp.controller.buffers.app.get()
280
        self.assertEqual(event_response.name,
281
                         'kytos/topology.updated')
282