OLD | NEW |
| (Empty) |
1 # -*- test-case-name: buildbot.test.test_status_push -*- | |
2 | |
3 import re | |
4 import os | |
5 | |
6 try: | |
7 import simplejson as json | |
8 except ImportError: | |
9 import json | |
10 | |
11 from twisted.internet import defer, reactor | |
12 from twisted.python import log | |
13 from twisted.trial import unittest | |
14 from twisted.web import server, resource | |
15 from twisted.web.error import Error | |
16 from zope.interface import implements, Interface | |
17 | |
18 from buildbot import master | |
19 from buildbot.changes import changes | |
20 from buildbot.slave import bot | |
21 from buildbot.status import status_push | |
22 from buildbot.status.persistent_queue import IQueue, ReadFile | |
23 from buildbot.test.runutils import RunMixin | |
24 from buildbot.test.status_push_server import EventsHandler | |
25 | |
26 | |
27 config_base = """ | |
28 from buildbot.process import factory | |
29 from buildbot.buildslave import BuildSlave | |
30 from buildbot.config import BuilderConfig | |
31 from buildbot.scheduler import Scheduler | |
32 from buildbot.status.persistent_queue import IQueue | |
33 from buildbot.status.status_push import StatusPush, HttpStatusPush | |
34 from buildbot.steps import dummy | |
35 | |
36 BuildmasterConfig = c = {} | |
37 | |
38 c['slaves'] = [BuildSlave('bot1', 'sekrit')] | |
39 c['schedulers'] = [Scheduler('dummy', None, 120, ['dummy'])] | |
40 | |
41 f1 = factory.QuickBuildFactory('fakerep', 'cvsmodule', configure=None) | |
42 c['builders'] = [ | |
43 BuilderConfig(name='dummy', slavename='bot1', factory=f1, | |
44 builddir='quickdir', slavebuilddir='slavequickdir'), | |
45 ] | |
46 c['slavePortnum'] = 0 | |
47 c['projectUrl'] = 'example.com/yay' | |
48 c['projectName'] = 'Pouet' | |
49 c['buildbotURL'] = 'build.example.com/yo' | |
50 | |
51 def doNothing(self): | |
52 # Creates self.fake_queue to store the object. | |
53 assert IQueue.providedBy(self.queue) | |
54 if not hasattr(self, 'fake_queue'): | |
55 self.fake_queue = [] | |
56 items = self.queue.popChunk() | |
57 self.fake_queue.extend(items) | |
58 self.queueNextServerPush() | |
59 """ | |
60 | |
61 config_no_http = (config_base + """ | |
62 c['status'] = [StatusPush(serverPushCb=doNothing)] | |
63 """) | |
64 | |
65 config_http = (config_base + """ | |
66 c['status'] = [HttpStatusPush('http://127.0.0.1:<PORT>/receiver')] | |
67 """) | |
68 | |
69 config_no_http_no_filter = (config_base + """ | |
70 c['status'] = [StatusPush(serverPushCb=doNothing, filter=False)] | |
71 """) | |
72 | |
73 config_http_no_filter = (config_base + """ | |
74 c['status'] = [HttpStatusPush('http://127.0.0.1:<PORT>/receiver', filter=False)] | |
75 """) | |
76 | |
77 EXPECTED = [ | |
78 { | |
79 'event': 'builderAdded', | |
80 'payload': { | |
81 'builder': { | |
82 "category": None, | |
83 "cachedBuilds": [], | |
84 "basedir": "quickdir", | |
85 "pendingBuilds": [], | |
86 "state": "offline", | |
87 "slaves": ["bot1"], | |
88 "currentBuilds": [] | |
89 }, | |
90 'builderName': 'dummy', | |
91 } | |
92 }, | |
93 { | |
94 "event": "builderChangedState", | |
95 "payload": { | |
96 'state': 'offline', | |
97 'builderName': 'dummy' | |
98 } | |
99 }, | |
100 { | |
101 "event": "start", | |
102 "payload": { | |
103 'status': { | |
104 "buildbotURL": 'build.example.com/yo', | |
105 "projectName": 'Pouet', | |
106 'projectURL': None, | |
107 } | |
108 } | |
109 }, | |
110 { | |
111 'event': 'slaveConnected', | |
112 'payload': { | |
113 'slave': { | |
114 'access_uri': None, | |
115 'admin': 'one', | |
116 'connected': True, | |
117 'host': None, | |
118 'name': 'bot1', | |
119 'runningBuilds': [], | |
120 'version': '0.7.12' | |
121 } | |
122 } | |
123 }, | |
124 { | |
125 'event': 'builderChangedState', | |
126 'payload': { | |
127 'state': 'idle', | |
128 'builderName': 'dummy' | |
129 }, | |
130 }, | |
131 { | |
132 "event": "changeAdded", | |
133 "payload": { | |
134 'change': { | |
135 "category": None, | |
136 "files": ["Makefile", "foo/bar.c"], | |
137 "who": "bob", | |
138 "when": "n0w", | |
139 "number": 1, | |
140 "comments": "changed stuff", | |
141 "branch": None, | |
142 "revlink": "", | |
143 "properties": [], | |
144 "revision": None | |
145 } | |
146 } | |
147 }, | |
148 { | |
149 'event': 'requestSubmitted', | |
150 'payload': { | |
151 'request': { | |
152 'builderName': 'test_builder', | |
153 'builds': [], | |
154 'source': { | |
155 'branch': None, | |
156 'changes': [], | |
157 'hasPatch': False, | |
158 'revision': None | |
159 }, | |
160 'submittedAt': 'yesterday', | |
161 } | |
162 } | |
163 }, | |
164 { | |
165 'event': 'builderChangedState', | |
166 'payload': { | |
167 'state': 'building', | |
168 'builderName': 'dummy' | |
169 } | |
170 }, | |
171 { | |
172 'event': 'buildStarted', | |
173 'payload': { | |
174 'build': { | |
175 'blame': [], | |
176 'builderName': 'dummy', | |
177 'changes': [], | |
178 'currentStep': None, | |
179 'eta': None, | |
180 'number': 0, | |
181 'properties': [ | |
182 ['branch', None, 'Build'], | |
183 ['buildername', 'dummy', 'Build'], | |
184 ['buildnumber', 0, 'Build'], | |
185 ['revision', None, 'Build'], | |
186 ['slavename', 'bot1', 'BuildSlave'] | |
187 ], | |
188 'reason': 'forced build', | |
189 'requests': [ | |
190 { | |
191 'builderName': 'test_builder', | |
192 'builds': [], | |
193 'source': { | |
194 'branch': None, | |
195 'changes': [], | |
196 'hasPatch': False, | |
197 'revision': None | |
198 }, | |
199 'submittedAt': 'yesterday' | |
200 } | |
201 ], | |
202 'results': None, | |
203 'slave': 'bot1', | |
204 'sourceStamp': { | |
205 'branch': None, | |
206 'hasPatch': False, | |
207 'changes': [], | |
208 'revision': None | |
209 }, | |
210 'steps': [ | |
211 { | |
212 'eta': None, | |
213 'expectations': [], | |
214 'isFinished': False, | |
215 'isStarted': False, | |
216 'name': 'cvs', | |
217 'results': [[None, []], []], | |
218 'statistics': {}, | |
219 'text': ['updating'], | |
220 'times': [None, None], | |
221 'urls': {} | |
222 }, | |
223 { | |
224 'eta': None, | |
225 'expectations': [], | |
226 'isFinished': False, | |
227 'isStarted': False, | |
228 'name': 'compile', | |
229 'results': [[None, []], []], | |
230 'statistics': {}, | |
231 'text': ['compiling'], | |
232 'times': [None, None], | |
233 'urls': {} | |
234 }, | |
235 { | |
236 'eta': None, | |
237 'expectations': [], | |
238 'isFinished': False, | |
239 'isStarted': False, | |
240 'name': 'test', | |
241 'results': [[None, []], []], | |
242 'statistics': {}, | |
243 'text': ['testing'], | |
244 'times': [None, None], | |
245 'urls': {} | |
246 } | |
247 ], | |
248 'text': [], | |
249 'times': [123, None] | |
250 } | |
251 } | |
252 }, | |
253 { | |
254 'event': 'stepStarted', | |
255 'payload': { | |
256 'step': { | |
257 'eta': None, | |
258 'expectations': [], | |
259 'isFinished': False, | |
260 'isStarted': True, | |
261 'name': 'cvs', | |
262 'results': [[None, []], []], | |
263 'statistics': {}, | |
264 'text': ['updating'], | |
265 'times': [123, None], | |
266 'urls': {} | |
267 }, | |
268 'properties': [ | |
269 ['branch', None, 'Build'], | |
270 ['buildername', 'dummy', 'Build'], | |
271 ['buildnumber', 0, 'Build'], | |
272 ['revision', None, 'Build'], | |
273 ['slavename', 'bot1', 'BuildSlave'] | |
274 ], | |
275 } | |
276 }, | |
277 { | |
278 'event': 'stepFinished', | |
279 'payload': { | |
280 'step': { | |
281 'eta': None, | |
282 'expectations': [], | |
283 'isFinished': True, | |
284 'isStarted': True, | |
285 'name': 'cvs', | |
286 'results': [2, ['cvs']], | |
287 'statistics': {}, | |
288 'text': ['update', 'failed'], | |
289 'times': [123, None], | |
290 'urls': {} | |
291 }, | |
292 'properties': [ | |
293 ['branch', None, 'Build'], | |
294 ['buildername', 'dummy', 'Build'], | |
295 ['buildnumber', 0, 'Build'], | |
296 ['revision', None, 'Build'], | |
297 ['slavename', 'bot1', 'BuildSlave'] | |
298 ], | |
299 } | |
300 }, | |
301 { | |
302 'event': 'buildFinished', | |
303 'payload': { | |
304 'build': { | |
305 'blame': [], | |
306 'builderName': 'dummy', | |
307 'changes': [], | |
308 'currentStep': None, | |
309 'eta': None, | |
310 'number': 0, | |
311 'properties': [ | |
312 ['branch', None, 'Build'], | |
313 ['buildername', 'dummy', 'Build'], | |
314 ['buildnumber', 0, 'Build'], | |
315 ['revision', None, 'Build'], | |
316 ['slavename', 'bot1', 'BuildSlave'] | |
317 ], | |
318 'reason': 'forced build', | |
319 'requests': [ | |
320 { | |
321 'builderName': 'test_builder', | |
322 'builds': [0], | |
323 'source': { | |
324 'branch': None, | |
325 'hasPatch': False, | |
326 'changes': [], | |
327 'revision': None}, | |
328 'submittedAt': 'yesterday' | |
329 } | |
330 ], | |
331 'results': 2, | |
332 'slave': 'bot1', | |
333 'sourceStamp': { | |
334 'branch': None, | |
335 'changes': [], | |
336 'hasPatch': False, | |
337 'revision': None | |
338 }, | |
339 'steps': [ | |
340 { | |
341 'eta': None, | |
342 'expectations': [], | |
343 'isFinished': True, | |
344 'isStarted': True, | |
345 'name': 'cvs', | |
346 'results': [2, ['cvs']], | |
347 'statistics': {}, | |
348 'text': ['update', 'failed'], | |
349 'times': [345, None], | |
350 'urls': {} | |
351 }, | |
352 { | |
353 'eta': None, | |
354 'expectations': [], | |
355 'isFinished': False, | |
356 'isStarted': False, | |
357 'name': 'compile', | |
358 'results': [[None, []], []], | |
359 'statistics': {}, | |
360 'text': ['compiling'], | |
361 'times': [345, None], | |
362 'urls': {} | |
363 }, | |
364 { | |
365 'eta': None, | |
366 'expectations': [], | |
367 'isFinished': False, | |
368 'isStarted': False, | |
369 'name': 'test', | |
370 'results': [[None, []], []], | |
371 'statistics': {}, | |
372 'text': ['testing'], | |
373 'times': [345, None], | |
374 'urls': {} | |
375 } | |
376 ], | |
377 'text': ['failed', 'cvs'], | |
378 'times': [123, None] | |
379 }, | |
380 } | |
381 }, | |
382 { | |
383 'event': 'builderChangedState', | |
384 'payload': { | |
385 'state': 'idle', | |
386 'builderName': 'dummy' | |
387 } | |
388 }, | |
389 { | |
390 'event': 'slaveDisconnected', | |
391 'payload': { | |
392 'slavename': 'bot1' | |
393 } | |
394 }, | |
395 { | |
396 'event': 'builderChangedState', | |
397 'payload': { | |
398 'state': 'offline', | |
399 'builderName': 'dummy', | |
400 } | |
401 }, | |
402 { | |
403 "event": "shutdown", | |
404 "payload": { | |
405 'status': { | |
406 "buildbotURL": 'build.example.com/yo', | |
407 "projectName": 'Pouet', | |
408 'projectURL': None, | |
409 } | |
410 } | |
411 }, | |
412 ] | |
413 | |
414 EXPECTED_SHORT = [ | |
415 { | |
416 'event': 'builderAdded', | |
417 'payload': { | |
418 'builder': { | |
419 "basedir": "quickdir", | |
420 "state": "offline", | |
421 "slaves": ["bot1"], | |
422 }, | |
423 'builderName': 'dummy', | |
424 } | |
425 }, | |
426 { | |
427 "event": "builderChangedState", | |
428 "payload": { | |
429 'state': 'offline', | |
430 'builderName': 'dummy' | |
431 } | |
432 }, | |
433 { | |
434 "event": "start", | |
435 "payload": { | |
436 'status': { | |
437 "buildbotURL": 'build.example.com/yo', | |
438 "projectName": 'Pouet', | |
439 } | |
440 } | |
441 }, | |
442 { | |
443 'event': 'slaveConnected', | |
444 'payload': { | |
445 'slave': { | |
446 'admin': 'one', | |
447 'connected': True, | |
448 'name': 'bot1', | |
449 'version': '0.7.12' | |
450 } | |
451 } | |
452 }, | |
453 { | |
454 'event': 'builderChangedState', | |
455 'payload': { | |
456 'state': 'idle', | |
457 'builderName': 'dummy' | |
458 }, | |
459 }, | |
460 { | |
461 "event": "changeAdded", | |
462 "payload": { | |
463 'change': { | |
464 "files": ["Makefile", "foo/bar.c"], | |
465 "who": "bob", | |
466 "when": "n0w", | |
467 "number": 1, | |
468 "comments": "changed stuff", | |
469 } | |
470 } | |
471 }, | |
472 { | |
473 'event': 'requestSubmitted', | |
474 'payload': { | |
475 'request': { | |
476 'builderName': 'test_builder', | |
477 'submittedAt': 'yesterday', | |
478 } | |
479 } | |
480 }, | |
481 { | |
482 'event': 'builderChangedState', | |
483 'payload': { | |
484 'state': 'building', | |
485 'builderName': 'dummy' | |
486 } | |
487 }, | |
488 { | |
489 'event': 'buildStarted', | |
490 'payload': { | |
491 'build': { | |
492 'builderName': 'dummy', | |
493 'properties': [ | |
494 ['branch', None, 'Build'], | |
495 ['buildername', 'dummy', 'Build'], | |
496 ['buildnumber', 0, 'Build'], | |
497 ['revision', None, 'Build'], | |
498 ['slavename', 'bot1', 'BuildSlave'] | |
499 ], | |
500 'reason': 'forced build', | |
501 'requests': [ | |
502 { | |
503 'builderName': 'test_builder', | |
504 'submittedAt': 'yesterday' | |
505 } | |
506 ], | |
507 'slave': 'bot1', | |
508 'steps': [ | |
509 { | |
510 'name': 'cvs', | |
511 'text': ['updating'], | |
512 }, | |
513 { | |
514 'name': 'compile', | |
515 'text': ['compiling'], | |
516 }, | |
517 { | |
518 'name': 'test', | |
519 'text': ['testing'], | |
520 } | |
521 ], | |
522 'times': [123, None] | |
523 } | |
524 } | |
525 }, | |
526 { | |
527 'event': 'stepStarted', | |
528 'payload': { | |
529 'step': { | |
530 'isStarted': True, | |
531 'name': 'cvs', | |
532 'text': ['updating'], | |
533 'times': [123, None], | |
534 }, | |
535 'properties': [ | |
536 ['branch', None, 'Build'], | |
537 ['buildername', 'dummy', 'Build'], | |
538 ['buildnumber', 0, 'Build'], | |
539 ['revision', None, 'Build'], | |
540 ['slavename', 'bot1', 'BuildSlave'] | |
541 ], | |
542 } | |
543 }, | |
544 { | |
545 'event': 'stepFinished', | |
546 'payload': { | |
547 'step': { | |
548 'isFinished': True, | |
549 'isStarted': True, | |
550 'name': 'cvs', | |
551 'results': [2, ['cvs']], | |
552 'text': ['update', 'failed'], | |
553 'times': [123, None], | |
554 }, | |
555 'properties': [ | |
556 ['branch', None, 'Build'], | |
557 ['buildername', 'dummy', 'Build'], | |
558 ['buildnumber', 0, 'Build'], | |
559 ['revision', None, 'Build'], | |
560 ['slavename', 'bot1', 'BuildSlave'] | |
561 ], | |
562 } | |
563 }, | |
564 { | |
565 'event': 'buildFinished', | |
566 'payload': { | |
567 'build': { | |
568 'builderName': 'dummy', | |
569 'properties': [ | |
570 ['branch', None, 'Build'], | |
571 ['buildername', 'dummy', 'Build'], | |
572 ['buildnumber', 0, 'Build'], | |
573 ['revision', None, 'Build'], | |
574 ['slavename', 'bot1', 'BuildSlave'] | |
575 ], | |
576 'reason': 'forced build', | |
577 'requests': [ | |
578 { | |
579 'builderName': 'test_builder', | |
580 'submittedAt': 'yesterday' | |
581 } | |
582 ], | |
583 'results': 2, | |
584 'slave': 'bot1', | |
585 'steps': [ | |
586 { | |
587 'isFinished': True, | |
588 'isStarted': True, | |
589 'name': 'cvs', | |
590 'results': [2, ['cvs']], | |
591 'text': ['update', 'failed'], | |
592 'times': [345, None], | |
593 }, | |
594 { | |
595 'name': 'compile', | |
596 'text': ['compiling'], | |
597 }, | |
598 { | |
599 'name': 'test', | |
600 'text': ['testing'], | |
601 } | |
602 ], | |
603 'text': ['failed', 'cvs'], | |
604 'times': [123, None] | |
605 }, | |
606 } | |
607 }, | |
608 { | |
609 'event': 'builderChangedState', | |
610 'payload': { | |
611 'state': 'idle', | |
612 'builderName': 'dummy' | |
613 } | |
614 }, | |
615 { | |
616 'event': 'slaveDisconnected', | |
617 'payload': { | |
618 'slavename': 'bot1' | |
619 } | |
620 }, | |
621 { | |
622 'event': 'builderChangedState', | |
623 'payload': { | |
624 'state': 'offline', | |
625 'builderName': 'dummy', | |
626 } | |
627 }, | |
628 { | |
629 "event": "shutdown", | |
630 "payload": { | |
631 'status': { | |
632 "buildbotURL": 'build.example.com/yo', | |
633 "projectName": 'Pouet', | |
634 } | |
635 } | |
636 }, | |
637 ] | |
638 | |
639 class Receiver(resource.Resource): | |
640 isLeaf = True | |
641 def __init__(self): | |
642 self.packets = [] | |
643 | |
644 def render_POST(self, request): | |
645 for packet in request.args['packets']: | |
646 data = json.loads(packet) | |
647 for p in data: | |
648 self.packets.append(p) | |
649 return "ok" | |
650 | |
651 | |
652 class StatusPushTestBase(RunMixin, unittest.TestCase): | |
653 def getStatusPush(self): | |
654 for i in self.master.services: | |
655 if isinstance(i, status_push.StatusPush): | |
656 return i | |
657 | |
658 def init(self, config): | |
659 # The master. | |
660 self.master.loadConfig(config) | |
661 self.master.readConfig = True | |
662 self.assertTrue(self.getStatusPush()) | |
663 self.master.startService() | |
664 | |
665 def tearDown(self): | |
666 """Similar to RunMixin.tearDown but skip over if self.master is None | |
667 since we do test stopService.""" | |
668 log.msg("doing tearDown") | |
669 if self.master: | |
670 d = self.shutdownAllSlaves() | |
671 d.addCallback(self._tearDown_1) | |
672 d.addCallback(self._tearDown_2) | |
673 return d | |
674 else: | |
675 return defer.succeed(None) | |
676 | |
677 def verifyItems(self, items, expected): | |
678 def QuickFix(item, *args): | |
679 """Strips time-specific values. | |
680 | |
681 None means an array. | |
682 Anything else is a key to a dict.""" | |
683 args = list(args) | |
684 value = args.pop() | |
685 | |
686 def Loop(item, value, *args): | |
687 args = list(args) | |
688 arg = args.pop(0) | |
689 if isinstance(item, list) and arg is None: | |
690 for i in item: | |
691 Loop(i, value, *args) | |
692 elif isinstance(item, dict): | |
693 if len(args) == 0 and arg in item: | |
694 item[arg] = value | |
695 elif arg in item: | |
696 Loop(item[arg], value, *args) | |
697 | |
698 Loop(item, value, *args) | |
699 | |
700 def FindItem(items, event, *args): | |
701 for i in items: | |
702 if i['event'] == event: | |
703 QuickFix(i, *args) | |
704 | |
705 # Cleanup time dependent values. It'd be nice to mock datetime instead. | |
706 for i in range(len(items)): | |
707 item = items[i] | |
708 del item['started'] | |
709 del item['timestamp'] | |
710 self.assertEqual('Pouet', item.pop('project')) | |
711 self.assertEqual(i + 1, item.pop('id')) | |
712 | |
713 FindItem(items, 'changeAdded', 'payload', 'change', 'when', | |
714 'n0w') | |
715 FindItem(items, 'requestSubmitted', 'payload', 'request', | |
716 'submittedAt', 'yesterday') | |
717 | |
718 FindItem(items, 'buildStarted', 'payload', 'build', 'requests', | |
719 None, 'submittedAt', 'yesterday') | |
720 FindItem(items, 'stepStarted', 'payload', 'build', 'requests', | |
721 None, 'submittedAt', 'yesterday') | |
722 FindItem(items, 'stepFinished', 'payload', 'build', 'requests', | |
723 None, 'submittedAt', 'yesterday') | |
724 FindItem(items, 'buildFinished', 'payload', 'build', 'requests', | |
725 None, 'submittedAt', 'yesterday') | |
726 | |
727 FindItem(items, 'buildStarted', 'payload', 'build', 'times', | |
728 [123, None]) | |
729 FindItem(items, 'stepStarted', 'payload', 'build', 'times', | |
730 [123, None]) | |
731 FindItem(items, 'stepStarted', 'payload', 'step', 'times', | |
732 [123, None]) | |
733 FindItem(items, 'stepFinished', 'payload', 'build', 'times', | |
734 [123, None]) | |
735 FindItem(items, 'stepFinished', 'payload', 'step', 'times', | |
736 [123, None]) | |
737 FindItem(items, 'buildFinished', 'payload', 'build', 'times', | |
738 [123, None]) | |
739 | |
740 FindItem(items, 'stepStarted', 'payload', 'build', | |
741 'current_step', 'times', [234, None]) | |
742 FindItem(items, 'stepFinished', 'payload', 'build', | |
743 'current_step', 'times', [234, None]) | |
744 FindItem(items, 'buildFinished', 'payload', 'build', | |
745 'current_step', 'times', [234, None]) | |
746 | |
747 FindItem(items, 'stepStarted', 'payload', 'build', 'steps', None, | |
748 'times', [345, None]) | |
749 FindItem(items, 'stepFinished', 'payload', 'build', 'steps', | |
750 None, 'times', [345, None]) | |
751 FindItem(items, 'buildFinished', 'payload', 'build', 'steps', | |
752 None, 'times', [345, None]) | |
753 | |
754 for i in range(min(len(expected), len(items))): | |
755 self.assertEqual(expected[i], items[i], str(i)) | |
756 self.assertEqual(len(expected), len(items)) | |
757 | |
758 | |
759 class StatusPushTest(StatusPushTestBase): | |
760 def testNotFiltered(self): | |
761 self.expected = EXPECTED | |
762 self.init(config_no_http_no_filter) | |
763 d = self.connectSlave() | |
764 d.addCallbacks(self._testPhase1) | |
765 return d | |
766 | |
767 def testFiltered(self): | |
768 self.expected = EXPECTED_SHORT | |
769 self.init(config_no_http) | |
770 d = self.connectSlave() | |
771 d.addCallbacks(self._testPhase1) | |
772 return d | |
773 | |
774 def _testPhase1(self, d): | |
775 # Now the slave is connected, trigger a change. | |
776 cm = self.master.change_svc | |
777 c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff") | |
778 cm.addChange(c) | |
779 d = self.requestBuild("dummy") | |
780 d.addCallback(self._testPhase2) | |
781 return d | |
782 | |
783 def _testPhase2(self, d): | |
784 d = self.shutdownAllSlaves() | |
785 d.addCallback(lambda x: self.master.stopService()) | |
786 d.addCallback(self._testPhase3) | |
787 return d | |
788 | |
789 def _testPhase3(self, d): | |
790 def TupleToList(items): | |
791 if isinstance(items, (list, tuple)): | |
792 return [TupleToList(i) for i in items] | |
793 if isinstance(items, dict): | |
794 return dict([(k, TupleToList(v)) | |
795 for (k, v) in items.iteritems()]) | |
796 else: | |
797 return items | |
798 self.assertEqual(0, self.getStatusPush().queue.nbItems()) | |
799 # Grabs fake_queue created in DoNothing(). | |
800 self.verifyItems(TupleToList(self.getStatusPush().fake_queue), | |
801 self.expected) | |
802 self.master = None | |
803 | |
804 | |
805 class HttpStatusPushTest(StatusPushTestBase): | |
806 def setUp(self): | |
807 StatusPushTestBase.setUp(self) | |
808 self.server = None | |
809 | |
810 def tearDown(self): | |
811 StatusPushTestBase.tearDown(self) | |
812 state_path = os.path.join(self.path, 'state') | |
813 state = json.loads(ReadFile(state_path)) | |
814 del state['started'] | |
815 self.assertEqual({"last_id_pushed": 0, "next_id": 17, }, state) | |
816 os.remove(state_path) | |
817 self.assertEqual([], os.listdir(self.path)) | |
818 | |
819 def testNotFiltered(self): | |
820 self.expected = EXPECTED | |
821 path = os.path.join(os.path.dirname(__file__), 'status_push_server.py') | |
822 self.site = server.Site(Receiver()) | |
823 self.server = reactor.listenTCP(0, self.site) | |
824 self.port = self.server.getHost().port | |
825 self.init(config_http_no_filter.replace('<PORT>', str(self.port))) | |
826 d = self.connectSlave() | |
827 d.addCallbacks(self._testPhase1) | |
828 return d | |
829 | |
830 def testFiltered(self): | |
831 self.expected = EXPECTED_SHORT | |
832 path = os.path.join(os.path.dirname(__file__), 'status_push_server.py') | |
833 self.site = server.Site(Receiver()) | |
834 self.server = reactor.listenTCP(0, self.site) | |
835 self.port = self.server.getHost().port | |
836 self.init(config_http.replace('<PORT>', str(self.port))) | |
837 d = self.connectSlave() | |
838 d.addCallbacks(self._testPhase1) | |
839 return d | |
840 | |
841 def _testPhase1(self, d): | |
842 g = self.getStatusPush() | |
843 self.path = g.path | |
844 # Now the slave is connected, trigger a change. | |
845 cm = self.master.change_svc | |
846 c = changes.Change("bob", ["Makefile", "foo/bar.c"], "changed stuff") | |
847 cm.addChange(c) | |
848 d = self.requestBuild("dummy") | |
849 d.addCallback(self._testPhase2) | |
850 return d | |
851 | |
852 def _testPhase2(self, d): | |
853 d = self.shutdownAllSlaves() | |
854 d.addCallback(lambda x: self.master.stopService()) | |
855 d.addCallback(self._testPhase3) | |
856 d.addCallback(lambda x: self.server.stopListening()) | |
857 return d | |
858 | |
859 def _testPhase3(self, d): | |
860 g = self.getStatusPush() | |
861 # Assert all the items were pushed. | |
862 self.assertEqual(0, g.queue.nbItems()) | |
863 self.verifyItems(self.site.resource.packets, self.expected) | |
864 self.master = None | |
865 | |
866 # vim: set ts=4 sts=4 sw=4 et: | |
OLD | NEW |