Test Failed
Pull Request — master (#78)
by
unknown
05:59
created

TestDeployer.test_mw_case_2()   B

Complexity

Conditions 5

Size

Total Lines 87
Code Lines 64

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 32
CRAP Score 5.0616

Importance

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