Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
namespace core\event;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
require_once(__DIR__.'/..//fixtures/event_fixtures.php');
22
 
23
/**
24
 * Tests for event manager, base event and observers.
25
 *
26
 * @package    core
27
 * @category   phpunit
28
 * @copyright  2013 Petr Skoda {@link http://skodak.org}
29
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 */
31
class base_test extends \advanced_testcase {
32
 
33
    const DEBUGGING_MSG = 'Events API using $handlers array has been deprecated in favour of Events 2 API, please use it instead.';
34
 
11 efrain 35
    public function test_event_properties(): void {
1 efrain 36
        global $USER;
37
 
38
        $system = \context_system::instance();
39
        $event = \core_tests\event\unittest_executed::create(array('context'=>$system, 'objectid'=>5, 'other'=>array('sample'=>null, 'xx'=>10)));
40
 
41
        $this->assertSame('\core_tests\event\unittest_executed', $event->eventname);
42
        $this->assertSame('core_tests', $event->component);
43
        $this->assertSame('executed', $event->action);
44
        $this->assertSame('unittest', $event->target);
45
        $this->assertSame(5, $event->objectid);
46
        $this->assertSame('u', $event->crud);
47
        $this->assertSame(\core\event\base::LEVEL_PARTICIPATING, $event->edulevel);
48
 
49
        $this->assertEquals($system, $event->get_context());
50
        $this->assertSame($system->id, $event->contextid);
51
        $this->assertSame($system->contextlevel, $event->contextlevel);
52
        $this->assertSame($system->instanceid, $event->contextinstanceid);
53
 
54
        $this->assertSame($USER->id, $event->userid);
55
        $this->assertSame(0, $event->courseid);
56
 
57
        $this->assertNull($event->relateduserid);
58
        $this->assertFalse(isset($event->relateduserid));
59
 
60
        $this->assertSame(0, $event->anonymous);
61
 
62
        $this->assertSame(array('sample'=>null, 'xx'=>10), $event->other);
63
        $this->assertTrue(isset($event->other['xx']));
64
        $this->assertFalse(isset($event->other['sample']));
65
 
66
        $this->assertLessThanOrEqual(time(), $event->timecreated);
67
 
68
        try {
69
            $event->courseid = 2;
70
            $this->fail('Exception expected on event modification');
71
        } catch (\moodle_exception $e) {
72
            $this->assertInstanceOf(\coding_exception::class, $e);
73
        }
74
 
75
        try {
76
            $event->xxxx = 1;
77
            $this->fail('Exception expected on event modification');
78
        } catch (\moodle_exception $e) {
79
            $this->assertInstanceOf(\coding_exception::class, $e);
80
        }
81
 
82
        $event2 = \core_tests\event\unittest_executed::create(array('contextid'=>$system->id, 'objectid'=>5, 'anonymous'=>1, 'other'=>array('sample'=>null, 'xx'=>10)));
83
        $this->assertEquals($event->get_context(), $event2->get_context());
84
        $this->assertSame(1, $event2->anonymous);
85
 
86
        $event3 = \core_tests\event\unittest_executed::create(array('contextid'=>$system->id, 'objectid'=>5, 'anonymous'=>true, 'other'=>array('sample'=>null, 'xx'=>10)));
87
        $this->assertSame(1, $event3->anonymous);
88
    }
89
 
11 efrain 90
    public function test_event_properties_guessing(): void {
1 efrain 91
        global $USER;
92
        $this->resetAfterTest();
93
 
94
        $course = $this->getDataGenerator()->create_course();
95
        $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
96
        $context = \context_module::instance($forum->cmid);
97
        $event = \core_tests\event\unittest_executed::create(array('context' => $context, 'objectid' => 5));
98
 
99
        // Check guessed course ID, and default properties.
100
        $this->assertSame('\core_tests\event\unittest_executed', $event->eventname);
101
        $this->assertSame('core_tests', $event->component);
102
        $this->assertSame('executed', $event->action);
103
        $this->assertSame('unittest', $event->target);
104
        $this->assertSame(5, $event->objectid);
105
        $this->assertEquals($context, $event->get_context());
106
        $this->assertEquals($course->id, $event->courseid);
107
        $this->assertSame($USER->id, $event->userid);
108
        $this->assertNull($event->relateduserid);
109
 
110
        $user = $this->getDataGenerator()->create_user();
111
        $context = \context_user::instance($user->id);
112
        $event = \core_tests\event\unittest_executed::create(array('contextid' => $context->id, 'objectid' => 5));
113
 
114
        // Check guessing on contextid, and user context level.
115
        $this->assertEquals($context, $event->get_context());
116
        $this->assertEquals($context->id, $event->contextid);
117
        $this->assertEquals($context->contextlevel, $event->contextlevel);
118
        $this->assertSame(0, $event->courseid);
119
        $this->assertSame($USER->id, $event->userid);
120
        $this->assertSame($user->id, $event->relateduserid);
121
    }
122
 
11 efrain 123
    public function test_observers_parsing(): void {
1 efrain 124
        global $CFG;
125
 
126
        $observers = array(
127
            array(
128
                'eventname'   => '*',
129
                'callback'    => array('\core_tests\event\unittest_observer', 'observe_all_alt'),
130
            ),
131
            array(
132
                'eventname'   => '\core_tests\event\unittest_executed',
133
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
134
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
135
            ),
136
            array(
137
                'eventname'   => '*',
138
                'callback'    => array('\core_tests\event\unittest_observer', 'observe_all'),
139
                'includefile' => null,
140
                'internal'    => 1,
141
                'priority'    => 10,
142
            ),
143
            array(
144
                'eventname'   => '\core\event\unknown_executed',
145
                'callback'    => '\core_tests\event\unittest_observer::broken_observer',
146
                'priority'    => 100,
147
            ),
148
            array(
149
                'eventname'   => '\core_tests\event\unittest_executed',
150
                'callback'    => '\core_tests\event\unittest_observer::external_observer',
151
                'priority'    => 200,
152
                'internal'    => 0,
153
            ),
154
        );
155
 
156
        $result = \core\event\manager::phpunit_replace_observers($observers);
157
        $this->assertCount(3, $result);
158
 
159
        $expected = array();
160
        $observer = new \stdClass();
161
        $observer->callable = '\core_tests\event\unittest_observer::external_observer';
162
        $observer->priority = 200;
163
        $observer->internal = false;
164
        $observer->includefile = null;
165
        $observer->plugintype = null;
166
        $observer->plugin = null;
167
        $expected[0] = $observer;
168
        $observer = new \stdClass();
169
        $observer->callable = '\core_tests\event\unittest_observer::observe_one';
170
        $observer->priority = 0;
171
        $observer->internal = true;
172
        $observer->includefile = $CFG->dirroot.'/lib/tests/fixtures/event_fixtures.php';
173
        $observer->plugintype = null;
174
        $observer->plugin = null;
175
        $expected[1] = $observer;
176
 
177
        $this->assertEquals($expected, $result['\core_tests\event\unittest_executed']);
178
 
179
        $expected = array();
180
        $observer = new \stdClass();
181
        $observer->callable = '\core_tests\event\unittest_observer::broken_observer';
182
        $observer->priority = 100;
183
        $observer->internal = true;
184
        $observer->includefile = null;
185
        $observer->plugintype = null;
186
        $observer->plugin = null;
187
        $expected[0] = $observer;
188
 
189
        $this->assertEquals($expected, $result['\core\event\unknown_executed']);
190
 
191
        $expected = array();
192
        $observer = new \stdClass();
193
        $observer->callable = array('\core_tests\event\unittest_observer', 'observe_all');
194
        $observer->priority = 10;
195
        $observer->internal = true;
196
        $observer->includefile = null;
197
        $observer->plugintype = null;
198
        $observer->plugin = null;
199
        $expected[0] = $observer;
200
        $observer = new \stdClass();
201
        $observer->callable = array('\core_tests\event\unittest_observer', 'observe_all_alt');
202
        $observer->priority = 0;
203
        $observer->internal = true;
204
        $observer->includefile = null;
205
        $observer->plugintype = null;
206
        $observer->plugin = null;
207
        $expected[1] = $observer;
208
 
209
        $this->assertEquals($expected, $result['\core\event\base']);
210
 
211
        // Now test broken stuff...
212
 
213
        $observers = array(
214
            array(
215
                'eventname'   => 'core_tests\event\unittest_executed', // Fix leading backslash.
216
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
217
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
218
                'internal'    => 1, // Cast to bool.
219
            ),
220
        );
221
        $result = \core\event\manager::phpunit_replace_observers($observers);
222
        $this->assertCount(1, $result);
223
        $expected = array();
224
        $observer = new \stdClass();
225
        $observer->callable = '\core_tests\event\unittest_observer::observe_one';
226
        $observer->priority = 0;
227
        $observer->internal = true;
228
        $observer->includefile = $CFG->dirroot.'/lib/tests/fixtures/event_fixtures.php';
229
        $observer->plugintype = null;
230
        $observer->plugin = null;
231
        $expected[0] = $observer;
232
        $this->assertEquals($expected, $result['\core_tests\event\unittest_executed']);
233
 
234
        $observers = array(
235
            array(
236
                // Missing eventclass.
237
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
238
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
239
            ),
240
        );
241
        $result = \core\event\manager::phpunit_replace_observers($observers);
242
        $this->assertCount(0, $result);
243
        $this->assertDebuggingCalled();
244
 
245
        $observers = array(
246
            array(
247
                'eventname'   => '', // Empty eventclass.
248
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
249
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
250
            ),
251
        );
252
        $result = \core\event\manager::phpunit_replace_observers($observers);
253
        $this->assertCount(0, $result);
254
        $this->assertDebuggingCalled();
255
 
256
        $observers = array(
257
            array(
258
                'eventname'   => '\core_tests\event\unittest_executed',
259
                // Missing callable.
260
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
261
            ),
262
        );
263
        $result = \core\event\manager::phpunit_replace_observers($observers);
264
        $this->assertCount(0, $result);
265
        $this->assertDebuggingCalled();
266
 
267
        $observers = array(
268
            array(
269
                'eventname'   => '\core_tests\event\unittest_executed',
270
                'callback'    => '', // Empty callable.
271
                'includefile' => 'lib/tests/fixtures/event_fixtures.php',
272
            ),
273
        );
274
        $result = \core\event\manager::phpunit_replace_observers($observers);
275
        $this->assertCount(0, $result);
276
        $this->assertDebuggingCalled();
277
 
278
        $observers = array(
279
            array(
280
                'eventname'   => '\core_tests\event\unittest_executed',
281
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
282
                'includefile' => 'lib/tests/fixtures/event_fixtures.php_xxx', // Missing file.
283
            ),
284
        );
285
        $result = \core\event\manager::phpunit_replace_observers($observers);
286
        $this->assertCount(0, $result);
287
        $this->assertDebuggingCalled();
288
    }
289
 
11 efrain 290
    public function test_normal_dispatching(): void {
1 efrain 291
        $observers = array(
292
            array(
293
                'eventname'   => '\core_tests\event\unittest_executed',
294
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
295
            ),
296
            array(
297
                'eventname'   => '*',
298
                'callback'    => '\core_tests\event\unittest_observer::observe_all',
299
                'includefile' => null,
300
                'internal'    => 1,
301
                'priority'    => 9999,
302
            ),
303
        );
304
 
305
        \core\event\manager::phpunit_replace_observers($observers);
306
        \core_tests\event\unittest_observer::reset();
307
 
308
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
309
        $event1->nest = 1;
310
        $this->assertFalse($event1->is_triggered());
311
        $this->assertFalse($event1->is_dispatched());
312
        $this->assertFalse($event1->is_restored());
313
        $event1->trigger();
314
        $this->assertTrue($event1->is_triggered());
315
        $this->assertTrue($event1->is_dispatched());
316
        $this->assertFalse($event1->is_restored());
317
 
318
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
319
        $event1->trigger();
320
 
321
        $this->assertSame(
322
            array('observe_all-nesting-1', 'observe_one-1', 'observe_all-666', 'observe_one-666', 'observe_all-2', 'observe_one-2'),
323
            \core_tests\event\unittest_observer::$info);
324
    }
325
 
11 efrain 326
    public function test_event_sink(): void {
1 efrain 327
        $sink = $this->redirectEvents();
328
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
329
        $event1->trigger();
330
        $this->assertSame(1, $sink->count());
331
        $retult = $sink->get_events();
332
        $this->assertSame($event1, $retult[0]);
333
 
334
        $event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
335
        $event2->trigger();
336
        $this->assertSame(2, $sink->count());
337
        $retult = $sink->get_events();
338
        $this->assertSame($event1, $retult[0]);
339
        $this->assertSame($event2, $retult[1]);
340
 
341
        $sink->clear();
342
        $this->assertSame(0, $sink->count());
343
        $this->assertSame(array(), $sink->get_events());
344
 
345
        $event3 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>3, 'xx'=>10)));
346
        $event3->trigger();
347
        $this->assertSame(1, $sink->count());
348
        $retult = $sink->get_events();
349
        $this->assertSame($event3, $retult[0]);
350
 
351
        $sink->close();
352
        $event4 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>4, 'xx'=>10)));
353
        $event4->trigger();
354
        $this->assertSame(1, $sink->count());
355
        $retult = $sink->get_events();
356
        $this->assertSame($event3, $retult[0]);
357
    }
358
 
11 efrain 359
    public function test_ignore_exceptions(): void {
1 efrain 360
        $observers = array(
361
 
362
            array(
363
                'eventname'   => '\core_tests\event\unittest_executed',
364
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
365
            ),
366
 
367
            array(
368
                'eventname'   => '\core_tests\event\unittest_executed',
369
                'callback'    => '\core_tests\event\unittest_observer::broken_observer',
370
                'priority'    => 100,
371
            ),
372
        );
373
 
374
        \core\event\manager::phpunit_replace_observers($observers);
375
        \core_tests\event\unittest_observer::reset();
376
 
377
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
378
        $event1->trigger();
379
        $this->assertDebuggingCalled();
380
 
381
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
382
        $event1->trigger();
383
        $this->assertDebuggingCalled();
384
 
385
        $this->assertSame(
386
            array('broken_observer-1', 'observe_one-1', 'broken_observer-2', 'observe_one-2'),
387
            \core_tests\event\unittest_observer::$info);
388
    }
389
 
11 efrain 390
    public function test_external_buffer(): void {
1 efrain 391
        global $DB;
392
 
393
        $this->preventResetByRollback();
394
 
395
        $observers = array(
396
 
397
            array(
398
                'eventname'   => '\core_tests\event\unittest_executed',
399
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
400
            ),
401
 
402
            array(
403
                'eventname'   => '\core_tests\event\unittest_executed',
404
                'callback'    => '\core_tests\event\unittest_observer::external_observer',
405
                'priority'    => 200,
406
                'internal'    => 0,
407
            ),
408
        );
409
 
410
        \core\event\manager::phpunit_replace_observers($observers);
411
        \core_tests\event\unittest_observer::reset();
412
 
413
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
414
        $event1->trigger();
415
        $event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
416
        $event2->trigger();
417
 
418
        $this->assertSame(
419
            array('external_observer-1', 'observe_one-1', 'external_observer-2', 'observe_one-2'),
420
            \core_tests\event\unittest_observer::$info);
421
 
422
        \core\event\manager::phpunit_replace_observers($observers);
423
        \core_tests\event\unittest_observer::reset();
424
 
425
        $this->assertSame(array(), \core_tests\event\unittest_observer::$info);
426
 
427
        $trans = $DB->start_delegated_transaction();
428
 
429
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
430
        $event1->trigger();
431
        $event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
432
        $event2->trigger();
433
 
434
        $this->assertSame(
435
            array('observe_one-1', 'observe_one-2'),
436
            \core_tests\event\unittest_observer::$info);
437
 
438
        $trans->allow_commit();
439
 
440
        $this->assertSame(
441
            array('observe_one-1', 'observe_one-2', 'external_observer-1', 'external_observer-2'),
442
            \core_tests\event\unittest_observer::$info);
443
 
444
        \core\event\manager::phpunit_replace_observers($observers);
445
        \core_tests\event\unittest_observer::reset();
446
 
447
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
448
        $event1->trigger();
449
        $trans = $DB->start_delegated_transaction();
450
        $event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>2, 'xx'=>10)));
451
        $event2->trigger();
452
        try {
453
            $trans->rollback(new \moodle_exception('xxx'));
454
            $this->fail('Expecting exception');
455
        } catch (\moodle_exception $e) {
456
            $this->assertInstanceOf(\moodle_exception::class, $e);
457
        }
458
 
459
        $this->assertSame(
460
            array('external_observer-1', 'observe_one-1', 'observe_one-2'),
461
            \core_tests\event\unittest_observer::$info);
462
    }
463
 
11 efrain 464
    public function test_rollback(): void {
1 efrain 465
        global $DB;
466
 
467
        $this->resetAfterTest();
468
        $this->preventResetByRollback();
469
 
470
        $observers = array(
471
            array(
472
                'eventname'   => '\core_tests\event\unittest_executed',
473
                'callback'    => '\core_tests\event\unittest_observer::external_observer',
474
                'internal'    => 0,
475
            ),
476
        );
477
 
478
        \core\event\manager::phpunit_replace_observers($observers);
479
        \core_tests\event\unittest_observer::reset();
480
 
481
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
482
 
483
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
484
        $this->assertCount(1, \core_tests\event\unittest_observer::$event);
485
        \core_tests\event\unittest_observer::reset();
486
 
487
        $transaction1 = $DB->start_delegated_transaction();
488
 
489
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
490
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
491
 
492
        $transaction2 = $DB->start_delegated_transaction();
493
 
494
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
495
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
496
 
497
        try {
498
            $transaction2->rollback(new \Exception('x'));
499
            $this->fail('Expecting exception');
500
        } catch (\Exception $e) {}
501
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
502
 
503
        $this->assertTrue($DB->is_transaction_started());
504
 
505
        try {
506
            $transaction1->rollback(new \Exception('x'));
507
            $this->fail('Expecting exception');
508
        } catch (\Exception $e) {}
509
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
510
 
511
        $this->assertFalse($DB->is_transaction_started());
512
 
513
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
514
        $this->assertCount(1, \core_tests\event\unittest_observer::$event);
515
    }
516
 
11 efrain 517
    public function test_forced_rollback(): void {
1 efrain 518
        global $DB;
519
 
520
        $this->resetAfterTest();
521
        $this->preventResetByRollback();
522
 
523
        $observers = array(
524
            array(
525
                'eventname'   => '\core_tests\event\unittest_executed',
526
                'callback'    => '\core_tests\event\unittest_observer::external_observer',
527
                'internal'    => 0,
528
            ),
529
        );
530
 
531
        \core\event\manager::phpunit_replace_observers($observers);
532
        \core_tests\event\unittest_observer::reset();
533
 
534
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
535
 
536
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
537
        $this->assertCount(1, \core_tests\event\unittest_observer::$event);
538
        \core_tests\event\unittest_observer::reset();
539
 
540
        $transaction1 = $DB->start_delegated_transaction();
541
 
542
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
543
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
544
 
545
        $transaction2 = $DB->start_delegated_transaction();
546
 
547
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
548
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
549
 
550
        $DB->force_transaction_rollback();
551
        $this->assertCount(0, \core_tests\event\unittest_observer::$event);
552
 
553
        $this->assertFalse($DB->is_transaction_started());
554
 
555
        \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)))->trigger();
556
        $this->assertCount(1, \core_tests\event\unittest_observer::$event);
557
    }
558
 
11 efrain 559
    public function test_deprecated(): void {
1 efrain 560
        global $DB;
561
 
562
        $this->resetAfterTest(true);
563
 
564
        $event = \core_tests\event\deprecated_event1::create();
565
        $this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
566
 
567
        $this->assertSame($event::LEVEL_TEACHING, $event->level);
568
        $this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
569
 
570
        $this->assertTrue(isset($event->level));
571
        $this->assertDebuggingCalled('level property is deprecated, use edulevel property instead');
572
 
573
        $this->assertSame($event::LEVEL_TEACHING, $event->edulevel);
574
    }
575
 
11 efrain 576
    public function test_legacy(): void {
1 efrain 577
        global $DB, $CFG;
578
 
579
        $this->resetAfterTest(true);
580
 
581
        $observers = array(
582
            array(
583
                'eventname'   => '\core_tests\event\unittest_executed',
584
                'callback'    => '\core_tests\event\unittest_observer::observe_one',
585
            ),
586
            array(
587
                'eventname'   => '*',
588
                'callback'    => '\core_tests\event\unittest_observer::observe_all',
589
                'includefile' => null,
590
                'internal'    => 1,
591
                'priority'    => 9999,
592
            ),
593
        );
594
 
595
        $DB->delete_records('log', array());
596
        $this->expectException(\coding_exception::class);
597
        events_update_definition('unittest');
598
 
599
        $DB->delete_records_select('events_handlers', "component <> 'unittest'");
600
 
601
        $this->assertDebuggingCalled(self::DEBUGGING_MSG, DEBUG_DEVELOPER);
602
        $this->assertEquals(3, $DB->count_records('events_handlers'));
603
        set_config('loglifetime', 60*60*24*5);
604
 
605
        \core\event\manager::phpunit_replace_observers($observers);
606
        \core_tests\event\unittest_observer::reset();
607
 
608
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
609
        $event1->trigger();
610
 
611
        $event2 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>6, 'xx'=>11)));
612
        $event2->nest = true;
613
        $event2->trigger();
614
 
615
        $this->assertSame(
616
            array('observe_all-5', 'observe_one-5', 'observe_all-nesting-6', 'observe_one-6', 'observe_all-666', 'observe_one-666'),
617
            \core_tests\event\unittest_observer::$info);
618
 
619
        $this->assertSame($event1, \core_tests\event\unittest_observer::$event[0]);
620
        $this->assertSame($event1, \core_tests\event\unittest_observer::$event[1]);
621
 
622
        $logs = $DB->get_records('log', array(), 'id ASC');
623
        $this->assertCount(0, $logs);
624
    }
625
 
11 efrain 626
    public function test_restore_event(): void {
1 efrain 627
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
628
        $data1 = $event1->get_data();
629
 
630
        $event2 = \core\event\base::restore($data1, array('origin'=>'clid'));
631
        $data2 = $event2->get_data();
632
 
633
        $this->assertTrue($event2->is_triggered());
634
        $this->assertTrue($event2->is_restored());
635
        $this->assertEquals($data1, $data2);
636
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event2);
637
 
638
        $this->assertEquals($event1->get_context(), $event2->get_context());
639
 
640
        // Now test problematic data.
641
        $data3 = $data1;
642
        $data3['eventname'] = '\\a\\b\\c';
643
        $event3 = \core\event\base::restore($data3, array());
644
        $this->assertFalse($event3, 'Class name must match');
645
 
646
        $data4 = $data1;
647
        unset($data4['userid']);
648
        $event4 = \core\event\base::restore($data4, array());
649
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event4);
650
        $this->assertDebuggingCalled();
651
 
652
        $data5 = $data1;
653
        $data5['xx'] = 'xx';
654
        $event5 = \core\event\base::restore($data5, array());
655
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event5);
656
        $this->assertDebuggingCalled();
657
 
658
    }
659
 
11 efrain 660
    public function test_trigger_problems(): void {
1 efrain 661
        $this->resetAfterTest(true);
662
 
663
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
664
        $event->trigger();
665
        try {
666
            $event->trigger();
667
            $this->fail('Exception expected on double trigger');
668
        } catch (\moodle_exception $e) {
669
            $this->assertInstanceOf(\coding_exception::class, $e);
670
        }
671
 
672
        $data = $event->get_data();
673
        $restored = \core_tests\event\unittest_executed::restore($data, array());
674
        $this->assertTrue($restored->is_triggered());
675
        $this->assertTrue($restored->is_restored());
676
 
677
        try {
678
            $restored->trigger();
679
            $this->fail('Exception expected on triggering of restored event');
680
        } catch (\moodle_exception $e) {
681
            $this->assertInstanceOf(\coding_exception::class, $e);
682
        }
683
 
684
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
685
        try {
686
            \core\event\manager::dispatch($event);
687
            $this->fail('Exception expected on manual event dispatching');
688
        } catch (\moodle_exception $e) {
689
            $this->assertInstanceOf(\coding_exception::class, $e);
690
        }
691
    }
692
 
11 efrain 693
    public function test_bad_events(): void {
1 efrain 694
        $this->resetAfterTest(true);
695
 
696
        try {
697
            $event = \core_tests\event\unittest_executed::create(array('other'=>array('sample'=>5, 'xx'=>10)));
698
            $this->fail('Exception expected when context and contextid missing');
699
        } catch (\moodle_exception $e) {
700
            $this->assertInstanceOf(\coding_exception::class, $e);
701
        }
702
 
703
        $event = \core_tests\event\bad_event1::create(array('context'=>\context_system::instance()));
704
        try {
705
            $event->trigger();
706
            $this->fail('Exception expected when $data not valid');
707
        } catch (\moodle_exception $e) {
708
            $this->assertInstanceOf(\coding_exception::class, $e);
709
        }
710
 
711
        $event = \core_tests\event\bad_event2::create(array('context'=>\context_system::instance()));
712
        try {
713
            $event->trigger();
714
            $this->fail('Exception expected when $data not valid');
715
        } catch (\moodle_exception $e) {
716
            $this->assertInstanceOf(\coding_exception::class, $e);
717
        }
718
 
719
        $event = \core_tests\event\bad_event2b::create(array('context'=>\context_system::instance()));
720
        @$event->trigger();
721
        $this->assertDebuggingCalled();
722
 
723
        $event = \core_tests\event\bad_event3::create(array('context'=>\context_system::instance()));
724
        @$event->trigger();
725
        $this->assertDebuggingCalled();
726
 
727
        $event = \core_tests\event\bad_event4::create(array('context'=>\context_system::instance()));
728
        @$event->trigger();
729
        $this->assertDebuggingCalled();
730
 
731
        $event = \core_tests\event\bad_event5::create(array('context'=>\context_system::instance()));
732
        @$event->trigger();
733
        $this->assertDebuggingCalled();
734
 
735
        $event = \core_tests\event\bad_event6::create(array('objectid'=>1, 'context'=>\context_system::instance()));
736
        $event->trigger();
737
        $this->assertDebuggingCalled('Unknown table specified in objecttable field');
738
 
739
        $event = \core_tests\event\bad_event7::create(array('objectid'=>1, 'context'=>\context_system::instance()));
740
        try {
741
            $event->trigger();
742
            $this->fail('Exception expected when $data contains objectid but objecttable not specified');
743
        } catch (\moodle_exception $e) {
744
            $this->assertInstanceOf(\coding_exception::class, $e);
745
        }
746
 
747
        $event = \core_tests\event\bad_event8::create(array('context'=>\context_system::instance()));
748
        $event->trigger();
749
        $this->assertDebuggingCalled('Event property objectid must be set when objecttable is defined');
750
    }
751
 
11 efrain 752
    public function test_problematic_events(): void {
1 efrain 753
        $this->resetAfterTest(true);
754
 
755
        $event1 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance()));
756
        $this->assertDebuggingNotCalled();
757
        $this->assertNull($event1->xxx);
758
        $this->assertDebuggingCalled();
759
 
760
        $event2 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
761
        $this->assertDebuggingCalled();
762
 
763
        set_debugging(DEBUG_NONE);
764
        $event3 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
765
        $this->assertDebuggingNotCalled();
766
        set_debugging(DEBUG_DEVELOPER);
767
 
768
        $event4 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>1)));
769
        $event4->trigger();
770
        $this->assertDebuggingNotCalled();
771
 
772
        // Check the invalid content that cannot be converted to JSON will trigger debugging messages.
773
        $event5 = \core_tests\event\problematic_event1::create(array('context' => \context_system::instance(), 'other' => [
774
            'a' => NAN
775
        ]));
776
        $this->assertDebuggingNotCalled();
777
        $event5->trigger();
778
        $this->assertDebuggingCalled();
779
 
780
        // Check that moodle_url object does not trigger debugging messages.
781
        $url = new \moodle_url('/admin/');
782
        $event6 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>$url)));
783
        $event6->trigger();
784
        $this->assertDebuggingNotCalled();
785
 
786
        // Check that whole float numbers do not trigger debugging messages.
787
        $event7 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(),
788
            'other' => array('wholenumber' => 90.0000, 'numberwithdecimals' => 54.7656, 'sample' => 1)));
789
        $event7->trigger();
790
        $this->assertDebuggingNotCalled();
791
 
792
        $event = \core_tests\event\problematic_event2::create(array());
793
        $this->assertDebuggingNotCalled();
794
        $event = \core_tests\event\problematic_event2::create(array('context'=>\context_system::instance()));
795
        $this->assertDebuggingCalled();
796
 
797
        $event = \core_tests\event\problematic_event3::create(array('other'=>1));
798
        $this->assertDebuggingNotCalled();
799
        $event = \core_tests\event\problematic_event3::create(array());
800
        $this->assertDebuggingCalled();
801
    }
802
 
11 efrain 803
    public function test_record_snapshots(): void {
1 efrain 804
        global $DB;
805
 
806
        $this->resetAfterTest(true);
807
 
808
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
809
        $course1 = $DB->get_record('course', array('id'=>1));
810
        $this->assertNotEmpty($course1);
811
 
812
        $event->add_record_snapshot('course', $course1);
813
 
814
        $result = $event->get_record_snapshot('course', $course1->id);
815
        // Convert to arrays because record snapshot returns a clone of the object.
816
        $this->assertSame((array)$course1, (array)$result);
817
 
818
        $user = $event->get_record_snapshot('user', 1);
819
        $this->assertEquals(1, $user->id);
820
        $this->assertSame('guest', $user->username);
821
 
822
        $event->add_record_snapshot('course', $course1);
823
        $event->trigger();
824
        try {
825
            $event->add_record_snapshot('course', $course1);
826
            $this->fail('Updating of snapshots after trigger is not ok');;
827
        } catch (\moodle_exception $e) {
828
            $this->assertInstanceOf(\coding_exception::class, $e);
829
        }
830
 
831
        $event2 = \core_tests\event\unittest_executed::restore($event->get_data(), array());
832
        try {
833
            $event2->get_record_snapshot('course', $course1->id);
834
            $this->fail('Reading of snapshots from restored events is not ok');;
835
        } catch (\moodle_exception $e) {
836
            $this->assertInstanceOf(\coding_exception::class, $e);
837
        }
838
    }
839
 
11 efrain 840
    public function test_get_name(): void {
1 efrain 841
        $event = \core_tests\event\noname_event::create(array('other' => array('sample' => 1, 'xx' => 10)));
842
        $this->assertEquals("core_tests: noname event", $event->get_name());
843
    }
844
 
11 efrain 845
    public function test_iteration(): void {
1 efrain 846
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
847
 
848
        $data = array();
849
        foreach ($event as $k => $v) {
850
            $data[$k] = $v;
851
        }
852
 
853
        $this->assertSame($event->get_data(), $data);
854
    }
855
 
856
    /**
857
     * Test that all observer information is returned correctly.
858
     */
11 efrain 859
    public function test_get_all_observers(): void {
1 efrain 860
        // Retrieve all observers.
861
        $observers = \core\event\manager::get_all_observers();
862
 
863
        // Expected information from the workshop allocation scheduled observer.
864
        $expected = new \stdClass();
865
        $expected->callable = '\workshopallocation_scheduled\observer::workshop_viewed';
866
        $expected->priority = 0;
867
        $expected->internal = true;
868
        $expected->includefile = null;
869
        $expected->plugintype = 'workshopallocation';
870
        $expected->plugin = 'scheduled';
871
 
872
        // May be more than one observer for the mod_workshop event.
873
        $found = false;
874
        foreach ($observers['\mod_workshop\event\course_module_viewed'] as $observer) {
875
            if ($expected == $observer) {
876
                $found = true;
877
                break;
878
            }
879
        }
880
        $this->assertTrue($found);
881
    }
882
 
883
    /**
884
     * Test formatting of the get_explanation method.
885
     * This formats the information from an events class docblock.
886
     */
11 efrain 887
    public function test_get_explanation(): void {
1 efrain 888
        $explanation = \core_tests\event\full_docblock::get_explanation();
889
 
890
        $expected = "This is an explanation of the event.
891
     - I'm making a point here.
892
     - I have a second {@link something}  point here.
893
     - whitespace is intentional to test it's removal.
894
I have something else *Yeah* that.";
895
 
896
        $this->assertEquals($explanation, $expected);
897
 
898
        $explanation = \core_tests\event\docblock_test2::get_explanation();
899
 
900
        $expected = "We have only the description in the docblock
901
and nothing else.";
902
 
903
        $this->assertEquals($explanation, $expected);
904
 
905
        $explanation = \core_tests\event\docblock_test3::get_explanation();
906
        $expected = "Calendar event created event.";
907
        $this->assertEquals($explanation, $expected);
908
 
909
    }
910
 
911
    /**
912
     * Test that general information about an event is returned
913
     * by the get_static_info() method.
914
     */
11 efrain 915
    public function test_get_static_info(): void {
1 efrain 916
        $staticinfo = \core_tests\event\static_info_viewing::get_static_info();
917
 
918
        $expected = array(
919
            'eventname'   => '\\core_tests\\event\\static_info_viewing',
920
            'component'   => 'core_tests',
921
            'target'      => 'static_info',
922
            'action'      => 'viewing',
923
            'crud'        => 'r',
924
            'edulevel'    => 0,
925
            'objecttable' => 'mod_unittest'
926
        );
927
        $this->assertEquals($staticinfo, $expected);
928
    }
929
 
930
    /**
931
     * This tests the internal method of \core\event\manager::get_observing_classes.
932
     *
933
     * What we are testing is if we can subscribe to a parent event class, instead of only
934
     * the base event class or the final, implemented event class.  This enables us to subscribe
935
     * to things like all course module view events, all comment created events, etc.
936
     */
11 efrain 937
    public function test_observe_parent_event(): void {
1 efrain 938
        $this->resetAfterTest();
939
 
940
        // Ensure this has been reset prior to using it.
941
        \core_tests\event\unittest_observer::reset();
942
 
943
        $course  = $this->getDataGenerator()->create_course();
944
        $feed    = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
945
        $context = \context_module::instance($feed->cmid);
946
        $data    = [
947
            'context'  => $context,
948
            'courseid' => $course->id,
949
            'objectid' => $feed->id
950
        ];
951
 
952
        // This assertion ensures that basic observe use case did not break.
953
        \core\event\manager::phpunit_replace_observers([[
954
            'eventname' => '\core_tests\event\course_module_viewed',
955
            'callback'  => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
956
        ]]);
957
 
958
        $pageevent = \core_tests\event\course_module_viewed::create($data);
959
        $pageevent->trigger();
960
 
961
        $this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing triggered event');
962
 
963
        \core_tests\event\unittest_observer::reset();
964
 
965
        // This assertion tests that we can observe an abstract (parent) class instead of the implemented class.
966
        \core\event\manager::phpunit_replace_observers([[
967
            'eventname' => '\core\event\course_module_viewed',
968
            'callback'  => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
969
        ]]);
970
 
971
        $pageevent = \core_tests\event\course_module_viewed::create($data);
972
        $pageevent->trigger();
973
 
974
        $this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing parent class event');
975
 
976
        \core_tests\event\unittest_observer::reset();
977
    }
978
}