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