xref: /openbmc/openbmc/poky/bitbake/lib/bb/tests/event.py (revision eb8dc403)
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3#
4# BitBake Tests for the Event implementation (event.py)
5#
6# Copyright (C) 2017 Intel Corporation
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20#
21
22import unittest
23import bb
24import logging
25import bb.compat
26import bb.event
27import importlib
28import threading
29import time
30import pickle
31from unittest.mock import Mock
32from unittest.mock import call
33from bb.msg import BBLogFormatter
34
35
36class EventQueueStubBase(object):
37    """ Base class for EventQueueStub classes """
38    def __init__(self):
39        self.event_calls = []
40        return
41
42    def _store_event_data_string(self, event):
43        if isinstance(event, logging.LogRecord):
44            formatter = BBLogFormatter("%(levelname)s: %(message)s")
45            self.event_calls.append(formatter.format(event))
46        else:
47            self.event_calls.append(bb.event.getName(event))
48        return
49
50
51class EventQueueStub(EventQueueStubBase):
52    """ Class used as specification for UI event handler queue stub objects """
53    def __init__(self):
54        super(EventQueueStub, self).__init__()
55
56    def send(self, event):
57        super(EventQueueStub, self)._store_event_data_string(event)
58
59
60class PickleEventQueueStub(EventQueueStubBase):
61    """ Class used as specification for UI event handler queue stub objects
62        with sendpickle method """
63    def __init__(self):
64        super(PickleEventQueueStub, self).__init__()
65
66    def sendpickle(self, pickled_event):
67        event = pickle.loads(pickled_event)
68        super(PickleEventQueueStub, self)._store_event_data_string(event)
69
70
71class UIClientStub(object):
72    """ Class used as specification for UI event handler stub objects """
73    def __init__(self):
74        self.event = None
75
76
77class EventHandlingTest(unittest.TestCase):
78    """ Event handling test class """
79
80
81    def setUp(self):
82        self._test_process = Mock()
83        ui_client1 = UIClientStub()
84        ui_client2 = UIClientStub()
85        self._test_ui1 = Mock(wraps=ui_client1)
86        self._test_ui2 = Mock(wraps=ui_client2)
87        importlib.reload(bb.event)
88
89    def _create_test_handlers(self):
90        """ Method used to create a test handler ordered dictionary """
91        test_handlers = bb.compat.OrderedDict()
92        test_handlers["handler1"] = self._test_process.handler1
93        test_handlers["handler2"] = self._test_process.handler2
94        return test_handlers
95
96    def test_class_handlers(self):
97        """ Test set_class_handlers and get_class_handlers methods """
98        test_handlers = self._create_test_handlers()
99        bb.event.set_class_handlers(test_handlers)
100        self.assertEqual(test_handlers,
101                         bb.event.get_class_handlers())
102
103    def test_handlers(self):
104        """ Test set_handlers and get_handlers """
105        test_handlers = self._create_test_handlers()
106        bb.event.set_handlers(test_handlers)
107        self.assertEqual(test_handlers,
108                         bb.event.get_handlers())
109
110    def test_clean_class_handlers(self):
111        """ Test clean_class_handlers method """
112        cleanDict = bb.compat.OrderedDict()
113        self.assertEqual(cleanDict,
114                         bb.event.clean_class_handlers())
115
116    def test_register(self):
117        """ Test register method for class handlers """
118        result = bb.event.register("handler", self._test_process.handler)
119        self.assertEqual(result, bb.event.Registered)
120        handlers_dict = bb.event.get_class_handlers()
121        self.assertIn("handler", handlers_dict)
122
123    def test_already_registered(self):
124        """ Test detection of an already registed class handler """
125        bb.event.register("handler", self._test_process.handler)
126        handlers_dict = bb.event.get_class_handlers()
127        self.assertIn("handler", handlers_dict)
128        result = bb.event.register("handler", self._test_process.handler)
129        self.assertEqual(result, bb.event.AlreadyRegistered)
130
131    def test_register_from_string(self):
132        """ Test register method receiving code in string """
133        result = bb.event.register("string_handler", "    return True")
134        self.assertEqual(result, bb.event.Registered)
135        handlers_dict = bb.event.get_class_handlers()
136        self.assertIn("string_handler", handlers_dict)
137
138    def test_register_with_mask(self):
139        """ Test register method with event masking """
140        mask = ["bb.event.OperationStarted",
141                "bb.event.OperationCompleted"]
142        result = bb.event.register("event_handler",
143                                   self._test_process.event_handler,
144                                   mask)
145        self.assertEqual(result, bb.event.Registered)
146        handlers_dict = bb.event.get_class_handlers()
147        self.assertIn("event_handler", handlers_dict)
148
149    def test_remove(self):
150        """ Test remove method for class handlers """
151        test_handlers = self._create_test_handlers()
152        bb.event.set_class_handlers(test_handlers)
153        count = len(test_handlers)
154        bb.event.remove("handler1", None)
155        test_handlers = bb.event.get_class_handlers()
156        self.assertEqual(len(test_handlers), count - 1)
157        with self.assertRaises(KeyError):
158            bb.event.remove("handler1", None)
159
160    def test_execute_handler(self):
161        """ Test execute_handler method for class handlers """
162        mask = ["bb.event.OperationProgress"]
163        result = bb.event.register("event_handler",
164                                   self._test_process.event_handler,
165                                   mask)
166        self.assertEqual(result, bb.event.Registered)
167        event = bb.event.OperationProgress(current=10, total=100)
168        bb.event.execute_handler("event_handler",
169                                 self._test_process.event_handler,
170                                 event,
171                                 None)
172        self._test_process.event_handler.assert_called_once_with(event)
173
174    def test_fire_class_handlers(self):
175        """ Test fire_class_handlers method """
176        mask = ["bb.event.OperationStarted"]
177        result = bb.event.register("event_handler1",
178                                   self._test_process.event_handler1,
179                                   mask)
180        self.assertEqual(result, bb.event.Registered)
181        result = bb.event.register("event_handler2",
182                                   self._test_process.event_handler2,
183                                   "*")
184        self.assertEqual(result, bb.event.Registered)
185        event1 = bb.event.OperationStarted()
186        event2 = bb.event.OperationCompleted(total=123)
187        bb.event.fire_class_handlers(event1, None)
188        bb.event.fire_class_handlers(event2, None)
189        bb.event.fire_class_handlers(event2, None)
190        expected_event_handler1 = [call(event1)]
191        expected_event_handler2 = [call(event1),
192                                   call(event2),
193                                   call(event2)]
194        self.assertEqual(self._test_process.event_handler1.call_args_list,
195                         expected_event_handler1)
196        self.assertEqual(self._test_process.event_handler2.call_args_list,
197                         expected_event_handler2)
198
199    def test_class_handler_filters(self):
200        """ Test filters for class handlers """
201        mask = ["bb.event.OperationStarted"]
202        result = bb.event.register("event_handler1",
203                                   self._test_process.event_handler1,
204                                   mask)
205        self.assertEqual(result, bb.event.Registered)
206        result = bb.event.register("event_handler2",
207                                   self._test_process.event_handler2,
208                                   "*")
209        self.assertEqual(result, bb.event.Registered)
210        bb.event.set_eventfilter(
211            lambda name, handler, event, d :
212            name == 'event_handler2' and
213            bb.event.getName(event) == "OperationStarted")
214        event1 = bb.event.OperationStarted()
215        event2 = bb.event.OperationCompleted(total=123)
216        bb.event.fire_class_handlers(event1, None)
217        bb.event.fire_class_handlers(event2, None)
218        bb.event.fire_class_handlers(event2, None)
219        expected_event_handler1 = []
220        expected_event_handler2 = [call(event1)]
221        self.assertEqual(self._test_process.event_handler1.call_args_list,
222                         expected_event_handler1)
223        self.assertEqual(self._test_process.event_handler2.call_args_list,
224                         expected_event_handler2)
225
226    def test_change_handler_event_mapping(self):
227        """ Test changing the event mapping for class handlers """
228        event1 = bb.event.OperationStarted()
229        event2 = bb.event.OperationCompleted(total=123)
230
231        # register handler for all events
232        result = bb.event.register("event_handler1",
233                                   self._test_process.event_handler1,
234                                   "*")
235        self.assertEqual(result, bb.event.Registered)
236        bb.event.fire_class_handlers(event1, None)
237        bb.event.fire_class_handlers(event2, None)
238        expected = [call(event1), call(event2)]
239        self.assertEqual(self._test_process.event_handler1.call_args_list,
240                         expected)
241
242        # unregister handler and register it only for OperationStarted
243        bb.event.remove("event_handler1",
244                        self._test_process.event_handler1)
245        mask = ["bb.event.OperationStarted"]
246        result = bb.event.register("event_handler1",
247                                   self._test_process.event_handler1,
248                                   mask)
249        self.assertEqual(result, bb.event.Registered)
250        bb.event.fire_class_handlers(event1, None)
251        bb.event.fire_class_handlers(event2, None)
252        expected = [call(event1), call(event2), call(event1)]
253        self.assertEqual(self._test_process.event_handler1.call_args_list,
254                         expected)
255
256        # unregister handler and register it only for OperationCompleted
257        bb.event.remove("event_handler1",
258                        self._test_process.event_handler1)
259        mask = ["bb.event.OperationCompleted"]
260        result = bb.event.register("event_handler1",
261                                   self._test_process.event_handler1,
262                                   mask)
263        self.assertEqual(result, bb.event.Registered)
264        bb.event.fire_class_handlers(event1, None)
265        bb.event.fire_class_handlers(event2, None)
266        expected = [call(event1), call(event2), call(event1), call(event2)]
267        self.assertEqual(self._test_process.event_handler1.call_args_list,
268                         expected)
269
270    def test_register_UIHhandler(self):
271        """ Test register_UIHhandler method """
272        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
273        self.assertEqual(result, 1)
274
275    def test_UIHhandler_already_registered(self):
276        """ Test registering an UIHhandler already existing """
277        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
278        self.assertEqual(result, 1)
279        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
280        self.assertEqual(result, 2)
281
282    def test_unregister_UIHhandler(self):
283        """ Test unregister_UIHhandler method """
284        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
285        self.assertEqual(result, 1)
286        result = bb.event.unregister_UIHhandler(1)
287        self.assertIs(result, None)
288
289    def test_fire_ui_handlers(self):
290        """ Test fire_ui_handlers method """
291        self._test_ui1.event = Mock(spec_set=EventQueueStub)
292        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
293        self.assertEqual(result, 1)
294        self._test_ui2.event = Mock(spec_set=PickleEventQueueStub)
295        result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
296        self.assertEqual(result, 2)
297        event1 = bb.event.OperationStarted()
298        bb.event.fire_ui_handlers(event1, None)
299        expected = [call(event1)]
300        self.assertEqual(self._test_ui1.event.send.call_args_list,
301                         expected)
302        expected = [call(pickle.dumps(event1))]
303        self.assertEqual(self._test_ui2.event.sendpickle.call_args_list,
304                         expected)
305
306    def test_ui_handler_mask_filter(self):
307        """ Test filters for UI handlers """
308        mask = ["bb.event.OperationStarted"]
309        debug_domains = {}
310        self._test_ui1.event = Mock(spec_set=EventQueueStub)
311        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
312        bb.event.set_UIHmask(result, logging.INFO, debug_domains, mask)
313        self._test_ui2.event = Mock(spec_set=PickleEventQueueStub)
314        result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
315        bb.event.set_UIHmask(result, logging.INFO, debug_domains, mask)
316
317        event1 = bb.event.OperationStarted()
318        event2 = bb.event.OperationCompleted(total=1)
319
320        bb.event.fire_ui_handlers(event1, None)
321        bb.event.fire_ui_handlers(event2, None)
322        expected = [call(event1)]
323        self.assertEqual(self._test_ui1.event.send.call_args_list,
324                         expected)
325        expected = [call(pickle.dumps(event1))]
326        self.assertEqual(self._test_ui2.event.sendpickle.call_args_list,
327                         expected)
328
329    def test_ui_handler_log_filter(self):
330        """ Test log filters for UI handlers """
331        mask = ["*"]
332        debug_domains = {'BitBake.Foo': logging.WARNING}
333
334        self._test_ui1.event = EventQueueStub()
335        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
336        bb.event.set_UIHmask(result, logging.ERROR, debug_domains, mask)
337        self._test_ui2.event = PickleEventQueueStub()
338        result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
339        bb.event.set_UIHmask(result, logging.ERROR, debug_domains, mask)
340
341        event1 = bb.event.OperationStarted()
342        bb.event.fire_ui_handlers(event1, None)   # All events match
343
344        event_log_handler = bb.event.LogHandler()
345        logger = logging.getLogger("BitBake")
346        logger.addHandler(event_log_handler)
347        logger1 = logging.getLogger("BitBake.Foo")
348        logger1.warning("Test warning LogRecord1") # Matches debug_domains level
349        logger1.info("Test info LogRecord")        # Filtered out
350        logger2 = logging.getLogger("BitBake.Bar")
351        logger2.error("Test error LogRecord")      # Matches filter base level
352        logger2.warning("Test warning LogRecord2") # Filtered out
353        logger.removeHandler(event_log_handler)
354
355        expected = ['OperationStarted',
356                    'WARNING: Test warning LogRecord1',
357                    'ERROR: Test error LogRecord']
358        self.assertEqual(self._test_ui1.event.event_calls, expected)
359        self.assertEqual(self._test_ui2.event.event_calls, expected)
360
361    def test_fire(self):
362        """ Test fire method used to trigger class and ui event handlers """
363        mask = ["bb.event.ConfigParsed"]
364        result = bb.event.register("event_handler1",
365                                   self._test_process.event_handler1,
366                                   mask)
367
368        self._test_ui1.event = Mock(spec_set=EventQueueStub)
369        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
370        self.assertEqual(result, 1)
371
372        event1 = bb.event.ConfigParsed()
373        bb.event.fire(event1, None)
374        expected = [call(event1)]
375        self.assertEqual(self._test_process.event_handler1.call_args_list,
376                         expected)
377        self.assertEqual(self._test_ui1.event.send.call_args_list,
378                         expected)
379
380    def test_fire_from_worker(self):
381        """ Test fire_from_worker method """
382        self._test_ui1.event = Mock(spec_set=EventQueueStub)
383        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
384        self.assertEqual(result, 1)
385        event1 = bb.event.ConfigParsed()
386        bb.event.fire_from_worker(event1, None)
387        expected = [call(event1)]
388        self.assertEqual(self._test_ui1.event.send.call_args_list,
389                         expected)
390
391    def test_worker_fire(self):
392        """ Test the triggering of bb.event.worker_fire callback """
393        bb.event.worker_fire = Mock()
394        event = bb.event.Event()
395        bb.event.fire(event, None)
396        expected = [call(event, None)]
397        self.assertEqual(bb.event.worker_fire.call_args_list, expected)
398
399    def test_print_ui_queue(self):
400        """ Test print_ui_queue method """
401        event1 = bb.event.OperationStarted()
402        event2 = bb.event.OperationCompleted(total=123)
403        bb.event.fire(event1, None)
404        bb.event.fire(event2, None)
405        event_log_handler = bb.event.LogHandler()
406        logger = logging.getLogger("BitBake")
407        logger.addHandler(event_log_handler)
408        logger.info("Test info LogRecord")
409        logger.warning("Test warning LogRecord")
410        with self.assertLogs("BitBake", level="INFO") as cm:
411            bb.event.print_ui_queue()
412        logger.removeHandler(event_log_handler)
413        self.assertEqual(cm.output,
414                         ["INFO:BitBake:Test info LogRecord",
415                          "WARNING:BitBake:Test warning LogRecord"])
416
417    def _set_threadlock_test_mockups(self):
418        """ Create UI event handler mockups used in enable and disable
419            threadlock tests """
420        def ui1_event_send(event):
421            if type(event) is bb.event.ConfigParsed:
422                self._threadlock_test_calls.append("w1_ui1")
423            if type(event) is bb.event.OperationStarted:
424                self._threadlock_test_calls.append("w2_ui1")
425            time.sleep(2)
426
427        def ui2_event_send(event):
428            if type(event) is bb.event.ConfigParsed:
429                self._threadlock_test_calls.append("w1_ui2")
430            if type(event) is bb.event.OperationStarted:
431                self._threadlock_test_calls.append("w2_ui2")
432            time.sleep(2)
433
434        self._threadlock_test_calls = []
435        self._test_ui1.event = EventQueueStub()
436        self._test_ui1.event.send = ui1_event_send
437        result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
438        self.assertEqual(result, 1)
439        self._test_ui2.event = EventQueueStub()
440        self._test_ui2.event.send = ui2_event_send
441        result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
442        self.assertEqual(result, 2)
443
444    def _set_and_run_threadlock_test_workers(self):
445        """ Create and run the workers used to trigger events in enable and
446            disable threadlock tests """
447        worker1 = threading.Thread(target=self._thread_lock_test_worker1)
448        worker2 = threading.Thread(target=self._thread_lock_test_worker2)
449        worker1.start()
450        time.sleep(1)
451        worker2.start()
452        worker1.join()
453        worker2.join()
454
455    def _thread_lock_test_worker1(self):
456        """ First worker used to fire the ConfigParsed event for enable and
457            disable threadlocks tests """
458        bb.event.fire(bb.event.ConfigParsed(), None)
459
460    def _thread_lock_test_worker2(self):
461        """ Second worker used to fire the OperationStarted event for enable
462            and disable threadlocks tests """
463        bb.event.fire(bb.event.OperationStarted(), None)
464
465    def test_enable_threadlock(self):
466        """ Test enable_threadlock method """
467        self._set_threadlock_test_mockups()
468        bb.event.enable_threadlock()
469        self._set_and_run_threadlock_test_workers()
470        # Calls to UI handlers should be in order as all the registered
471        # handlers for the event coming from the first worker should be
472        # called before processing the event from the second worker.
473        self.assertEqual(self._threadlock_test_calls,
474                         ["w1_ui1", "w1_ui2", "w2_ui1", "w2_ui2"])
475
476
477    def test_disable_threadlock(self):
478        """ Test disable_threadlock method """
479        self._set_threadlock_test_mockups()
480        bb.event.disable_threadlock()
481        self._set_and_run_threadlock_test_workers()
482        # Calls to UI handlers should be intertwined together. Thanks to the
483        # delay in the registered handlers for the event coming from the first
484        # worker, the event coming from the second worker starts being
485        # processed before finishing handling the first worker event.
486        self.assertEqual(self._threadlock_test_calls,
487                         ["w1_ui1", "w2_ui1", "w1_ui2", "w2_ui2"])
488
489
490class EventClassesTest(unittest.TestCase):
491    """ Event classes test class """
492
493    _worker_pid = 54321
494
495    def setUp(self):
496        bb.event.worker_pid = EventClassesTest._worker_pid
497
498    def test_Event(self):
499        """ Test the Event base class """
500        event = bb.event.Event()
501        self.assertEqual(event.pid, EventClassesTest._worker_pid)
502
503    def test_HeartbeatEvent(self):
504        """ Test the HeartbeatEvent class """
505        time = 10
506        event = bb.event.HeartbeatEvent(time)
507        self.assertEqual(event.time, time)
508        self.assertEqual(event.pid, EventClassesTest._worker_pid)
509
510    def test_OperationStarted(self):
511        """ Test OperationStarted event class """
512        msg = "Foo Bar"
513        event = bb.event.OperationStarted(msg)
514        self.assertEqual(event.msg, msg)
515        self.assertEqual(event.pid, EventClassesTest._worker_pid)
516
517    def test_OperationCompleted(self):
518        """ Test OperationCompleted event class """
519        msg = "Foo Bar"
520        total = 123
521        event = bb.event.OperationCompleted(total, msg)
522        self.assertEqual(event.msg, msg)
523        self.assertEqual(event.total, total)
524        self.assertEqual(event.pid, EventClassesTest._worker_pid)
525
526    def test_OperationProgress(self):
527        """ Test OperationProgress event class """
528        msg = "Foo Bar"
529        total = 123
530        current = 111
531        event = bb.event.OperationProgress(current, total, msg)
532        self.assertEqual(event.msg, msg + ": %s/%s" % (current, total))
533        self.assertEqual(event.pid, EventClassesTest._worker_pid)
534
535    def test_ConfigParsed(self):
536        """ Test the ConfigParsed class """
537        event = bb.event.ConfigParsed()
538        self.assertEqual(event.pid, EventClassesTest._worker_pid)
539
540    def test_MultiConfigParsed(self):
541        """ Test MultiConfigParsed event class """
542        mcdata = {"foobar": "Foo Bar"}
543        event = bb.event.MultiConfigParsed(mcdata)
544        self.assertEqual(event.mcdata, mcdata)
545        self.assertEqual(event.pid, EventClassesTest._worker_pid)
546
547    def test_RecipeEvent(self):
548        """ Test RecipeEvent event base class """
549        callback = lambda a: 2 * a
550        event = bb.event.RecipeEvent(callback)
551        self.assertEqual(event.fn(1), callback(1))
552        self.assertEqual(event.pid, EventClassesTest._worker_pid)
553
554    def test_RecipePreFinalise(self):
555        """ Test RecipePreFinalise event class """
556        callback = lambda a: 2 * a
557        event = bb.event.RecipePreFinalise(callback)
558        self.assertEqual(event.fn(1), callback(1))
559        self.assertEqual(event.pid, EventClassesTest._worker_pid)
560
561    def test_RecipeTaskPreProcess(self):
562        """ Test RecipeTaskPreProcess event class """
563        callback = lambda a: 2 * a
564        tasklist = [("foobar", callback)]
565        event = bb.event.RecipeTaskPreProcess(callback, tasklist)
566        self.assertEqual(event.fn(1), callback(1))
567        self.assertEqual(event.tasklist, tasklist)
568        self.assertEqual(event.pid, EventClassesTest._worker_pid)
569
570    def test_RecipeParsed(self):
571        """ Test RecipeParsed event base class """
572        callback = lambda a: 2 * a
573        event = bb.event.RecipeParsed(callback)
574        self.assertEqual(event.fn(1), callback(1))
575        self.assertEqual(event.pid, EventClassesTest._worker_pid)
576
577    def test_StampUpdate(self):
578        targets = ["foo", "bar"]
579        stampfns = [lambda:"foobar"]
580        event = bb.event.StampUpdate(targets, stampfns)
581        self.assertEqual(event.targets, targets)
582        self.assertEqual(event.stampPrefix, stampfns)
583        self.assertEqual(event.pid, EventClassesTest._worker_pid)
584
585    def test_BuildBase(self):
586        """ Test base class for bitbake build events """
587        name = "foo"
588        pkgs = ["bar"]
589        failures = 123
590        event = bb.event.BuildBase(name, pkgs, failures)
591        self.assertEqual(event.name, name)
592        self.assertEqual(event.pkgs, pkgs)
593        self.assertEqual(event.getFailures(), failures)
594        name = event.name = "bar"
595        pkgs = event.pkgs = ["foo"]
596        self.assertEqual(event.name, name)
597        self.assertEqual(event.pkgs, pkgs)
598        self.assertEqual(event.getFailures(), failures)
599        self.assertEqual(event.pid, EventClassesTest._worker_pid)
600
601    def test_BuildInit(self):
602        """ Test class for bitbake build invocation events """
603        event = bb.event.BuildInit()
604        self.assertEqual(event.name, None)
605        self.assertEqual(event.pkgs, [])
606        self.assertEqual(event.getFailures(), 0)
607        name = event.name = "bar"
608        pkgs = event.pkgs = ["foo"]
609        self.assertEqual(event.name, name)
610        self.assertEqual(event.pkgs, pkgs)
611        self.assertEqual(event.getFailures(), 0)
612        self.assertEqual(event.pid, EventClassesTest._worker_pid)
613
614    def test_BuildStarted(self):
615        """ Test class for build started events """
616        name = "foo"
617        pkgs = ["bar"]
618        failures = 123
619        event = bb.event.BuildStarted(name, pkgs, failures)
620        self.assertEqual(event.name, name)
621        self.assertEqual(event.pkgs, pkgs)
622        self.assertEqual(event.getFailures(), failures)
623        self.assertEqual(event.msg, "Building Started")
624        name = event.name = "bar"
625        pkgs = event.pkgs = ["foo"]
626        msg = event.msg = "foobar"
627        self.assertEqual(event.name, name)
628        self.assertEqual(event.pkgs, pkgs)
629        self.assertEqual(event.getFailures(), failures)
630        self.assertEqual(event.msg, msg)
631        self.assertEqual(event.pid, EventClassesTest._worker_pid)
632
633    def test_BuildCompleted(self):
634        """ Test class for build completed events """
635        total = 1000
636        name = "foo"
637        pkgs = ["bar"]
638        failures = 123
639        interrupted = 1
640        event = bb.event.BuildCompleted(total, name, pkgs, failures,
641                                        interrupted)
642        self.assertEqual(event.name, name)
643        self.assertEqual(event.pkgs, pkgs)
644        self.assertEqual(event.getFailures(), failures)
645        self.assertEqual(event.msg, "Building Failed")
646        event2 = bb.event.BuildCompleted(total, name, pkgs)
647        self.assertEqual(event2.name, name)
648        self.assertEqual(event2.pkgs, pkgs)
649        self.assertEqual(event2.getFailures(), 0)
650        self.assertEqual(event2.msg, "Building Succeeded")
651        self.assertEqual(event2.pid, EventClassesTest._worker_pid)
652
653    def test_DiskFull(self):
654        """ Test DiskFull event class """
655        dev = "/dev/foo"
656        type = "ext4"
657        freespace = "104M"
658        mountpoint = "/"
659        event = bb.event.DiskFull(dev, type, freespace, mountpoint)
660        self.assertEqual(event.pid, EventClassesTest._worker_pid)
661
662    def test_MonitorDiskEvent(self):
663        """ Test MonitorDiskEvent class """
664        available_bytes = 10000000
665        free_bytes = 90000000
666        total_bytes = 1000000000
667        du = bb.event.DiskUsageSample(available_bytes, free_bytes,
668                                      total_bytes)
669        event = bb.event.MonitorDiskEvent(du)
670        self.assertEqual(event.disk_usage.available_bytes, available_bytes)
671        self.assertEqual(event.disk_usage.free_bytes, free_bytes)
672        self.assertEqual(event.disk_usage.total_bytes, total_bytes)
673        self.assertEqual(event.pid, EventClassesTest._worker_pid)
674
675    def test_NoProvider(self):
676        """ Test NoProvider event class """
677        item = "foobar"
678        event1 = bb.event.NoProvider(item)
679        self.assertEqual(event1.getItem(), item)
680        self.assertEqual(event1.isRuntime(), False)
681        self.assertEqual(str(event1), "Nothing PROVIDES 'foobar'")
682        runtime = True
683        dependees = ["foo", "bar"]
684        reasons = None
685        close_matches = ["foibar", "footbar"]
686        event2 = bb.event.NoProvider(item, runtime, dependees, reasons,
687                                     close_matches)
688        self.assertEqual(event2.isRuntime(), True)
689        expected = ("Nothing RPROVIDES 'foobar' (but foo, bar RDEPENDS"
690                    " on or otherwise requires it). Close matches:\n"
691                    "  foibar\n"
692                    "  footbar")
693        self.assertEqual(str(event2), expected)
694        reasons = ["Item does not exist on database"]
695        close_matches = ["foibar", "footbar"]
696        event3 = bb.event.NoProvider(item, runtime, dependees, reasons,
697                                     close_matches)
698        expected = ("Nothing RPROVIDES 'foobar' (but foo, bar RDEPENDS"
699                    " on or otherwise requires it)\n"
700                    "Item does not exist on database")
701        self.assertEqual(str(event3), expected)
702        self.assertEqual(event3.pid, EventClassesTest._worker_pid)
703
704    def test_MultipleProviders(self):
705        """ Test MultipleProviders event class """
706        item = "foobar"
707        candidates = ["foobarv1", "foobars"]
708        event1 = bb.event.MultipleProviders(item, candidates)
709        self.assertEqual(event1.isRuntime(), False)
710        self.assertEqual(event1.getItem(), item)
711        self.assertEqual(event1.getCandidates(), candidates)
712        expected = ("Multiple providers are available for foobar (foobarv1,"
713                    " foobars)\n"
714                    "Consider defining a PREFERRED_PROVIDER entry to match "
715                    "foobar")
716        self.assertEqual(str(event1), expected)
717        runtime = True
718        event2 = bb.event.MultipleProviders(item, candidates, runtime)
719        self.assertEqual(event2.isRuntime(), runtime)
720        expected = ("Multiple providers are available for runtime foobar "
721                    "(foobarv1, foobars)\n"
722                    "Consider defining a PREFERRED_RPROVIDER entry to match "
723                    "foobar")
724        self.assertEqual(str(event2), expected)
725        self.assertEqual(event2.pid, EventClassesTest._worker_pid)
726
727    def test_ParseStarted(self):
728        """ Test ParseStarted event class """
729        total = 123
730        event = bb.event.ParseStarted(total)
731        self.assertEqual(event.msg, "Recipe parsing Started")
732        self.assertEqual(event.total, total)
733        self.assertEqual(event.pid, EventClassesTest._worker_pid)
734
735    def test_ParseCompleted(self):
736        """ Test ParseCompleted event class """
737        cached = 10
738        parsed = 13
739        skipped = 7
740        virtuals = 2
741        masked = 1
742        errors = 0
743        total = 23
744        event = bb.event.ParseCompleted(cached, parsed, skipped, masked,
745                                        virtuals, errors, total)
746        self.assertEqual(event.msg, "Recipe parsing Completed")
747        expected = [cached, parsed, skipped, virtuals, masked, errors,
748                    cached + parsed, total]
749        actual = [event.cached, event.parsed, event.skipped, event.virtuals,
750                  event.masked, event.errors, event.sofar, event.total]
751        self.assertEqual(str(actual), str(expected))
752        self.assertEqual(event.pid, EventClassesTest._worker_pid)
753
754    def test_ParseProgress(self):
755        """ Test ParseProgress event class """
756        current = 10
757        total = 100
758        event = bb.event.ParseProgress(current, total)
759        self.assertEqual(event.msg,
760                         "Recipe parsing" + ": %s/%s" % (current, total))
761        self.assertEqual(event.pid, EventClassesTest._worker_pid)
762
763    def test_CacheLoadStarted(self):
764        """ Test CacheLoadStarted event class """
765        total = 123
766        event = bb.event.CacheLoadStarted(total)
767        self.assertEqual(event.msg, "Loading cache Started")
768        self.assertEqual(event.total, total)
769        self.assertEqual(event.pid, EventClassesTest._worker_pid)
770
771    def test_CacheLoadProgress(self):
772        """ Test CacheLoadProgress event class """
773        current = 10
774        total = 100
775        event = bb.event.CacheLoadProgress(current, total)
776        self.assertEqual(event.msg,
777                         "Loading cache" + ": %s/%s" % (current, total))
778        self.assertEqual(event.pid, EventClassesTest._worker_pid)
779
780    def test_CacheLoadCompleted(self):
781        """ Test CacheLoadCompleted event class """
782        total = 23
783        num_entries = 12
784        event = bb.event.CacheLoadCompleted(total, num_entries)
785        self.assertEqual(event.msg, "Loading cache Completed")
786        expected = [total, num_entries]
787        actual = [event.total, event.num_entries]
788        self.assertEqual(str(actual), str(expected))
789        self.assertEqual(event.pid, EventClassesTest._worker_pid)
790
791    def test_TreeDataPreparationStarted(self):
792        """ Test TreeDataPreparationStarted event class """
793        event = bb.event.TreeDataPreparationStarted()
794        self.assertEqual(event.msg, "Preparing tree data Started")
795        self.assertEqual(event.pid, EventClassesTest._worker_pid)
796
797    def test_TreeDataPreparationProgress(self):
798        """ Test TreeDataPreparationProgress event class """
799        current = 10
800        total = 100
801        event = bb.event.TreeDataPreparationProgress(current, total)
802        self.assertEqual(event.msg,
803                         "Preparing tree data" + ": %s/%s" % (current, total))
804        self.assertEqual(event.pid, EventClassesTest._worker_pid)
805
806    def test_TreeDataPreparationCompleted(self):
807        """ Test TreeDataPreparationCompleted event class """
808        total = 23
809        event = bb.event.TreeDataPreparationCompleted(total)
810        self.assertEqual(event.msg, "Preparing tree data Completed")
811        self.assertEqual(event.total, total)
812        self.assertEqual(event.pid, EventClassesTest._worker_pid)
813
814    def test_DepTreeGenerated(self):
815        """ Test DepTreeGenerated event class """
816        depgraph = Mock()
817        event = bb.event.DepTreeGenerated(depgraph)
818        self.assertEqual(event.pid, EventClassesTest._worker_pid)
819
820    def test_TargetsTreeGenerated(self):
821        """ Test TargetsTreeGenerated event class """
822        model = Mock()
823        event = bb.event.TargetsTreeGenerated(model)
824        self.assertEqual(event.pid, EventClassesTest._worker_pid)
825
826    def test_ReachableStamps(self):
827        """ Test ReachableStamps event class """
828        stamps = [Mock(), Mock()]
829        event = bb.event.ReachableStamps(stamps)
830        self.assertEqual(event.stamps, stamps)
831        self.assertEqual(event.pid, EventClassesTest._worker_pid)
832
833    def test_FilesMatchingFound(self):
834        """ Test FilesMatchingFound event class """
835        pattern = "foo.*bar"
836        matches = ["foobar"]
837        event = bb.event.FilesMatchingFound(pattern, matches)
838        self.assertEqual(event.pid, EventClassesTest._worker_pid)
839
840    def test_ConfigFilesFound(self):
841        """ Test ConfigFilesFound event class """
842        variable = "FOO_BAR"
843        values = ["foo", "bar"]
844        event = bb.event.ConfigFilesFound(variable, values)
845        self.assertEqual(event.pid, EventClassesTest._worker_pid)
846
847    def test_ConfigFilePathFound(self):
848        """ Test ConfigFilePathFound event class """
849        path = "/foo/bar"
850        event = bb.event.ConfigFilePathFound(path)
851        self.assertEqual(event.pid, EventClassesTest._worker_pid)
852
853    def test_message_classes(self):
854        """ Test message event classes """
855        msg = "foobar foo bar"
856        event = bb.event.MsgBase(msg)
857        self.assertEqual(event.pid, EventClassesTest._worker_pid)
858        event = bb.event.MsgDebug(msg)
859        self.assertEqual(event.pid, EventClassesTest._worker_pid)
860        event = bb.event.MsgNote(msg)
861        self.assertEqual(event.pid, EventClassesTest._worker_pid)
862        event = bb.event.MsgWarn(msg)
863        self.assertEqual(event.pid, EventClassesTest._worker_pid)
864        event = bb.event.MsgError(msg)
865        self.assertEqual(event.pid, EventClassesTest._worker_pid)
866        event = bb.event.MsgFatal(msg)
867        self.assertEqual(event.pid, EventClassesTest._worker_pid)
868        event = bb.event.MsgPlain(msg)
869        self.assertEqual(event.pid, EventClassesTest._worker_pid)
870
871    def test_LogExecTTY(self):
872        """ Test LogExecTTY event class """
873        msg = "foo bar"
874        prog = "foo.sh"
875        sleep_delay = 10
876        retries = 3
877        event = bb.event.LogExecTTY(msg, prog, sleep_delay, retries)
878        self.assertEqual(event.msg, msg)
879        self.assertEqual(event.prog, prog)
880        self.assertEqual(event.sleep_delay, sleep_delay)
881        self.assertEqual(event.retries, retries)
882        self.assertEqual(event.pid, EventClassesTest._worker_pid)
883
884    def _throw_zero_division_exception(self):
885        a = 1 / 0
886        return
887
888    def _worker_handler(self, event, d):
889        self._returned_event = event
890        return
891
892    def test_LogHandler(self):
893        """ Test LogHandler class """
894        logger = logging.getLogger("TestEventClasses")
895        logger.propagate = False
896        handler = bb.event.LogHandler(logging.INFO)
897        logger.addHandler(handler)
898        bb.event.worker_fire = self._worker_handler
899        try:
900            self._throw_zero_division_exception()
901        except ZeroDivisionError as ex:
902            logger.exception(ex)
903        event = self._returned_event
904        try:
905            pe = pickle.dumps(event)
906            newevent = pickle.loads(pe)
907        except:
908            self.fail('Logged event is not serializable')
909        self.assertEqual(event.taskpid, EventClassesTest._worker_pid)
910
911    def test_MetadataEvent(self):
912        """ Test MetadataEvent class """
913        eventtype = "footype"
914        eventdata = {"foo": "bar"}
915        event = bb.event.MetadataEvent(eventtype, eventdata)
916        self.assertEqual(event.type, eventtype)
917        self.assertEqual(event.pid, EventClassesTest._worker_pid)
918
919    def test_ProcessStarted(self):
920        """ Test ProcessStarted class """
921        processname = "foo"
922        total = 9783128974
923        event = bb.event.ProcessStarted(processname, total)
924        self.assertEqual(event.processname, processname)
925        self.assertEqual(event.total, total)
926        self.assertEqual(event.pid, EventClassesTest._worker_pid)
927
928    def test_ProcessProgress(self):
929        """ Test ProcessProgress class """
930        processname = "foo"
931        progress = 243224
932        event = bb.event.ProcessProgress(processname, progress)
933        self.assertEqual(event.processname, processname)
934        self.assertEqual(event.progress, progress)
935        self.assertEqual(event.pid, EventClassesTest._worker_pid)
936
937    def test_ProcessFinished(self):
938        """ Test ProcessFinished class """
939        processname = "foo"
940        total = 1242342344
941        event = bb.event.ProcessFinished(processname)
942        self.assertEqual(event.processname, processname)
943        self.assertEqual(event.pid, EventClassesTest._worker_pid)
944
945    def test_SanityCheck(self):
946        """ Test SanityCheck class """
947        event1 = bb.event.SanityCheck()
948        self.assertEqual(event1.generateevents, True)
949        self.assertEqual(event1.pid, EventClassesTest._worker_pid)
950        generateevents = False
951        event2 = bb.event.SanityCheck(generateevents)
952        self.assertEqual(event2.generateevents, generateevents)
953        self.assertEqual(event2.pid, EventClassesTest._worker_pid)
954
955    def test_SanityCheckPassed(self):
956        """ Test SanityCheckPassed class """
957        event = bb.event.SanityCheckPassed()
958        self.assertEqual(event.pid, EventClassesTest._worker_pid)
959
960    def test_SanityCheckFailed(self):
961        """ Test SanityCheckFailed class """
962        msg = "The sanity test failed."
963        event1 = bb.event.SanityCheckFailed(msg)
964        self.assertEqual(event1.pid, EventClassesTest._worker_pid)
965        network_error = True
966        event2 = bb.event.SanityCheckFailed(msg, network_error)
967        self.assertEqual(event2.pid, EventClassesTest._worker_pid)
968
969    def test_network_event_classes(self):
970        """ Test network event classes """
971        event1 = bb.event.NetworkTest()
972        generateevents = False
973        self.assertEqual(event1.pid, EventClassesTest._worker_pid)
974        event2 = bb.event.NetworkTest(generateevents)
975        self.assertEqual(event2.pid, EventClassesTest._worker_pid)
976        event3 = bb.event.NetworkTestPassed()
977        self.assertEqual(event3.pid, EventClassesTest._worker_pid)
978        event4 = bb.event.NetworkTestFailed()
979        self.assertEqual(event4.pid, EventClassesTest._worker_pid)
980
981    def test_FindSigInfoResult(self):
982        """ Test FindSigInfoResult event class """
983        result = [Mock()]
984        event = bb.event.FindSigInfoResult(result)
985        self.assertEqual(event.result, result)
986        self.assertEqual(event.pid, EventClassesTest._worker_pid)
987