See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 and 401]
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 namespace core; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 /** 22 * Unit tests for the progress classes. 23 * 24 * @package core 25 * @category test 26 * @copyright 2013 The Open University 27 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 28 */ 29 class progress_test extends \basic_testcase { 30 31 /** 32 * Tests for basic use with simple numeric progress. 33 */ 34 public function test_basic() { 35 $progress = new core_mock_progress(); 36 37 // Check values of empty progress things. 38 $this->assertFalse($progress->is_in_progress_section()); 39 40 // Start progress counting, check basic values and check that update 41 // gets called. 42 $progress->start_progress('hello', 10); 43 $this->assertTrue($progress->was_update_called()); 44 $this->assertTrue($progress->is_in_progress_section()); 45 $this->assertEquals('hello', $progress->get_current_description()); 46 47 // Check numeric position and indeterminate count. 48 $this->assert_min_max(0.0, 0.0, $progress); 49 $this->assertEquals(0, $progress->get_progress_count()); 50 51 // Make some progress and check that the time limit gets added. 52 $progress->step_time(); 53 \core_php_time_limit::get_and_clear_unit_test_data(); 54 $progress->progress(2); 55 $this->assertTrue($progress->was_update_called()); 56 $this->assertEquals(array(\core\progress\base::TIME_LIMIT_WITHOUT_PROGRESS), 57 \core_php_time_limit::get_and_clear_unit_test_data()); 58 59 // Check the new value. 60 $this->assert_min_max(0.2, 0.2, $progress); 61 62 // Do another progress run at same time, it should be ignored. 63 $progress->progress(3); 64 $this->assertFalse($progress->was_update_called()); 65 $this->assert_min_max(0.3, 0.3, $progress); 66 67 // End the section. This should cause an update. 68 $progress->end_progress(); 69 $this->assertTrue($progress->was_update_called()); 70 71 // Because there are no sections left open, it thinks we finished. 72 $this->assert_min_max(1.0, 1.0, $progress); 73 74 // There was 1 progress call. 75 $this->assertEquals(1, $progress->get_progress_count()); 76 } 77 78 /** 79 * Tests progress that is nested and/or indeterminate. 80 */ 81 public function test_nested() { 82 // Outer progress goes from 0 to 10. 83 $progress = new core_mock_progress(); 84 $progress->start_progress('hello', 10); 85 86 // Get up to 4, check position. 87 $progress->step_time(); 88 $progress->progress(4); 89 $this->assert_min_max(0.4, 0.4, $progress); 90 $this->assertEquals('hello', $progress->get_current_description()); 91 92 // Now start indeterminate progress. 93 $progress->start_progress('world'); 94 $this->assert_min_max(0.4, 0.5, $progress); 95 $this->assertEquals('world', $progress->get_current_description()); 96 97 // Do some indeterminate progress and count it (once per second). 98 $progress->step_time(); 99 $progress->progress(); 100 $this->assertEquals(2, $progress->get_progress_count()); 101 $progress->progress(); 102 $this->assertEquals(2, $progress->get_progress_count()); 103 $progress->step_time(); 104 $progress->progress(); 105 $this->assertEquals(3, $progress->get_progress_count()); 106 $this->assert_min_max(0.4, 0.5, $progress); 107 108 // Exit the indeterminate section. 109 $progress->end_progress(); 110 $this->assert_min_max(0.5, 0.5, $progress); 111 112 $progress->step_time(); 113 $progress->progress(7); 114 $this->assert_min_max(0.7, 0.7, $progress); 115 116 // Enter a numbered section (this time with a range of 5). 117 $progress->start_progress('frogs', 5); 118 $this->assert_min_max(0.7, 0.7, $progress); 119 $progress->step_time(); 120 $progress->progress(1); 121 $this->assert_min_max(0.72, 0.72, $progress); 122 $progress->step_time(); 123 $progress->progress(3); 124 $this->assert_min_max(0.76, 0.76, $progress); 125 126 // Now enter another indeterminate section. 127 $progress->start_progress('and'); 128 $this->assert_min_max(0.76, 0.78, $progress); 129 130 // Make some progress, should increment indeterminate count. 131 $progress->step_time(); 132 $progress->progress(); 133 $this->assertEquals(7, $progress->get_progress_count()); 134 135 // Enter numbered section, won't make any difference to values. 136 $progress->start_progress('zombies', 2); 137 $progress->step_time(); 138 $progress->progress(1); 139 $this->assert_min_max(0.76, 0.78, $progress); 140 $this->assertEquals(8, $progress->get_progress_count()); 141 142 // Leaving it will make no difference too. 143 $progress->end_progress(); 144 145 // Leaving the indeterminate section will though. 146 $progress->end_progress(); 147 $this->assert_min_max(0.78, 0.78, $progress); 148 149 // Leave the two numbered sections. 150 $progress->end_progress(); 151 $this->assert_min_max(0.8, 0.8, $progress); 152 $progress->end_progress(); 153 $this->assertFalse($progress->is_in_progress_section()); 154 } 155 156 /** 157 * Tests the feature for 'weighting' nested progress. 158 */ 159 public function test_nested_weighted() { 160 $progress = new core_mock_progress(); 161 $progress->start_progress('', 10); 162 163 // First nested child has 2 units of its own and is worth 1 unit. 164 $progress->start_progress('', 2); 165 $progress->step_time(); 166 $progress->progress(1); 167 $this->assert_min_max(0.05, 0.05, $progress); 168 $progress->end_progress(); 169 $this->assert_min_max(0.1, 0.1, $progress); 170 171 // Next child has 2 units of its own but is worth 3 units. 172 $progress->start_progress('weighted', 2, 3); 173 $progress->step_time(); 174 $progress->progress(1); 175 $this->assert_min_max(0.25, 0.25, $progress); 176 $progress->end_progress(); 177 $this->assert_min_max(0.4, 0.4, $progress); 178 179 // Next indeterminate child is worth 6 units. 180 $progress->start_progress('', \core\progress\base::INDETERMINATE, 6); 181 $progress->step_time(); 182 $progress->progress(); 183 $this->assert_min_max(0.4, 1.0, $progress); 184 $progress->end_progress(); 185 $this->assert_min_max(1.0, 1.0, $progress); 186 } 187 188 /** 189 * I had some issues with real use in backup/restore, this test is intended 190 * to be similar. 191 */ 192 public function test_realistic() { 193 $progress = new core_mock_progress(); 194 $progress->start_progress('parent', 100); 195 $progress->start_progress('child', 1); 196 $progress->progress(1); 197 $this->assert_min_max(0.01, 0.01, $progress); 198 $progress->end_progress(); 199 $this->assert_min_max(0.01, 0.01, $progress); 200 } 201 202 /** 203 * To avoid causing problems, progress needs to work for sections that have 204 * zero entries. 205 */ 206 public function test_zero() { 207 $progress = new core_mock_progress(); 208 $progress->start_progress('parent', 100); 209 $progress->progress(1); 210 $this->assert_min_max(0.01, 0.01, $progress); 211 $progress->start_progress('child', 0); 212 213 // For 'zero' progress, the progress section as immediately complete 214 // within the parent count, so it moves up to 2%. 215 $this->assert_min_max(0.02, 0.02, $progress); 216 $progress->progress(0); 217 $this->assert_min_max(0.02, 0.02, $progress); 218 $progress->end_progress(); 219 $this->assert_min_max(0.02, 0.02, $progress); 220 } 221 222 /** 223 * Tests for any exceptions due to invalid calls. 224 */ 225 public function test_exceptions() { 226 $progress = new core_mock_progress(); 227 228 // Check errors when empty. 229 try { 230 $progress->progress(); 231 $this->fail(); 232 } catch (\coding_exception $e) { 233 $this->assertEquals(1, preg_match('~without start_progress~', $e->getMessage())); 234 } 235 try { 236 $progress->end_progress(); 237 $this->fail(); 238 } catch (\coding_exception $e) { 239 $this->assertEquals(1, preg_match('~without start_progress~', $e->getMessage())); 240 } 241 try { 242 $progress->get_current_description(); 243 $this->fail(); 244 } catch (\coding_exception $e) { 245 $this->assertEquals(1, preg_match('~Not inside progress~', $e->getMessage())); 246 } 247 try { 248 $progress->start_progress('', 1, 7); 249 $this->fail(); 250 } catch (\coding_exception $e) { 251 $this->assertEquals(1, preg_match('~must be 1~', $e->getMessage())); 252 } 253 254 // Check invalid start (-2). 255 try { 256 $progress->start_progress('hello', -2); 257 $this->fail(); 258 } catch (\coding_exception $e) { 259 $this->assertEquals(1, preg_match('~cannot be negative~', $e->getMessage())); 260 } 261 262 // Indeterminate when value expected. 263 $progress->start_progress('hello', 10); 264 try { 265 $progress->progress(\core\progress\base::INDETERMINATE); 266 $this->fail(); 267 } catch (\coding_exception $e) { 268 $this->assertEquals(1, preg_match('~expecting value~', $e->getMessage())); 269 } 270 271 // Value when indeterminate expected. 272 $progress->start_progress('hello'); 273 try { 274 $progress->progress(4); 275 $this->fail(); 276 } catch (\coding_exception $e) { 277 $this->assertEquals(1, preg_match('~expecting INDETERMINATE~', $e->getMessage())); 278 } 279 280 // Illegal values. 281 $progress->start_progress('hello', 10); 282 try { 283 $progress->progress(-2); 284 $this->fail(); 285 } catch (\coding_exception $e) { 286 $this->assertEquals(1, preg_match('~out of range~', $e->getMessage())); 287 } 288 try { 289 $progress->progress(11); 290 $this->fail(); 291 } catch (\coding_exception $e) { 292 $this->assertEquals(1, preg_match('~out of range~', $e->getMessage())); 293 } 294 295 // You are allowed two with the same value... 296 $progress->progress(4); 297 $progress->step_time(); 298 $progress->progress(4); 299 $progress->step_time(); 300 301 // ...but not to go backwards. 302 try { 303 $progress->progress(3); 304 $this->fail(); 305 } catch (\coding_exception $e) { 306 $this->assertEquals(1, preg_match('~backwards~', $e->getMessage())); 307 } 308 309 // When you go forward, you can't go further than there is room. 310 try { 311 $progress->start_progress('', 1, 7); 312 $this->fail(); 313 } catch (\coding_exception $e) { 314 $this->assertEquals(1, preg_match('~would exceed max~', $e->getMessage())); 315 } 316 } 317 318 public function test_progress_change() { 319 320 $progress = new core_mock_progress(); 321 322 $progress->start_progress('hello', 50); 323 324 325 for ($n = 1; $n <= 10; $n++) { 326 $progress->increment_progress(); 327 } 328 329 // Check numeric position and indeterminate count. 330 $this->assert_min_max(0.2, 0.2, $progress); 331 $this->assertEquals(1, $progress->get_progress_count()); 332 333 // Make some progress and check that the time limit gets added. 334 $progress->step_time(); 335 336 for ($n = 1; $n <= 20; $n++) { 337 $progress->increment_progress(); 338 } 339 340 $this->assertTrue($progress->was_update_called()); 341 342 // Check the new value. 343 $this->assert_min_max(0.6, 0.6, $progress); 344 $this->assertEquals(2, $progress->get_progress_count()); 345 346 for ($n = 1; $n <= 10; $n++) { 347 $progress->increment_progress(); 348 } 349 $this->assertFalse($progress->was_update_called()); 350 $this->assert_min_max(0.8, 0.8, $progress); 351 $this->assertEquals(2, $progress->get_progress_count()); 352 353 // Do another progress run at same time, it should be ignored. 354 $progress->increment_progress(5); 355 $this->assertFalse($progress->was_update_called()); 356 $this->assert_min_max(0.9, 0.9, $progress); 357 $this->assertEquals(2, $progress->get_progress_count()); 358 359 for ($n = 1; $n <= 3; $n++) { 360 $progress->step_time(); 361 $progress->increment_progress(1); 362 } 363 $this->assertTrue($progress->was_update_called()); 364 $this->assert_min_max(0.96, 0.96, $progress); 365 $this->assertEquals(5, $progress->get_progress_count()); 366 367 368 // End the section. This should cause an update. 369 $progress->end_progress(); 370 $this->assertTrue($progress->was_update_called()); 371 $this->assertEquals(5, $progress->get_progress_count()); 372 373 // Because there are no sections left open, it thinks we finished. 374 $this->assert_min_max(1.0, 1.0, $progress); 375 } 376 377 /** 378 * Checks the current progress values are as expected. 379 * 380 * @param number $min Expected min progress 381 * @param number $max Expected max progress 382 * @param core_mock_progress $progress 383 */ 384 private function assert_min_max($min, $max, core_mock_progress $progress) { 385 $this->assertEquals(array($min, $max), 386 $progress->get_progress_proportion_range()); 387 } 388 } 389 390 /** 391 * Helper class that records when update_progress is called and allows time 392 * stepping. 393 */ 394 class core_mock_progress extends \core\progress\base { 395 private $updatecalled = false; 396 private $time = 1; 397 398 /** 399 * Checks if update was called since the last call to this function. 400 * 401 * @return boolean True if update was called 402 */ 403 public function was_update_called() { 404 if ($this->updatecalled) { 405 $this->updatecalled = false; 406 return true; 407 } 408 return false; 409 } 410 411 /** 412 * Steps the current time by 1 second. 413 */ 414 public function step_time() { 415 $this->time++; 416 } 417 418 protected function update_progress() { 419 $this->updatecalled = true; 420 } 421 422 protected function get_time() { 423 return $this->time; 424 } 425 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body