c5d796102f8b380f4ea135932e23d414d6d757f1
[moodle.git] / lib / tests / adhoc_task_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  * This file contains the unittests for adhock tasks.
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  */
26 defined('MOODLE_INTERNAL') || die();
27 require_once(__DIR__ . '/fixtures/task_fixtures.php');
30 /**
31  * Test class for adhoc tasks.
32  *
33  * @package core
34  * @category task
35  * @copyright 2013 Damyon Wiese
36  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class core_adhoc_task_testcase extends advanced_testcase {
40     /**
41      * Test basic adhoc task execution.
42      */
43     public function test_get_next_adhoc_task_now() {
44         $this->resetAfterTest(true);
46         // Create an adhoc task.
47         $task = new \core\task\adhoc_test_task();
49         // Queue it.
50         \core\task\manager::queue_adhoc_task($task);
52         $now = time();
53         // Get it from the scheduler.
54         $task = \core\task\manager::get_next_adhoc_task($now);
55         $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task);
56         $task->execute();
57         \core\task\manager::adhoc_task_complete($task);
58     }
60     /**
61      * Test adhoc task failure retry backoff.
62      */
63     public function test_get_next_adhoc_task_fail_retry() {
64         $this->resetAfterTest(true);
66         // Create an adhoc task.
67         $task = new \core\task\adhoc_test_task();
68         \core\task\manager::queue_adhoc_task($task);
70         $now = time();
72         // Get it from the scheduler, execute it, and mark it as failed.
73         $task = \core\task\manager::get_next_adhoc_task($now);
74         $task->execute();
75         \core\task\manager::adhoc_task_failed($task);
77         // The task will not be returned immediately.
78         $this->assertNull(\core\task\manager::get_next_adhoc_task($now));
80         // Should get the adhoc task (retry after delay).
81         $task = \core\task\manager::get_next_adhoc_task($now + 120);
82         $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task);
83         $task->execute();
85         \core\task\manager::adhoc_task_complete($task);
87         // Should not get any task.
88         $this->assertNull(\core\task\manager::get_next_adhoc_task($now));
89     }
91     /**
92      * Test future adhoc task execution.
93      */
94     public function test_get_next_adhoc_task_future() {
95         $this->resetAfterTest(true);
97         $now = time();
98         // Create an adhoc task in future.
99         $task = new \core\task\adhoc_test_task();
100         $task->set_next_run_time($now + 1000);
101         \core\task\manager::queue_adhoc_task($task);
103         // Fetching the next task should not return anything.
104         $this->assertNull(\core\task\manager::get_next_adhoc_task($now));
106         // Fetching in the future should return the task.
107         $task = \core\task\manager::get_next_adhoc_task($now + 1020);
108         $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task);
109         $task->execute();
110         \core\task\manager::adhoc_task_complete($task);
111     }
113     /**
114      * Test empty set of adhoc tasks
115      */
116     public function test_get_adhoc_tasks_empty_set() {
117         $this->resetAfterTest(true);
119         $this->assertEquals([], \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task'));
120     }
122     /**
123      * Test correct set of adhoc tasks is returned for class.
124      */
125     public function test_get_adhoc_tasks_result_set() {
126         $this->resetAfterTest(true);
128         for ($i = 0; $i < 3; $i++) {
129             $task = new \core\task\adhoc_test_task();
130             \core\task\manager::queue_adhoc_task($task);
131         }
133         for ($i = 0; $i < 3; $i++) {
134             $task = new \core\task\adhoc_test2_task();
135             \core\task\manager::queue_adhoc_task($task);
136         }
138         $adhoctests = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test_task');
139         $adhoctest2s = \core\task\manager::get_adhoc_tasks('\\core\\task\\adhoc_test2_task');
141         $this->assertCount(3, $adhoctests);
142         $this->assertCount(3, $adhoctest2s);
144         foreach ($adhoctests as $task) {
145             $this->assertInstanceOf('\\core\\task\\adhoc_test_task', $task);
146         }
148         foreach ($adhoctest2s as $task) {
149             $this->assertInstanceOf('\\core\\task\\adhoc_test2_task', $task);
150         }
151     }
153     /**
154      * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if no tasks exist.
155      */
156     public function test_reschedule_or_queue_adhoc_task_no_existing() {
157         $this->resetAfterTest(true);
159         // Schedule adhoc task.
160         $task = new \core\task\adhoc_test_task();
161         $task->set_custom_data(['courseid' => 10]);
162         \core\task\manager::reschedule_or_queue_adhoc_task($task);
163         $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
164     }
166     /**
167      * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task for the same user does
168      * not exist.
169      */
170     public function test_reschedule_or_queue_adhoc_task_different_user() {
171         $this->resetAfterTest(true);
172         $user = \core_user::get_user_by_username('admin');
174         // Schedule adhoc task.
175         $task = new \core\task\adhoc_test_task();
176         $task->set_custom_data(['courseid' => 10]);
177         \core\task\manager::reschedule_or_queue_adhoc_task($task);
179         // Schedule adhoc task for a different user.
180         $task = new \core\task\adhoc_test_task();
181         $task->set_custom_data(['courseid' => 10]);
182         $task->set_userid($user->id);
183         \core\task\manager::reschedule_or_queue_adhoc_task($task);
185         $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
186     }
188     /**
189      * Ensure that the reschedule_or_queue_adhoc_task function will schedule a new task if a task with different custom
190      * data exists.
191      */
192     public function test_reschedule_or_queue_adhoc_task_different_data() {
193         $this->resetAfterTest(true);
195         // Schedule adhoc task.
196         $task = new \core\task\adhoc_test_task();
197         $task->set_custom_data(['courseid' => 10]);
198         \core\task\manager::reschedule_or_queue_adhoc_task($task);
200         // Schedule adhoc task for a different user.
201         $task = new \core\task\adhoc_test_task();
202         $task->set_custom_data(['courseid' => 11]);
203         \core\task\manager::reschedule_or_queue_adhoc_task($task);
205         $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
206     }
208     /**
209      * Ensure that the reschedule_or_queue_adhoc_task function will not make any change for matching data if no time was
210      * specified.
211      */
212     public function test_reschedule_or_queue_adhoc_task_match_no_change() {
213         $this->resetAfterTest(true);
215         // Schedule adhoc task.
216         $task = new \core\task\adhoc_test_task();
217         $task->set_custom_data(['courseid' => 10]);
218         $task->set_next_run_time(time() + DAYSECS);
219         \core\task\manager::reschedule_or_queue_adhoc_task($task);
221         $before = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task');
223         // Schedule the task again but do not specify a time.
224         $task = new \core\task\adhoc_test_task();
225         $task->set_custom_data(['courseid' => 10]);
226         \core\task\manager::reschedule_or_queue_adhoc_task($task);
228         $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
229         $this->assertEquals($before, \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task'));
230     }
232     /**
233      * Ensure that the reschedule_or_queue_adhoc_task function will update the run time if there are planned changes.
234      */
235     public function test_reschedule_or_queue_adhoc_task_match_update_runtime() {
236         $this->resetAfterTest(true);
237         $initialruntime = time() + DAYSECS;
238         $newruntime = time() + WEEKSECS;
240         // Schedule adhoc task.
241         $task = new \core\task\adhoc_test_task();
242         $task->set_custom_data(['courseid' => 10]);
243         $task->set_next_run_time($initialruntime);
244         \core\task\manager::reschedule_or_queue_adhoc_task($task);
246         $before = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task');
248         // Schedule the task again.
249         $task = new \core\task\adhoc_test_task();
250         $task->set_custom_data(['courseid' => 10]);
251         $task->set_next_run_time($newruntime);
252         \core\task\manager::reschedule_or_queue_adhoc_task($task);
254         $tasks = \core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task');
255         $this->assertEquals(1, count($tasks));
256         $this->assertNotEquals($before, $tasks);
257         $firsttask = reset($tasks);
258         $this->assertEquals($newruntime, $firsttask->get_next_run_time());
259     }
261     /**
262      * Test queue_adhoc_task "if not scheduled".
263      */
264     public function test_queue_adhoc_task_if_not_scheduled() {
265         $this->resetAfterTest(true);
266         $user = \core_user::get_user_by_username('admin');
268         // Schedule adhoc task.
269         $task = new \core\task\adhoc_test_task();
270         $task->set_custom_data(array('courseid' => 10));
271         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true));
272         $this->assertEquals(1, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
274         // Schedule adhoc task with a user.
275         $task = new \core\task\adhoc_test_task();
276         $task->set_custom_data(array('courseid' => 10));
277         $task->set_userid($user->id);
278         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true));
279         $this->assertEquals(2, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
281         // Schedule same adhoc task with different custom data.
282         $task = new \core\task\adhoc_test_task();
283         $task->set_custom_data(array('courseid' => 1));
284         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true));
285         $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
287         // Schedule same adhoc task with same custom data.
288         $task = new \core\task\adhoc_test_task();
289         $task->set_custom_data(array('courseid' => 1));
290         $this->assertEmpty(\core\task\manager::queue_adhoc_task($task, true));
291         $this->assertEquals(3, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
293         // Schedule same adhoc task with same custom data and a user.
294         $task = new \core\task\adhoc_test_task();
295         $task->set_custom_data(array('courseid' => 1));
296         $task->set_userid($user->id);
297         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true));
298         $this->assertEquals(4, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
300         // Schedule same adhoc task without custom data.
301         // Note: This task was created earlier.
302         $task = new \core\task\adhoc_test_task();
303         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task, true));
304         $this->assertEquals(5, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
306         // Schedule same adhoc task without custom data (again).
307         $task5 = new \core\task\adhoc_test_task();
308         $this->assertEmpty(\core\task\manager::queue_adhoc_task($task5, true));
309         $this->assertEquals(5, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
311         // Schedule same adhoc task without custom data but with a userid.
312         $task6 = new \core\task\adhoc_test_task();
313         $user = \core_user::get_user_by_username('admin');
314         $task6->set_userid($user->id);
315         $this->assertNotEmpty(\core\task\manager::queue_adhoc_task($task6, true));
316         $this->assertEquals(6, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
318         // Schedule same adhoc task again without custom data but with a userid.
319         $task6 = new \core\task\adhoc_test_task();
320         $user = \core_user::get_user_by_username('admin');
321         $task6->set_userid($user->id);
322         $this->assertEmpty(\core\task\manager::queue_adhoc_task($task6, true));
323         $this->assertEquals(6, count(\core\task\manager::get_adhoc_tasks('core\task\adhoc_test_task')));
324     }
326     /**
327      * Test that when no userid is specified, it returns empty from the DB
328      * too.
329      */
330     public function test_adhoc_task_user_empty() {
331         $this->resetAfterTest(true);
333         // Create an adhoc task in future.
334         $task = new \core\task\adhoc_test_task();
335         \core\task\manager::queue_adhoc_task($task);
337         // Get it back from the scheduler.
338         $now = time();
339         $task = \core\task\manager::get_next_adhoc_task($now);
340         \core\task\manager::adhoc_task_complete($task);
342         $this->assertEmpty($task->get_userid());
343     }
345     /**
346      * Test that when a userid is specified, that userid is subsequently
347      * returned.
348      */
349     public function test_adhoc_task_user_set() {
350         $this->resetAfterTest(true);
352         // Create an adhoc task in future.
353         $task = new \core\task\adhoc_test_task();
354         $user = \core_user::get_user_by_username('admin');
355         $task->set_userid($user->id);
356         \core\task\manager::queue_adhoc_task($task);
358         // Get it back from the scheduler.
359         $now = time();
360         $task = \core\task\manager::get_next_adhoc_task($now);
361         \core\task\manager::adhoc_task_complete($task);
363         $this->assertEquals($user->id, $task->get_userid());
364     }