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