Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
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 * Quiz attempt overdue handling tests 19 * 20 * @package mod_quiz 21 * @category phpunit 22 * @copyright 2012 Matt Petro 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->dirroot.'/group/lib.php'); 30 31 /** 32 * Unit tests for quiz attempt overdue handling 33 * 34 * @package mod_quiz 35 * @category phpunit 36 * @copyright 2012 Matt Petro 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class mod_quiz_attempt_overdue_testcase extends advanced_testcase { 40 41 /** 42 * Test the functions quiz_update_open_attempts(), get_list_of_overdue_attempts() and 43 * update_overdue_attempts(). 44 */ 45 public function test_bulk_update_functions() { 46 global $DB,$CFG; 47 48 require_once($CFG->dirroot.'/mod/quiz/cronlib.php'); 49 50 $this->resetAfterTest(); 51 52 $this->setAdminUser(); 53 54 // Setup course, user and groups 55 56 $course = $this->getDataGenerator()->create_course(); 57 $user1 = $this->getDataGenerator()->create_user(); 58 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 59 $this->assertNotEmpty($studentrole); 60 $this->assertTrue(enrol_try_internal_enrol($course->id, $user1->id, $studentrole->id)); 61 $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 62 $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 63 $group3 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 64 $this->assertTrue(groups_add_member($group1, $user1)); 65 $this->assertTrue(groups_add_member($group2, $user1)); 66 67 $usertimes = []; 68 69 /** @var mod_quiz_generator $quizgenerator */ 70 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 71 72 // Basic quiz settings 73 74 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 75 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 76 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 77 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test1A', 'time1000state' => 'finished']; 78 79 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 1800]); 80 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 81 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 82 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 1800, 'message' => 'Test1B', 'time1000state' => 'inprogress']; 83 84 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 85 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 86 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 87 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 0, 'message' => 'Test1C', 'time1000state' => 'inprogress']; 88 89 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 90 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 91 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 92 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 600, 'message' => 'Test1D', 'time1000state' => 'finished']; 93 94 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 0]); 95 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 96 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 97 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 0, 'message' => 'Test1E', 'time1000state' => 'inprogress']; 98 99 // Group overrides 100 101 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 102 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 103 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 104 $DB->insert_record('quiz_overrides', 105 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 106 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 0, 'message' => 'Test2A', 'time1000state' => 'inprogress']; 107 108 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 109 $DB->insert_record('quiz_overrides', 110 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1100, 'timelimit' => null]); 111 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 112 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 113 $usertimes[$attemptid] = ['timeclose' => 1100, 'timelimit' => 0, 'message' => 'Test2B', 'time1000state' => 'inprogress']; 114 115 $quiz = $quizgenerator->create_instance( 116 ['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600, 'overduehandling' => 'autoabandon']); 117 $DB->insert_record('quiz_overrides', 118 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 700]); 119 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 120 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 121 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 700, 'message' => 'Test2C', 'time1000state' => 'abandoned']; 122 123 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 124 $DB->insert_record('quiz_overrides', 125 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 500]); 126 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 127 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 128 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 500, 'message' => 'Test2D', 'time1000state' => 'finished']; 129 130 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600]); 131 $DB->insert_record('quiz_overrides', 132 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 0]); 133 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 134 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 135 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 0, 'message' => 'Test2E', 'time1000state' => 'inprogress']; 136 137 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 138 $DB->insert_record('quiz_overrides', 139 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 140 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 141 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 142 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 500, 'message' => 'Test2F', 'time1000state' => 'finished']; 143 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 144 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 145 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 500, 'message' => 'Test2G', 'time1000state' => 'inprogress']; 146 147 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 148 $DB->insert_record('quiz_overrides', 149 ['quiz' => $quiz->id, 'groupid' => $group3->id, 'timeclose' => 1300, 'timelimit' => 500]); // User not in group. 150 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 151 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 152 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test2H', 'time1000state' => 'finished']; 153 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 154 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 155 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test2I', 'time1000state' => 'inprogress']; 156 157 // Multiple group overrides 158 159 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 160 $DB->insert_record('quiz_overrides', 161 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 501]); 162 $DB->insert_record('quiz_overrides', 163 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => 500]); 164 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 165 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 166 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3A', 'time1000state' => 'finished']; 167 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 168 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 169 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3B', 'time1000state' => 'inprogress']; 170 171 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 172 $DB->insert_record('quiz_overrides', 173 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1301, 'timelimit' => 500]); 174 $DB->insert_record('quiz_overrides', 175 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1300, 'timelimit' => 501]); 176 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 177 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 178 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3C', 'time1000state' => 'finished']; 179 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 180 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 181 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3D', 'time1000state' => 'inprogress']; 182 183 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 184 'overduehandling' => 'autoabandon']); 185 $DB->insert_record('quiz_overrides', 186 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1301, 'timelimit' => 500]); 187 $DB->insert_record('quiz_overrides', 188 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1300, 'timelimit' => 501]); 189 $DB->insert_record('quiz_overrides', 190 ['quiz' => $quiz->id, 'groupid' => $group3->id, 'timeclose' => 1500, 'timelimit' => 1000]); // User not in group. 191 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 192 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 193 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3E', 'time1000state' => 'abandoned']; 194 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 195 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 196 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 501, 'message' => 'Test3F', 'time1000state' => 'inprogress']; 197 198 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 199 $DB->insert_record('quiz_overrides', 200 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 201 $DB->insert_record('quiz_overrides', 202 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => null, 'timelimit' => 501]); 203 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 204 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 205 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 501, 'message' => 'Test3G', 'time1000state' => 'finished']; 206 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 207 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 208 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 501, 'message' => 'Test3H', 'time1000state' => 'inprogress']; 209 210 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 211 $DB->insert_record('quiz_overrides', 212 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 213 $DB->insert_record('quiz_overrides', 214 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => null]); 215 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 216 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 217 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 500, 'message' => 'Test3I', 'time1000state' => 'finished']; 218 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 219 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 220 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 500, 'message' => 'Test3J', 'time1000state' => 'inprogress']; 221 222 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 223 $DB->insert_record('quiz_overrides', 224 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 225 $DB->insert_record('quiz_overrides', 226 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1301, 'timelimit' => 0]); 227 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 228 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 229 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 0, 'message' => 'Test3K', 'time1000state' => 'inprogress']; 230 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 231 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 232 $usertimes[$attemptid] = ['timeclose' => 1301, 'timelimit' => 0, 'message' => 'Test3L', 'time1000state' => 'inprogress']; 233 234 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 235 $DB->insert_record('quiz_overrides', 236 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 500]); 237 $DB->insert_record('quiz_overrides', 238 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 0, 'timelimit' => 501]); 239 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 240 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 241 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 501, 'message' => 'Test3M', 'time1000state' => 'finished']; 242 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 243 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 244 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 501, 'message' => 'Test3N', 'time1000state' => 'inprogress']; 245 246 // User overrides 247 248 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 249 $DB->insert_record('quiz_overrides', 250 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 251 $DB->insert_record('quiz_overrides', 252 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => 601]); 253 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 254 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 255 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 601, 'message' => 'Test4A', 'time1000state' => 'finished']; 256 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 257 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 258 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 601, 'message' => 'Test4B', 'time1000state' => 'inprogress']; 259 260 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 261 $DB->insert_record('quiz_overrides', 262 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 263 $DB->insert_record('quiz_overrides', 264 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 0, 'timelimit' => 601]); 265 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 266 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 267 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 601, 'message' => 'Test4C', 'time1000state' => 'finished']; 268 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 269 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 270 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 601, 'message' => 'Test4D', 'time1000state' => 'inprogress']; 271 272 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 273 $DB->insert_record('quiz_overrides', 274 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 275 $DB->insert_record('quiz_overrides', 276 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => 0]); 277 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 278 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 279 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 0, 'message' => 'Test4E', 'time1000state' => 'inprogress']; 280 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 281 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 282 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 0, 'message' => 'Test4F', 'time1000state' => 'inprogress']; 283 284 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 285 'overduehandling' => 'autoabandon']); 286 $DB->insert_record('quiz_overrides', 287 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 288 $DB->insert_record('quiz_overrides', 289 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => null, 'timelimit' => 601]); 290 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 291 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 292 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 601, 'message' => 'Test4G', 'time1000state' => 'abandoned']; 293 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 294 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 295 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 601, 'message' => 'Test4H', 'time1000state' => 'inprogress']; 296 297 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 298 $DB->insert_record('quiz_overrides', 299 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => null, 'timelimit' => 700]); 300 $DB->insert_record('quiz_overrides', 301 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => null, 'timelimit' => 601]); 302 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 303 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 304 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 601, 'message' => 'Test4I', 'time1000state' => 'finished']; 305 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 306 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 307 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 601, 'message' => 'Test4J', 'time1000state' => 'inprogress']; 308 309 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 310 $DB->insert_record('quiz_overrides', 311 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 312 $DB->insert_record('quiz_overrides', 313 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => null]); 314 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 315 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 316 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 700, 'message' => 'Test4K', 'time1000state' => 'finished']; 317 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 318 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 319 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 700, 'message' => 'Test4L', 'time1000state' => 'inprogress']; 320 321 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 322 $DB->insert_record('quiz_overrides', 323 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 324 $DB->insert_record('quiz_overrides', 325 ['quiz' => $quiz->id, 'userid' => $user1->id, 'timeclose' => 1201, 'timelimit' => null]); 326 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 327 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 328 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 600, 'message' => 'Test4M', 'time1000state' => 'finished']; 329 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 330 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 331 $usertimes[$attemptid] = ['timeclose' => 1201, 'timelimit' => 600, 'message' => 'Test4N', 'time1000state' => 'inprogress']; 332 333 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600]); 334 $DB->insert_record('quiz_overrides', 335 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => 700]); 336 $DB->insert_record('quiz_overrides', 337 ['quiz' => $quiz->id, 'userid' => 0, 'timeclose' => 1201, 'timelimit' => 601]); // Not user. 338 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 339 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 340 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 700, 'message' => 'Test4O', 'time1000state' => 'finished']; 341 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 342 'timestart' => 1000, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz), 'attempt' => 1]); 343 $usertimes[$attemptid] = ['timeclose' => 1300, 'timelimit' => 700, 'message' => 'Test4P', 'time1000state' => 'inprogress']; 344 345 // Attempt state overdue 346 347 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 600, 348 'overduehandling' => 'graceperiod', 'graceperiod' => 250]); 349 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'overdue', 350 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 351 $usertimes[$attemptid] = ['timeclose' => 1200, 'timelimit' => 600, 'message' => 'Test5A', 'time1000state' => 'overdue']; 352 353 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 0, 'timelimit' => 600, 354 'overduehandling' => 'graceperiod', 'graceperiod' => 250]); 355 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'overdue', 356 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 357 $usertimes[$attemptid] = ['timeclose' => 0, 'timelimit' => 600, 'message' => 'Test5B', 'time1000state' => 'overdue']; 358 359 // Compute expected end time for each attempt. 360 foreach ($usertimes as $attemptid => $times) { 361 $attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid], '*', MUST_EXIST); 362 363 if ($times['timeclose'] > 0 && $times['timelimit'] > 0) { 364 $usertimes[$attemptid]['timedue'] = min($times['timeclose'], $attempt->timestart + $times['timelimit']); 365 } else if ($times['timeclose'] > 0) { 366 $usertimes[$attemptid]['timedue'] = $times['timeclose']; 367 } else if ($times['timelimit'] > 0) { 368 $usertimes[$attemptid]['timedue'] = $attempt->timestart + $times['timelimit']; 369 } 370 } 371 372 // 373 // Test quiz_update_open_attempts(). 374 // 375 376 quiz_update_open_attempts(['courseid' => $course->id]); 377 foreach ($usertimes as $attemptid => $times) { 378 $attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid], '*', MUST_EXIST); 379 380 if ($attempt->state == 'overdue') { 381 $graceperiod = $DB->get_field('quiz', 'graceperiod', ['id' => $attempt->quiz]); 382 } else { 383 $graceperiod = 0; 384 } 385 if (isset($times['timedue'])) { 386 $this->assertEquals($times['timedue'] + $graceperiod, $attempt->timecheckstate, $times['message']); 387 } else { 388 $this->assertNull($attempt->timecheckstate, $times['message']); 389 } 390 } 391 392 // 393 // Test get_list_of_overdue_attempts(). 394 // 395 396 $overduehander = new mod_quiz_overdue_attempt_updater(); 397 398 $attempts = $overduehander->get_list_of_overdue_attempts(100000); // way in the future 399 $count = 0; 400 foreach ($attempts as $attempt) { 401 $this->assertTrue(isset($usertimes[$attempt->id])); 402 $times = $usertimes[$attempt->id]; 403 $this->assertEquals($times['timeclose'], $attempt->usertimeclose, $times['message']); 404 $this->assertEquals($times['timelimit'], $attempt->usertimelimit, $times['message']); 405 $count++; 406 407 } 408 $attempts->close(); 409 $this->assertEquals($DB->count_records_select('quiz_attempts', 'timecheckstate IS NOT NULL'), $count); 410 411 $attempts = $overduehander->get_list_of_overdue_attempts(0); // before all attempts 412 $count = 0; 413 foreach ($attempts as $attempt) { 414 $count++; 415 } 416 $attempts->close(); 417 $this->assertEquals(0, $count); 418 419 // 420 // Test update_overdue_attempts(). 421 // 422 423 [$count, $quizcount] = $overduehander->update_overdue_attempts(1000, 940); 424 425 $attempts = $DB->get_records('quiz_attempts', null, 'quiz, userid, attempt', 426 'id, quiz, userid, attempt, state, timestart, timefinish, timecheckstate'); 427 foreach ($attempts as $attempt) { 428 $this->assertTrue(isset($usertimes[$attempt->id])); 429 $times = $usertimes[$attempt->id]; 430 $this->assertEquals($times['time1000state'], $attempt->state, $times['message']); 431 switch ($times['time1000state']) { 432 case 'finished': 433 $this->assertEquals($times['timedue'], $attempt->timefinish, $times['message']); 434 $this->assertNull($attempt->timecheckstate, $times['message']); 435 break; 436 437 case 'overdue': 438 $this->assertEquals(0, $attempt->timefinish, $times['message']); 439 $graceperiod = $DB->get_field('quiz', 'graceperiod', ['id' => $attempt->quiz]); 440 $this->assertEquals($times['timedue'] + $graceperiod, $attempt->timecheckstate, $times['message']); 441 break; 442 443 case 'abandoned': 444 $this->assertEquals(0, $attempt->timefinish, $times['message']); 445 $this->assertNull($attempt->timecheckstate, $times['message']); 446 break; 447 } 448 } 449 450 $this->assertEquals(19, $count); 451 $this->assertEquals(19, $quizcount); 452 } 453 454 /** 455 * Make any old question usage for a quiz. 456 * 457 * The attempts used in test_bulk_update_functions must have some 458 * question usage to store in uniqueid, but they don't have to be 459 * very realistic. 460 * 461 * @param stdClass $quiz 462 * @return int question usage id. 463 */ 464 protected function usage_id(stdClass $quiz): int { 465 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', 466 context_module::instance($quiz->cmid)); 467 $quba->set_preferred_behaviour('deferredfeedback'); 468 question_engine::save_questions_usage_by_activity($quba); 469 return $quba->get_id(); 470 } 471 472 /** 473 * Test the group event handlers 474 */ 475 public function test_group_event_handlers() { 476 global $DB; 477 478 $this->resetAfterTest(); 479 480 $this->setAdminUser(); 481 482 // Setup course, user and groups 483 484 $course = $this->getDataGenerator()->create_course(); 485 $user1 = $this->getDataGenerator()->create_user(); 486 $studentrole = $DB->get_record('role', ['shortname' => 'student']); 487 $this->assertNotEmpty($studentrole); 488 $this->assertTrue(enrol_try_internal_enrol($course->id, $user1->id, $studentrole->id)); 489 $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 490 $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); 491 $this->assertTrue(groups_add_member($group1, $user1)); 492 $this->assertTrue(groups_add_member($group2, $user1)); 493 494 /** @var mod_quiz_generator $quizgenerator */ 495 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 496 497 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'timeclose' => 1200, 'timelimit' => 0]); 498 499 // add a group1 override 500 $DB->insert_record('quiz_overrides', 501 ['quiz' => $quiz->id, 'groupid' => $group1->id, 'timeclose' => 1300, 'timelimit' => null]); 502 503 // add an attempt 504 $attemptid = $DB->insert_record('quiz_attempts', ['quiz' => $quiz->id, 'userid' => $user1->id, 'state' => 'inprogress', 505 'timestart' => 100, 'timecheckstate' => 0, 'layout' => '', 'uniqueid' => $this->usage_id($quiz)]); 506 507 // update timecheckstate 508 quiz_update_open_attempts(['quizid' => $quiz->id]); 509 $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 510 511 // remove from group 512 $this->assertTrue(groups_remove_member($group1, $user1)); 513 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 514 515 // add back to group 516 $this->assertTrue(groups_add_member($group1, $user1)); 517 $this->assertEquals(1300, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 518 519 // delete group 520 groups_delete_group($group1); 521 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 522 $this->assertEquals(0, $DB->count_records('quiz_overrides', ['quiz' => $quiz->id])); 523 524 // add a group2 override 525 $DB->insert_record('quiz_overrides', 526 ['quiz' => $quiz->id, 'groupid' => $group2->id, 'timeclose' => 1400, 'timelimit' => null]); 527 quiz_update_open_attempts(['quizid' => $quiz->id]); 528 $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 529 530 // delete user1 from all groups 531 groups_delete_group_members($course->id, $user1->id); 532 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 533 534 // add back to group2 535 $this->assertTrue(groups_add_member($group2, $user1)); 536 $this->assertEquals(1400, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 537 538 // delete everyone from all groups 539 groups_delete_group_members($course->id); 540 $this->assertEquals(1200, $DB->get_field('quiz_attempts', 'timecheckstate', ['id' => $attemptid])); 541 } 542 543 /** 544 * Test the functions quiz_create_attempt_handling_errors 545 */ 546 public function test_quiz_create_attempt_handling_errors() { 547 $this->resetAfterTest(true); 548 $this->setAdminUser(); 549 550 // Make a quiz. 551 $course = $this->getDataGenerator()->create_course(); 552 $user1 = $this->getDataGenerator()->create_user(); 553 $student = $this->getDataGenerator()->create_user(); 554 $this->getDataGenerator()->enrol_user($student->id, $course->id, 'student'); 555 /** @var mod_quiz_generator $quizgenerator */ 556 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 557 /** @var core_question_generator $questiongenerator */ 558 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 559 $quiz = $quizgenerator->create_instance(['course' => $course->id, 'questionsperpage' => 0, 'grade' => 100.0, 560 'sumgrades' => 2]); 561 // Create questions. 562 $cat = $questiongenerator->create_question_category(); 563 $saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 564 $numq = $questiongenerator->create_question('numerical', null, ['category' => $cat->id]); 565 // Add them to the quiz. 566 quiz_add_quiz_question($saq->id, $quiz); 567 quiz_add_quiz_question($numq->id, $quiz); 568 $quizobj = quiz::create($quiz->id, $user1->id); 569 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 570 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 571 $timenow = time(); 572 // Create an attempt. 573 $attempt = quiz_create_attempt($quizobj, 1, null, $timenow, false, $user1->id); 574 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); 575 quiz_attempt_save_started($quizobj, $quba, $attempt); 576 $result = quiz_create_attempt_handling_errors($attempt->id, $quiz->cmid); 577 $this->assertEquals($result->get_attemptid(), $attempt->id); 578 try { 579 $result = quiz_create_attempt_handling_errors($attempt->id, 9999); 580 $this->fail('Exception expected due to invalid course module id.'); 581 } catch (moodle_exception $e) { 582 $this->assertEquals('invalidcoursemodule', $e->errorcode); 583 } 584 try { 585 quiz_create_attempt_handling_errors(9999, $result->get_cmid()); 586 $this->fail('Exception expected due to quiz content change.'); 587 } catch (moodle_exception $e) { 588 $this->assertEquals('attempterrorcontentchange', $e->errorcode); 589 } 590 try { 591 quiz_create_attempt_handling_errors(9999); 592 $this->fail('Exception expected due to invalid quiz attempt id.'); 593 } catch (moodle_exception $e) { 594 $this->assertEquals('attempterrorinvalid', $e->errorcode); 595 } 596 // Set up as normal user without permission to view preview. 597 $this->setUser($student->id); 598 try { 599 quiz_create_attempt_handling_errors(9999, $result->get_cmid()); 600 $this->fail('Exception expected due to quiz content change for user without permission.'); 601 } catch (moodle_exception $e) { 602 $this->assertEquals('attempterrorcontentchangeforuser', $e->errorcode); 603 } 604 try { 605 quiz_create_attempt_handling_errors($attempt->id, 9999); 606 $this->fail('Exception expected due to invalid course module id for user without permission.'); 607 } catch (moodle_exception $e) { 608 $this->assertEquals('invalidcoursemodule', $e->errorcode); 609 } 610 } 611 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body