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
/**
18
 * Unit tests for backups cron helper.
19
 *
20
 * @package   core_backup
21
 * @category  test
22
 * @copyright 2012 Frédéric Massart <fred@moodle.com>
23
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
namespace core_backup;
27
 
28
use backup;
29
use backup_cron_automated_helper;
30
 
31
defined('MOODLE_INTERNAL') || die();
32
 
33
global $CFG;
34
require_once($CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php');
35
require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php');
36
require_once("$CFG->dirroot/backup/backup.class.php");
37
 
38
/**
39
 * Unit tests for backups cron helper.
40
 *
41
 * @package   core_backup
42
 * @category  test
43
 * @copyright 2012 Frédéric Massart <fred@moodle.com>
44
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
45
 */
46
class cronhelper_test extends \advanced_testcase {
47
    /**
48
     * Test {@link backup_cron_automated_helper::calculate_next_automated_backup}.
49
     */
11 efrain 50
    public function test_next_automated_backup(): void {
1 efrain 51
        global $CFG;
52
 
53
        $this->resetAfterTest();
54
        set_config('backup_auto_active', '1', 'backup');
55
 
56
        $this->setTimezone('Australia/Perth');
57
 
58
        // Notes
59
        // - backup_auto_weekdays starts on Sunday
60
        // - Tests cannot be done in the past
61
        // - Only the DST on the server side is handled.
62
 
63
        // Every Tue and Fri at 11pm.
64
        set_config('backup_auto_weekdays', '0010010', 'backup');
65
        set_config('backup_auto_hour', '23', 'backup');
66
        set_config('backup_auto_minute', '0', 'backup');
67
 
68
        $timezone = 99; // Ignored, everything is calculated in server timezone!!!
69
 
70
        $now = strtotime('next Monday 17:00:00');
71
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
72
        $this->assertEquals('2-23:00', date('w-H:i', $next));
73
 
74
        $now = strtotime('next Tuesday 18:00:00');
75
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
76
        $this->assertEquals('2-23:00', date('w-H:i', $next));
77
 
78
        $now = strtotime('next Wednesday 17:00:00');
79
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
80
        $this->assertEquals('5-23:00', date('w-H:i', $next));
81
 
82
        $now = strtotime('next Thursday 17:00:00');
83
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
84
        $this->assertEquals('5-23:00', date('w-H:i', $next));
85
 
86
        $now = strtotime('next Friday 17:00:00');
87
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
88
        $this->assertEquals('5-23:00', date('w-H:i', $next));
89
 
90
        $now = strtotime('next Saturday 17:00:00');
91
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
92
        $this->assertEquals('2-23:00', date('w-H:i', $next));
93
 
94
        $now = strtotime('next Sunday 17:00:00');
95
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
96
        $this->assertEquals('2-23:00', date('w-H:i', $next));
97
 
98
        // Every Sun and Sat at 12pm.
99
        set_config('backup_auto_weekdays', '1000001', 'backup');
100
        set_config('backup_auto_hour', '0', 'backup');
101
        set_config('backup_auto_minute', '0', 'backup');
102
 
103
        $now = strtotime('next Monday 17:00:00');
104
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
105
        $this->assertEquals('6-00:00', date('w-H:i', $next));
106
 
107
        $now = strtotime('next Tuesday 17:00:00');
108
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
109
        $this->assertEquals('6-00:00', date('w-H:i', $next));
110
 
111
        $now = strtotime('next Wednesday 17:00:00');
112
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
113
        $this->assertEquals('6-00:00', date('w-H:i', $next));
114
 
115
        $now = strtotime('next Thursday 17:00:00');
116
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
117
        $this->assertEquals('6-00:00', date('w-H:i', $next));
118
 
119
        $now = strtotime('next Friday 17:00:00');
120
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
121
        $this->assertEquals('6-00:00', date('w-H:i', $next));
122
 
123
        $now = strtotime('next Saturday 17:00:00');
124
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
125
        $this->assertEquals('0-00:00', date('w-H:i', $next));
126
 
127
        $now = strtotime('next Sunday 17:00:00');
128
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
129
        $this->assertEquals('6-00:00', date('w-H:i', $next));
130
 
131
        // Every Sun at 4am.
132
        set_config('backup_auto_weekdays', '1000000', 'backup');
133
        set_config('backup_auto_hour', '4', 'backup');
134
        set_config('backup_auto_minute', '0', 'backup');
135
 
136
        $now = strtotime('next Monday 17:00:00');
137
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
138
        $this->assertEquals('0-04:00', date('w-H:i', $next));
139
 
140
        $now = strtotime('next Tuesday 17:00:00');
141
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
142
        $this->assertEquals('0-04:00', date('w-H:i', $next));
143
 
144
        $now = strtotime('next Wednesday 17:00:00');
145
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
146
        $this->assertEquals('0-04:00', date('w-H:i', $next));
147
 
148
        $now = strtotime('next Thursday 17:00:00');
149
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
150
        $this->assertEquals('0-04:00', date('w-H:i', $next));
151
 
152
        $now = strtotime('next Friday 17:00:00');
153
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
154
        $this->assertEquals('0-04:00', date('w-H:i', $next));
155
 
156
        $now = strtotime('next Saturday 17:00:00');
157
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
158
        $this->assertEquals('0-04:00', date('w-H:i', $next));
159
 
160
        $now = strtotime('next Sunday 17:00:00');
161
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
162
        $this->assertEquals('0-04:00', date('w-H:i', $next));
163
 
164
        // Every day but Wed at 8:30pm.
165
        set_config('backup_auto_weekdays', '1110111', 'backup');
166
        set_config('backup_auto_hour', '20', 'backup');
167
        set_config('backup_auto_minute', '30', 'backup');
168
 
169
        $now = strtotime('next Monday 17:00:00');
170
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
171
        $this->assertEquals('1-20:30', date('w-H:i', $next));
172
 
173
        $now = strtotime('next Tuesday 17:00:00');
174
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
175
        $this->assertEquals('2-20:30', date('w-H:i', $next));
176
 
177
        $now = strtotime('next Wednesday 17:00:00');
178
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
179
        $this->assertEquals('4-20:30', date('w-H:i', $next));
180
 
181
        $now = strtotime('next Thursday 17:00:00');
182
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
183
        $this->assertEquals('4-20:30', date('w-H:i', $next));
184
 
185
        $now = strtotime('next Friday 17:00:00');
186
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
187
        $this->assertEquals('5-20:30', date('w-H:i', $next));
188
 
189
        $now = strtotime('next Saturday 17:00:00');
190
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
191
        $this->assertEquals('6-20:30', date('w-H:i', $next));
192
 
193
        $now = strtotime('next Sunday 17:00:00');
194
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
195
        $this->assertEquals('0-20:30', date('w-H:i', $next));
196
 
197
        // Sun, Tue, Thu, Sat at 12pm.
198
        set_config('backup_auto_weekdays', '1010101', 'backup');
199
        set_config('backup_auto_hour', '0', 'backup');
200
        set_config('backup_auto_minute', '0', 'backup');
201
 
202
        $now = strtotime('next Monday 13:00:00');
203
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
204
        $this->assertEquals('2-00:00', date('w-H:i', $next));
205
 
206
        $now = strtotime('next Tuesday 13:00:00');
207
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
208
        $this->assertEquals('4-00:00', date('w-H:i', $next));
209
 
210
        $now = strtotime('next Wednesday 13:00:00');
211
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
212
        $this->assertEquals('4-00:00', date('w-H:i', $next));
213
 
214
        $now = strtotime('next Thursday 13:00:00');
215
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
216
        $this->assertEquals('6-00:00', date('w-H:i', $next));
217
 
218
        $now = strtotime('next Friday 13:00:00');
219
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
220
        $this->assertEquals('6-00:00', date('w-H:i', $next));
221
 
222
        $now = strtotime('next Saturday 13:00:00');
223
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
224
        $this->assertEquals('0-00:00', date('w-H:i', $next));
225
 
226
        $now = strtotime('next Sunday 13:00:00');
227
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
228
        $this->assertEquals('2-00:00', date('w-H:i', $next));
229
 
230
        // None.
231
        set_config('backup_auto_weekdays', '0000000', 'backup');
232
        set_config('backup_auto_hour', '15', 'backup');
233
        set_config('backup_auto_minute', '30', 'backup');
234
 
235
        $now = strtotime('next Sunday 13:00:00');
236
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
237
        $this->assertEquals('0', $next);
238
 
239
        // Playing with timezones.
240
        set_config('backup_auto_weekdays', '1111111', 'backup');
241
        set_config('backup_auto_hour', '20', 'backup');
242
        set_config('backup_auto_minute', '00', 'backup');
243
 
244
        $this->setTimezone('Australia/Perth');
245
        $now = strtotime('18:00:00');
246
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
247
        $this->assertEquals(date('w-20:00'), date('w-H:i', $next));
248
 
249
        $this->setTimezone('Europe/Brussels');
250
        $now = strtotime('18:00:00');
251
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
252
        $this->assertEquals(date('w-20:00'), date('w-H:i', $next));
253
 
254
        $this->setTimezone('America/New_York');
255
        $now = strtotime('18:00:00');
256
        $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
257
        $this->assertEquals(date('w-20:00'), date('w-H:i', $next));
258
    }
259
 
260
    /**
261
     * Test {@link backup_cron_automated_helper::get_backups_to_delete}.
262
     */
11 efrain 263
    public function test_get_backups_to_delete(): void {
1 efrain 264
        $this->resetAfterTest();
265
        // Active only backup_auto_max_kept config to 2 days.
266
        set_config('backup_auto_max_kept', '2', 'backup');
267
        set_config('backup_auto_delete_days', '0', 'backup');
268
        set_config('backup_auto_min_kept', '0', 'backup');
269
 
270
        // No backups to delete.
271
        $backupfiles = array(
272
            '1000000000' => 'file1.mbz',
273
            '1000432000' => 'file3.mbz'
274
        );
275
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000432000);
276
        $this->assertFalse($deletedbackups);
277
 
278
        // Older backup to delete.
279
        $backupfiles['1000172800'] = 'file2.mbz';
280
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000432000);
281
        $this->assertEquals(1, count($deletedbackups));
282
        $this->assertArrayHasKey('1000000000', $backupfiles);
283
        $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
284
 
285
        // Activate backup_auto_max_kept to 5 days and backup_auto_delete_days to 10 days.
286
        set_config('backup_auto_max_kept', '5', 'backup');
287
        set_config('backup_auto_delete_days', '10', 'backup');
288
        set_config('backup_auto_min_kept', '0', 'backup');
289
 
290
        // No backups to delete. Timestamp is 1000000000 + 10 days.
291
        $backupfiles['1000432001'] = 'file4.mbz';
292
        $backupfiles['1000864000'] = 'file5.mbz';
293
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000864000);
294
        $this->assertFalse($deletedbackups);
295
 
296
        // One old backup to delete. Timestamp is 1000000000 + 10 days + 1 second.
297
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000864001);
298
        $this->assertEquals(1, count($deletedbackups));
299
        $this->assertArrayHasKey('1000000000', $backupfiles);
300
        $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
301
 
302
        // Two old backups to delete. Timestamp is 1000000000 + 12 days + 1 second.
303
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1001036801);
304
        $this->assertEquals(2, count($deletedbackups));
305
        $this->assertArrayHasKey('1000000000', $backupfiles);
306
        $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
307
        $this->assertArrayHasKey('1000172800', $backupfiles);
308
        $this->assertEquals('file2.mbz', $backupfiles['1000172800']);
309
 
310
        // Activate backup_auto_max_kept to 5 days, backup_auto_delete_days to 10 days and backup_auto_min_kept to 2.
311
        set_config('backup_auto_max_kept', '5', 'backup');
312
        set_config('backup_auto_delete_days', '10', 'backup');
313
        set_config('backup_auto_min_kept', '2', 'backup');
314
 
315
        // Three instead of four old backups are deleted. Timestamp is 1000000000 + 16 days.
316
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1001382400);
317
        $this->assertEquals(3, count($deletedbackups));
318
        $this->assertArrayHasKey('1000000000', $backupfiles);
319
        $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
320
        $this->assertArrayHasKey('1000172800', $backupfiles);
321
        $this->assertEquals('file2.mbz', $backupfiles['1000172800']);
322
        $this->assertArrayHasKey('1000432000', $backupfiles);
323
        $this->assertEquals('file3.mbz', $backupfiles['1000432000']);
324
 
325
        // Three instead of all five backups are deleted. Timestamp is 1000000000 + 60 days.
326
        $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1005184000);
327
        $this->assertEquals(3, count($deletedbackups));
328
        $this->assertArrayHasKey('1000000000', $backupfiles);
329
        $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
330
        $this->assertArrayHasKey('1000172800', $backupfiles);
331
        $this->assertEquals('file2.mbz', $backupfiles['1000172800']);
332
        $this->assertArrayHasKey('1000432000', $backupfiles);
333
        $this->assertEquals('file3.mbz', $backupfiles['1000432000']);
334
    }
335
 
336
    /**
337
     * Test {@link backup_cron_automated_helper::is_course_modified}.
338
     */
11 efrain 339
    public function test_is_course_modified(): void {
1 efrain 340
        $this->resetAfterTest();
341
        $this->preventResetByRollback();
342
 
343
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
344
        set_config('buffersize', 0, 'logstore_standard');
345
        set_config('logguests', 1, 'logstore_standard');
346
 
347
        $course = $this->getDataGenerator()->create_course();
348
 
349
        // New courses should be backed up.
350
        $this->assertTrue(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, 0));
351
 
352
        $timepriortobackup = time();
353
        $this->waitForSecond();
354
        $otherarray = [
355
            'format' => backup::FORMAT_MOODLE,
356
            'mode' => backup::MODE_GENERAL,
357
            'interactive' => backup::INTERACTIVE_YES,
358
            'type' => backup::TYPE_1COURSE,
359
        ];
360
        $event = \core\event\course_backup_created::create([
361
            'objectid' => $course->id,
362
            'context'  => \context_course::instance($course->id),
363
            'other'    => $otherarray
364
        ]);
365
        $event->trigger();
366
 
367
        // If the only action since last backup was a backup then no backup.
368
        $this->assertFalse(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, $timepriortobackup));
369
 
370
        $course->groupmode = SEPARATEGROUPS;
371
        $course->groupmodeforce = true;
372
        update_course($course);
373
 
374
        // Updated courses should be backed up.
375
        $this->assertTrue(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, $timepriortobackup));
376
    }
377
 
378
    /**
379
     * Create courses and backup records for tests.
380
     *
381
     * @return array Created courses.
382
     */
383
    private function course_setup() {
384
        global $DB;
385
 
386
        // Create test courses.
387
        $course1 = $this->getDataGenerator()->create_course(array('timecreated' => 1553402000)); // Newest.
388
        $course2 = $this->getDataGenerator()->create_course(array('timecreated' => 1552179600));
389
        $course3 = $this->getDataGenerator()->create_course(array('timecreated' => 1552179600));
390
        $course4 = $this->getDataGenerator()->create_course(array('timecreated' => 1552179600));
391
 
392
        // Create backup course records for the courses that need them.
393
        $backupcourse3 = new \stdClass;
394
        $backupcourse3->courseid = $course3->id;
395
        $backupcourse3->laststatus = testable_backup_cron_automated_helper::BACKUP_STATUS_OK;
396
        $backupcourse3->nextstarttime = 1554822160;
397
        $DB->insert_record('backup_courses', $backupcourse3);
398
 
399
        $backupcourse4 = new \stdClass;
400
        $backupcourse4->courseid = $course4->id;
401
        $backupcourse4->laststatus = testable_backup_cron_automated_helper::BACKUP_STATUS_OK;
402
        $backupcourse4->nextstarttime = 1554858160;
403
        $DB->insert_record('backup_courses', $backupcourse4);
404
 
405
        return array($course1, $course2, $course3, $course4);
406
    }
407
 
408
    /**
409
     * Test the selection and ordering of courses to be backed up.
410
     */
11 efrain 411
    public function test_get_courses(): void {
1 efrain 412
        $this->resetAfterTest();
413
 
414
        list($course1, $course2, $course3, $course4) = $this->course_setup();
415
 
416
        $now = 1559215025;
417
 
418
        // Get the courses in order.
419
        $courseset = testable_backup_cron_automated_helper::testable_get_courses($now);
420
 
421
        $coursearray = array();
422
        foreach ($courseset as $course) {
423
            if ($course->id != SITEID) { // Skip system course for test.
424
                $coursearray[] = $course->id;
425
            }
426
 
427
        }
428
        $courseset->close();
429
 
430
        // First should be course 1, it is the more recently modified without a backup.
431
        $this->assertEquals($course1->id, $coursearray[0]);
432
 
433
        // Second should be course 2, it is the next more recently modified without a backup.
434
        $this->assertEquals($course2->id, $coursearray[1]);
435
 
436
        // Third should be course 3, it is the course with the oldest backup.
437
        $this->assertEquals($course3->id, $coursearray[2]);
438
 
439
        // Fourth should be course 4, it is the course with the newest backup.
440
        $this->assertEquals($course4->id, $coursearray[3]);
441
    }
442
 
443
    /**
444
     * Test the selection and ordering of courses to be backed up.
445
     * Where it is not yet time to start backups for courses with existing backups.
446
     */
11 efrain 447
    public function test_get_courses_starttime(): void {
1 efrain 448
        $this->resetAfterTest();
449
 
450
        list($course1, $course2, $course3, $course4) = $this->course_setup();
451
 
452
        $now = 1554858000;
453
 
454
        // Get the courses in order.
455
        $courseset = testable_backup_cron_automated_helper::testable_get_courses($now);
456
 
457
        $coursearray = array();
458
        foreach ($courseset as $course) {
459
            if ($course->id != SITEID) { // Skip system course for test.
460
                $coursearray[] = $course->id;
461
            }
462
 
463
        }
464
        $courseset->close();
465
 
466
        // Should only be two courses.
467
        // First should be course 1, it is the more recently modified without a backup.
468
        $this->assertEquals($course1->id, $coursearray[0]);
469
 
470
        // Second should be course 2, it is the next more recently modified without a backup.
471
        $this->assertEquals($course2->id, $coursearray[1]);
472
    }
473
 
474
}
475
 
476
 
477
 
478
/**
479
 * Provides access to protected methods we want to explicitly test
480
 *
481
 * @copyright 2015 Jean-Philippe Gaudreau <jp.gaudreau@umontreal.ca>
482
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
483
 */
484
class testable_backup_cron_automated_helper extends backup_cron_automated_helper {
485
 
486
    /**
487
     * Provides access to protected method get_backups_to_remove.
488
     *
489
     * @param array $backupfiles Existing backup files
490
     * @param int $now Starting time of the process
491
     * @return array Backup files to remove
492
     */
493
    public static function testable_get_backups_to_delete($backupfiles, $now) {
494
        return parent::get_backups_to_delete($backupfiles, $now);
495
    }
496
 
497
    /**
498
     * Provides access to protected method get_backups_to_remove.
499
     *
500
     * @param int $courseid course id to check
501
     * @param int $since timestamp, from which to check
502
     *
503
     * @return bool true if the course was modified, false otherwise. This also returns false if no readers are enabled. This is
504
     * intentional, since we cannot reliably determine if any modification was made or not.
505
     */
506
    public static function testable_is_course_modified($courseid, $since) {
507
        return parent::is_course_modified($courseid, $since);
508
    }
509
 
510
    /**
511
     * Provides access to protected method get_courses.
512
     *
513
     * @param int $now Timestamp to use.
514
     * @return moodle_recordset The returned courses as a Moodle recordest.
515
     */
516
    public static function testable_get_courses($now) {
517
        return parent::get_courses($now);
518
    }
519
 
520
}