Passed
Pull Request — master (#78)
by
unknown
02:40
created

TestDeployer.test_mw_case_1()   C

Complexity

Conditions 7

Size

Total Lines 90
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 44
CRAP Score 7

Importance

Changes 0
Metric Value
cc 7
eloc 70
nop 1
dl 0
loc 90
ccs 44
cts 44
cp 1
crap 7
rs 6.5818
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""Tests for the models module."""
2
3 1
from unittest import TestCase
4 1
from unittest.mock import patch, MagicMock, call
5
6 1
from collections import Counter
7
8 1
from apscheduler.jobstores.base import JobLookupError
9 1
from apscheduler.triggers.date import DateTrigger
10 1
from datetime import datetime, timedelta
11 1
import pytz
12 1
from kytos.lib.helpers import get_controller_mock
13 1
from napps.kytos.maintenance.models import MaintenanceWindow as MW, Status
14
15 1
from napps.kytos.maintenance.managers.deployer import (
16
    MaintenanceDeployer,
17
)
18
19 1
from napps.kytos.maintenance.managers.scheduler import (
20
    MaintenanceScheduler as Scheduler,
21
    MaintenanceStart,
22
    MaintenanceEnd,
23
)
24 1
TIME_FMT = "%Y-%m-%dT%H:%M:%S%z"
25
26
27 1
class TestMW(TestCase):
28
    """Test of the MaintenanceWindow class."""
29
30
    # pylint: disable=protected-access
31
32 1
    def setUp(self):
33
        """Initialize before tests are executed."""
34 1
        self.controller = get_controller_mock()
35 1
        self.start = datetime.now(pytz.utc)
36 1
        self.start += timedelta(days=1)
37 1
        self.end = self.start + timedelta(hours=6)
38 1
        self.switches = [
39
            "01:23:45:67:89:ab:cd:ef"
40
        ]
41 1
        self.maintenance = MW(
42
            start=self.start,
43
            end=self.end,
44
            switches=self.switches
45
        )
46
47 1
    def test_as_dict(self):
48
        """Test as_dict method."""
49 1
        mw_dict = self.maintenance.dict()
50 1
        expected_dict = {
51
            'description': '',
52
            'start': self.start,
53
            'end': self.end,
54
            'id': self.maintenance.id,
55
            'switches': self.switches,
56
            'interfaces': [],
57
            'links': [],
58
            'status': Status.PENDING,
59
            'inserted_at': None,
60
            'updated_at': None,
61
        }
62 1
        self.assertEqual(mw_dict, expected_dict)
63
64 1
    def test_start_in_past(self):
65 1
        start = datetime.now(pytz.utc) - timedelta(days=1)
66
67 1
        self.assertRaises(ValueError, MW,
68
            start=start,
69
            end=self.end,
70
            switches=self.switches,
71
        )
72
73 1
    def test_end_before_start(self):
74 1
        end = datetime.now(pytz.utc) - timedelta(days=1)
75
76 1
        self.assertRaises(ValueError, MW,
77
            start=self.start,
78
            end=end,
79
            switches=self.switches,
80
        )
81
82 1
    def test_items_empty(self):
83
84 1
        self.assertRaises(ValueError, MW,
85
            start=self.start,
86
            end=self.end,
87
        )
88
89 1
class TestDeployer(TestCase):
90
    """Test of the MaintenanceDeployer class."""
91 1
    def setUp(self):
92 1
        self.controller = get_controller_mock()
93 1
        self.start = datetime.now(pytz.utc)
94 1
        self.start += timedelta(days=1)
95 1
        self.end = self.start + timedelta(hours=6)
96 1
        self.switches = [
97
            "01:23:45:67:89:ab:cd:ef"
98
        ]
99 1
        self.maintenance = MW(
100
            start=self.start,
101
            end=self.end,
102
            switches=self.switches
103
        )
104
105 1
        self.deployer = MaintenanceDeployer(self.controller, Counter(), Counter(), Counter())
106
        # Initialize Switches
107 1
        self.controller.switches = {
108
            '01:23:45:67:89:ab:cd:ef': MagicMock(
109
                id='01:23:45:67:89:ab:cd:ef',
110
                interfaces = {},
111
            ),
112
            '01:23:45:67:65:ab:cd:ef': MagicMock(
113
                id='01:23:45:67:65:ab:cd:ef',
114
                interfaces = {},
115
            ),
116
            '01:23:45:67:66:ab:cd:ef': MagicMock(
117
                id='01:23:45:67:66:ab:cd:ef',
118
                interfaces = {},
119
            ),
120
        }
121
        # Initialize Interfaces
122 1
        self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces = {
123
            0: MagicMock(
124
                id = '01:23:45:67:89:ab:cd:ef:0',
125
                switch = self.controller.switches['01:23:45:67:89:ab:cd:ef'],
126
                link = None,
127
            ),
128
            1: MagicMock(
129
                id = '01:23:45:67:89:ab:cd:ef:1',
130
                switch = self.controller.switches['01:23:45:67:89:ab:cd:ef'],
131
                link = None,
132
            ),
133
            2: MagicMock(
134
                id = '01:23:45:67:89:ab:cd:ef:2',
135
                switch = self.controller.switches['01:23:45:67:89:ab:cd:ef'],
136
                link = None,
137
            ),
138
        }
139
140 1
        self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces = {
141
            0: MagicMock(
142
                id = '01:23:45:67:65:ab:cd:ef:0',
143
                switch = self.controller.switches['01:23:45:67:65:ab:cd:ef'],
144
                link = None,
145
            ),
146
            1: MagicMock(
147
                id = '01:23:45:67:65:ab:cd:ef:1',
148
                switch = self.controller.switches['01:23:45:67:65:ab:cd:ef'],
149
                link = None,
150
            ),
151
            2: MagicMock(
152
                id = '01:23:45:67:65:ab:cd:ef:2',
153
                switch = self.controller.switches['01:23:45:67:65:ab:cd:ef'],
154
                link = None,
155
            ),
156
        }
157
158 1
        self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces = {
159
            0: MagicMock(
160
                id = '01:23:45:67:66:ab:cd:ef:0',
161
                switch = self.controller.switches['01:23:45:67:66:ab:cd:ef'],
162
                link = None,
163
            ),
164
            1: MagicMock(
165
                id = '01:23:45:67:66:ab:cd:ef:1',
166
                switch = self.controller.switches['01:23:45:67:66:ab:cd:ef'],
167
                link = None,
168
            ),
169
            2: MagicMock(
170
                id = '01:23:45:67:66:ab:cd:ef:2',
171
                switch = self.controller.switches['01:23:45:67:66:ab:cd:ef'],
172
                link = None,
173
            ),
174
        }
175
176
        # Initialize Links
177 1
        self.link_1 = MagicMock(
178
            id = 'link_1',
179
            endpoint_a = self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[0],
180
            endpoint_b = self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces[0],
181
        )
182 1
        self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[0].link = self.link_1
183 1
        self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces[0].link = self.link_1
184
185 1
        self.link_2 = MagicMock(
186
            id = 'link_2',
187
            endpoint_a = self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[1],
188
            endpoint_b = self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[0],
189
        )
190 1
        self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[1].link = self.link_2
191 1
        self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[0].link = self.link_2
192
193 1
        self.link_3 = MagicMock(
194
            id = 'link_3',
195
            endpoint_a = self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[1],
196
            endpoint_b = self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[2],
197
        )
198 1
        self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[1].link = self.link_3
199 1
        self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces[2].link = self.link_3
200
201
202 1
        self.controller.napps[('kytos', 'topology')] = MagicMock(
203
            links = {
204
                'link_1': self.link_1,
205
                'link_2': self.link_2,
206
                'link_3': self.link_3,
207
            }
208
        )
209
210 1
    def test_mw_case_1(self):
211
        """Test deploying a maintenance window to switches."""
212 1
        buffer_put_mock = MagicMock()
213 1
        self.controller.buffers.app.put = buffer_put_mock
214 1
        maintenance = self.maintenance.copy(
215
            update = {
216
                'switches': [
217
                    '01:23:45:67:89:ab:cd:ef',
218
                    '01:23:45:67:65:ab:cd:ef'
219
                ],
220
                'interfaces': [],
221
                'links': [],
222
            }
223
        )
224 1
        self.deployer.start_mw(maintenance)
225 1
        args, kwargs = buffer_put_mock.call_args
226 1
        event = args[0]
227 1
        assert event.name == 'topology.interruption.start'
228 1
        assert event.content['type'] == 'maintenance'
229 1
        assert sorted(event.content['switches']) == [
230
            '01:23:45:67:65:ab:cd:ef',
231
            '01:23:45:67:89:ab:cd:ef',
232
        ]
233 1
        assert sorted(event.content['interfaces']) == [
234
            '01:23:45:67:65:ab:cd:ef:0',
235
            '01:23:45:67:65:ab:cd:ef:1',
236
            '01:23:45:67:65:ab:cd:ef:2',
237
            '01:23:45:67:89:ab:cd:ef:0',
238
            '01:23:45:67:89:ab:cd:ef:1',
239
            '01:23:45:67:89:ab:cd:ef:2',
240
        ]
241 1
        assert sorted(event.content['links']) == [
242
            'link_1',
243
            'link_2',
244
        ]
245
246
        # Check whats in maintenance
247
        # Switches
248 1
        assert not self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
249 1
        assert not self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
250 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
251
        # Interfaces
252 1
        for interface in self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces.values():
253 1
            assert not self.deployer.interface_not_in_maintenance(interface)
254 1
        for interface in self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces.values():
255 1
            assert not self.deployer.interface_not_in_maintenance(interface)
256 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
257 1
            assert     self.deployer.interface_not_in_maintenance(interface)
258
        # Links
259 1
        assert not self.deployer.link_not_in_maintenance(self.link_1)
260 1
        assert not self.deployer.link_not_in_maintenance(self.link_2)
261 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
262
263 1
        self.deployer.end_mw(maintenance)
264 1
        args, kwargs = buffer_put_mock.call_args
265 1
        event = args[0]
266 1
        assert event.name == 'topology.interruption.end'
267 1
        assert event.content['type'] == 'maintenance'
268 1
        assert sorted(event.content['switches']) == [
269
            '01:23:45:67:65:ab:cd:ef',
270
            '01:23:45:67:89:ab:cd:ef',
271
        ]
272 1
        assert sorted(event.content['interfaces']) == [
273
            '01:23:45:67:65:ab:cd:ef:0',
274
            '01:23:45:67:65:ab:cd:ef:1',
275
            '01:23:45:67:65:ab:cd:ef:2',
276
            '01:23:45:67:89:ab:cd:ef:0',
277
            '01:23:45:67:89:ab:cd:ef:1',
278
            '01:23:45:67:89:ab:cd:ef:2',
279
        ]
280 1
        assert sorted(event.content['links']) == [
281
            'link_1',
282
            'link_2',
283
        ]
284
        # Check whats in maintenance
285
        # Switches
286 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
287 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
288 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
289
        # Interfaces
290 1
        for interface in self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces.values():
291 1
            assert     self.deployer.interface_not_in_maintenance(interface)
292 1
        for interface in self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces.values():
293 1
            assert     self.deployer.interface_not_in_maintenance(interface)
294 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
295 1
            assert     self.deployer.interface_not_in_maintenance(interface)
296
        # Links
297 1
        assert     self.deployer.link_not_in_maintenance(self.link_1)
298 1
        assert     self.deployer.link_not_in_maintenance(self.link_2)
299 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
300
301 1
    def test_mw_case_2(self):
302
        """Test deploying a maintenance window to interfaces."""
303 1
        buffer_put_mock = MagicMock()
304 1
        self.controller.buffers.app.put = buffer_put_mock
305
        
306 1
        maintenance = self.maintenance.copy(
307
            update = {
308
                'switches': [],
309
                'interfaces': [
310
                    '01:23:45:67:65:ab:cd:ef:0',
311
                    '01:23:45:67:89:ab:cd:ef:0',
312
                    '01:23:45:67:89:ab:cd:ef:1',
313
                ],
314
                'links': [],
315
            }
316
        )
317 1
        self.deployer.start_mw(maintenance)
318 1
        args, kwargs = buffer_put_mock.call_args
319 1
        event = args[0]
320 1
        assert event.name == 'topology.interruption.start'
321 1
        assert event.content['type'] == 'maintenance'
322 1
        assert sorted(event.content['switches']) == []
323 1
        assert sorted(event.content['interfaces']) == [
324
            '01:23:45:67:65:ab:cd:ef:0',
325
            '01:23:45:67:89:ab:cd:ef:0',
326
            '01:23:45:67:89:ab:cd:ef:1',
327
        ]
328 1
        assert sorted(event.content['links']) == [
329
            'link_1',
330
            'link_2',
331
        ]
332
333
        # Check whats in maintenance
334
        # Switches
335 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
336 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
337 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
338
        # Interfaces
339
340 1
        assert not self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[0])
341 1
        assert not self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[1])
342 1
        assert     self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces[2])
343
344 1
        assert not self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces[0])
345 1
        assert     self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces[1])
346 1
        assert     self.deployer.interface_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces[2])
347
348 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
349 1
            assert     self.deployer.interface_not_in_maintenance(interface)
350
351
        # Links
352 1
        assert not self.deployer.link_not_in_maintenance(self.link_1)
353 1
        assert not self.deployer.link_not_in_maintenance(self.link_2)
354 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
355
356 1
        self.deployer.end_mw(maintenance)
357 1
        args, kwargs = buffer_put_mock.call_args
358 1
        event = args[0]
359 1
        assert event.name == 'topology.interruption.end'
360 1
        assert event.content['type'] == 'maintenance'
361 1
        assert sorted(event.content['switches']) == []
362 1
        assert sorted(event.content['switches']) == []
363 1
        assert sorted(event.content['interfaces']) == [
364
            '01:23:45:67:65:ab:cd:ef:0',
365
            '01:23:45:67:89:ab:cd:ef:0',
366
            '01:23:45:67:89:ab:cd:ef:1',
367
        ]
368 1
        assert sorted(event.content['links']) == [
369
            'link_1',
370
            'link_2',
371
        ]
372
        # Check whats in maintenance
373
        # Switches
374 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
375 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
376 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
377
        # Interfaces
378 1
        for interface in self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces.values():
379 1
            assert     self.deployer.interface_not_in_maintenance(interface)
380 1
        for interface in self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces.values():
381 1
            assert     self.deployer.interface_not_in_maintenance(interface)
382 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
383 1
            assert     self.deployer.interface_not_in_maintenance(interface)
384
        # Links
385 1
        assert     self.deployer.link_not_in_maintenance(self.link_1)
386 1
        assert     self.deployer.link_not_in_maintenance(self.link_2)
387 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
388
389 1
    def test_mw_case_3(self):
390
        """Test deploying a maintenance window to links."""
391 1
        buffer_put_mock = MagicMock()
392 1
        self.controller.buffers.app.put = buffer_put_mock
393 1
        maintenance = self.maintenance.copy(
394
            update = {
395
                'switches': [],
396
                'interfaces': [],
397
                'links': ['link_1', 'link_2'],
398
            }
399
        )
400 1
        self.deployer.start_mw(maintenance)
401 1
        args, kwargs = buffer_put_mock.call_args
402 1
        event = args[0]
403 1
        assert event.name == 'topology.interruption.start'
404 1
        assert event.content['type'] == 'maintenance'
405 1
        assert sorted(event.content['switches']) == []
406 1
        assert sorted(event.content['interfaces']) == []
407 1
        assert sorted(event.content['links']) == [
408
            'link_1',
409
            'link_2',
410
        ]
411
412
        # Check whats in maintenance
413
        # Switches
414 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
415 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
416 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
417
        # Interfaces
418 1
        for interface in self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces.values():
419 1
            assert     self.deployer.interface_not_in_maintenance(interface)
420 1
        for interface in self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces.values():
421 1
            assert     self.deployer.interface_not_in_maintenance(interface)
422 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
423 1
            assert     self.deployer.interface_not_in_maintenance(interface)
424
        # Links
425 1
        assert not self.deployer.link_not_in_maintenance(self.link_1)
426 1
        assert not self.deployer.link_not_in_maintenance(self.link_2)
427 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
428
429 1
        self.deployer.end_mw(maintenance)
430 1
        args, kwargs = buffer_put_mock.call_args
431 1
        event = args[0]
432 1
        assert event.name == 'topology.interruption.end'
433 1
        assert event.content['type'] == 'maintenance'
434 1
        assert sorted(event.content['switches']) == []
435 1
        assert sorted(event.content['interfaces']) == []
436 1
        assert sorted(event.content['links']) == [
437
            'link_1',
438
            'link_2',
439
        ]
440
        # Check whats in maintenance
441
        # Switches
442 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:89:ab:cd:ef'])
443 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:65:ab:cd:ef'])
444 1
        assert     self.deployer.switch_not_in_maintenance(self.controller.switches['01:23:45:67:66:ab:cd:ef'])
445
        # Interfaces
446 1
        for interface in self.controller.switches['01:23:45:67:89:ab:cd:ef'].interfaces.values():
447 1
            assert     self.deployer.interface_not_in_maintenance(interface)
448 1
        for interface in self.controller.switches['01:23:45:67:65:ab:cd:ef'].interfaces.values():
449 1
            assert     self.deployer.interface_not_in_maintenance(interface)
450 1
        for interface in self.controller.switches['01:23:45:67:66:ab:cd:ef'].interfaces.values():
451 1
            assert     self.deployer.interface_not_in_maintenance(interface)
452
        # Links
453 1
        assert     self.deployer.link_not_in_maintenance(self.link_1)
454 1
        assert     self.deployer.link_not_in_maintenance(self.link_2)
455 1
        assert     self.deployer.link_not_in_maintenance(self.link_3)
456
457
458 1
class TestScheduler(TestCase):
459
    """Test of the Scheduler Class"""
460
    
461 1
    def setUp(self) -> None:
462 1
        self.maintenance_deployer = MagicMock()
463 1
        self.db_controller = MagicMock()
464 1
        self.task_scheduler = MagicMock()
465
        
466 1
        self.now = datetime.now(pytz.utc)
467
468 1
        self.window = MW.construct(
469
            id = 'Test Window',
470
            description = '',
471
            start = self.now + timedelta(hours=1),
472
            end = self.now + timedelta(hours=2),
473
            status = 'pending',
474
            switches = [],
475
            interfaces = [],
476
            links = [],
477
            updated_at = self.now - timedelta(days=1),
478
            inserted_at = self.now - timedelta(days=1),
479
        )
480
481 1
        self.scheduler = Scheduler(self.maintenance_deployer, self.db_controller, self.task_scheduler)
482
483 1
    def test_start(self):
484
485 1
        pending_window = self.window.copy(
486
            update={'id': 'pending window', 'status': 'pending'}
487
        )
488 1
        running_window = self.window.copy(
489
            update={'id': 'running window', 'status': 'running'}
490
        )
491 1
        finished_window = self.window.copy(
492
            update={'id': 'finished window', 'status': 'finished'}
493
        )
494
495 1
        expected_schedule_calls = [
496
            call(MaintenanceStart(self.scheduler, 'pending window'),
497
            'date', id='pending window-start',
498
            run_date = pending_window.start),
499
            call(MaintenanceEnd(self.scheduler, 'running window'),
500
            'date', id='running window-end',
501
            run_date = running_window.end),
502
        ]
503
504 1
        self.db_controller.get_windows.return_value = [
505
            pending_window,
506
            running_window,
507
            finished_window,
508
        ]
509 1
        self.scheduler.start()
510
511 1
        resultant_schedule_calls = self.task_scheduler.add_job.call_args_list
512 1
        self.assertEqual(resultant_schedule_calls, expected_schedule_calls)
513
514 1
        self.maintenance_deployer.start_mw.assert_called_once_with(running_window)
515
516 1
    def test_shutdown(self):
517 1
        pending_window = self.window.copy(
518
            update={'id': 'pending window', 'status': 'pending'}
519
        )
520 1
        running_window = self.window.copy(
521
            update={'id': 'running window', 'status': 'running'}
522
        )
523 1
        finished_window = self.window.copy(
524
            update={'id': 'finished window', 'status': 'finished'}
525
        )
526
527 1
        self.db_controller.get_windows.return_value = [
528
            pending_window,
529
            running_window,
530
            finished_window,
531
        ]
532
533 1
        remove_job_effects = {
534
            'pending window-start': False,
535
            'pending window-end': True,
536
            'running window-start': True,
537
            'running window-end': False,
538
            'finished window-start': True,
539
            'finished window-end': True,
540
        }
541
542 1
        def side_effect(job_id):
543 1
            effect = remove_job_effects[job_id]
544 1
            if effect:
545 1
                raise JobLookupError(job_id)
546
            else:
547 1
                return None
548
549 1
        self.task_scheduler.remove_job.side_effect = side_effect
550
551 1
        self.scheduler.shutdown()
552
553 1
        self.maintenance_deployer.end_mw.assert_called_once_with(running_window)
554
555 1
    def test_update(self):
556 1
        pending_window = self.window.copy(
557
            update={'id': 'pending window', 'status': 'pending'}
558
        )
559 1
        running_window = self.window.copy(
560
            update={'id': 'running window', 'status': 'running'}
561
        )
562 1
        finished_window = self.window.copy(
563
            update={'id': 'finished window', 'status': 'finished'}
564
        )
565
566 1
        modify_job_effects = {
567
            'pending window-start': (False, DateTrigger(pending_window.start)),
568
            'pending window-end': (True, DateTrigger(pending_window.end)),
569
            'running window-start': (True, DateTrigger(running_window.start)),
570
            'running window-end': (False, DateTrigger(running_window.end)),
571
            'finished window-start': (True, DateTrigger(finished_window.start)),
572
            'finished window-end': (True, DateTrigger(finished_window.end)),
573
        }
574
575 1
        def side_effect(job_id, trigger):
576
            throw, expected_trigger = modify_job_effects[job_id]
577
            self.assertEqual(trigger.run_date, expected_trigger.run_date)
578
            if throw:
579
                raise JobLookupError(job_id)
580
            else:
581
                return None
582
        
583 1
        self.task_scheduler.modify_job.side_effect = side_effect
584
585 1
        self.scheduler.update(pending_window)
586 1
        self.scheduler.update(running_window)
587 1
        self.scheduler.update(finished_window)
588
589 1
    def test_maintenance_start(self):
590
591 1
        pending_window = self.window.copy(
592
            update={'id': 'pending window', 'status': 'pending'}
593
        )
594 1
        next_window = self.window.copy(
595
            update={'id': 'pending window', 'status': 'running'}
596
        )
597
598 1
        self.db_controller.start_window.return_value = next_window
599 1
        start = MaintenanceStart(self.scheduler, pending_window.id)
600 1
        start()
601 1
        self.maintenance_deployer.start_mw.assert_called_once_with(next_window)
602
603 1
        self.task_scheduler.add_job.assert_called_once_with(
604
            MaintenanceEnd(self.scheduler, pending_window.id),
605
            'date',
606
            id='pending window-end',
607
            run_date=pending_window.end
608
        )
609
610 1
    def test_maintenance_end(self):
611
612 1
        running_window = self.window.copy(
613
            update={'id': 'running window', 'status': 'running'}
614
        )
615 1
        next_window = self.window.copy(
616
            update={'id': 'running window', 'status': 'finished'}
617
        )
618
619 1
        self.db_controller.end_window.return_value = next_window
620 1
        end = MaintenanceEnd(self.scheduler, running_window.id)
621 1
        end()
622 1
        self.maintenance_deployer.end_mw.assert_called_once_with(next_window)
623
624