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
/**
18
 * Privacy provider tests.
19
 *
20
 * @package    core_question
21
 * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace core_question\privacy;
25
 
26
use core_privacy\local\metadata\collection;
27
use core_privacy\local\request\deletion_criteria;
28
use core_privacy\local\request\writer;
29
use core_question\privacy\provider;
30
 
31
defined('MOODLE_INTERNAL') || die();
32
 
33
global $CFG;
34
require_once($CFG->libdir . '/xmlize.php');
35
require_once(__DIR__ . '/../privacy_helper.php');
36
require_once(__DIR__ . '/../../engine/tests/helpers.php');
37
 
38
/**
39
 * Privacy provider tests class.
40
 *
41
 * @package    core_question
42
 * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
43
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44
 */
1441 ariadna 45
final class provider_test extends \core_privacy\tests\provider_testcase {
1 efrain 46
 
47
    // Include the privacy helper which has assertions on it.
48
    use \core_question_privacy_helper;
49
 
50
    /**
51
     * Prepare a question attempt.
52
     *
53
     * @return  question_usage_by_activity
54
     */
55
    protected function prepare_question_attempt() {
56
        // Create a question with a usage from the current user.
57
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
58
        $cat = $questiongenerator->create_question_category();
59
        $quba = \question_engine::make_questions_usage_by_activity('core_question_preview', \context_system::instance());
60
        $quba->set_preferred_behaviour('deferredfeedback');
61
        $questiondata = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]);
62
        $question = \question_bank::load_question($questiondata->id);
63
        $quba->add_question($question);
64
        $quba->start_all_questions();
65
 
66
        \question_engine::save_questions_usage_by_activity($quba);
67
 
68
        return $quba;
69
    }
70
 
71
    /**
72
     * Test that calling export_question_usage on a usage belonging to a
73
     * different user does not export any data.
74
     */
11 efrain 75
    public function test_export_question_usage_no_usage(): void {
1 efrain 76
        $this->resetAfterTest();
77
 
78
        $quba = $this->prepare_question_attempt();
79
 
80
        // Create a question with a usage from the current user.
81
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
82
        $cat = $questiongenerator->create_question_category();
83
        $quba = \question_engine::make_questions_usage_by_activity('core_question_preview', \context_system::instance());
84
        $quba->set_preferred_behaviour('deferredfeedback');
85
        $questiondata = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]);
86
        $question = \question_bank::load_question($questiondata->id);
87
        $quba->add_question($question);
88
        $quba->start_all_questions();
89
 
90
        \question_engine::save_questions_usage_by_activity($quba);
91
 
92
        // Set the user.
93
        $testuser = $this->getDataGenerator()->create_user();
94
        $this->setUser($testuser);
95
        $context = $quba->get_owning_context();
96
        $options = new \question_display_options();
97
 
98
        provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, false);
99
        /** @var \core_privacy\tests\request\content_writer $writer */
100
        $writer = writer::with_context($context);
101
 
102
        $this->assertFalse($writer->has_any_data_in_any_context());
103
    }
104
 
105
    /**
106
     * Test that calling export_question_usage on a usage belonging to a
107
     * different user but ignoring the user match
108
     */
11 efrain 109
    public function test_export_question_usage_with_usage(): void {
1 efrain 110
        $this->resetAfterTest();
111
 
112
        $quba = $this->prepare_question_attempt();
113
 
114
        // Create a question with a usage from the current user.
115
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
116
        $cat = $questiongenerator->create_question_category();
117
        $quba = \question_engine::make_questions_usage_by_activity('core_question_preview', \context_system::instance());
118
        $quba->set_preferred_behaviour('deferredfeedback');
119
 
120
        $questiondata = $questiongenerator->create_question('truefalse', 'true', ['category' => $cat->id]);
121
        $quba->add_question(\question_bank::load_question($questiondata->id));
122
        $questiondata = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
123
        $quba->add_question(\question_bank::load_question($questiondata->id));
124
 
125
        // Set the user and answer the questions.
126
        $testuser = $this->getDataGenerator()->create_user();
127
        $this->setUser($testuser);
128
 
129
        $quba->start_all_questions();
130
        $quba->process_action(1, ['answer' => 1]);
131
        $quba->process_action(2, ['answer' => 'cat']);
132
        $quba->finish_all_questions();
133
 
134
        \question_engine::save_questions_usage_by_activity($quba);
135
 
136
        $context = $quba->get_owning_context();
137
 
138
        // Export all questions for this attempt.
139
        $options = new \question_display_options();
140
        provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, true);
141
        /** @var \core_privacy\tests\request\content_writer $writer */
142
        $writer = writer::with_context($context);
143
 
144
        $this->assertTrue($writer->has_any_data_in_any_context());
145
        $this->assertTrue($writer->has_any_data());
146
 
147
        $slots = $quba->get_slots();
148
        $this->assertCount(2, $slots);
149
 
150
        foreach ($slots as $slotno) {
151
            $data = $writer->get_data([get_string('questions', 'core_question'), $slotno]);
152
            $this->assertNotNull($data);
153
            $this->assert_question_slot_equals($quba, $slotno, $options, $data);
154
        }
155
 
156
        $this->assertEmpty($writer->get_data([get_string('questions', 'core_question'), $quba->next_slot_number()]));
157
 
158
        // Disable some options and re-export.
159
        writer::reset();
160
        $options = new \question_display_options();
161
        $options->hide_all_feedback();
162
        $options->flags = \question_display_options::HIDDEN;
163
        $options->marks = \question_display_options::HIDDEN;
164
 
165
        provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, true);
166
        /** @var \core_privacy\tests\request\content_writer $writer */
167
        $writer = writer::with_context($context);
168
 
169
        $this->assertTrue($writer->has_any_data_in_any_context());
170
        $this->assertTrue($writer->has_any_data());
171
 
172
        $slots = $quba->get_slots();
173
        $this->assertCount(2, $slots);
174
 
175
        foreach ($slots as $slotno) {
176
            $data = $writer->get_data([get_string('questions', 'core_question'), $slotno]);
177
            $this->assertNotNull($data);
178
            $this->assert_question_slot_equals($quba, $slotno, $options, $data);
179
        }
180
 
181
        $this->assertEmpty($writer->get_data([get_string('questions', 'core_question'), $quba->next_slot_number()]));
182
    }
183
 
184
    /**
185
     * Test that questions owned by a user are exported and never deleted.
186
     */
11 efrain 187
    public function test_question_owned_is_handled(): void {
1 efrain 188
        global $DB;
189
        $this->resetAfterTest();
190
 
191
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
192
 
193
        // Create the two test users.
194
        $user = $this->getDataGenerator()->create_user();
195
        $otheruser = $this->getDataGenerator()->create_user();
196
 
197
        // Create one question as each user in diferent contexts.
198
        $this->setUser($user);
199
        $userdata = $questiongenerator->setup_course_and_questions();
1441 ariadna 200
        $expectedcontext = \context_module::instance($userdata[4]->cmid);
1 efrain 201
 
202
        $this->setUser($otheruser);
203
        $otheruserdata = $questiongenerator->setup_course_and_questions();
1441 ariadna 204
        $unexpectedcontext = \context_module::instance($otheruserdata[4]->cmid);
1 efrain 205
 
206
        // And create another one where we'll update a question as the test user.
207
        $moreotheruserdata = $questiongenerator->setup_course_and_questions();
1441 ariadna 208
        $otherexpectedcontext = \context_module::instance($moreotheruserdata[4]->cmid);
1 efrain 209
        $morequestions = $moreotheruserdata[3];
210
 
211
        // Update the third set of questions.
212
        $this->setUser($user);
213
 
214
        foreach ($morequestions as $question) {
215
            $questiongenerator->update_question($question);
216
        }
217
 
218
        // Run the get_contexts_for_userid as default user.
219
        $this->setUser();
220
 
221
        // There should be two contexts returned - the first course, and the third.
222
        $contextlist = provider::get_contexts_for_userid($user->id);
223
        $this->assertCount(2, $contextlist);
224
 
225
        $expectedcontexts = [
226
                $expectedcontext->id,
227
                $otherexpectedcontext->id,
228
            ];
1441 ariadna 229
        $this->assertEqualsCanonicalizing(
230
            $expectedcontexts,
231
            array_values($contextlist->get_contextids()),
232
            'Contexts not equal',
233
        );
1 efrain 234
 
235
        // Run the export_user_Data as the test user.
236
        $this->setUser($user);
237
 
238
        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
239
            \core_user::get_user($user->id),
240
            'core_question',
241
            $expectedcontexts
242
        );
243
        provider::export_user_data($approvedcontextlist);
244
 
245
        // There should be data for the user's question context.
246
        $writer = writer::with_context($expectedcontext);
247
        $this->assertTrue($writer->has_any_data());
248
 
249
        // And for the course we updated.
250
        $otherwriter = writer::with_context($otherexpectedcontext);
251
        $this->assertTrue($otherwriter->has_any_data());
252
 
253
        // But not for the other user's course.
254
        $otherwriter = writer::with_context($unexpectedcontext);
255
        $this->assertFalse($otherwriter->has_any_data());
256
 
257
        // The question data is exported as an XML export in custom files.
258
        $writer = writer::with_context($expectedcontext);
259
        $subcontext = [get_string('questionbank', 'core_question')];
260
 
261
        $exportfile = $writer->get_custom_file($subcontext, 'questions.xml');
262
        $this->assertNotEmpty($exportfile);
263
 
264
        $xmlized = xmlize($exportfile);
265
        $xmlquestions = $xmlized['quiz']['#']['question'];
266
 
267
        $this->assertCount(2, $xmlquestions);
268
 
269
        // Run the delete functions as default user.
270
        $this->setUser();
271
 
272
        // Find out how many questions are in the question bank to start with.
273
        $questioncount = $DB->count_records('question');
274
 
275
        // The delete functions should do nothing here.
276
 
277
        // Delete for all users in context.
278
        provider::delete_data_for_all_users_in_context($expectedcontext);
279
        $this->assertEquals($questioncount, $DB->count_records('question'));
280
 
281
        provider::delete_data_for_user($approvedcontextlist);
282
        $this->assertEquals($questioncount, $DB->count_records('question'));
283
    }
284
 
285
    /**
286
     * Deleting questions should only unset their created and modified user.
287
     */
11 efrain 288
    public function test_question_delete_data_for_user_anonymised(): void {
1 efrain 289
        global $DB;
290
        $this->resetAfterTest(true);
291
 
292
        $user = \core_user::get_user_by_username('admin');
293
        $otheruser = $this->getDataGenerator()->create_user();
294
 
295
        $course = $this->getDataGenerator()->create_course();
1441 ariadna 296
        $qbank1 = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
297
        $qbank1context = \context_module::instance($qbank1->cmid);
298
        $qbank2 = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
299
        $qbank2context = \context_module::instance($qbank2->cmid);
1 efrain 300
 
301
        // Create a couple of questions.
302
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
303
        $cat = $questiongenerator->create_question_category([
1441 ariadna 304
            'contextid' => $qbank1context->id,
1 efrain 305
        ]);
306
        $othercat = $questiongenerator->create_question_category([
1441 ariadna 307
            'contextid' => $qbank2context->id,
1 efrain 308
        ]);
309
 
310
        // Create questions:
311
        // Q1 - Created by the UUT, Modified by UUT.
312
        // Q2 - Created by the UUT, Modified by the other user.
313
        // Q3 - Created by the other user, Modified by UUT
314
        // Q4 - Created by the other user, Modified by the other user.
315
        // Q5 - Created by the UUT, Modified by the UUT, but in a different context.
316
        $this->setUser($user);
317
        $q1 = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
318
        $q2 = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
319
 
320
        $this->setUser($otheruser);
321
        // When we update a question, a new question/version is created.
322
        $q2updated = $questiongenerator->update_question($q2);
323
        $q3 = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
324
        $q4 = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
325
 
326
        $this->setUser($user);
327
        // When we update a question, a new question/version is created.
328
        $q3updated = $questiongenerator->update_question($q3);
329
        $q5 = $questiongenerator->create_question('shortanswer', null, ['category' => $othercat->id]);
330
 
331
        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
332
            $user,
333
            'core_question',
1441 ariadna 334
            [$qbank1context->id]
1 efrain 335
        );
336
 
337
        // Find out how many questions are in the question bank to start with.
338
        $questioncount = $DB->count_records('question');
339
 
340
        // Delete the data and check it is removed.
341
        $this->setUser();
342
        provider::delete_data_for_user($approvedcontextlist);
343
 
344
        $this->assertEquals($questioncount, $DB->count_records('question'));
345
 
346
        $qrecord = $DB->get_record('question', ['id' => $q1->id]);
347
        $this->assertEquals(0, $qrecord->createdby);
348
        $this->assertEquals(0, $qrecord->modifiedby);
349
 
350
        $qrecord = $DB->get_record('question', ['id' => $q2updated->id]);
351
        $this->assertEquals($otheruser->id, $qrecord->createdby);
352
        $this->assertEquals($otheruser->id, $qrecord->modifiedby);
353
 
354
        $qrecord = $DB->get_record('question', ['id' => $q3updated->id]);
355
        $this->assertEquals(0, $qrecord->createdby);
356
        $this->assertEquals(0, $qrecord->modifiedby);
357
 
358
        $qrecord = $DB->get_record('question', ['id' => $q4->id]);
359
        $this->assertEquals($otheruser->id, $qrecord->createdby);
360
        $this->assertEquals($otheruser->id, $qrecord->modifiedby);
361
 
362
        $qrecord = $DB->get_record('question', ['id' => $q5->id]);
363
        $this->assertEquals($user->id, $qrecord->createdby);
364
        $this->assertEquals($user->id, $qrecord->modifiedby);
365
    }
366
 
367
    /**
368
     * Deleting questions should only unset their created and modified user for all questions in a context.
369
     */
11 efrain 370
    public function test_question_delete_data_for_all_users_in_context_anonymised(): void {
1 efrain 371
        global $DB;
372
        $this->resetAfterTest(true);
373
 
374
        $user = \core_user::get_user_by_username('admin');
375
        $otheruser = $this->getDataGenerator()->create_user();
376
 
377
        $course = $this->getDataGenerator()->create_course();
1441 ariadna 378
        $qbank1 = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
379
        $qbank1context = \context_module::instance($qbank1->cmid);
380
        $qbank2 = self::getDataGenerator()->create_module('qbank', ['course' => $course->id]);
381
        $qbank2context = \context_module::instance($qbank2->cmid);
1 efrain 382
 
383
        // Create a couple of questions.
384
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
385
        $cat = $questiongenerator->create_question_category([
1441 ariadna 386
            'contextid' => $qbank1context->id,
1 efrain 387
        ]);
388
        $othercat = $questiongenerator->create_question_category([
1441 ariadna 389
            'contextid' => $qbank2context->id,
1 efrain 390
        ]);
391
 
392
        // Create questions:
393
        // Q1 - Created by the UUT, Modified by UUT.
394
        // Q2 - Created by the UUT, Modified by the other user.
395
        // Q3 - Created by the other user, Modified by UUT
396
        // Q4 - Created by the other user, Modified by the other user.
397
        // Q5 - Created by the UUT, Modified by the UUT, but in a different context.
398
        $this->setUser($user);
399
        $q1 = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
400
        $q2 = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
401
 
402
        $this->setUser($otheruser);
403
        $questiongenerator->update_question($q2);
404
        $q3 = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
405
        $q4 = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
406
 
407
        $this->setUser($user);
408
        $questiongenerator->update_question($q3);
409
        $q5 = $questiongenerator->create_question('shortanswer', null, array('category' => $othercat->id));
410
 
411
        // Find out how many questions are in the question bank to start with.
412
        $questioncount = $DB->count_records('question');
413
 
414
        // Delete the data and check it is removed.
415
        $this->setUser();
1441 ariadna 416
        provider::delete_data_for_all_users_in_context($qbank1context);
1 efrain 417
 
418
        $this->assertEquals($questioncount, $DB->count_records('question'));
419
 
420
        $qrecord = $DB->get_record('question', ['id' => $q1->id]);
421
        $this->assertEquals(0, $qrecord->createdby);
422
        $this->assertEquals(0, $qrecord->modifiedby);
423
 
424
        $qrecord = $DB->get_record('question', ['id' => $q2->id]);
425
        $this->assertEquals(0, $qrecord->createdby);
426
        $this->assertEquals(0, $qrecord->modifiedby);
427
 
428
        $qrecord = $DB->get_record('question', ['id' => $q3->id]);
429
        $this->assertEquals(0, $qrecord->createdby);
430
        $this->assertEquals(0, $qrecord->modifiedby);
431
 
432
        $qrecord = $DB->get_record('question', ['id' => $q4->id]);
433
        $this->assertEquals(0, $qrecord->createdby);
434
        $this->assertEquals(0, $qrecord->modifiedby);
435
 
436
        $qrecord = $DB->get_record('question', ['id' => $q5->id]);
437
        $this->assertEquals($user->id, $qrecord->createdby);
438
        $this->assertEquals($user->id, $qrecord->modifiedby);
439
    }
440
 
441
    /**
442
     * Test for provider::get_users_in_context().
443
     */
11 efrain 444
    public function test_get_users_in_context(): void {
1 efrain 445
        $this->resetAfterTest();
446
 
447
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
448
 
449
        // Create three test users.
450
        $user1 = $this->getDataGenerator()->create_user();
451
        $user2 = $this->getDataGenerator()->create_user();
452
        $user3 = $this->getDataGenerator()->create_user();
453
 
454
        // Create one question as each user in different contexts.
455
        $this->setUser($user1);
456
        $user1data = $questiongenerator->setup_course_and_questions();
457
        $this->setUser($user2);
458
        $user2data = $questiongenerator->setup_course_and_questions();
459
 
1441 ariadna 460
        $qbankcontext = \context_module::instance($user1data[4]->cmid);
461
        $questions = $user1data[3];
1 efrain 462
 
463
        // Log in as user3 and update the questions in course1.
464
        $this->setUser($user3);
465
 
1441 ariadna 466
        foreach ($questions as $question) {
1 efrain 467
            $questiongenerator->update_question($question);
468
        }
469
 
1441 ariadna 470
        $userlist = new \core_privacy\local\request\userlist($qbankcontext, 'core_question');
1 efrain 471
        provider::get_users_in_context($userlist);
472
 
473
        // User1 has created questions and user3 has edited them.
474
        $this->assertCount(2, $userlist);
475
        $this->assertEqualsCanonicalizing([$user1->id, $user3->id], $userlist->get_userids());
476
    }
477
 
478
    /**
479
     * Test for provider::delete_data_for_users().
480
     */
11 efrain 481
    public function test_delete_data_for_users(): void {
1 efrain 482
        global $DB;
483
 
484
        $this->resetAfterTest();
485
 
486
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
487
 
488
        // Create three test users.
489
        $user1 = $this->getDataGenerator()->create_user();
490
        $user2 = $this->getDataGenerator()->create_user();
491
        $user3 = $this->getDataGenerator()->create_user();
492
 
493
        // Create one question as each user in different contexts.
494
        $this->setUser($user1);
1441 ariadna 495
        $coursedata = $questiongenerator->setup_course_and_questions();
496
        $qbank = $coursedata[4];
497
        $course1qcat = $coursedata[2];
498
        $questions = $coursedata[3];
499
        $qbankcontext = \context_module::instance($qbank->cmid);
1 efrain 500
 
501
        // Log in as user2 and update the questions in course1.
502
        $this->setUser($user2);
503
 
1441 ariadna 504
        foreach ($questions as $question) {
1 efrain 505
            $questiongenerator->update_question($question);
506
        }
507
 
508
        // Add 2 more questions to course1 by user3.
509
        $this->setUser($user3);
510
        $questiongenerator->create_question('shortanswer', null, ['category' => $course1qcat->id]);
511
        $questiongenerator->create_question('shortanswer', null, ['category' => $course1qcat->id]);
512
 
513
        // Now, log in as user1 again, and then create a new course and add questions to that.
514
        $this->setUser($user1);
515
        $questiongenerator->setup_course_and_questions();
516
 
1441 ariadna 517
        $approveduserlist = new \core_privacy\local\request\approved_userlist($qbankcontext, 'core_question',
1 efrain 518
                [$user1->id, $user2->id]);
519
        provider::delete_data_for_users($approveduserlist);
520
 
521
        // Now, there should be no question related to user1 or user2 in course1.
522
        $this->assertEquals(0,
523
                $DB->count_records_sql("SELECT COUNT(q.id)
524
                                          FROM {question} q
525
                                          JOIN {question_versions} qv ON qv.questionid = q.id
526
                                          JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
527
                                          JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
528
                                         WHERE qc.contextid = ?
529
                                           AND (q.createdby = ? OR q.modifiedby = ? OR q.createdby = ? OR q.modifiedby = ?)",
1441 ariadna 530
                        [$qbankcontext->id, $user1->id, $user1->id, $user2->id, $user2->id])
1 efrain 531
        );
532
 
533
        // User3 data in course1 should not change.
534
        $this->assertEquals(2,
535
                $DB->count_records_sql("SELECT COUNT(q.id)
536
                                          FROM {question} q
537
                                          JOIN {question_versions} qv ON qv.questionid = q.id
538
                                          JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid
539
                                          JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid
540
                                         WHERE qc.contextid = ? AND (q.createdby = ? OR q.modifiedby = ?)",
1441 ariadna 541
                        [$qbankcontext->id, $user3->id, $user3->id])
1 efrain 542
        );
543
 
544
        // User1 has authored 2 questions in another course.
545
        $this->assertEquals(
546
                2,
547
                $DB->count_records_select('question', "createdby = ? OR modifiedby = ?", [$user1->id, $user1->id])
548
        );
549
    }
550
}