From 62401e8fd557cc9c9d5c159d3b80a11cb586d8af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20S=CC=8Ckoda?= Date: Sat, 13 Jul 2013 12:40:16 +0200 Subject: [PATCH] MDL-39846 implement event sink for unit testing --- lib/classes/event/base.php | 6 ++ lib/phpunit/classes/advanced_testcase.php | 13 ++++ lib/phpunit/classes/event_sink.php | 87 +++++++++++++++++++++++ lib/phpunit/classes/util.php | 59 +++++++++++++++ lib/phpunit/lib.php | 1 + lib/tests/event_test.php | 33 +++++++++ 6 files changed, 199 insertions(+) create mode 100644 lib/phpunit/classes/event_sink.php diff --git a/lib/classes/event/base.php b/lib/classes/event/base.php index 4e272c78ae8..f4f73beca3e 100644 --- a/lib/classes/event/base.php +++ b/lib/classes/event/base.php @@ -451,6 +451,12 @@ abstract class base { } } + if (PHPUNIT_TEST and \phpunit_util::is_redirecting_events()) { + $this->dispatched = true; + \phpunit_util::event_triggered($this); + return; + } + \core\event\manager::dispatch($this); $this->dispatched = true; diff --git a/lib/phpunit/classes/advanced_testcase.php b/lib/phpunit/classes/advanced_testcase.php index c04d3399cde..418a9a996c3 100644 --- a/lib/phpunit/classes/advanced_testcase.php +++ b/lib/phpunit/classes/advanced_testcase.php @@ -319,6 +319,19 @@ abstract class advanced_testcase extends PHPUnit_Framework_TestCase { return phpunit_util::start_message_redirection(); } + /** + * Starts event redirection. + * + * You can verify if events were triggered or not by inspecting the events + * array in the returned event sink instance. The redirection + * can be stopped by calling $sink->close(); + * + * @return phpunit_event_sink + */ + public function redirectEvents() { + return phpunit_util::start_event_redirection(); + } + /** * Cleanup after all tests are executed. * diff --git a/lib/phpunit/classes/event_sink.php b/lib/phpunit/classes/event_sink.php new file mode 100644 index 00000000000..cf3f3c467ce --- /dev/null +++ b/lib/phpunit/classes/event_sink.php @@ -0,0 +1,87 @@ +. + +/** + * Event sink. + * + * @package core + * @category phpunit + * @copyright 2013 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * Event redirection sink. + * + * @package core + * @category phpunit + * @copyright 2013 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class phpunit_event_sink { + /** @var \core\event\base[] array of events */ + protected $events = array(); + + /** + * Stop event redirection. + * + * Use if you do not want event redirected any more. + */ + public function close() { + phpunit_util::stop_event_redirection(); + } + + /** + * To be called from phpunit_util only! + * + * @private + * @param stdClass $event record from event_read table + */ + public function add_event($event) { + /* Number events from 0. */ + $this->events[] = $event; + } + + /** + * Returns all redirected events. + * + * The instances are records form the event_read table. + * The array indexes are numbered from 0 and the order is matching + * the creation of events. + * + * @return array + */ + public function get_events() { + return $this->events; + } + + /** + * Return number of events redirected to this sink. + * + * @return int + */ + public function count() { + return count($this->events); + } + + /** + * Removes all previously stored events. + */ + public function clear() { + $this->events = array(); + } +} diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index e5a62ba7db1..09a4f827a6f 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -43,6 +43,9 @@ class phpunit_util extends testing_util { /** @var phpunit_message_sink alternative target for moodle messaging */ protected static $messagesink = null; + /** @var phpunit_message_sink alternative target for moodle messaging */ + protected static $eventsink = null; + /** * @var array Files to skip when resetting dataroot folder */ @@ -95,6 +98,9 @@ class phpunit_util extends testing_util { // Stop any message redirection. phpunit_util::stop_message_redirection(); + // Stop any message redirection. + phpunit_util::stop_event_redirection(); + // Release memory and indirectly call destroy() methods to release resource handles, etc. gc_collect_cycles(); @@ -661,4 +667,57 @@ class phpunit_util extends testing_util { self::$messagesink->add_message($message); } } + + /** + * Start event redirection. + * + * @private + * Note: Do not call directly from tests, + * use $sink = $this->redirectEvents() instead. + * + * @return phpunit_event_sink + */ + public static function start_event_redirection() { + if (self::$eventsink) { + self::stop_event_redirection(); + } + self::$eventsink = new phpunit_event_sink(); + return self::$eventsink; + } + + /** + * End event redirection. + * + * @private + * Note: Do not call directly from tests, + * use $sink->close() instead. + */ + public static function stop_event_redirection() { + self::$eventsink = null; + } + + /** + * Are events redirected to some sink? + * + * Note: to be called from \core\event\base only! + * + * @private + * @return bool + */ + public static function is_redirecting_events() { + return !empty(self::$eventsink); + } + + /** + * To be called from \core\event\base only! + * + * @private + * @param \core\event\base $event record from event_read table + * @return bool true means send event, false means event "sent" to sink. + */ + public static function event_triggered(\core\event\base $event) { + if (self::$eventsink) { + self::$eventsink->add_event($event); + } + } } diff --git a/lib/phpunit/lib.php b/lib/phpunit/lib.php index 2ceaf3e9860..5dfdeab7c65 100644 --- a/lib/phpunit/lib.php +++ b/lib/phpunit/lib.php @@ -29,6 +29,7 @@ require_once('PHPUnit/Autoload.php'); require_once('PHPUnit/Extensions/Database/Autoload.php'); require_once(__DIR__.'/classes/util.php'); +require_once(__DIR__.'/classes/event_sink.php'); require_once(__DIR__.'/classes/message_sink.php'); require_once(__DIR__.'/classes/basic_testcase.php'); require_once(__DIR__.'/classes/database_driver_testcase.php'); diff --git a/lib/tests/event_test.php b/lib/tests/event_test.php index 6273cef3693..1c32ede9197 100644 --- a/lib/tests/event_test.php +++ b/lib/tests/event_test.php @@ -271,6 +271,39 @@ class core_event_testcase extends advanced_testcase { \core_tests\event\unittest_observer::$info); } + public function test_event_sink() { + $sink = $this->redirectEvents(); + $event1 = \core_tests\event\unittest_executed::create(array('courseid'=>1, 'context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10))); + $event1->trigger(); + $this->assertSame(1, $sink->count()); + $retult = $sink->get_events(); + $this->assertSame($event1, $retult[0]); + + $event2 = \core_tests\event\unittest_executed::create(array('courseid'=>1, 'context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10))); + $event2->trigger(); + $this->assertSame(2, $sink->count()); + $retult = $sink->get_events(); + $this->assertSame($event1, $retult[0]); + $this->assertSame($event2, $retult[1]); + + $sink->clear(); + $this->assertSame(0, $sink->count()); + $this->assertSame(array(), $sink->get_events()); + + $event3 = \core_tests\event\unittest_executed::create(array('courseid'=>1, 'context'=>\context_system::instance(), 'other'=>array('sample'=>3, 'xx'=>10))); + $event3->trigger(); + $this->assertSame(1, $sink->count()); + $retult = $sink->get_events(); + $this->assertSame($event3, $retult[0]); + + $sink->close(); + $event4 = \core_tests\event\unittest_executed::create(array('courseid'=>1, 'context'=>\context_system::instance(), 'other'=>array('sample'=>4, 'xx'=>10))); + $event4->trigger(); + $this->assertSame(1, $sink->count()); + $retult = $sink->get_events(); + $this->assertSame($event3, $retult[0]); + } + public function test_ignore_exceptions() { $observers = array(