Proyectos de Subversion Moodle

Rev

Rev 11 | | 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
 */
1441 ariadna 31
final class base_test extends \advanced_testcase {
1 efrain 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_restore_event(): void {
1 efrain 577
        $event1 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
578
        $data1 = $event1->get_data();
579
 
580
        $event2 = \core\event\base::restore($data1, array('origin'=>'clid'));
581
        $data2 = $event2->get_data();
582
 
583
        $this->assertTrue($event2->is_triggered());
584
        $this->assertTrue($event2->is_restored());
585
        $this->assertEquals($data1, $data2);
586
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event2);
587
 
588
        $this->assertEquals($event1->get_context(), $event2->get_context());
589
 
590
        // Now test problematic data.
591
        $data3 = $data1;
592
        $data3['eventname'] = '\\a\\b\\c';
593
        $event3 = \core\event\base::restore($data3, array());
594
        $this->assertFalse($event3, 'Class name must match');
595
 
596
        $data4 = $data1;
597
        unset($data4['userid']);
598
        $event4 = \core\event\base::restore($data4, array());
599
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event4);
600
        $this->assertDebuggingCalled();
601
 
602
        $data5 = $data1;
603
        $data5['xx'] = 'xx';
604
        $event5 = \core\event\base::restore($data5, array());
605
        $this->assertInstanceOf(\core_tests\event\unittest_executed::class, $event5);
606
        $this->assertDebuggingCalled();
607
 
608
    }
609
 
11 efrain 610
    public function test_trigger_problems(): void {
1 efrain 611
        $this->resetAfterTest(true);
612
 
613
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
614
        $event->trigger();
615
        try {
616
            $event->trigger();
617
            $this->fail('Exception expected on double trigger');
618
        } catch (\moodle_exception $e) {
619
            $this->assertInstanceOf(\coding_exception::class, $e);
620
        }
621
 
622
        $data = $event->get_data();
623
        $restored = \core_tests\event\unittest_executed::restore($data, array());
624
        $this->assertTrue($restored->is_triggered());
625
        $this->assertTrue($restored->is_restored());
626
 
627
        try {
628
            $restored->trigger();
629
            $this->fail('Exception expected on triggering of restored event');
630
        } catch (\moodle_exception $e) {
631
            $this->assertInstanceOf(\coding_exception::class, $e);
632
        }
633
 
634
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>5, 'xx'=>10)));
635
        try {
636
            \core\event\manager::dispatch($event);
637
            $this->fail('Exception expected on manual event dispatching');
638
        } catch (\moodle_exception $e) {
639
            $this->assertInstanceOf(\coding_exception::class, $e);
640
        }
641
    }
642
 
11 efrain 643
    public function test_bad_events(): void {
1 efrain 644
        $this->resetAfterTest(true);
645
 
646
        try {
647
            $event = \core_tests\event\unittest_executed::create(array('other'=>array('sample'=>5, 'xx'=>10)));
648
            $this->fail('Exception expected when context and contextid missing');
649
        } catch (\moodle_exception $e) {
650
            $this->assertInstanceOf(\coding_exception::class, $e);
651
        }
652
 
653
        $event = \core_tests\event\bad_event1::create(array('context'=>\context_system::instance()));
654
        try {
655
            $event->trigger();
656
            $this->fail('Exception expected when $data not valid');
657
        } catch (\moodle_exception $e) {
658
            $this->assertInstanceOf(\coding_exception::class, $e);
659
        }
660
 
661
        $event = \core_tests\event\bad_event2::create(array('context'=>\context_system::instance()));
662
        try {
663
            $event->trigger();
664
            $this->fail('Exception expected when $data not valid');
665
        } catch (\moodle_exception $e) {
666
            $this->assertInstanceOf(\coding_exception::class, $e);
667
        }
668
 
669
        $event = \core_tests\event\bad_event2b::create(array('context'=>\context_system::instance()));
670
        @$event->trigger();
671
        $this->assertDebuggingCalled();
672
 
673
        $event = \core_tests\event\bad_event3::create(array('context'=>\context_system::instance()));
674
        @$event->trigger();
675
        $this->assertDebuggingCalled();
676
 
677
        $event = \core_tests\event\bad_event4::create(array('context'=>\context_system::instance()));
678
        @$event->trigger();
679
        $this->assertDebuggingCalled();
680
 
681
        $event = \core_tests\event\bad_event5::create(array('context'=>\context_system::instance()));
682
        @$event->trigger();
683
        $this->assertDebuggingCalled();
684
 
685
        $event = \core_tests\event\bad_event6::create(array('objectid'=>1, 'context'=>\context_system::instance()));
686
        $event->trigger();
687
        $this->assertDebuggingCalled('Unknown table specified in objecttable field');
688
 
689
        $event = \core_tests\event\bad_event7::create(array('objectid'=>1, 'context'=>\context_system::instance()));
690
        try {
691
            $event->trigger();
692
            $this->fail('Exception expected when $data contains objectid but objecttable not specified');
693
        } catch (\moodle_exception $e) {
694
            $this->assertInstanceOf(\coding_exception::class, $e);
695
        }
696
 
697
        $event = \core_tests\event\bad_event8::create(array('context'=>\context_system::instance()));
698
        $event->trigger();
699
        $this->assertDebuggingCalled('Event property objectid must be set when objecttable is defined');
700
    }
701
 
11 efrain 702
    public function test_problematic_events(): void {
1 efrain 703
        $this->resetAfterTest(true);
704
 
705
        $event1 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance()));
706
        $this->assertDebuggingNotCalled();
707
        $this->assertNull($event1->xxx);
708
        $this->assertDebuggingCalled();
709
 
710
        $event2 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
711
        $this->assertDebuggingCalled();
712
 
713
        set_debugging(DEBUG_NONE);
714
        $event3 = \core_tests\event\problematic_event1::create(array('xxx'=>0, 'context'=>\context_system::instance()));
715
        $this->assertDebuggingNotCalled();
716
        set_debugging(DEBUG_DEVELOPER);
717
 
718
        $event4 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>1)));
719
        $event4->trigger();
720
        $this->assertDebuggingNotCalled();
721
 
722
        // Check the invalid content that cannot be converted to JSON will trigger debugging messages.
723
        $event5 = \core_tests\event\problematic_event1::create(array('context' => \context_system::instance(), 'other' => [
724
            'a' => NAN
725
        ]));
726
        $this->assertDebuggingNotCalled();
727
        $event5->trigger();
728
        $this->assertDebuggingCalled();
729
 
730
        // Check that moodle_url object does not trigger debugging messages.
731
        $url = new \moodle_url('/admin/');
732
        $event6 = \core_tests\event\problematic_event1::create(array('context'=>\context_system::instance(), 'other'=>array('a'=>$url)));
733
        $event6->trigger();
734
        $this->assertDebuggingNotCalled();
735
 
736
        // Check that whole float numbers do not trigger debugging messages.
737
        $event7 = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(),
738
            'other' => array('wholenumber' => 90.0000, 'numberwithdecimals' => 54.7656, 'sample' => 1)));
739
        $event7->trigger();
740
        $this->assertDebuggingNotCalled();
741
 
742
        $event = \core_tests\event\problematic_event2::create(array());
743
        $this->assertDebuggingNotCalled();
744
        $event = \core_tests\event\problematic_event2::create(array('context'=>\context_system::instance()));
745
        $this->assertDebuggingCalled();
746
 
747
        $event = \core_tests\event\problematic_event3::create(array('other'=>1));
748
        $this->assertDebuggingNotCalled();
749
        $event = \core_tests\event\problematic_event3::create(array());
750
        $this->assertDebuggingCalled();
751
    }
752
 
11 efrain 753
    public function test_record_snapshots(): void {
1 efrain 754
        global $DB;
755
 
756
        $this->resetAfterTest(true);
757
 
758
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
759
        $course1 = $DB->get_record('course', array('id'=>1));
760
        $this->assertNotEmpty($course1);
761
 
762
        $event->add_record_snapshot('course', $course1);
763
 
764
        $result = $event->get_record_snapshot('course', $course1->id);
765
        // Convert to arrays because record snapshot returns a clone of the object.
766
        $this->assertSame((array)$course1, (array)$result);
767
 
768
        $user = $event->get_record_snapshot('user', 1);
769
        $this->assertEquals(1, $user->id);
770
        $this->assertSame('guest', $user->username);
771
 
772
        $event->add_record_snapshot('course', $course1);
773
        $event->trigger();
774
        try {
775
            $event->add_record_snapshot('course', $course1);
776
            $this->fail('Updating of snapshots after trigger is not ok');;
777
        } catch (\moodle_exception $e) {
778
            $this->assertInstanceOf(\coding_exception::class, $e);
779
        }
780
 
781
        $event2 = \core_tests\event\unittest_executed::restore($event->get_data(), array());
782
        try {
783
            $event2->get_record_snapshot('course', $course1->id);
784
            $this->fail('Reading of snapshots from restored events is not ok');;
785
        } catch (\moodle_exception $e) {
786
            $this->assertInstanceOf(\coding_exception::class, $e);
787
        }
788
    }
789
 
11 efrain 790
    public function test_get_name(): void {
1 efrain 791
        $event = \core_tests\event\noname_event::create(array('other' => array('sample' => 1, 'xx' => 10)));
792
        $this->assertEquals("core_tests: noname event", $event->get_name());
793
    }
794
 
11 efrain 795
    public function test_iteration(): void {
1 efrain 796
        $event = \core_tests\event\unittest_executed::create(array('context'=>\context_system::instance(), 'other'=>array('sample'=>1, 'xx'=>10)));
797
 
798
        $data = array();
799
        foreach ($event as $k => $v) {
800
            $data[$k] = $v;
801
        }
802
 
803
        $this->assertSame($event->get_data(), $data);
804
    }
805
 
806
    /**
807
     * Test that all observer information is returned correctly.
808
     */
11 efrain 809
    public function test_get_all_observers(): void {
1 efrain 810
        // Retrieve all observers.
811
        $observers = \core\event\manager::get_all_observers();
812
 
813
        // Expected information from the workshop allocation scheduled observer.
814
        $expected = new \stdClass();
815
        $expected->callable = '\workshopallocation_scheduled\observer::workshop_viewed';
816
        $expected->priority = 0;
817
        $expected->internal = true;
818
        $expected->includefile = null;
819
        $expected->plugintype = 'workshopallocation';
820
        $expected->plugin = 'scheduled';
821
 
822
        // May be more than one observer for the mod_workshop event.
823
        $found = false;
824
        foreach ($observers['\mod_workshop\event\course_module_viewed'] as $observer) {
825
            if ($expected == $observer) {
826
                $found = true;
827
                break;
828
            }
829
        }
830
        $this->assertTrue($found);
831
    }
832
 
833
    /**
834
     * Test formatting of the get_explanation method.
835
     * This formats the information from an events class docblock.
836
     */
11 efrain 837
    public function test_get_explanation(): void {
1 efrain 838
        $explanation = \core_tests\event\full_docblock::get_explanation();
839
 
840
        $expected = "This is an explanation of the event.
841
     - I'm making a point here.
842
     - I have a second {@link something}  point here.
843
     - whitespace is intentional to test it's removal.
844
I have something else *Yeah* that.";
845
 
846
        $this->assertEquals($explanation, $expected);
847
 
848
        $explanation = \core_tests\event\docblock_test2::get_explanation();
849
 
850
        $expected = "We have only the description in the docblock
851
and nothing else.";
852
 
853
        $this->assertEquals($explanation, $expected);
854
 
855
        $explanation = \core_tests\event\docblock_test3::get_explanation();
856
        $expected = "Calendar event created event.";
857
        $this->assertEquals($explanation, $expected);
858
 
859
    }
860
 
861
    /**
862
     * Test that general information about an event is returned
863
     * by the get_static_info() method.
864
     */
11 efrain 865
    public function test_get_static_info(): void {
1 efrain 866
        $staticinfo = \core_tests\event\static_info_viewing::get_static_info();
867
 
868
        $expected = array(
869
            'eventname'   => '\\core_tests\\event\\static_info_viewing',
870
            'component'   => 'core_tests',
871
            'target'      => 'static_info',
872
            'action'      => 'viewing',
873
            'crud'        => 'r',
874
            'edulevel'    => 0,
875
            'objecttable' => 'mod_unittest'
876
        );
877
        $this->assertEquals($staticinfo, $expected);
878
    }
879
 
880
    /**
881
     * This tests the internal method of \core\event\manager::get_observing_classes.
882
     *
883
     * What we are testing is if we can subscribe to a parent event class, instead of only
884
     * the base event class or the final, implemented event class.  This enables us to subscribe
885
     * to things like all course module view events, all comment created events, etc.
886
     */
11 efrain 887
    public function test_observe_parent_event(): void {
1 efrain 888
        $this->resetAfterTest();
889
 
890
        // Ensure this has been reset prior to using it.
891
        \core_tests\event\unittest_observer::reset();
892
 
893
        $course  = $this->getDataGenerator()->create_course();
894
        $feed    = $this->getDataGenerator()->create_module('feedback', ['course' => $course->id]);
895
        $context = \context_module::instance($feed->cmid);
896
        $data    = [
897
            'context'  => $context,
898
            'courseid' => $course->id,
899
            'objectid' => $feed->id
900
        ];
901
 
902
        // This assertion ensures that basic observe use case did not break.
903
        \core\event\manager::phpunit_replace_observers([[
904
            'eventname' => '\core_tests\event\course_module_viewed',
905
            'callback'  => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
906
        ]]);
907
 
908
        $pageevent = \core_tests\event\course_module_viewed::create($data);
909
        $pageevent->trigger();
910
 
911
        $this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing triggered event');
912
 
913
        \core_tests\event\unittest_observer::reset();
914
 
915
        // This assertion tests that we can observe an abstract (parent) class instead of the implemented class.
916
        \core\event\manager::phpunit_replace_observers([[
917
            'eventname' => '\core\event\course_module_viewed',
918
            'callback'  => ['\core_tests\event\unittest_observer', 'observe_all_alt'],
919
        ]]);
920
 
921
        $pageevent = \core_tests\event\course_module_viewed::create($data);
922
        $pageevent->trigger();
923
 
924
        $this->assertSame(['observe_all_alt'], \core_tests\event\unittest_observer::$info, 'Error observing parent class event');
925
 
926
        \core_tests\event\unittest_observer::reset();
927
    }
928
}