source: moodle/trunk/fuentes/admin/tool/monitor/tests/eventobservers_test.php @ 136

Last change on this file since 136 was 136, checked in by mabarracus, 4 years ago

Ported code to xenial

File size: 23.3 KB
Line 
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for event observers.
19 *
20 * @package    tool_monitor
21 * @category   test
22 * @copyright  2014 onwards Ankit Agarwal <ankit.agrr@gmail.com>
23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28global $CFG;
29require_once($CFG->dirroot . '/blog/locallib.php');
30require_once($CFG->dirroot . '/blog/lib.php');
31
32/**
33 * Class tool_monitor_eventobservers_testcase
34 *
35 * Tests for event observers
36 */
37class tool_monitor_eventobservers_testcase extends advanced_testcase {
38    /**
39     * Set up method.
40     */
41    public function setUp() {
42        // Enable monitor.
43        set_config('enablemonitor', 1, 'tool_monitor');
44    }
45
46    /**
47     * Test observer for course delete event.
48     */
49    public function test_course_deleted() {
50        global $DB;
51
52        $this->setAdminUser();
53        $this->resetAfterTest(true);
54
55        $user = $this->getDataGenerator()->create_user();
56        $course1 = $this->getDataGenerator()->create_course();
57        $course2 = $this->getDataGenerator()->create_course();
58        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
59
60        $rule = new stdClass();
61        $rule->userid = $user->id;
62        $rule->courseid = $course1->id;
63        $rule->plugin = 'test';
64
65        $sub = new stdClass();
66        $sub->courseid = $course1->id;
67        $sub->userid = $user->id;
68
69        // Add 10 rules for this course with subscriptions.
70        for ($i = 0; $i < 10; $i++) {
71            $createdrule = $monitorgenerator->create_rule($rule);
72            $sub->ruleid = $createdrule->id;
73            $monitorgenerator->create_subscription($sub);
74        }
75
76        // Add 10 random rules for course 2.
77        $rule->courseid = $course2->id;
78        for ($i = 0; $i < 10; $i++) {
79            $createdrule = $monitorgenerator->create_rule($rule);
80            $sub->courseid = $rule->courseid;
81            $sub->ruleid = $createdrule->id;
82            $monitorgenerator->create_subscription($sub);
83        }
84
85        // Add a site rule.
86        $rule = new stdClass();
87        $rule->userid = $user->id;
88        $rule->courseid = 0;
89        $rule->plugin = 'core';
90        $monitorgenerator->create_rule($rule);
91
92        // Verify that if we do not specify that we do not want the site rules, they are returned.
93        $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id);
94        $this->assertCount(11, $courserules);
95
96        // Verify data before course delete.
97        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
98        $this->assertCount(20, $totalrules);
99        $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
100        $this->assertCount(10, $courserules);
101        $this->assertEquals(20, $DB->count_records('tool_monitor_subscriptions'));
102        $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
103        $this->assertCount(10, $coursesubs);
104
105        // Let us delete the course now.
106        delete_course($course1->id, false);
107
108        // Confirm the site rule still exists.
109        $this->assertEquals(1, $DB->count_records('tool_monitor_rules', array('courseid' => 0)));
110
111        // Verify data after course delete.
112        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
113        $this->assertCount(10, $totalrules);
114        $courserules = \tool_monitor\rule_manager::get_rules_by_courseid($course1->id, 0, 0, false);
115        $this->assertCount(0, $courserules); // Making sure all rules are deleted.
116        $this->assertEquals(10, $DB->count_records('tool_monitor_subscriptions'));
117        $coursesubs = \tool_monitor\subscription_manager::get_user_subscriptions_for_course($course1->id, 0, 0, $user->id);
118        $this->assertCount(0, $coursesubs); // Making sure all subscriptions are deleted.
119    }
120
121    /**
122     * This tests if writing of the events to the table tool_monitor_events is working fine.
123     */
124    public function test_flush() {
125        global $DB;
126
127        $this->resetAfterTest();
128
129        // Create the necessary items for testing.
130        $user = $this->getDataGenerator()->create_user();
131        $course = $this->getDataGenerator()->create_course();
132        $course2 = $this->getDataGenerator()->create_course();
133        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
134
135        // Fire a bunch of events.
136        // Trigger a bunch of other events.
137        $eventparams = array(
138            'context' => context_course::instance($course->id)
139        );
140        for ($i = 0; $i < 5; $i++) {
141            \core\event\course_viewed::create($eventparams)->trigger();
142            \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
143            \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
144        }
145
146        // Confirm that nothing was stored in the tool_monitor_events table
147        // as we do not have any subscriptions associated for the above events.
148        $this->assertEquals(0, $DB->count_records('tool_monitor_events'));
149
150        // Now, let's create a rule so an event can be stored.
151        $rule = new stdClass();
152        $rule->courseid = $course->id;
153        $rule->plugin = 'mod_book';
154        $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
155        $rule = $monitorgenerator->create_rule($rule);
156
157        // Let's subscribe to this rule.
158        $sub = new stdClass;
159        $sub->courseid = $course->id;
160        $sub->ruleid = $rule->id;
161        $sub->userid = $user->id;
162        $monitorgenerator->create_subscription($sub);
163
164        // Again, let's just fire more events to make sure they still aren't stored.
165        for ($i = 0; $i < 5; $i++) {
166            \core\event\course_viewed::create($eventparams)->trigger();
167            \mod_quiz\event\course_module_instance_list_viewed::create($eventparams)->trigger();
168            \mod_scorm\event\course_module_instance_list_viewed::create($eventparams)->trigger();
169        }
170
171        // Fire the event we want to capture.
172        $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
173        $event->trigger();
174
175        // Check that the event data is valid.
176        $events = $DB->get_records('tool_monitor_events');
177        $this->assertEquals(1, count($events));
178        $monitorevent = array_pop($events);
179        $this->assertEquals($event->eventname, $monitorevent->eventname);
180        $this->assertEquals($event->contextid, $monitorevent->contextid);
181        $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
182        $this->assertEquals($event->get_url()->out(), $monitorevent->link);
183        $this->assertEquals($event->courseid, $monitorevent->courseid);
184        $this->assertEquals($event->timecreated, $monitorevent->timecreated);
185
186        // Remove the stored events.
187        $DB->delete_records('tool_monitor_events');
188
189        // Now, let's create a site wide rule.
190        $rule = new stdClass();
191        $rule->courseid = 0;
192        $rule->plugin = 'mod_book';
193        $rule->eventname = '\mod_book\event\course_module_instance_list_viewed';
194        $rule = $monitorgenerator->create_rule($rule);
195
196        // Let's subscribe to this rule.
197        $sub = new stdClass;
198        $sub->courseid = 0;
199        $sub->ruleid = $rule->id;
200        $sub->userid = $user->id;
201        $monitorgenerator->create_subscription($sub);
202
203        // Fire the event we want to capture - but in a different course.
204        $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course2);
205        $event->trigger();
206
207        // Check that the event data is valid.
208        $events = $DB->get_records('tool_monitor_events');
209        $this->assertEquals(1, count($events));
210        $monitorevent = array_pop($events);
211        $this->assertEquals($event->eventname, $monitorevent->eventname);
212        $this->assertEquals($event->contextid, $monitorevent->contextid);
213        $this->assertEquals($event->contextlevel, $monitorevent->contextlevel);
214        $this->assertEquals($event->get_url()->out(), $monitorevent->link);
215        $this->assertEquals($event->courseid, $monitorevent->courseid);
216        $this->assertEquals($event->timecreated, $monitorevent->timecreated);
217    }
218
219    /**
220     * Test the notification sending features.
221     */
222    public function test_process_event() {
223
224        global $DB, $USER;
225
226        $this->resetAfterTest();
227        $this->setAdminUser();
228        $msgsink = $this->redirectMessages();
229
230        // Generate data.
231        $course = $this->getDataGenerator()->create_course();
232        $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
233
234        $rulerecord = new stdClass();
235        $rulerecord->courseid = $course->id;
236        $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
237        $rulerecord->frequency = 1;
238
239        $rule = $toolgenerator->create_rule($rulerecord);
240
241        $subrecord = new stdClass();
242        $subrecord->courseid = $course->id;
243        $subrecord->ruleid = $rule->id;
244        $subrecord->userid = $USER->id;
245        $toolgenerator->create_subscription($subrecord);
246
247        $recordexists = $DB->record_exists('task_adhoc', array('component' => 'tool_monitor'));
248        $this->assertFalse($recordexists);
249
250        // Now let us trigger the event.
251        $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
252        $event->trigger();
253
254        $this->verify_processed_data($msgsink);
255
256        // Clean up.
257        \tool_monitor\rule_manager::delete_rule($rule->id);
258        $DB->delete_records('tool_monitor_events');
259
260        // Let us create a rule with more than 1 frequency.
261        $rulerecord->frequency = 5;
262        $rule = $toolgenerator->create_rule($rulerecord);
263        $subrecord->ruleid = $rule->id;
264        $toolgenerator->create_subscription($subrecord);
265
266        // Let us trigger events.
267        for ($i = 0; $i < 5; $i++) {
268            $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
269            $event->trigger();
270            if ($i != 4) {
271                $this->verify_message_not_sent_yet($msgsink);
272            }
273        }
274
275        $this->verify_processed_data($msgsink);
276
277        // Clean up.
278        \tool_monitor\rule_manager::delete_rule($rule->id);
279        $DB->delete_records('tool_monitor_events');
280
281        // Now let us create a rule specific to a module instance.
282        $cm = new stdClass();
283        $cm->course = $course->id;
284        $book = $this->getDataGenerator()->create_module('book', $cm);
285        $rulerecord->eventname = '\mod_book\event\course_module_viewed';
286        $rulerecord->cmid = $book->cmid;
287        $rule = $toolgenerator->create_rule($rulerecord);
288        $subrecord->ruleid = $rule->id;
289        $toolgenerator->create_subscription($subrecord);
290
291        // Let us trigger events.
292        $params = array(
293            'context' => context_module::instance($book->cmid),
294            'objectid' => $book->id
295        );
296        for ($i = 0; $i < 5; $i++) {
297            $event = \mod_book\event\course_module_viewed::create($params);
298            $event->trigger();
299            if ($i != 4) {
300                $this->verify_message_not_sent_yet($msgsink);
301            }
302        }
303
304        $this->verify_processed_data($msgsink);
305
306        // Clean up.
307        \tool_monitor\rule_manager::delete_rule($rule->id);
308        $DB->delete_records('tool_monitor_events');
309
310        // Now let us create a rule for event that happens in category context events.
311        $rulerecord->eventname = '\core\event\course_category_created';
312        $rulerecord->courseid = 0;
313        $rule = $toolgenerator->create_rule($rulerecord);
314        $subrecord->courseid = 0;
315        $subrecord->ruleid = $rule->id;
316        $toolgenerator->create_subscription($subrecord);
317
318        // Let us trigger events.
319        for ($i = 0; $i < 5; $i++) {
320            $this->getDataGenerator()->create_category();
321            if ($i != 4) {
322                $this->verify_message_not_sent_yet($msgsink);
323            }
324        }
325        $this->verify_processed_data($msgsink);
326
327        // Clean up.
328        \tool_monitor\rule_manager::delete_rule($rule->id);
329        $DB->delete_records('tool_monitor_events');
330
331        // Now let us create a rule at site level.
332        $rulerecord->eventname = '\core\event\blog_entry_created';
333        $rulerecord->courseid = 0;
334        $rule = $toolgenerator->create_rule($rulerecord);
335        $subrecord->courseid = 0;
336        $subrecord->ruleid = $rule->id;
337        $toolgenerator->create_subscription($subrecord);
338
339        // Let us trigger events.
340        $blog = new blog_entry();
341        $blog->subject = "Subject of blog";
342        $blog->userid = $USER->id;
343        $states = blog_entry::get_applicable_publish_states();
344        $blog->publishstate = reset($states);
345        for ($i = 0; $i < 5; $i++) {
346            $newblog = fullclone($blog);
347            $newblog->add();
348            if ($i != 4) {
349                $this->verify_message_not_sent_yet($msgsink);
350            }
351        }
352
353        $this->verify_processed_data($msgsink);
354    }
355
356    /**
357     * Test that same events are not used twice to calculate conditions for a single subscription.
358     */
359    public function test_multiple_notification_not_sent() {
360        global $USER;
361
362        $this->resetAfterTest();
363        $this->setAdminUser();
364        $messagesink = $this->redirectMessages();
365
366        // Generate data.
367        $course = $this->getDataGenerator()->create_course();
368        $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
369
370        $rulerecord = new stdClass();
371        $rulerecord->courseid = $course->id;
372        $rulerecord->eventname = '\mod_book\event\course_module_instance_list_viewed';
373        $rulerecord->frequency = 5;
374
375        $rule = $toolgenerator->create_rule($rulerecord);
376
377        $subrecord = new stdClass();
378        $subrecord->courseid = $course->id;
379        $subrecord->ruleid = $rule->id;
380        $subrecord->userid = $USER->id;
381        $toolgenerator->create_subscription($subrecord);
382
383        for ($i = 0; $i < 7; $i++) {
384            // Now let us trigger 7 instances of the event.
385            $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
386            $event->trigger();
387            sleep(1); // Add a second delay, to prevent time collisions.
388        }
389        $this->run_adhock_tasks();
390        $messages = $messagesink->get_messages();
391        $this->assertCount(1, $messages); // There should be only one message not 3.
392        for ($i = 0; $i < 3; $i++) {
393            // Now let us trigger 5 more instances of the event.
394            $event = \mod_book\event\course_module_instance_list_viewed::create_from_course($course);
395            $event->trigger();
396        }
397
398        $this->run_adhock_tasks();
399        $messages = $messagesink->get_messages();
400        $this->assertCount(2, $messages); // There should be two messages now.
401    }
402
403    /**
404     * Run adhoc tasks.
405     */
406    protected function run_adhock_tasks() {
407        while ($task = \core\task\manager::get_next_adhoc_task(time())) {
408            $task->execute();
409            \core\task\manager::adhoc_task_complete($task);
410        }
411        $this->expectOutputRegex("/^Sending message to the user with id \d+ for the subscription with id \d+\.\.\..Sent./ms");
412    }
413
414    /**
415     * Verify that task was scheduled and a message was sent as expected.
416     *
417     * @param phpunit_message_sink $msgsink Message sink
418     */
419    protected function verify_processed_data(phpunit_message_sink $msgsink) {
420        global $DB, $USER;
421
422        $recordexists = $DB->count_records('task_adhoc', array('component' => 'tool_monitor'));
423        $this->assertEquals(1, $recordexists); // We should have an adhock task now to send notifications.
424        $this->run_adhock_tasks();
425        $this->assertEquals(1, $msgsink->count());
426        $msgs = $msgsink->get_messages();
427        $msg = array_pop($msgs);
428        $this->assertEquals($USER->id, $msg->useridto);
429        $this->assertEquals(1, $msg->notification);
430        $msgsink->clear();
431    }
432
433    /**
434     * Verify that a message was not sent.
435     *
436     * @param phpunit_message_sink $msgsink Message sink
437     */
438    protected function verify_message_not_sent_yet(phpunit_message_sink $msgsink) {
439        $msgs = $msgsink->get_messages();
440        $this->assertCount(0, $msgs);
441        $msgsink->clear();
442    }
443
444    /**
445     * Tests for replace_placeholders method.
446     */
447    public function test_replace_placeholders() {
448        global $USER;
449
450        $this->resetAfterTest();
451        $this->setAdminUser();
452        $msgsink = $this->redirectMessages();
453
454        // Generate data.
455        $course = $this->getDataGenerator()->create_course();
456        $toolgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
457        $context = \context_user::instance($USER->id, IGNORE_MISSING);
458
459        // Creating book.
460        $cm = new stdClass();
461        $cm->course = $course->id;
462        $book = $this->getDataGenerator()->create_module('book', $cm);
463
464        // Creating rule.
465        $rulerecord = new stdClass();
466        $rulerecord->courseid = $course->id;
467        $rulerecord->eventname = '\mod_book\event\course_module_viewed';
468        $rulerecord->cmid = $book->cmid;
469        $rulerecord->frequency = 1;
470        $rulerecord->template = '{link} {modulelink} {rulename} {description} {eventname}';
471
472        $rule = $toolgenerator->create_rule($rulerecord);
473
474        // Creating subscription.
475        $subrecord = new stdClass();
476        $subrecord->courseid = $course->id;
477        $subrecord->ruleid = $rule->id;
478        $subrecord->userid = $USER->id;
479        $toolgenerator->create_subscription($subrecord);
480
481        // Now let us trigger the event.
482        $params = array(
483            'context' => context_module::instance($book->cmid),
484            'objectid' => $book->id
485        );
486
487        $event = \mod_book\event\course_module_viewed::create($params);
488        $event->trigger();
489        $this->run_adhock_tasks();
490        $msgs = $msgsink->get_messages();
491        $msg = array_pop($msgs);
492
493        $modurl = new moodle_url('/mod/book/view.php', array('id' => $book->cmid));
494        $expectedmsg = $event->get_url()->out() . ' ' .
495                        $modurl->out()  . ' ' .
496                        $rule->get_name($context) . ' ' .
497                        $rule->get_description($context) . ' ' .
498                        $rule->get_event_name();
499
500        $this->assertEquals($expectedmsg, $msg->fullmessage);
501    }
502
503    /**
504     * Test observer for user delete event.
505     */
506    public function test_user_deleted() {
507        global $DB;
508
509        $this->setAdminUser();
510        $this->resetAfterTest(true);
511
512        $user = $this->getDataGenerator()->create_user();
513        $course1 = $this->getDataGenerator()->create_course();
514        $course2 = $this->getDataGenerator()->create_course();
515        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
516
517        $rule = new stdClass();
518        $rule->userid = $user->id;
519        $rule->courseid = $course1->id;
520        $rule->plugin = 'test';
521
522        $sub = new stdClass();
523        $sub->courseid = $course1->id;
524        $sub->userid = $user->id;
525
526        // Add 10 rules for this course with subscriptions.
527        for ($i = 0; $i < 10; $i++) {
528            $createdrule = $monitorgenerator->create_rule($rule);
529            $sub->ruleid = $createdrule->id;
530            $monitorgenerator->create_subscription($sub);
531        }
532
533        // Add 10 random rules for course 2.
534        $rule->courseid = $course2->id;
535        for ($i = 0; $i < 10; $i++) {
536            $createdrule = $monitorgenerator->create_rule($rule);
537            $sub->courseid = $rule->courseid;
538            $sub->ruleid = $createdrule->id;
539            $monitorgenerator->create_subscription($sub);
540        }
541
542        // Verify data before user delete.
543        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
544        $this->assertCount(20, $totalrules);
545        $totalsubs = $DB->get_records('tool_monitor_subscriptions');
546        $this->assertCount(20, $totalsubs);
547
548        // Let us delete the user now.
549        delete_user($user);
550
551        // Verify data after course delete.
552        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
553        $this->assertCount(20, $totalrules);
554        $totalsubs = $DB->get_records('tool_monitor_subscriptions');
555        $this->assertCount(0, $totalsubs); // Make sure all subscriptions are deleted.
556    }
557
558    /**
559     * Test observer for course module delete event.
560     */
561    public function test_course_module_deleted() {
562        global $DB;
563
564        $this->setAdminUser();
565        $this->resetAfterTest(true);
566
567        $user = $this->getDataGenerator()->create_user();
568        $course1 = $this->getDataGenerator()->create_course();
569        $course2 = $this->getDataGenerator()->create_course();
570        $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
571
572        // Now let us create a rule specific to a module instance.
573        $cm = new stdClass();
574        $cm->course = $course1->id;
575        $book = $this->getDataGenerator()->create_module('book', $cm);
576
577        $rule = new stdClass();
578        $rule->userid = $user->id;
579        $rule->courseid = $course1->id;
580        $rule->plugin = 'test';
581
582        $sub = new stdClass();
583        $sub->courseid = $course1->id;
584        $sub->userid = $user->id;
585        $sub->cmid = $book->cmid;
586
587        // Add 10 rules for this course with subscriptions for this module.
588        for ($i = 0; $i < 10; $i++) {
589            $createdrule = $monitorgenerator->create_rule($rule);
590            $sub->ruleid = $createdrule->id;
591            $monitorgenerator->create_subscription($sub);
592        }
593
594        // Add 10 random rules for course 2.
595        $rule->courseid = $course2->id;
596        for ($i = 0; $i < 10; $i++) {
597            $createdrule = $monitorgenerator->create_rule($rule);
598            $sub->courseid = $rule->courseid;
599            $sub->ruleid = $createdrule->id;
600            $sub->cmid = 0;
601            $monitorgenerator->create_subscription($sub);
602        }
603
604        // Verify data before module delete.
605        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
606        $this->assertCount(20, $totalrules);
607        $totalsubs = $DB->get_records('tool_monitor_subscriptions');
608        $this->assertCount(20, $totalsubs);
609
610        // Let us delete the user now.
611        course_delete_module($book->cmid);
612
613        // Verify data after course delete.
614        $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test');
615        $this->assertCount(20, $totalrules);
616        $totalsubs = $DB->get_records('tool_monitor_subscriptions');
617        $this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted.
618    }
619
620}
Note: See TracBrowser for help on using the repository browser.