MDL-47572 libraries: modify unittest to avoid random timing fail
[moodle.git] / lib / tests / cronlib_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 the cron.
19  *
20  * @package   core
21  * @category  test
22  * @copyright 2013 Tim Gusak <tim.gusak@remote-learner.net>
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->libdir.'/cronlib.php');
31 class cronlib_testcase extends basic_testcase {
33     /**
34      * Data provider for cron_delete_from_temp.
35      *
36      * @return array Provider data
37      */
38     public function cron_delete_from_temp_provider() {
39         global $CFG;
41         $tmpdir = realpath($CFG->tempdir);
42         // This is a relative time.
43         $time = 0;
45         // Relative time stamps. Did you know data providers get executed during phpunit init?
46         $lastweekstime = strtotime('-1 week') - time();
47         $beforelastweekstime = $lastweekstime - 60;
48         $afterlastweekstime = $lastweekstime + 60;
50         $nodes = array();
51         // Really old directory to remove.
52         $nodes[] = $this->generate_test_path('/dir1/dir1_1/dir1_1_1/dir1_1_1_1/', true, $lastweekstime * 52, false);
54         // New Directory to keep.
55         $nodes[] = $this->generate_test_path('/dir1/dir1_2/', true, $time, true);
57         // Directory a little less than 1 week old, keep.
58         $nodes[] = $this->generate_test_path('/dir2/', true, $afterlastweekstime, true);
60         // Directory older than 1 week old, remove.
61         $nodes[] = $this->generate_test_path('/dir3/', true, $beforelastweekstime, false);
63         // File older than 1 week old, remove.
64         $nodes[] = $this->generate_test_path('/dir1/dir1_1/dir1_1_1/file1_1_1_1', false, $beforelastweekstime, false);
66         // New File to keep.
67         $nodes[] = $this->generate_test_path('/dir1/dir1_1/dir1_1_1/file1_1_1_2', false, $time, true);
69         // File older than 1 week old, remove.
70         $nodes[] = $this->generate_test_path('/dir1/dir1_2/file1_1_2_1', false, $beforelastweekstime, false);
72         // New file to keep.
73         $nodes[] = $this->generate_test_path('/dir1/dir1_2/file1_1_2_2', false, $time, true);
75         // New file to keep.
76         $nodes[] = $this->generate_test_path('/file1', false, $time, true);
78         // File older than 1 week, keep.
79         $nodes[] = $this->generate_test_path('/file2', false, $beforelastweekstime, false);
81         // Directory older than 1 week to keep.
82         // Note: Since this directory contains a directory that contains a file that is also older than a week
83         // the directory won't be deleted since it's mtime will be updated when the file is deleted.
85         $nodes[] = $this->generate_test_path('/dir4/dir4_1', true, $beforelastweekstime, true);
87         $nodes[] = $this->generate_test_path('/dir4/dir4_1/dir4_1_1/', true, $beforelastweekstime, true);
89         // File older than 1 week to remove.
90         $nodes[] = $this->generate_test_path('/dir4/dir4_1/dir4_1_1/file4_1_1_1', false, $beforelastweekstime, false);
92         $expectednodes = array();
93         foreach ($nodes as $node) {
94             if ($node->keep) {
95                 $path = $tmpdir;
96                 $pelements = preg_split('/\//', $node->path);
97                 foreach ($pelements as $pelement) {
98                     if ($pelement === '') {
99                         continue;
100                     }
101                     $path .= DIRECTORY_SEPARATOR . $pelement;
102                     if (!in_array($path, $expectednodes)) {
103                         $expectednodes[] = $path;
104                     }
105                 }
106             }
107         }
108         sort($expectednodes);
110         $data = array(
111                 array(
112                     $nodes,
113                     $expectednodes
114                 ),
115                 array(
116                     array(),
117                     array()
118                 )
119         );
121         return $data;
122     }
124     /**
125      * Function to populate node array.
126      *
127      * @param string $path Path of directory or file
128      * @param bool $isdir Is the node a directory
129      * @param int $time modified time of the node in epoch
130      * @param bool $keep Should the node exist after the delete function has run
131      */
132     private function generate_test_path($path, $isdir = false, $time = 0, $keep = false) {
133         $node = new stdClass();
134         $node->path = $path;
135         $node->isdir = $isdir;
136         $node->time = $time;
137         $node->keep = $keep;
138         return $node;
139     }
140     /**
141      * Test removing files and directories from tempdir.
142      *
143      * @dataProvider cron_delete_from_temp_provider
144      * @param array $nodes List of files and directories
145      * @param array $expected The expected results
146      */
147     public function test_cron_delete_from_temp($nodes, $expected) {
148         global $CFG;
150         $tmpdir = $CFG->tempdir;
152         foreach ($nodes as $data) {
153             if ($data->isdir) {
154                 mkdir($tmpdir.$data->path, $CFG->directorypermissions, true);
155             }
156         }
157         // We need to iterate through again since adding a file to a directory will
158         // update the modified time of the directory.
159         foreach ($nodes as $data) {
160             touch($tmpdir.$data->path, time() + $data->time);
161         }
163         $task = new \core\task\file_temp_cleanup_task();
164         $task->execute();
166         $dir = new RecursiveDirectoryIterator($tmpdir);
167         $iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST);
169         $actual = array();
170         for ($iter->rewind(); $iter->valid(); $iter->next()) {
171             if (!$iter->isDot()) {
172                 $actual[] = $iter->getRealPath();
173             }
174         }
176         // Sort results to guarantee actual order.
177         sort($actual);
179         $this->assertEquals($expected, $actual);
180     }