Passed
Pull Request — master (#121)
by
unknown
02:10
created

build.tests.unit.test_main   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 966
Duplicated Lines 22.98 %

Importance

Changes 0
Metric Value
eloc 760
dl 222
loc 966
rs 8.7199
c 0
b 0
f 0
wmc 44

43 Methods

Rating   Name   Duplication   Size   Complexity  
B TestMain.test_verify_api_urls() 48 48 1
A TestMain.test_get_event_listeners() 0 19 1
A TestMain.setUp() 0 12 2
A TestMain.test_handle_new_switch() 0 11 1
A TestMain.test_handle_switch_maintenance_start() 22 22 1
A TestMain.test_save_metadata_on_store() 0 29 1
A TestMain.test_notify_port_created() 0 9 1
A TestMain.test_disable_switch() 21 21 1
A TestMain.test_disable_link() 0 17 1
A TestMain.test_add_switch_metadata() 0 21 1
A TestMain.test_notify_topology_update() 0 8 1
A TestMain.test_get_switch_metadata() 0 17 1
A TestMain.test_get_link_from_interface() 0 14 1
A TestMain.test_add_links() 0 9 1
B TestMain.test_get_topology() 0 53 1
A TestMain.test_notify_link_status_change() 0 9 1
A TestMain.test_enable_link() 0 17 1
A TestMain.test_verify_storehouse() 0 9 1
A TestMain.test_handle_interface_down() 0 11 1
A TestMain.test_save_status_on_store() 0 8 1
A TestMain.test_interface_link_up() 0 28 1
B TestMain.test_restore_network_status() 0 66 1
A TestMain.test_add_interface_metadata() 0 32 1
A TestMain.test_enable_switch() 21 21 1
A TestMain.test_delete_interface_metadata() 0 39 1
A TestMain.test_handle_interface_up() 0 11 1
A TestMain.test_handle_switch_maintenance_end() 22 22 1
B TestMain.test_enable_interfaces() 44 44 1
A TestMain.test_get_interface_metadata() 0 26 1
A TestMain.test_request_retrieve_entities() 0 16 1
A TestMain.test_delete_switch_metadata() 0 21 1
A TestMain.test_handle_link_maintenance_start() 0 15 1
A TestMain.test_get_link_or_create() 0 16 1
A TestMain.test_interface_deleted() 0 6 1
A TestMain.test_handle_link_maintenance_end() 0 15 1
B TestMain.test_disable_interfaces() 44 44 1
A TestMain.test_add_link_metadata() 0 22 1
A TestMain.test_get_link_metadata() 0 19 1
A TestMain.test_delete_link_metadata() 0 29 1
A TestMain.test_interface_link_down() 0 17 1
A TestMain.test_handle_connection_lost() 0 9 1
A TestMain.test_notify_metadata_changes() 0 13 1
A TestMain.test_handle_interface_created() 0 6 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like build.tests.unit.test_main often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Module to test the main napp file."""
2
import time
3
import json
4
5
from unittest import TestCase
6
from unittest.mock import MagicMock, create_autospec, patch
7
8
from kytos.core.switch import Switch
9
from kytos.core.interface import Interface
10
from kytos.core.link import Link
11
from kytos.lib.helpers import (get_switch_mock, get_interface_mock,
12
                               get_test_client, get_link_mock)
13
14
15
from tests.unit.helpers import get_controller_mock, get_napp_urls
16
17
18
# pylint: disable=too-many-public-methods
19
class TestMain(TestCase):
20
    """Test the Main class."""
21
    # pylint: disable=too-many-public-methods, protected-access
22
23
    def setUp(self):
24
        """Execute steps before each tests.
25
26
        Set the server_name_url_url from kytos/topology
27
        """
28
        self.server_name_url = 'http://localhost:8181/api/kytos/topology'
29
30
        patch('kytos.core.helpers.run_on_thread', lambda x: x).start()
31
        from napps.kytos.topology.main import Main
32
        self.addCleanup(patch.stopall)
33
34
        self.napp = Main(get_controller_mock())
35
36
    def test_get_event_listeners(self):
37
        """Verify all event listeners registered."""
38
        expected_events = ['kytos/core.shutdown',
39
                           'kytos/core.shutdown.kytos/topology',
40
                           'kytos/maintenance.start_link',
41
                           'kytos/maintenance.end_link',
42
                           'kytos/maintenance.start_switch',
43
                           'kytos/maintenance.end_switch',
44
                           '.*.interface.is.nni',
45
                           '.*.connection.lost',
46
                           '.*.switch.interface.created',
47
                           '.*.switch.interface.deleted',
48
                           '.*.switch.interface.link_down',
49
                           '.*.switch.interface.link_up',
50
                           '.*.switch.(new|reconnected)',
51
                           '.*.switch.port.created',
52
                           'kytos/topology.*.metadata.*']
53
        actual_events = self.napp.listeners()
54
        self.assertCountEqual(expected_events, actual_events)
55
56 View Code Duplication
    def test_verify_api_urls(self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
57
        """Verify all APIs registered."""
58
        expected_urls = [
59
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/interfaces'),
60
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/switches'),
61
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/restore'),
62
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/links'),
63
         ({}, {'GET', 'OPTIONS', 'HEAD'}, '/api/kytos/topology/v3/'),
64
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
65
          '/api/kytos/topology/v3/interfaces/switch/<dpid>/disable'),
66
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
67
          '/api/kytos/topology/v3/interfaces/switch/<dpid>/enable'),
68
         ({'key': '[key]', 'interface_id': '[interface_id]'},
69
          {'OPTIONS', 'DELETE'},
70
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata/<key>'),
71
         ({'interface_id': '[interface_id]'}, {'POST', 'OPTIONS'},
72
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata'),
73
         ({'interface_id': '[interface_id]'}, {'GET', 'OPTIONS', 'HEAD'},
74
          '/api/kytos/topology/v3/interfaces/<interface_id>/metadata'),
75
         ({'interface_disable_id': '[interface_disable_id]'},
76
          {'POST', 'OPTIONS'},
77
          '/api/kytos/topology/v3/interfaces/<interface_disable_id>/disable'),
78
         ({'interface_enable_id': '[interface_enable_id]'},
79
          {'POST', 'OPTIONS'},
80
          '/api/kytos/topology/v3/interfaces/<interface_enable_id>/enable'),
81
         ({'dpid': '[dpid]', 'key': '[key]'}, {'OPTIONS', 'DELETE'},
82
          '/api/kytos/topology/v3/switches/<dpid>/metadata/<key>'),
83
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
84
          '/api/kytos/topology/v3/switches/<dpid>/metadata'),
85
         ({'dpid': '[dpid]'}, {'GET', 'OPTIONS', 'HEAD'},
86
          '/api/kytos/topology/v3/switches/<dpid>/metadata'),
87
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
88
          '/api/kytos/topology/v3/switches/<dpid>/disable'),
89
         ({'dpid': '[dpid]'}, {'POST', 'OPTIONS'},
90
          '/api/kytos/topology/v3/switches/<dpid>/enable'),
91
         ({'link_id': '[link_id]', 'key': '[key]'}, {'OPTIONS', 'DELETE'},
92
          '/api/kytos/topology/v3/links/<link_id>/metadata/<key>'),
93
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
94
          '/api/kytos/topology/v3/links/<link_id>/metadata'),
95
         ({'link_id': '[link_id]'}, {'GET', 'OPTIONS', 'HEAD'},
96
          '/api/kytos/topology/v3/links/<link_id>/metadata'),
97
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
98
          '/api/kytos/topology/v3/links/<link_id>/disable'),
99
         ({'link_id': '[link_id]'}, {'POST', 'OPTIONS'},
100
          '/api/kytos/topology/v3/links/<link_id>/enable')]
101
102
        urls = get_napp_urls(self.napp)
103
        self.assertEqual(expected_urls, urls)
104
105
    def test_get_link_or_create(self):
106
        """Test _get_link_or_create."""
107
        dpid_a = "00:00:00:00:00:00:00:01"
108
        dpid_b = "00:00:00:00:00:00:00:02"
109
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
110
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
111
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
112
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
113
        mock_interface_a.id = dpid_a
114
        mock_interface_b.id = dpid_b
115
116
        link = self.napp._get_link_or_create(mock_interface_a,
117
                                             mock_interface_b)
118
        self.assertEqual(link.endpoint_a.id, dpid_a)
119
        self.assertEqual(link.endpoint_b.id, dpid_b)
120
        print(self.napp.links)
121
122
    def test_get_link_from_interface(self):
123
        """Test _get_link_from_interface."""
124
        mock_switch_a = get_switch_mock("00:00:00:00:00:00:00:01", 0x04)
125
        mock_switch_b = get_switch_mock("00:00:00:00:00:00:00:02", 0x04)
126
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
127
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
128
        mock_interface_c = get_interface_mock('s2-eth1', 2, mock_switch_b)
129
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
130
        self.napp.links = {'0e2b5d7bc858b9f38db11b69': mock_link}
131
        response = self.napp._get_link_from_interface(mock_interface_a)
132
        self.assertEqual(response, mock_link)
133
134
        response = self.napp._get_link_from_interface(mock_interface_c)
135
        self.assertEqual(response, None)
136
137
    def test_get_topology(self):
138
        """Test get_topology."""
139
        dpid_a = "00:00:00:00:00:00:00:01"
140
        dpid_b = "00:00:00:00:00:00:00:02"
141
        expected = {
142
                      "topology": {
143
                        "switches": {
144
                          "00:00:00:00:00:00:00:01": {
145
                            "metadata": {
146
                              "lat": "0.0",
147
                              "lng": "-30.0"
148
                            }
149
                          },
150
                          "00:00:00:00:00:00:00:02": {
151
                            "metadata": {
152
                              "lat": "0.0",
153
                              "lng": "-30.0"
154
                            }
155
                          }
156
                        },
157
                        "links": {
158
                          "cf0f4071be4": {
159
                            "id": "cf0f4071be4"
160
                          }
161
                        }
162
                      }
163
                    }
164
165
        mock_switch_a = get_switch_mock(dpid_a, 0x04)
166
        mock_switch_b = get_switch_mock(dpid_b, 0x04)
167
        mock_interface_a = get_interface_mock('s1-eth1', 1, mock_switch_a)
168
        mock_interface_b = get_interface_mock('s2-eth1', 1, mock_switch_b)
169
170
        mock_link = get_link_mock(mock_interface_a, mock_interface_b)
171
        mock_link.id = 'cf0f4071be4'
172
        mock_switch_a.id = dpid_a
173
        mock_switch_a.as_dict.return_value = {'metadata': {'lat': '0.0',
174
                                              'lng': '-30.0'}}
175
        mock_switch_b.id = dpid_b
176
        mock_switch_b.as_dict.return_value = {'metadata': {'lat': '0.0',
177
                                              'lng': '-30.0'}}
178
179
        self.napp.controller.switches = {dpid_a: mock_switch_a,
180
                                         dpid_b: mock_switch_b}
181
182
        self.napp.links = {"cf0f4071be4": mock_link}
183
        mock_link.as_dict.return_value = {"id": "cf0f4071be4"}
184
        api = get_test_client(self.napp.controller, self.napp)
185
186
        url = f'{self.server_name_url}/v3/'
187
        response = api.get(url)
188
        self.assertEqual(response.status_code, 200)
189
        self.assertEqual(json.loads(response.data), expected)
190
191
    @patch('napps.kytos.topology.main.StoreHouse.get_data')
192
    def test_restore_network_status(self, mock_storehouse):
193
        """Test restore_network_status."""
194
        dpid = '00:00:00:00:00:00:00:01'
195
        mock_switch = get_switch_mock(dpid)
196
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
197
        mock_switch.interfaces = {1: mock_interface}
198
        self.napp.controller.switches = {dpid: mock_switch}
199
        status = {
200
            'network_status': {
201
                'id': 'network_status',
202
                'switches': {
203
                    '00:00:00:00:00:00:00:01': {
204
                        'dpid': '00:00:00:00:00:00:00:01',
205
                        'enabled': True,
206
                        'id': '00:00:00:00:00:00:00:01',
207
                        'interfaces': {
208
                            '00:00:00:00:00:00:00:01:1': {
209
                                'enabled': True,
210
                                'id': '00:00:00:00:00:00:00:01:1',
211
                            }
212
                        }
213
                    }
214
                }
215
            }
216
        }
217
        status_disable = {
218
            'network_status': {
219
                'id': 'network_status',
220
                'switches': {
221
                    '00:00:00:00:00:00:00:01': {
222
                        'dpid': '00:00:00:00:00:00:00:01',
223
                        'enabled': False,
224
                        'id': '00:00:00:00:00:00:00:01',
225
                        'interfaces': {
226
                            '00:00:00:00:00:00:00:01:1': {
227
                                'enabled': False,
228
                                'id': '00:00:00:00:00:00:00:01:1',
229
                            }
230
                        }
231
                    }
232
                }
233
            }
234
        }
235
236
        api = get_test_client(self.napp.controller, self.napp)
237
        mock_storehouse.side_effect = [{}, status, status_disable]
238
239
        # fail case
240
        url = f'{self.server_name_url}/v3/restore'
241
        response = api.get(url)
242
        self.assertEqual(response.status_code, 404, response.data)
243
244
        # enable
245
        url = f'{self.server_name_url}/v3/restore'
246
        response = api.get(url)
247
        self.assertEqual(response.status_code, 200, response.data)
248
        self.assertEqual(mock_switch.enable.call_count, 1)
249
        self.assertEqual(mock_interface.enable.call_count, 1)
250
251
        # disable
252
        url = f'{self.server_name_url}/v3/restore'
253
        response = api.get(url)
254
        self.assertEqual(response.status_code, 200, response.data)
255
        self.assertEqual(mock_switch.disable.call_count, 1)
256
        self.assertEqual(mock_interface.disable.call_count, 1)
257
258 View Code Duplication
    @patch('napps.kytos.topology.main.Main.save_status_on_storehouse')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
259
    def test_enable_switch(self, mock_save_status):
260
        """Test enable_switch."""
261
        dpid = "00:00:00:00:00:00:00:01"
262
        mock_switch = get_switch_mock(dpid)
263
        self.napp.controller.switches = {dpid: mock_switch}
264
        api = get_test_client(self.napp.controller, self.napp)
265
266
        url = f'{self.server_name_url}/v3/switches/{dpid}/enable'
267
        response = api.post(url)
268
        self.assertEqual(response.status_code, 201, response.data)
269
        self.assertEqual(mock_switch.enable.call_count, 1)
270
        mock_save_status.assert_called()
271
272
        # fail case
273
        mock_switch.enable.call_count = 0
274
        dpid = "00:00:00:00:00:00:00:02"
275
        url = f'{self.server_name_url}/v3/switches/{dpid}/enable'
276
        response = api.post(url)
277
        self.assertEqual(response.status_code, 404, response.data)
278
        self.assertEqual(mock_switch.enable.call_count, 0)
279
280 View Code Duplication
    @patch('napps.kytos.topology.main.Main.save_status_on_storehouse')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
281
    def test_disable_switch(self, mock_save_status):
282
        """Test disable_switch."""
283
        dpid = "00:00:00:00:00:00:00:01"
284
        mock_switch = get_switch_mock(dpid)
285
        self.napp.controller.switches = {dpid: mock_switch}
286
        api = get_test_client(self.napp.controller, self.napp)
287
288
        url = f'{self.server_name_url}/v3/switches/{dpid}/disable'
289
        response = api.post(url)
290
        self.assertEqual(response.status_code, 201, response.data)
291
        self.assertEqual(mock_switch.disable.call_count, 1)
292
        mock_save_status.assert_called()
293
294
        # fail case
295
        mock_switch.disable.call_count = 0
296
        dpid = "00:00:00:00:00:00:00:02"
297
        url = f'{self.server_name_url}/v3/switches/{dpid}/disable'
298
        response = api.post(url)
299
        self.assertEqual(response.status_code, 404, response.data)
300
        self.assertEqual(mock_switch.disable.call_count, 0)
301
302
    def test_get_switch_metadata(self):
303
        """Test get_switch_metadata."""
304
        dpid = "00:00:00:00:00:00:00:01"
305
        mock_switch = get_switch_mock(dpid)
306
        mock_switch.metadata = "A"
307
        self.napp.controller.switches = {dpid: mock_switch}
308
        api = get_test_client(self.napp.controller, self.napp)
309
310
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata'
311
        response = api.get(url)
312
        self.assertEqual(response.status_code, 200, response.data)
313
314
        # fail case
315
        dpid = "00:00:00:00:00:00:00:02"
316
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata'
317
        response = api.get(url)
318
        self.assertEqual(response.status_code, 404, response.data)
319
320
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
321
    def test_add_switch_metadata(self, mock_metadata_changes):
322
        """Test add_switch_metadata."""
323
        dpid = "00:00:00:00:00:00:00:01"
324
        mock_switch = get_switch_mock(dpid)
325
        self.napp.controller.switches = {dpid: mock_switch}
326
        api = get_test_client(self.napp.controller, self.napp)
327
        payload = {"data": "A"}
328
329
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata'
330
        response = api.post(url, data=json.dumps(payload),
331
                            content_type='application/json')
332
        self.assertEqual(response.status_code, 201, response.data)
333
        mock_metadata_changes.assert_called()
334
335
        # fail case
336
        dpid = "00:00:00:00:00:00:00:02"
337
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata'
338
        response = api.post(url, data=json.dumps(payload),
339
                            content_type='application/json')
340
        self.assertEqual(response.status_code, 404, response.data)
341
342
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
343
    def test_delete_switch_metadata(self, mock_metadata_changes):
344
        """Test delete_switch_metadata."""
345
        dpid = "00:00:00:00:00:00:00:01"
346
        mock_switch = get_switch_mock(dpid)
347
        self.napp.controller.switches = {dpid: mock_switch}
348
        api = get_test_client(self.napp.controller, self.napp)
349
350
        key = "A"
351
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata/{key}'
352
        response = api.delete(url)
353
        mock_metadata_changes.assert_called()
354
        self.assertEqual(response.status_code, 200, response.data)
355
356
        # fail case
357
        key = "A"
358
        dpid = "00:00:00:00:00:00:00:02"
359
        url = f'{self.server_name_url}/v3/switches/{dpid}/metadata/{key}'
360
        response = api.delete(url)
361
        mock_metadata_changes.assert_called()
362
        self.assertEqual(response.status_code, 404, response.data)
363
364 View Code Duplication
    @patch('napps.kytos.topology.main.Main.save_status_on_storehouse')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
365
    def test_enable_interfaces(self, mock_save_status):
366
        """Test enable_interfaces."""
367
        dpid = '00:00:00:00:00:00:00:01'
368
        mock_switch = get_switch_mock(dpid)
369
        mock_interface_1 = get_interface_mock('s1-eth1', 1, mock_switch)
370
        mock_interface_2 = get_interface_mock('s1-eth2', 2, mock_switch)
371
        mock_switch.interfaces = {1: mock_interface_1, 2: mock_interface_2}
372
        self.napp.controller.switches = {dpid: mock_switch}
373
        api = get_test_client(self.napp.controller, self.napp)
374
375
        interface_id = '00:00:00:00:00:00:00:01:1'
376
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/enable'
377
        response = api.post(url)
378
        self.assertEqual(response.status_code, 200, response.data)
379
        self.assertEqual(mock_interface_1.enable.call_count, 1)
380
        self.assertEqual(mock_interface_2.enable.call_count, 0)
381
        mock_save_status.assert_called()
382
383
        mock_interface_1.enable.call_count = 0
384
        mock_interface_2.enable.call_count = 0
385
        url = f'{self.server_name_url}/v3/interfaces/switch/{dpid}/enable'
386
        response = api.post(url)
387
        self.assertEqual(response.status_code, 200, response.data)
388
        self.assertEqual(mock_interface_1.enable.call_count, 1)
389
        self.assertEqual(mock_interface_2.enable.call_count, 1)
390
391
        # test interface not found
392
        interface_id = '00:00:00:00:00:00:00:01:3'
393
        mock_interface_1.enable.call_count = 0
394
        mock_interface_2.enable.call_count = 0
395
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/enable'
396
        response = api.post(url)
397
        self.assertEqual(response.status_code, 409, response.data)
398
        self.assertEqual(mock_interface_1.enable.call_count, 0)
399
        self.assertEqual(mock_interface_2.enable.call_count, 0)
400
401
        # test switch not found
402
        dpid = '00:00:00:00:00:00:00:02'
403
        url = f'{self.server_name_url}/v3/interfaces/switch/{dpid}/enable'
404
        response = api.post(url)
405
        self.assertEqual(response.status_code, 404, response.data)
406
        self.assertEqual(mock_interface_1.enable.call_count, 0)
407
        self.assertEqual(mock_interface_2.enable.call_count, 0)
408
409 View Code Duplication
    @patch('napps.kytos.topology.main.Main.save_status_on_storehouse')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
410
    def test_disable_interfaces(self, mock_save_status):
411
        """Test disable_interfaces."""
412
        interface_id = '00:00:00:00:00:00:00:01:1'
413
        dpid = '00:00:00:00:00:00:00:01'
414
        mock_switch = get_switch_mock(dpid)
415
        mock_interface_1 = get_interface_mock('s1-eth1', 1, mock_switch)
416
        mock_interface_2 = get_interface_mock('s1-eth2', 2, mock_switch)
417
        mock_switch.interfaces = {1: mock_interface_1, 2: mock_interface_2}
418
        self.napp.controller.switches = {dpid: mock_switch}
419
        api = get_test_client(self.napp.controller, self.napp)
420
421
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/disable'
422
        response = api.post(url)
423
        self.assertEqual(response.status_code, 200, response.data)
424
        self.assertEqual(mock_interface_1.disable.call_count, 1)
425
        self.assertEqual(mock_interface_2.disable.call_count, 0)
426
        mock_save_status.assert_called()
427
428
        mock_interface_1.disable.call_count = 0
429
        mock_interface_2.disable.call_count = 0
430
        url = f'{self.server_name_url}/v3/interfaces/switch/{dpid}/disable'
431
        response = api.post(url)
432
        self.assertEqual(response.status_code, 200, response.data)
433
        self.assertEqual(mock_interface_1.disable.call_count, 1)
434
        self.assertEqual(mock_interface_2.disable.call_count, 1)
435
436
        # test interface not found
437
        interface_id = '00:00:00:00:00:00:00:01:3'
438
        mock_interface_1.disable.call_count = 0
439
        mock_interface_2.disable.call_count = 0
440
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/disable'
441
        response = api.post(url)
442
        self.assertEqual(response.status_code, 409, response.data)
443
        self.assertEqual(mock_interface_1.disable.call_count, 0)
444
        self.assertEqual(mock_interface_2.disable.call_count, 0)
445
446
        # test switch not found
447
        dpid = '00:00:00:00:00:00:00:02'
448
        url = f'{self.server_name_url}/v3/interfaces/switch/{dpid}/disable'
449
        response = api.post(url)
450
        self.assertEqual(response.status_code, 404, response.data)
451
        self.assertEqual(mock_interface_1.disable.call_count, 0)
452
        self.assertEqual(mock_interface_2.disable.call_count, 0)
453
454
    def test_get_interface_metadata(self):
455
        """Test get_interface_metada."""
456
        interface_id = '00:00:00:00:00:00:00:01:1'
457
        dpid = '00:00:00:00:00:00:00:01'
458
        mock_switch = get_switch_mock(dpid)
459
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
460
        mock_interface.metadata = {"metada": "A"}
461
        mock_switch.interfaces = {1: mock_interface}
462
        self.napp.controller.switches = {dpid: mock_switch}
463
        api = get_test_client(self.napp.controller, self.napp)
464
465
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
466
        response = api.get(url)
467
        self.assertEqual(response.status_code, 200, response.data)
468
469
        # fail case switch not found
470
        interface_id = '00:00:00:00:00:00:00:02:1'
471
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
472
        response = api.get(url)
473
        self.assertEqual(response.status_code, 404, response.data)
474
475
        # fail case interface not found
476
        interface_id = '00:00:00:00:00:00:00:01:2'
477
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
478
        response = api.get(url)
479
        self.assertEqual(response.status_code, 404, response.data)
480
481
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
482
    def test_add_interface_metadata(self, mock_metadata_changes):
483
        """Test add_interface_metadata."""
484
        interface_id = '00:00:00:00:00:00:00:01:1'
485
        dpid = '00:00:00:00:00:00:00:01'
486
        mock_switch = get_switch_mock(dpid)
487
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
488
        mock_interface.metadata = {"metada": "A"}
489
        mock_switch.interfaces = {1: mock_interface}
490
        self.napp.controller.switches = {dpid: mock_switch}
491
        api = get_test_client(self.napp.controller, self.napp)
492
493
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
494
        payload = {"metada": "A"}
495
        response = api.post(url, data=json.dumps(payload),
496
                            content_type='application/json')
497
        self.assertEqual(response.status_code, 201, response.data)
498
        mock_metadata_changes.assert_called()
499
500
        # fail case switch not found
501
        interface_id = '00:00:00:00:00:00:00:02:1'
502
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
503
        response = api.post(url, data=json.dumps(payload),
504
                            content_type='application/json')
505
        self.assertEqual(response.status_code, 404, response.data)
506
507
        # fail case interface not found
508
        interface_id = '00:00:00:00:00:00:00:01:2'
509
        url = f'{self.server_name_url}/v3/interfaces/{interface_id}/metadata'
510
        response = api.post(url, data=json.dumps(payload),
511
                            content_type='application/json')
512
        self.assertEqual(response.status_code, 404, response.data)
513
514
    def test_delete_interface_metadata(self):
515
        """Test delete_interface_metadata."""
516
        interface_id = '00:00:00:00:00:00:00:01:1'
517
        dpid = '00:00:00:00:00:00:00:01'
518
        iface_url = '/v3/interfaces/'
519
        mock_switch = get_switch_mock(dpid)
520
        mock_interface = get_interface_mock('s1-eth1', 1, mock_switch)
521
        mock_interface.remove_metadata.side_effect = [True, False]
522
        mock_interface.metadata = {"metada": "A"}
523
        mock_switch.interfaces = {1: mock_interface}
524
        self.napp.controller.switches = {'00:00:00:00:00:00:00:01':
525
                                         mock_switch}
526
        api = get_test_client(self.napp.controller, self.napp)
527
528
        key = 'A'
529
        url = f'{self.server_name_url}{iface_url}{interface_id}/metadata/{key}'
530
        response = api.delete(url)
531
        self.assertEqual(response.status_code, 200, response.data)
532
533
        # fail case switch not found
534
        key = 'A'
535
        interface_id = '00:00:00:00:00:00:00:02:1'
536
        url = f'{self.server_name_url}{iface_url}{interface_id}/metadata/{key}'
537
        response = api.delete(url)
538
        self.assertEqual(response.status_code, 404, response.data)
539
540
        # fail case interface not found
541
        key = 'A'
542
        interface_id = '00:00:00:00:00:00:00:01:2'
543
        url = f'{self.server_name_url}{iface_url}{interface_id}/metadata/{key}'
544
        response = api.delete(url)
545
        self.assertEqual(response.status_code, 404, response.data)
546
547
        # fail case metadata not found
548
        key = 'A'
549
        interface_id = '00:00:00:00:00:00:00:01:1'
550
        url = f'{self.server_name_url}{iface_url}{interface_id}/metadata/{key}'
551
        response = api.delete(url)
552
        self.assertEqual(response.status_code, 404, response.data)
553
554
    def test_enable_link(self):
555
        """Test enable_link."""
556
        mock_link = MagicMock(Link)
557
        self.napp.links = {'1': mock_link}
558
        api = get_test_client(self.napp.controller, self.napp)
559
560
        link_id = 1
561
        url = f'{self.server_name_url}/v3/links/{link_id}/enable'
562
        response = api.post(url)
563
        self.assertEqual(response.status_code, 201, response.data)
564
        self.assertEqual(mock_link.enable.call_count, 1)
565
566
        # fail case
567
        link_id = 2
568
        url = f'{self.server_name_url}/v3/links/{link_id}/enable'
569
        response = api.post(url)
570
        self.assertEqual(response.status_code, 404, response.data)
571
572
    def test_disable_link(self):
573
        """Test disable_link."""
574
        mock_link = MagicMock(Link)
575
        self.napp.links = {'1': mock_link}
576
        api = get_test_client(self.napp.controller, self.napp)
577
578
        link_id = 1
579
        url = f'{self.server_name_url}/v3/links/{link_id}/disable'
580
        response = api.post(url)
581
        self.assertEqual(response.status_code, 201, response.data)
582
        self.assertEqual(mock_link.disable.call_count, 1)
583
584
        # fail case
585
        link_id = 2
586
        url = f'{self.server_name_url}/v3/links/{link_id}/disable'
587
        response = api.post(url)
588
        self.assertEqual(response.status_code, 404, response.data)
589
590
    def test_get_link_metadata(self):
591
        """Test get_link_metadata."""
592
        mock_link = MagicMock(Link)
593
        mock_link.metadata = "A"
594
        self.napp.links = {'1': mock_link}
595
        msg_success = {"metadata": "A"}
596
        api = get_test_client(self.napp.controller, self.napp)
597
598
        link_id = 1
599
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata'
600
        response = api.get(url)
601
        self.assertEqual(response.status_code, 200, response.data)
602
        self.assertEqual(msg_success, json.loads(response.data))
603
604
        # fail case
605
        link_id = 2
606
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata'
607
        response = api.get(url)
608
        self.assertEqual(response.status_code, 404, response.data)
609
610
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
611
    def test_add_link_metadata(self, mock_metadata_changes):
612
        """Test add_link_metadata."""
613
        mock_link = MagicMock(Link)
614
        mock_link.metadata = "A"
615
        self.napp.links = {'1': mock_link}
616
        payload = {"metadata": "A"}
617
        api = get_test_client(self.napp.controller, self.napp)
618
619
        link_id = 1
620
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata'
621
        response = api.post(url, data=json.dumps(payload),
622
                            content_type='application/json')
623
        self.assertEqual(response.status_code, 201, response.data)
624
        mock_metadata_changes.assert_called()
625
626
        # fail case
627
        link_id = 2
628
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata'
629
        response = api.post(url, data=json.dumps(payload),
630
                            content_type='application/json')
631
        self.assertEqual(response.status_code, 404, response.data)
632
633
    @patch('napps.kytos.topology.main.Main.notify_metadata_changes')
634
    def test_delete_link_metadata(self, mock_metadata_changes):
635
        """Test delete_link_metadata."""
636
        mock_link = MagicMock(Link)
637
        mock_link.metadata = "A"
638
        mock_link.remove_metadata.side_effect = [True, False]
639
        self.napp.links = {'1': mock_link}
640
        api = get_test_client(self.napp.controller, self.napp)
641
642
        link_id = 1
643
        key = 'A'
644
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata/{key}'
645
        response = api.delete(url)
646
        self.assertEqual(response.status_code, 200, response.data)
647
        mock_metadata_changes.assert_called()
648
649
        # fail case link not found
650
        link_id = 2
651
        key = 'A'
652
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata/{key}'
653
        response = api.delete(url)
654
        self.assertEqual(response.status_code, 404, response.data)
655
656
        # fail case metadata not found
657
        link_id = 1
658
        key = 'A'
659
        url = f'{self.server_name_url}/v3/links/{link_id}/metadata/{key}'
660
        response = api.delete(url)
661
        self.assertEqual(response.status_code, 404, response.data)
662
663
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
664
    @patch('napps.kytos.topology.main.Main.update_instance_metadata')
665
    def test_handle_new_switch(self, *args):
666
        """Test handle_new_switch."""
667
        (mock_instance_metadata, mock_notify_topology_update) = args
668
        mock_event = MagicMock()
669
        mock_switch = create_autospec(Switch)
670
        mock_event.content['switch'] = mock_switch
671
        self.napp.handle_new_switch(mock_event)
672
        mock_notify_topology_update.assert_called()
673
        mock_instance_metadata.assert_called()
674
675
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
676
    def test_handle_connection_lost(self, mock_notify_topology_update):
677
        """Test handle connection_lost."""
678
        mock_event = MagicMock()
679
        mock_switch = create_autospec(Switch)
680
        mock_switch.return_value = True
681
        mock_event.content['source'] = mock_switch
682
        self.napp.handle_connection_lost(mock_event)
683
        mock_notify_topology_update.assert_called()
684
685
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
686
    @patch('napps.kytos.topology.main.Main.update_instance_metadata')
687
    def test_handle_interface_up(self, *args):
688
        """Test handle_interface_up."""
689
        (mock_instance_metadata, mock_notify_topology_update) = args
690
        mock_event = MagicMock()
691
        mock_interface = create_autospec(Interface)
692
        mock_event.content['interface'] = mock_interface
693
        self.napp.handle_interface_up(mock_event)
694
        mock_notify_topology_update.assert_called()
695
        mock_instance_metadata.assert_called()
696
697
    @patch('napps.kytos.topology.main.Main.handle_interface_up')
698
    def test_handle_interface_created(self, mock_handle_interface_up):
699
        """Test handle interface created."""
700
        mock_event = MagicMock()
701
        self.napp.handle_interface_created(mock_event)
702
        mock_handle_interface_up.assert_called()
703
704
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
705
    @patch('napps.kytos.topology.main.Main.handle_interface_link_down')
706
    def test_handle_interface_down(self, *args):
707
        """Test handle interface down."""
708
        (mock_handle_interface_link_down, mock_notify_topology_update) = args
709
        mock_event = MagicMock()
710
        mock_interface = create_autospec(Interface)
711
        mock_event.content['interface'] = mock_interface
712
        self.napp.handle_interface_down(mock_event)
713
        mock_handle_interface_link_down.assert_called()
714
        mock_notify_topology_update.assert_called()
715
716
    @patch('napps.kytos.topology.main.Main.handle_interface_down')
717
    def test_interface_deleted(self, mock_handle_interface_link_down):
718
        """Test interface deleted."""
719
        mock_event = MagicMock()
720
        self.napp.handle_interface_deleted(mock_event)
721
        mock_handle_interface_link_down.assert_called()
722
723
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
724
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
725
    @patch('napps.kytos.topology.main.Main.update_instance_metadata')
726
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
727
    def test_interface_link_up(self, *args):
728
        """Test interface link_up."""
729
        (mock_status_change, mock_instance_metadata, mock_topology_update,
730
         mock_link_from_interface) = args
731
732
        now = time.time()
733
        mock_event = MagicMock()
734
        mock_interface_a = create_autospec(Interface)
735
        mock_interface_a.is_active.return_value = False
736
        mock_interface_b = create_autospec(Interface)
737
        mock_interface_b.is_active.return_value = True
738
        mock_link = create_autospec(Link)
739
        mock_link.get_metadata.return_value = now
740
        mock_link.is_active.side_effect = [False, True]
741
        mock_link.endpoint_a = mock_interface_a
742
        mock_link.endpoint_b = mock_interface_b
743
        mock_link_from_interface.return_value = mock_link
744
        content = {'interface': mock_interface_a}
745
        mock_event.content = content
746
        self.napp.link_up_timer = 1
747
        self.napp.handle_interface_link_up(mock_event)
748
        mock_topology_update.assert_called()
749
        mock_instance_metadata.assert_called()
750
        mock_status_change.assert_called()
751
752
    @patch('napps.kytos.topology.main.Main._get_link_from_interface')
753
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
754
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
755
    def test_interface_link_down(self, *args):
756
        """Test interface link down."""
757
        (mock_status_change, mock_topology_update,
758
         mock_link_from_interface) = args
759
760
        mock_event = MagicMock()
761
        mock_interface = create_autospec(Interface)
762
        mock_link = create_autospec(Link)
763
        mock_link.is_active.return_value = True
764
        mock_link_from_interface.return_value = mock_link
765
        mock_event.content['interface'] = mock_interface
766
        self.napp.handle_interface_link_down(mock_event)
767
        mock_topology_update.assert_called()
768
        mock_status_change.assert_called()
769
770
    @patch('napps.kytos.topology.main.Main._get_link_or_create')
771
    @patch('napps.kytos.topology.main.Main.notify_topology_update')
772
    def test_add_links(self, *args):
773
        """Test add_links."""
774
        (mock_notify_topology_update, mock_get_link_or_create) = args
775
        mock_event = MagicMock()
776
        self.napp.add_links(mock_event)
777
        mock_get_link_or_create.assert_called()
778
        mock_notify_topology_update.assert_called()
779
780
    @patch('napps.kytos.topology.main.Main._get_switches_dict')
781
    @patch('napps.kytos.topology.main.StoreHouse.save_status')
782
    def test_save_status_on_store(self, *args):
783
        """Test save_status_on_storehouse."""
784
        (mock_save_status, mock_get_switches_dict) = args
785
        self.napp.save_status_on_storehouse()
786
        mock_get_switches_dict.assert_called()
787
        mock_save_status.assert_called()
788
789
    @patch('napps.kytos.topology.main.KytosEvent')
790
    @patch('kytos.core.buffers.KytosEventBuffer.put')
791
    def test_notify_topology_update(self, *args):
792
        """Test notify_topology_update."""
793
        (mock_buffers_put, mock_event) = args
794
        self.napp.notify_topology_update()
795
        mock_event.assert_called()
796
        mock_buffers_put.assert_called()
797
798
    @patch('napps.kytos.topology.main.KytosEvent')
799
    @patch('kytos.core.buffers.KytosEventBuffer.put')
800
    def test_notify_link_status_change(self, *args):
801
        """Test notify link status change."""
802
        (mock_buffers_put, mock_event) = args
803
        mock_link = create_autospec(Link)
804
        self.napp.notify_link_status_change(mock_link)
805
        mock_event.assert_called()
806
        mock_buffers_put.assert_called()
807
808
    @patch('napps.kytos.topology.main.KytosEvent')
809
    @patch('kytos.core.buffers.KytosEventBuffer.put')
810
    @patch('napps.kytos.topology.main.isinstance')
811
    def test_notify_metadata_changes(self, *args):
812
        """Test notify metadata changes."""
813
        (mock_isinstance, mock_buffers_put, mock_event) = args
814
        mock_isinstance.return_value = True
815
        mock_obj = MagicMock()
816
        mock_action = create_autospec(Switch)
817
        self.napp.notify_metadata_changes(mock_obj, mock_action)
818
        mock_event.assert_called()
819
        mock_isinstance.assert_called()
820
        mock_buffers_put.assert_called()
821
822
    @patch('napps.kytos.topology.main.KytosEvent')
823
    @patch('kytos.core.buffers.KytosEventBuffer.put')
824
    def test_notify_port_created(self, *args):
825
        """Test notify port created."""
826
        (mock_buffers_put, mock_kytos_event) = args
827
        mock_event = MagicMock()
828
        self.napp.notify_port_created(mock_event)
829
        mock_kytos_event.assert_called()
830
        mock_buffers_put.assert_called()
831
832
    @patch('napps.kytos.topology.main.KytosEvent')
833
    @patch('kytos.core.buffers.KytosEventBuffer.put')
834
    def test_save_metadata_on_store(self, *args):
835
        """Test test_save_metadata_on_store."""
836
        (mock_buffers_put, mock_kytos_event) = args
837
        mock_event = MagicMock()
838
        mock_switch = MagicMock()
839
        mock_interface = MagicMock()
840
        mock_link = MagicMock()
841
        self.napp.store_items = {'switches': mock_switch,
842
                                 'interfaces': mock_interface,
843
                                 'links': mock_link}
844
        # test switches
845
        mock_event.content = {'switch': mock_switch}
846
        self.napp.save_metadata_on_store(mock_event)
847
        mock_kytos_event.assert_called()
848
        mock_buffers_put.assert_called()
849
850
        # test interfaces
851
        mock_event.content = {'interface': mock_interface}
852
        self.napp.save_metadata_on_store(mock_event)
853
        mock_kytos_event.assert_called()
854
        mock_buffers_put.assert_called()
855
856
        # test link
857
        mock_event.content = {'link': mock_link}
858
        self.napp.save_metadata_on_store(mock_event)
859
        mock_kytos_event.assert_called()
860
        mock_buffers_put.assert_called()
861
862
    @patch('napps.kytos.topology.main.KytosEvent')
863
    @patch('kytos.core.buffers.KytosEventBuffer.put')
864
    def test_verify_storehouse(self, *args):
865
        """Test verify_storehouse."""
866
        (mock_buffers_put, mock_kytos_event) = args
867
        mock_entities = MagicMock()
868
        self.napp.verify_storehouse(mock_entities)
869
        mock_buffers_put.assert_called()
870
        mock_kytos_event.assert_called()
871
872
    @patch('napps.kytos.topology.main.KytosEvent')
873
    @patch('kytos.core.buffers.KytosEventBuffer.put')
874
    def test_request_retrieve_entities(self, *args):
875
        """Test retrive_entities."""
876
        (mock_buffers_put, mock_kytos_event) = args
877
        mock_event = MagicMock()
878
        mock_data = MagicMock()
879
        mock_error = MagicMock()
880
        mock_event.content = {"namespace": "test_box"}
881
        self.napp.request_retrieve_entities(mock_event, mock_data, mock_error)
882
        mock_kytos_event.assert_called()
883
        mock_buffers_put.assert_called()
884
885
        self.napp.request_retrieve_entities(mock_event, None, mock_error)
886
        mock_kytos_event.assert_called()
887
        mock_buffers_put.assert_called()
888
889
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
890
    def test_handle_link_maintenance_start(self, status_change_mock):
891
        """Test handle_link_maintenance_start."""
892
        link1 = MagicMock()
893
        link1.id = 2
894
        link2 = MagicMock()
895
        link2.id = 3
896
        link3 = MagicMock()
897
        link3.id = 4
898
        content = {'links': [link1, link2]}
899
        event = MagicMock()
900
        event.content = content
901
        self.napp.links = {2: link1, 4: link3}
902
        self.napp.handle_link_maintenance_start(event)
903
        status_change_mock.assert_called_once_with(link1)
904
905
    @patch('napps.kytos.topology.main.Main.notify_link_status_change')
906
    def test_handle_link_maintenance_end(self, status_change_mock):
907
        """Test handle_link_maintenance_end."""
908
        link1 = MagicMock()
909
        link1.id = 2
910
        link2 = MagicMock()
911
        link2.id = 3
912
        link3 = MagicMock()
913
        link3.id = 4
914
        content = {'links': [link1, link2]}
915
        event = MagicMock()
916
        event.content = content
917
        self.napp.links = {2: link1, 4: link3}
918
        self.napp.handle_link_maintenance_end(event)
919
        status_change_mock.assert_called_once_with(link1)
920
921 View Code Duplication
    @patch('napps.kytos.topology.main.Main.handle_link_down')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
922
    def test_handle_switch_maintenance_start(self, handle_link_down_mock):
923
        """Test handle_switch_maintenance_start."""
924
        switch1 = MagicMock()
925
        interface1 = MagicMock()
926
        interface1.is_active.return_value = True
927
        interface2 = MagicMock()
928
        interface2.is_active.return_value = False
929
        interface3 = MagicMock()
930
        interface3.is_active.return_value = True
931
        switch1.interfaces = {1: interface1, 2: interface2, 3: interface3}
932
        switch2 = MagicMock()
933
        interface4 = MagicMock()
934
        interface4.is_active.return_value = False
935
        interface5 = MagicMock()
936
        interface5.is_active.return_value = True
937
        switch2.interfaces = {1: interface4, 2: interface5}
938
        content = {'switches': [switch1, switch2]}
939
        event = MagicMock()
940
        event.content = content
941
        self.napp.handle_switch_maintenance_start(event)
942
        self.assertEqual(handle_link_down_mock.call_count, 3)
943
944 View Code Duplication
    @patch('napps.kytos.topology.main.Main.handle_link_up')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
945
    def test_handle_switch_maintenance_end(self, handle_link_up_mock):
946
        """Test handle_switch_maintenance_end."""
947
        switch1 = MagicMock()
948
        interface1 = MagicMock()
949
        interface1.is_active.return_value = True
950
        interface2 = MagicMock()
951
        interface2.is_active.return_value = False
952
        interface3 = MagicMock()
953
        interface3.is_active.return_value = True
954
        switch1.interfaces = {1: interface1, 2: interface2, 3: interface3}
955
        switch2 = MagicMock()
956
        interface4 = MagicMock()
957
        interface4.is_active.return_value = False
958
        interface5 = MagicMock()
959
        interface5.is_active.return_value = True
960
        switch2.interfaces = {1: interface4, 2: interface5}
961
        content = {'switches': [switch1, switch2]}
962
        event = MagicMock()
963
        event.content = content
964
        self.napp.handle_switch_maintenance_end(event)
965
        self.assertEqual(handle_link_up_mock.call_count, 5)
966