Commit | Line | Data |
---|---|---|
309ae892 DW |
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 | /** | |
0a5aa65b | 18 | * This file contains the unittests for scheduled tasks. |
309ae892 DW |
19 | * |
20 | * @package core | |
21 | * @category phpunit | |
22 | * @copyright 2013 Damyon Wiese | |
23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
24 | */ | |
25 | ||
26 | defined('MOODLE_INTERNAL') || die(); | |
0a5aa65b | 27 | require_once(__DIR__ . '/fixtures/task_fixtures.php'); |
309ae892 DW |
28 | |
29 | /** | |
30 | * Test class for scheduled task. | |
31 | * | |
32 | * @package core | |
33 | * @category task | |
34 | * @copyright 2013 Damyon Wiese | |
35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
36 | */ | |
0a5aa65b | 37 | class core_scheduled_task_testcase extends advanced_testcase { |
309ae892 DW |
38 | |
39 | /** | |
40 | * Test the cron scheduling method | |
41 | */ | |
42 | public function test_eval_cron_field() { | |
0a5aa65b | 43 | $testclass = new \core\task\scheduled_test_task(); |
309ae892 DW |
44 | |
45 | $this->assertEquals(20, count($testclass->eval_cron_field('*/3', 0, 59))); | |
46 | $this->assertEquals(31, count($testclass->eval_cron_field('1,*/2', 0, 59))); | |
47 | $this->assertEquals(15, count($testclass->eval_cron_field('1-10,5-15', 0, 59))); | |
48 | $this->assertEquals(13, count($testclass->eval_cron_field('1-10,5-15/2', 0, 59))); | |
49 | $this->assertEquals(3, count($testclass->eval_cron_field('1,2,3,1,2,3', 0, 59))); | |
50 | $this->assertEquals(1, count($testclass->eval_cron_field('-1,10,80', 0, 59))); | |
51 | } | |
52 | ||
53 | public function test_get_next_scheduled_time() { | |
54 | // Test job run at 1 am. | |
0a5aa65b | 55 | $testclass = new \core\task\scheduled_test_task(); |
309ae892 DW |
56 | |
57 | // All fields default to '*'. | |
58 | $testclass->set_hour('1'); | |
59 | $testclass->set_minute('0'); | |
60 | // Next valid time should be 1am of the next day. | |
61 | $nexttime = $testclass->get_next_scheduled_time(); | |
62 | ||
63 | $oneam = mktime(1, 0, 0); | |
64 | // Make it 1 am tomorrow if the time is after 1am. | |
65 | if ($oneam < time()) { | |
66 | $oneam += 86400; | |
67 | } | |
68 | ||
69 | $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); | |
70 | ||
0a5aa65b PŠ |
71 | // Disabled flag does not affect next time. |
72 | $testclass->set_disabled(true); | |
73 | $nexttime = $testclass->get_next_scheduled_time(); | |
74 | $this->assertEquals($oneam, $nexttime, 'Next scheduled time is 1am.'); | |
75 | ||
309ae892 | 76 | // Now test for job run every 10 minutes. |
0a5aa65b | 77 | $testclass = new \core\task\scheduled_test_task(); |
309ae892 DW |
78 | |
79 | // All fields default to '*'. | |
80 | $testclass->set_minute('*/10'); | |
81 | // Next valid time should be next 10 minute boundary. | |
82 | $nexttime = $testclass->get_next_scheduled_time(); | |
83 | ||
84 | $minutes = ((intval(date('i') / 10))+1) * 10; | |
85 | $nexttenminutes = mktime(date('H'), $minutes, 0); | |
86 | ||
87 | $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); | |
0a5aa65b PŠ |
88 | |
89 | // Disabled flag does not affect next time. | |
90 | $testclass->set_disabled(true); | |
91 | $nexttime = $testclass->get_next_scheduled_time(); | |
92 | $this->assertEquals($nexttenminutes, $nexttime, 'Next scheduled time is in 10 minutes.'); | |
dc561732 DM |
93 | |
94 | // Test hourly job executed on Sundays only. | |
95 | $testclass = new \core\task\scheduled_test_task(); | |
96 | $testclass->set_minute('0'); | |
97 | $testclass->set_day_of_week('7'); | |
98 | ||
99 | $nexttime = $testclass->get_next_scheduled_time(); | |
100 | ||
101 | $this->assertEquals(7, date('N', $nexttime)); | |
102 | $this->assertEquals(0, date('i', $nexttime)); | |
103 | ||
104 | // Test monthly job | |
105 | $testclass = new \core\task\scheduled_test_task(); | |
106 | $testclass->set_minute('32'); | |
107 | $testclass->set_hour('0'); | |
108 | $testclass->set_day('1'); | |
109 | ||
110 | $nexttime = $testclass->get_next_scheduled_time(); | |
111 | ||
112 | $this->assertEquals(32, date('i', $nexttime)); | |
113 | $this->assertEquals(0, date('G', $nexttime)); | |
114 | $this->assertEquals(1, date('j', $nexttime)); | |
309ae892 DW |
115 | } |
116 | ||
bbd9226c DW |
117 | public function test_timezones() { |
118 | global $CFG, $USER; | |
119 | ||
120 | // The timezones used in this test are chosen because they do not use DST - that would break the test. | |
121 | ||
122 | $currenttimezonephp = date_default_timezone_get(); | |
123 | $currenttimezonecfg = null; | |
124 | if (!empty($CFG->timezone)) { | |
125 | $currenttimezonecfg = $CFG->timezone; | |
126 | } | |
127 | $userstimezone = null; | |
128 | if (!empty($USER->timezone)) { | |
129 | $userstimezone = $USER->timezone; | |
130 | } | |
131 | ||
132 | // We are testing a difference between $CFG->timezone and the php.ini timezone. | |
133 | // GMT+8. | |
134 | date_default_timezone_set('Australia/Perth'); | |
135 | // GMT-04:30. | |
136 | $CFG->timezone = 'America/Caracas'; | |
137 | ||
0a5aa65b | 138 | $testclass = new \core\task\scheduled_test_task(); |
bbd9226c DW |
139 | |
140 | // Scheduled tasks should always use servertime - so this is 03:30 GMT. | |
141 | $testclass->set_hour('1'); | |
142 | $testclass->set_minute('0'); | |
143 | ||
144 | // Next valid time should be 1am of the next day. | |
145 | $nexttime = $testclass->get_next_scheduled_time(); | |
146 | ||
147 | // GMT+05:45. | |
148 | $USER->timezone = 'Asia/Kathmandu'; | |
149 | $userdate = userdate($nexttime); | |
150 | ||
151 | // Should be displayed in user timezone. | |
152 | // I used http://www.timeanddate.com/worldclock/fixedtime.html?msg=Moodle+Test&iso=20140314T01&p1=58 | |
153 | // to verify this time. | |
9be8583a | 154 | $this->assertContains('11:15 AM', core_text::strtoupper($userdate)); |
bbd9226c DW |
155 | |
156 | $CFG->timezone = $currenttimezonecfg; | |
157 | date_default_timezone_set($currenttimezonephp); | |
158 | } | |
159 | ||
309ae892 DW |
160 | public function test_get_next_scheduled_task() { |
161 | global $DB; | |
162 | ||
163 | $this->resetAfterTest(true); | |
164 | // Delete all existing scheduled tasks. | |
165 | $DB->delete_records('task_scheduled'); | |
166 | // Add a scheduled task. | |
167 | ||
168 | // A task that runs once per hour. | |
169 | $record = new stdClass(); | |
170 | $record->blocking = true; | |
171 | $record->minute = '0'; | |
172 | $record->hour = '0'; | |
173 | $record->dayofweek = '*'; | |
174 | $record->day = '*'; | |
175 | $record->month = '*'; | |
176 | $record->component = 'test_scheduled_task'; | |
0a5aa65b | 177 | $record->classname = '\core\task\scheduled_test_task'; |
309ae892 DW |
178 | |
179 | $DB->insert_record('task_scheduled', $record); | |
180 | // And another one to test failures. | |
0a5aa65b PŠ |
181 | $record->classname = '\core\task\scheduled_test2_task'; |
182 | $DB->insert_record('task_scheduled', $record); | |
183 | // And disabled test. | |
184 | $record->classname = '\core\task\scheduled_test3_task'; | |
185 | $record->disabled = 1; | |
309ae892 | 186 | $DB->insert_record('task_scheduled', $record); |
0a5aa65b | 187 | |
309ae892 DW |
188 | $now = time(); |
189 | ||
190 | // Should get handed the first task. | |
191 | $task = \core\task\manager::get_next_scheduled_task($now); | |
0a5aa65b | 192 | $this->assertInstanceOf('\core\task\scheduled_test_task', $task); |
309ae892 DW |
193 | $task->execute(); |
194 | ||
195 | \core\task\manager::scheduled_task_complete($task); | |
196 | // Should get handed the second task. | |
197 | $task = \core\task\manager::get_next_scheduled_task($now); | |
0a5aa65b | 198 | $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); |
309ae892 DW |
199 | $task->execute(); |
200 | ||
201 | \core\task\manager::scheduled_task_failed($task); | |
202 | // Should not get any task. | |
203 | $task = \core\task\manager::get_next_scheduled_task($now); | |
204 | $this->assertNull($task); | |
205 | ||
206 | // Should get the second task (retry after delay). | |
207 | $task = \core\task\manager::get_next_scheduled_task($now + 120); | |
0a5aa65b | 208 | $this->assertInstanceOf('\core\task\scheduled_test2_task', $task); |
309ae892 DW |
209 | $task->execute(); |
210 | ||
211 | \core\task\manager::scheduled_task_complete($task); | |
212 | ||
213 | // Should not get any task. | |
214 | $task = \core\task\manager::get_next_scheduled_task($now); | |
215 | $this->assertNull($task); | |
216 | } | |
a0ac4060 DW |
217 | |
218 | public function test_get_broken_scheduled_task() { | |
219 | global $DB; | |
220 | ||
221 | $this->resetAfterTest(true); | |
222 | // Delete all existing scheduled tasks. | |
223 | $DB->delete_records('task_scheduled'); | |
224 | // Add a scheduled task. | |
225 | ||
226 | // A broken task that runs all the time. | |
227 | $record = new stdClass(); | |
228 | $record->blocking = true; | |
229 | $record->minute = '*'; | |
230 | $record->hour = '*'; | |
231 | $record->dayofweek = '*'; | |
232 | $record->day = '*'; | |
233 | $record->month = '*'; | |
234 | $record->component = 'test_scheduled_task'; | |
235 | $record->classname = '\core\task\scheduled_test_task_broken'; | |
236 | ||
237 | $DB->insert_record('task_scheduled', $record); | |
238 | ||
239 | $now = time(); | |
240 | // Should not get any task. | |
241 | $task = \core\task\manager::get_next_scheduled_task($now); | |
242 | $this->assertDebuggingCalled(); | |
243 | $this->assertNull($task); | |
244 | } | |
309ae892 | 245 | } |