MDL-61578 backup: Added unit test for is_course_modified check.
[moodle.git] / backup / util / helper / tests / cronhelper_test.php
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/>.
17 /**
18  * Unit tests for backups cron helper.
19  *
20  * @package   core_backup
21  * @category  phpunit
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  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot . '/backup/util/helper/backup_cron_helper.class.php');
30 require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php');
31 require_once("$CFG->dirroot/backup/backup.class.php");
33 /**
34  * Unit tests for backup cron helper
35  */
36 class backup_cron_helper_testcase extends advanced_testcase {
37     /**
38      * Test {@link backup_cron_automated_helper::calculate_next_automated_backup}.
39      */
40     public function test_next_automated_backup() {
41         global $CFG;
43         $this->resetAfterTest();
44         set_config('backup_auto_active', '1', 'backup');
46         $this->setTimezone('Australia/Perth');
48         // Notes
49         // - backup_auto_weekdays starts on Sunday
50         // - Tests cannot be done in the past
51         // - Only the DST on the server side is handled.
53         // Every Tue and Fri at 11pm.
54         set_config('backup_auto_weekdays', '0010010', 'backup');
55         set_config('backup_auto_hour', '23', 'backup');
56         set_config('backup_auto_minute', '0', 'backup');
58         $timezone = 99; // Ignored, everything is calculated in server timezone!!!
60         $now = strtotime('next Monday 17:00:00');
61         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
62         $this->assertEquals('2-23:00', date('w-H:i', $next));
64         $now = strtotime('next Tuesday 18:00:00');
65         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
66         $this->assertEquals('2-23:00', date('w-H:i', $next));
68         $now = strtotime('next Wednesday 17:00:00');
69         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
70         $this->assertEquals('5-23:00', date('w-H:i', $next));
72         $now = strtotime('next Thursday 17:00:00');
73         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
74         $this->assertEquals('5-23:00', date('w-H:i', $next));
76         $now = strtotime('next Friday 17:00:00');
77         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
78         $this->assertEquals('5-23:00', date('w-H:i', $next));
80         $now = strtotime('next Saturday 17:00:00');
81         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
82         $this->assertEquals('2-23:00', date('w-H:i', $next));
84         $now = strtotime('next Sunday 17:00:00');
85         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
86         $this->assertEquals('2-23:00', date('w-H:i', $next));
88         // Every Sun and Sat at 12pm.
89         set_config('backup_auto_weekdays', '1000001', 'backup');
90         set_config('backup_auto_hour', '0', 'backup');
91         set_config('backup_auto_minute', '0', 'backup');
93         $now = strtotime('next Monday 17:00:00');
94         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
95         $this->assertEquals('6-00:00', date('w-H:i', $next));
97         $now = strtotime('next Tuesday 17:00:00');
98         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
99         $this->assertEquals('6-00:00', date('w-H:i', $next));
101         $now = strtotime('next Wednesday 17:00:00');
102         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
103         $this->assertEquals('6-00:00', date('w-H:i', $next));
105         $now = strtotime('next Thursday 17:00:00');
106         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
107         $this->assertEquals('6-00:00', date('w-H:i', $next));
109         $now = strtotime('next Friday 17:00:00');
110         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
111         $this->assertEquals('6-00:00', date('w-H:i', $next));
113         $now = strtotime('next Saturday 17:00:00');
114         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
115         $this->assertEquals('0-00:00', date('w-H:i', $next));
117         $now = strtotime('next Sunday 17:00:00');
118         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
119         $this->assertEquals('6-00:00', date('w-H:i', $next));
121         // Every Sun at 4am.
122         set_config('backup_auto_weekdays', '1000000', 'backup');
123         set_config('backup_auto_hour', '4', 'backup');
124         set_config('backup_auto_minute', '0', 'backup');
126         $now = strtotime('next Monday 17:00:00');
127         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
128         $this->assertEquals('0-04:00', date('w-H:i', $next));
130         $now = strtotime('next Tuesday 17:00:00');
131         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
132         $this->assertEquals('0-04:00', date('w-H:i', $next));
134         $now = strtotime('next Wednesday 17:00:00');
135         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
136         $this->assertEquals('0-04:00', date('w-H:i', $next));
138         $now = strtotime('next Thursday 17:00:00');
139         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
140         $this->assertEquals('0-04:00', date('w-H:i', $next));
142         $now = strtotime('next Friday 17:00:00');
143         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
144         $this->assertEquals('0-04:00', date('w-H:i', $next));
146         $now = strtotime('next Saturday 17:00:00');
147         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
148         $this->assertEquals('0-04:00', date('w-H:i', $next));
150         $now = strtotime('next Sunday 17:00:00');
151         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
152         $this->assertEquals('0-04:00', date('w-H:i', $next));
154         // Every day but Wed at 8:30pm.
155         set_config('backup_auto_weekdays', '1110111', 'backup');
156         set_config('backup_auto_hour', '20', 'backup');
157         set_config('backup_auto_minute', '30', 'backup');
159         $now = strtotime('next Monday 17:00:00');
160         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
161         $this->assertEquals('1-20:30', date('w-H:i', $next));
163         $now = strtotime('next Tuesday 17:00:00');
164         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
165         $this->assertEquals('2-20:30', date('w-H:i', $next));
167         $now = strtotime('next Wednesday 17:00:00');
168         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
169         $this->assertEquals('4-20:30', date('w-H:i', $next));
171         $now = strtotime('next Thursday 17:00:00');
172         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
173         $this->assertEquals('4-20:30', date('w-H:i', $next));
175         $now = strtotime('next Friday 17:00:00');
176         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
177         $this->assertEquals('5-20:30', date('w-H:i', $next));
179         $now = strtotime('next Saturday 17:00:00');
180         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
181         $this->assertEquals('6-20:30', date('w-H:i', $next));
183         $now = strtotime('next Sunday 17:00:00');
184         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
185         $this->assertEquals('0-20:30', date('w-H:i', $next));
187         // Sun, Tue, Thu, Sat at 12pm.
188         set_config('backup_auto_weekdays', '1010101', 'backup');
189         set_config('backup_auto_hour', '0', 'backup');
190         set_config('backup_auto_minute', '0', 'backup');
192         $now = strtotime('next Monday 13:00:00');
193         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
194         $this->assertEquals('2-00:00', date('w-H:i', $next));
196         $now = strtotime('next Tuesday 13:00:00');
197         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
198         $this->assertEquals('4-00:00', date('w-H:i', $next));
200         $now = strtotime('next Wednesday 13:00:00');
201         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
202         $this->assertEquals('4-00:00', date('w-H:i', $next));
204         $now = strtotime('next Thursday 13:00:00');
205         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
206         $this->assertEquals('6-00:00', date('w-H:i', $next));
208         $now = strtotime('next Friday 13:00:00');
209         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
210         $this->assertEquals('6-00:00', date('w-H:i', $next));
212         $now = strtotime('next Saturday 13:00:00');
213         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
214         $this->assertEquals('0-00:00', date('w-H:i', $next));
216         $now = strtotime('next Sunday 13:00:00');
217         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
218         $this->assertEquals('2-00:00', date('w-H:i', $next));
220         // None.
221         set_config('backup_auto_weekdays', '0000000', 'backup');
222         set_config('backup_auto_hour', '15', 'backup');
223         set_config('backup_auto_minute', '30', 'backup');
225         $now = strtotime('next Sunday 13:00:00');
226         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
227         $this->assertEquals('0', $next);
229         // Playing with timezones.
230         set_config('backup_auto_weekdays', '1111111', 'backup');
231         set_config('backup_auto_hour', '20', 'backup');
232         set_config('backup_auto_minute', '00', 'backup');
234         $this->setTimezone('Australia/Perth');
235         $now = strtotime('18:00:00');
236         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
237         $this->assertEquals(date('w-20:00'), date('w-H:i', $next));
239         $this->setTimezone('Europe/Brussels');
240         $now = strtotime('18:00:00');
241         $next = backup_cron_automated_helper::calculate_next_automated_backup($timezone, $now);
242         $this->assertEquals(date('w-20:00'), date('w-H:i', $next));
244         $this->setTimezone('America/New_York');
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     }
250     /**
251      * Test {@link backup_cron_automated_helper::get_backups_to_delete}.
252      */
253     public function test_get_backups_to_delete() {
254         $this->resetAfterTest();
255         // Active only backup_auto_max_kept config to 2 days.
256         set_config('backup_auto_max_kept', '2', 'backup');
257         set_config('backup_auto_delete_days', '0', 'backup');
258         set_config('backup_auto_min_kept', '0', 'backup');
260         // No backups to delete.
261         $backupfiles = array(
262             '1000000000' => 'file1.mbz',
263             '1000432000' => 'file3.mbz'
264         );
265         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000432000);
266         $this->assertFalse($deletedbackups);
268         // Older backup to delete.
269         $backupfiles['1000172800'] = 'file2.mbz';
270         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000432000);
271         $this->assertEquals(1, count($deletedbackups));
272         $this->assertArrayHasKey('1000000000', $backupfiles);
273         $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
275         // Activate backup_auto_max_kept to 5 days and backup_auto_delete_days to 10 days.
276         set_config('backup_auto_max_kept', '5', 'backup');
277         set_config('backup_auto_delete_days', '10', 'backup');
278         set_config('backup_auto_min_kept', '0', 'backup');
280         // No backups to delete. Timestamp is 1000000000 + 10 days.
281         $backupfiles['1000432001'] = 'file4.mbz';
282         $backupfiles['1000864000'] = 'file5.mbz';
283         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000864000);
284         $this->assertFalse($deletedbackups);
286         // One old backup to delete. Timestamp is 1000000000 + 10 days + 1 second.
287         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1000864001);
288         $this->assertEquals(1, count($deletedbackups));
289         $this->assertArrayHasKey('1000000000', $backupfiles);
290         $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
292         // Two old backups to delete. Timestamp is 1000000000 + 12 days + 1 second.
293         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1001036801);
294         $this->assertEquals(2, count($deletedbackups));
295         $this->assertArrayHasKey('1000000000', $backupfiles);
296         $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
297         $this->assertArrayHasKey('1000172800', $backupfiles);
298         $this->assertEquals('file2.mbz', $backupfiles['1000172800']);
300         // Activate backup_auto_max_kept to 5 days, backup_auto_delete_days to 10 days and backup_auto_min_kept to 2.
301         set_config('backup_auto_max_kept', '5', 'backup');
302         set_config('backup_auto_delete_days', '10', 'backup');
303         set_config('backup_auto_min_kept', '2', 'backup');
305         // Three instead of four old backups are deleted. Timestamp is 1000000000 + 16 days.
306         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1001382400);
307         $this->assertEquals(3, count($deletedbackups));
308         $this->assertArrayHasKey('1000000000', $backupfiles);
309         $this->assertEquals('file1.mbz', $backupfiles['1000000000']);
310         $this->assertArrayHasKey('1000172800', $backupfiles);
311         $this->assertEquals('file2.mbz', $backupfiles['1000172800']);
312         $this->assertArrayHasKey('1000432000', $backupfiles);
313         $this->assertEquals('file3.mbz', $backupfiles['1000432000']);
315         // Three instead of all five backups are deleted. Timestamp is 1000000000 + 60 days.
316         $deletedbackups = testable_backup_cron_automated_helper::testable_get_backups_to_delete($backupfiles, 1005184000);
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     }
326     /**
327      * Test {@link backup_cron_automated_helper::is_course_modified}.
328      */
329     public function test_is_course_modified() {
330         $this->resetAfterTest();
331         $this->preventResetByRollback();
333         set_config('enabled_stores', 'logstore_standard', 'tool_log');
334         set_config('buffersize', 0, 'logstore_standard');
335         set_config('logguests', 1, 'logstore_standard');
337         $course = $this->getDataGenerator()->create_course();
339         // New courses should be backed up.
340         $this->assertTrue(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, 0));
342         $timepriortobackup = time();
343         $this->waitForSecond();
344         $otherarray = [
345             'format' => backup::FORMAT_MOODLE,
346             'mode' => backup::MODE_GENERAL,
347             'interactive' => backup::INTERACTIVE_YES,
348             'type' => backup::TYPE_1COURSE,
349         ];
350         $event = \core\event\course_backup_created::create([
351             'objectid' => $course->id,
352             'context'  => context_course::instance($course->id),
353             'other'    => $otherarray
354         ]);
355         $event->trigger();
357         // If the only action since last backup was a backup then no backup.
358         $this->assertFalse(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, $timepriortobackup));
360         $course->groupmode = SEPARATEGROUPS;
361         $course->groupmodeforce = true;
362         update_course($course);
364         // Updated courses should be backed up.
365         $this->assertTrue(testable_backup_cron_automated_helper::testable_is_course_modified($course->id, $timepriortobackup));
366     }
369 /**
370  * Provides access to protected methods we want to explicitly test
371  *
372  * @copyright 2015 Jean-Philippe Gaudreau <jp.gaudreau@umontreal.ca>
373  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
374  */
375 class testable_backup_cron_automated_helper extends backup_cron_automated_helper {
377     /**
378      * Provides access to protected method get_backups_to_remove.
379      *
380      * @param array $backupfiles Existing backup files
381      * @param int $now Starting time of the process
382      * @return array Backup files to remove
383      */
384     public static function testable_get_backups_to_delete($backupfiles, $now) {
385         return parent::get_backups_to_delete($backupfiles, $now);
386     }
388     /**
389      * Provides access to protected method get_backups_to_remove.
390      *
391      * @param int $courseid course id to check
392      * @param int $since timestamp, from which to check
393      *
394      * @return bool true if the course was modified, false otherwise. This also returns false if no readers are enabled. This is
395      * intentional, since we cannot reliably determine if any modification was made or not.
396      */
397     public static function testable_is_course_modified($courseid, $since) {
398         return parent::is_course_modified($courseid, $since);
399     }