[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 * Unit tests for (some of) ../moodlelib.php. 19 * 20 * @package core 21 * @category phpunit 22 * @copyright © 2006 The Open University 23 * @author T.J.Hunt@open.ac.uk 24 * @author nicolas@moodle.com 25 */ 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 class core_moodlelib_testcase extends advanced_testcase { 30 31 public static $includecoverage = array('lib/moodlelib.php'); 32 33 /** 34 * Define a local decimal separator. 35 * 36 * It is not possible to directly change the result of get_string in 37 * a unit test. Instead, we create a language pack for language 'xx' in 38 * dataroot and make langconfig.php with the string we need to change. 39 * The example separator used here is 'X'; on PHP 5.3 and before this 40 * must be a single byte character due to PHP bug/limitation in 41 * number_format, so you can't use UTF-8 characters. 42 */ 43 protected function define_local_decimal_separator() { 44 global $SESSION, $CFG; 45 46 $SESSION->lang = 'xx'; 47 $langconfig = "<?php\n\$string['decsep'] = 'X';"; 48 $langfolder = $CFG->dataroot . '/lang/xx'; 49 check_dir_exists($langfolder); 50 file_put_contents($langfolder . '/langconfig.php', $langconfig); 51 } 52 53 public function test_cleanremoteaddr() { 54 // IPv4. 55 $this->assertNull(cleanremoteaddr('1023.121.234.1')); 56 $this->assertSame('123.121.234.1', cleanremoteaddr('123.121.234.01 ')); 57 58 // IPv6. 59 $this->assertNull(cleanremoteaddr('0:0:0:0:0:0:0:0:0')); 60 $this->assertNull(cleanremoteaddr('0:0:0:0:0:0:0:abh')); 61 $this->assertNull(cleanremoteaddr('0:0:0:::0:0:1')); 62 $this->assertSame('::', cleanremoteaddr('0:0:0:0:0:0:0:0', true)); 63 $this->assertSame('::1:1', cleanremoteaddr('0:0:0:0:0:0:1:1', true)); 64 $this->assertSame('abcd:ef::', cleanremoteaddr('abcd:00ef:0:0:0:0:0:0', true)); 65 $this->assertSame('1::1', cleanremoteaddr('1:0:0:0:0:0:0:1', true)); 66 $this->assertSame('0:0:0:0:0:0:10:1', cleanremoteaddr('::10:1', false)); 67 $this->assertSame('1:1:0:0:0:0:0:0', cleanremoteaddr('01:1::', false)); 68 $this->assertSame('10:0:0:0:0:0:0:10', cleanremoteaddr('10::10', false)); 69 $this->assertSame('::ffff:c0a8:11', cleanremoteaddr('::ffff:192.168.1.1', true)); 70 } 71 72 public function test_address_in_subnet() { 73 // 1: xxx.xxx.xxx.xxx/nn or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/nnn (number of bits in net mask). 74 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.1/32')); 75 $this->assertFalse(address_in_subnet('123.121.23.1', '123.121.23.0/32')); 76 $this->assertTrue(address_in_subnet('10.10.10.100', '123.121.23.45/0')); 77 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/24')); 78 $this->assertFalse(address_in_subnet('123.121.34.1', '123.121.234.0/24')); 79 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/30')); 80 $this->assertFalse(address_in_subnet('123.121.23.8', '123.121.23.0/30')); 81 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128')); 82 $this->assertFalse(address_in_subnet('bab:baba::baba', 'bab:baba::cece/128')); 83 $this->assertTrue(address_in_subnet('baba:baba::baba', 'cece:cece::cece/0')); 84 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128')); 85 $this->assertTrue(address_in_subnet('baba:baba::00ba', 'baba:baba::/120')); 86 $this->assertFalse(address_in_subnet('baba:baba::aba', 'baba:baba::/120')); 87 $this->assertTrue(address_in_subnet('baba::baba:00ba', 'baba::baba:0/112')); 88 $this->assertFalse(address_in_subnet('baba::aba:00ba', 'baba::baba:0/112')); 89 $this->assertFalse(address_in_subnet('aba::baba:0000', 'baba::baba:0/112')); 90 91 // Fixed input. 92 $this->assertTrue(address_in_subnet('123.121.23.1 ', ' 123.121.23.0 / 24')); 93 $this->assertTrue(address_in_subnet('::ffff:10.1.1.1', ' 0:0:0:000:0:ffff:a1:10 / 126')); 94 95 // Incorrect input. 96 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/-2')); 97 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/64')); 98 $this->assertFalse(address_in_subnet('123.121.234.x', '123.121.234.1/24')); 99 $this->assertFalse(address_in_subnet('123.121.234.0', '123.121.234.xx/24')); 100 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/xx0')); 101 $this->assertFalse(address_in_subnet('::1', '::aa:0/xx0')); 102 $this->assertFalse(address_in_subnet('::1', '::aa:0/-5')); 103 $this->assertFalse(address_in_subnet('::1', '::aa:0/130')); 104 $this->assertFalse(address_in_subnet('x:1', '::aa:0/130')); 105 $this->assertFalse(address_in_subnet('::1', '::ax:0/130')); 106 107 // 2: xxx.xxx.xxx.xxx-yyy or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::xxxx-yyyy (a range of IP addresses in the last group). 108 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12-14')); 109 $this->assertTrue(address_in_subnet('123.121.234.13', '123.121.234.12-14')); 110 $this->assertTrue(address_in_subnet('123.121.234.14', '123.121.234.12-14')); 111 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.12-14')); 112 $this->assertFalse(address_in_subnet('123.121.234.20', '123.121.234.12-14')); 113 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.234.12-14')); 114 $this->assertFalse(address_in_subnet('123.12.234.12', '123.121.234.12-14')); 115 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba-babe')); 116 $this->assertTrue(address_in_subnet('baba:baba::babc', 'baba:baba::baba-babe')); 117 $this->assertTrue(address_in_subnet('baba:baba::babe', 'baba:baba::baba-babe')); 118 $this->assertFalse(address_in_subnet('bab:baba::bab0', 'bab:baba::baba-babe')); 119 $this->assertFalse(address_in_subnet('bab:baba::babf', 'bab:baba::baba-babe')); 120 $this->assertFalse(address_in_subnet('bab:baba::bfbe', 'bab:baba::baba-babe')); 121 $this->assertFalse(address_in_subnet('bfb:baba::babe', 'bab:baba::baba-babe')); 122 123 // Fixed input. 124 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12 - 14 ')); 125 $this->assertTrue(address_in_subnet('bab:baba::babe', 'bab:baba::baba - babe ')); 126 127 // Incorrect input. 128 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-234.14')); 129 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-256')); 130 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12--256')); 131 132 // 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx. (incomplete address, a bit non-technical ;-). 133 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12')); 134 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.23.13')); 135 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.')); 136 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234')); 137 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121')); 138 $this->assertTrue(address_in_subnet('123.121.234.12', '123')); 139 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234.')); 140 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234')); 141 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba::bab')); 142 $this->assertFalse(address_in_subnet('baba:baba::ba', 'baba:baba::bc')); 143 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba')); 144 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:')); 145 $this->assertFalse(address_in_subnet('bab:baba::bab', 'baba:')); 146 147 // Multiple subnets. 148 $this->assertTrue(address_in_subnet('123.121.234.12', '::1/64, 124., 123.121.234.10-30')); 149 $this->assertTrue(address_in_subnet('124.121.234.12', '::1/64, 124., 123.121.234.10-30')); 150 $this->assertTrue(address_in_subnet('::2', '::1/64, 124., 123.121.234.10-30')); 151 $this->assertFalse(address_in_subnet('12.121.234.12', '::1/64, 124., 123.121.234.10-30')); 152 153 // Other incorrect input. 154 $this->assertFalse(address_in_subnet('123.123.123.123', '')); 155 } 156 157 public function test_fix_utf8() { 158 // Make sure valid data including other types is not changed. 159 $this->assertSame(null, fix_utf8(null)); 160 $this->assertSame(1, fix_utf8(1)); 161 $this->assertSame(1.1, fix_utf8(1.1)); 162 $this->assertSame(true, fix_utf8(true)); 163 $this->assertSame('', fix_utf8('')); 164 $this->assertSame('abc', fix_utf8('abc')); 165 $array = array('do', 're', 'mi'); 166 $this->assertSame($array, fix_utf8($array)); 167 $object = new stdClass(); 168 $object->a = 'aa'; 169 $object->b = 'bb'; 170 $this->assertEquals($object, fix_utf8($object)); 171 172 // valid utf8 string 173 $this->assertSame("žlutý koníček přeskočil potůček \n\t\r", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0")); 174 175 // Invalid utf8 string. 176 $this->assertSame('aš', fix_utf8('a'.chr(130).'š'), 'This fails with buggy iconv() when mbstring extenstion is not available as fallback.'); 177 } 178 179 public function test_optional_param() { 180 global $CFG; 181 182 $_POST['username'] = 'post_user'; 183 $_GET['username'] = 'get_user'; 184 $this->assertSame($_POST['username'], optional_param('username', 'default_user', PARAM_RAW)); 185 186 unset($_POST['username']); 187 $this->assertSame($_GET['username'], optional_param('username', 'default_user', PARAM_RAW)); 188 189 unset($_GET['username']); 190 $this->assertSame('default_user', optional_param('username', 'default_user', PARAM_RAW)); 191 192 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 193 $_POST['username'] = 'post_user'; 194 try { 195 optional_param('username', 'default_user', null); 196 $this->fail('coding_exception expected'); 197 } catch (moodle_exception $ex) { 198 $this->assertInstanceOf('coding_exception', $ex); 199 } 200 try { 201 @optional_param('username', 'default_user'); 202 $this->fail('coding_exception expected'); 203 } catch (moodle_exception $ex) { 204 $this->assertInstanceOf('coding_exception', $ex); 205 } 206 try { 207 @optional_param('username'); 208 $this->fail('coding_exception expected'); 209 } catch (moodle_exception $ex) { 210 $this->assertInstanceOf('coding_exception', $ex); 211 } 212 try { 213 optional_param('', 'default_user', PARAM_RAW); 214 $this->fail('coding_exception expected'); 215 } catch (moodle_exception $ex) { 216 $this->assertInstanceOf('coding_exception', $ex); 217 } 218 219 // Make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3. 220 $_POST['username'] = array('a'=>'a'); 221 $this->assertSame($_POST['username'], optional_param('username', 'default_user', PARAM_RAW)); 222 $this->assertDebuggingCalled(); 223 } 224 225 public function test_optional_param_array() { 226 global $CFG; 227 228 $_POST['username'] = array('a'=>'post_user'); 229 $_GET['username'] = array('a'=>'get_user'); 230 $this->assertSame($_POST['username'], optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 231 232 unset($_POST['username']); 233 $this->assertSame($_GET['username'], optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 234 235 unset($_GET['username']); 236 $this->assertSame(array('a'=>'default_user'), optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 237 238 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 239 $_POST['username'] = array('a'=>'post_user'); 240 try { 241 optional_param_array('username', array('a'=>'default_user'), null); 242 $this->fail('coding_exception expected'); 243 } catch (moodle_exception $ex) { 244 $this->assertInstanceOf('coding_exception', $ex); 245 } 246 try { 247 @optional_param_array('username', array('a'=>'default_user')); 248 $this->fail('coding_exception expected'); 249 } catch (moodle_exception $ex) { 250 $this->assertInstanceOf('coding_exception', $ex); 251 } 252 try { 253 @optional_param_array('username'); 254 $this->fail('coding_exception expected'); 255 } catch (moodle_exception $ex) { 256 $this->assertInstanceOf('coding_exception', $ex); 257 } 258 try { 259 optional_param_array('', array('a'=>'default_user'), PARAM_RAW); 260 $this->fail('coding_exception expected'); 261 } catch (moodle_exception $ex) { 262 $this->assertInstanceOf('coding_exception', $ex); 263 } 264 265 // Do not allow nested arrays. 266 try { 267 $_POST['username'] = array('a'=>array('b'=>'post_user')); 268 optional_param_array('username', array('a'=>'default_user'), PARAM_RAW); 269 $this->fail('coding_exception expected'); 270 } catch (coding_exception $ex) { 271 $this->assertTrue(true); 272 } 273 274 // Do not allow non-arrays. 275 $_POST['username'] = 'post_user'; 276 $this->assertSame(array('a'=>'default_user'), optional_param_array('username', array('a'=>'default_user'), PARAM_RAW)); 277 $this->assertDebuggingCalled(); 278 279 // Make sure array keys are sanitised. 280 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user'); 281 $this->assertSame(array('a1_-'=>'post_user'), optional_param_array('username', array(), PARAM_RAW)); 282 $this->assertDebuggingCalled(); 283 } 284 285 public function test_required_param() { 286 $_POST['username'] = 'post_user'; 287 $_GET['username'] = 'get_user'; 288 $this->assertSame('post_user', required_param('username', PARAM_RAW)); 289 290 unset($_POST['username']); 291 $this->assertSame('get_user', required_param('username', PARAM_RAW)); 292 293 unset($_GET['username']); 294 try { 295 $this->assertSame('default_user', required_param('username', PARAM_RAW)); 296 $this->fail('moodle_exception expected'); 297 } catch (moodle_exception $ex) { 298 $this->assertInstanceOf('moodle_exception', $ex); 299 } 300 301 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 302 $_POST['username'] = 'post_user'; 303 try { 304 @required_param('username'); 305 $this->fail('coding_exception expected'); 306 } catch (moodle_exception $ex) { 307 $this->assertInstanceOf('coding_exception', $ex); 308 } 309 try { 310 required_param('username', ''); 311 $this->fail('coding_exception expected'); 312 } catch (moodle_exception $ex) { 313 $this->assertInstanceOf('coding_exception', $ex); 314 } 315 try { 316 required_param('', PARAM_RAW); 317 $this->fail('coding_exception expected'); 318 } catch (moodle_exception $ex) { 319 $this->assertInstanceOf('coding_exception', $ex); 320 } 321 322 // Make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3. 323 $_POST['username'] = array('a'=>'a'); 324 $this->assertSame($_POST['username'], required_param('username', PARAM_RAW)); 325 $this->assertDebuggingCalled(); 326 } 327 328 public function test_required_param_array() { 329 global $CFG; 330 331 $_POST['username'] = array('a'=>'post_user'); 332 $_GET['username'] = array('a'=>'get_user'); 333 $this->assertSame($_POST['username'], required_param_array('username', PARAM_RAW)); 334 335 unset($_POST['username']); 336 $this->assertSame($_GET['username'], required_param_array('username', PARAM_RAW)); 337 338 // Make sure exception is triggered when some params are missing, hide error notices here - new in 2.2. 339 $_POST['username'] = array('a'=>'post_user'); 340 try { 341 required_param_array('username', null); 342 $this->fail('coding_exception expected'); 343 } catch (moodle_exception $ex) { 344 $this->assertInstanceOf('coding_exception', $ex); 345 } 346 try { 347 @required_param_array('username'); 348 $this->fail('coding_exception expected'); 349 } catch (moodle_exception $ex) { 350 $this->assertInstanceOf('coding_exception', $ex); 351 } 352 try { 353 required_param_array('', PARAM_RAW); 354 $this->fail('coding_exception expected'); 355 } catch (moodle_exception $ex) { 356 $this->assertInstanceOf('coding_exception', $ex); 357 } 358 359 // Do not allow nested arrays. 360 try { 361 $_POST['username'] = array('a'=>array('b'=>'post_user')); 362 required_param_array('username', PARAM_RAW); 363 $this->fail('coding_exception expected'); 364 } catch (moodle_exception $ex) { 365 $this->assertInstanceOf('coding_exception', $ex); 366 } 367 368 // Do not allow non-arrays. 369 try { 370 $_POST['username'] = 'post_user'; 371 required_param_array('username', PARAM_RAW); 372 $this->fail('moodle_exception expected'); 373 } catch (moodle_exception $ex) { 374 $this->assertInstanceOf('moodle_exception', $ex); 375 } 376 377 // Make sure array keys are sanitised. 378 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user'); 379 $this->assertSame(array('a1_-'=>'post_user'), required_param_array('username', PARAM_RAW)); 380 $this->assertDebuggingCalled(); 381 } 382 383 public function test_clean_param() { 384 // Forbid objects and arrays. 385 try { 386 clean_param(array('x', 'y'), PARAM_RAW); 387 $this->fail('coding_exception expected'); 388 } catch (moodle_exception $ex) { 389 $this->assertInstanceOf('coding_exception', $ex); 390 } 391 try { 392 $param = new stdClass(); 393 $param->id = 1; 394 clean_param($param, PARAM_RAW); 395 $this->fail('coding_exception expected'); 396 } catch (moodle_exception $ex) { 397 $this->assertInstanceOf('coding_exception', $ex); 398 } 399 400 // Require correct type. 401 try { 402 clean_param('x', 'xxxxxx'); 403 $this->fail('moodle_exception expected'); 404 } catch (moodle_exception $ex) { 405 $this->assertInstanceOf('moodle_exception', $ex); 406 } 407 try { 408 @clean_param('x'); 409 $this->fail('moodle_exception expected'); 410 } catch (moodle_exception $ex) { 411 $this->assertInstanceOf('moodle_exception', $ex); 412 } 413 } 414 415 public function test_clean_param_array() { 416 $this->assertSame(array(), clean_param_array(null, PARAM_RAW)); 417 $this->assertSame(array('a', 'b'), clean_param_array(array('a', 'b'), PARAM_RAW)); 418 $this->assertSame(array('a', array('b')), clean_param_array(array('a', array('b')), PARAM_RAW, true)); 419 420 // Require correct type. 421 try { 422 clean_param_array(array('x'), 'xxxxxx'); 423 $this->fail('moodle_exception expected'); 424 } catch (moodle_exception $ex) { 425 $this->assertInstanceOf('moodle_exception', $ex); 426 } 427 try { 428 @clean_param_array(array('x')); 429 $this->fail('moodle_exception expected'); 430 } catch (moodle_exception $ex) { 431 $this->assertInstanceOf('moodle_exception', $ex); 432 } 433 434 try { 435 clean_param_array(array('x', array('y')), PARAM_RAW); 436 $this->fail('coding_exception expected'); 437 } catch (moodle_exception $ex) { 438 $this->assertInstanceOf('coding_exception', $ex); 439 } 440 441 // Test recursive. 442 } 443 444 public function test_clean_param_raw() { 445 $this->assertSame( 446 '#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', 447 clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_RAW)); 448 } 449 450 public function test_clean_param_trim() { 451 $this->assertSame('Frog toad', clean_param(" Frog toad \r\n ", PARAM_RAW_TRIMMED)); 452 } 453 454 public function test_clean_param_clean() { 455 // PARAM_CLEAN is an ugly hack, do not use in new code (skodak), 456 // instead use more specific type, or submit sothing that can be verified properly. 457 $this->assertSame('xx', clean_param('xx<script>', PARAM_CLEAN)); 458 } 459 460 public function test_clean_param_alpha() { 461 $this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHA)); 462 } 463 464 public function test_clean_param_alphanum() { 465 $this->assertSame('978942897DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHANUM)); 466 } 467 468 public function test_clean_param_alphaext() { 469 $this->assertSame('DSFMOSDJ', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHAEXT)); 470 } 471 472 public function test_clean_param_sequence() { 473 $this->assertSame(',9789,42897', clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_SEQUENCE)); 474 } 475 476 public function test_clean_param_component() { 477 // Please note the cleaning of component names is very strict, no guessing here. 478 $this->assertSame('mod_forum', clean_param('mod_forum', PARAM_COMPONENT)); 479 $this->assertSame('block_online_users', clean_param('block_online_users', PARAM_COMPONENT)); 480 $this->assertSame('block_blond_online_users', clean_param('block_blond_online_users', PARAM_COMPONENT)); 481 $this->assertSame('mod_something2', clean_param('mod_something2', PARAM_COMPONENT)); 482 $this->assertSame('forum', clean_param('forum', PARAM_COMPONENT)); 483 $this->assertSame('user', clean_param('user', PARAM_COMPONENT)); 484 $this->assertSame('rating', clean_param('rating', PARAM_COMPONENT)); 485 $this->assertSame('feedback360', clean_param('feedback360', PARAM_COMPONENT)); 486 $this->assertSame('mod_feedback360', clean_param('mod_feedback360', PARAM_COMPONENT)); 487 $this->assertSame('', clean_param('mod_2something', PARAM_COMPONENT)); 488 $this->assertSame('', clean_param('2mod_something', PARAM_COMPONENT)); 489 $this->assertSame('', clean_param('mod_something_xx', PARAM_COMPONENT)); 490 $this->assertSame('', clean_param('auth_something__xx', PARAM_COMPONENT)); 491 $this->assertSame('', clean_param('mod_Something', PARAM_COMPONENT)); 492 $this->assertSame('', clean_param('mod_somethíng', PARAM_COMPONENT)); 493 $this->assertSame('', clean_param('mod__something', PARAM_COMPONENT)); 494 $this->assertSame('', clean_param('auth_xx-yy', PARAM_COMPONENT)); 495 $this->assertSame('', clean_param('_auth_xx', PARAM_COMPONENT)); 496 $this->assertSame('', clean_param('a2uth_xx', PARAM_COMPONENT)); 497 $this->assertSame('', clean_param('auth_xx_', PARAM_COMPONENT)); 498 $this->assertSame('', clean_param('auth_xx.old', PARAM_COMPONENT)); 499 $this->assertSame('', clean_param('_user', PARAM_COMPONENT)); 500 $this->assertSame('', clean_param('2rating', PARAM_COMPONENT)); 501 $this->assertSame('', clean_param('user_', PARAM_COMPONENT)); 502 } 503 504 public function test_is_valid_plugin_name() { 505 $this->assertTrue(is_valid_plugin_name('forum')); 506 $this->assertTrue(is_valid_plugin_name('forum2')); 507 $this->assertTrue(is_valid_plugin_name('feedback360')); 508 $this->assertTrue(is_valid_plugin_name('online_users')); 509 $this->assertTrue(is_valid_plugin_name('blond_online_users')); 510 $this->assertFalse(is_valid_plugin_name('online__users')); 511 $this->assertFalse(is_valid_plugin_name('forum ')); 512 $this->assertFalse(is_valid_plugin_name('forum.old')); 513 $this->assertFalse(is_valid_plugin_name('xx-yy')); 514 $this->assertFalse(is_valid_plugin_name('2xx')); 515 $this->assertFalse(is_valid_plugin_name('Xx')); 516 $this->assertFalse(is_valid_plugin_name('_xx')); 517 $this->assertFalse(is_valid_plugin_name('xx_')); 518 } 519 520 public function test_clean_param_plugin() { 521 // Please note the cleaning of plugin names is very strict, no guessing here. 522 $this->assertSame('forum', clean_param('forum', PARAM_PLUGIN)); 523 $this->assertSame('forum2', clean_param('forum2', PARAM_PLUGIN)); 524 $this->assertSame('feedback360', clean_param('feedback360', PARAM_PLUGIN)); 525 $this->assertSame('online_users', clean_param('online_users', PARAM_PLUGIN)); 526 $this->assertSame('blond_online_users', clean_param('blond_online_users', PARAM_PLUGIN)); 527 $this->assertSame('', clean_param('online__users', PARAM_PLUGIN)); 528 $this->assertSame('', clean_param('forum ', PARAM_PLUGIN)); 529 $this->assertSame('', clean_param('forum.old', PARAM_PLUGIN)); 530 $this->assertSame('', clean_param('xx-yy', PARAM_PLUGIN)); 531 $this->assertSame('', clean_param('2xx', PARAM_PLUGIN)); 532 $this->assertSame('', clean_param('Xx', PARAM_PLUGIN)); 533 $this->assertSame('', clean_param('_xx', PARAM_PLUGIN)); 534 $this->assertSame('', clean_param('xx_', PARAM_PLUGIN)); 535 } 536 537 public function test_clean_param_area() { 538 // Please note the cleaning of area names is very strict, no guessing here. 539 $this->assertSame('something', clean_param('something', PARAM_AREA)); 540 $this->assertSame('something2', clean_param('something2', PARAM_AREA)); 541 $this->assertSame('some_thing', clean_param('some_thing', PARAM_AREA)); 542 $this->assertSame('some_thing_xx', clean_param('some_thing_xx', PARAM_AREA)); 543 $this->assertSame('feedback360', clean_param('feedback360', PARAM_AREA)); 544 $this->assertSame('', clean_param('_something', PARAM_AREA)); 545 $this->assertSame('', clean_param('something_', PARAM_AREA)); 546 $this->assertSame('', clean_param('2something', PARAM_AREA)); 547 $this->assertSame('', clean_param('Something', PARAM_AREA)); 548 $this->assertSame('', clean_param('some-thing', PARAM_AREA)); 549 $this->assertSame('', clean_param('somethííng', PARAM_AREA)); 550 $this->assertSame('', clean_param('something.x', PARAM_AREA)); 551 } 552 553 public function test_clean_param_text() { 554 $this->assertSame(PARAM_TEXT, PARAM_MULTILANG); 555 // Standard. 556 $this->assertSame('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', clean_param('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', PARAM_TEXT)); 557 $this->assertSame('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', clean_param('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', PARAM_TEXT)); 558 $this->assertSame('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', clean_param('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', PARAM_TEXT)); 559 // Malformed. 560 $this->assertSame('<span lang="en" class="multilang">aa</span>', clean_param('<span lang="en" class="multilang">aa</span>', PARAM_TEXT)); 561 $this->assertSame('aa', clean_param('<span lang="en" class="nothing" class="multilang">aa</span>', PARAM_TEXT)); 562 $this->assertSame('aa', clean_param('<lang lang="en" class="multilang">aa</lang>', PARAM_TEXT)); 563 $this->assertSame('aa', clean_param('<lang lang="en!!">aa</lang>', PARAM_TEXT)); 564 $this->assertSame('aa', clean_param('<span lang="en==" class="multilang">aa</span>', PARAM_TEXT)); 565 $this->assertSame('abc', clean_param('a<em>b</em>c', PARAM_TEXT)); 566 $this->assertSame('a>c>', clean_param('a><xx >c>', PARAM_TEXT)); // Standard strip_tags() behaviour. 567 $this->assertSame('a', clean_param('a<b', PARAM_TEXT)); 568 $this->assertSame('a>b', clean_param('a>b', PARAM_TEXT)); 569 $this->assertSame('<lang lang="en">a>a</lang>', clean_param('<lang lang="en">a>a</lang>', PARAM_TEXT)); // Standard strip_tags() behaviour. 570 $this->assertSame('a', clean_param('<lang lang="en">a<a</lang>', PARAM_TEXT)); 571 $this->assertSame('<lang lang="en">aa</lang>', clean_param('<lang lang="en">a<br>a</lang>', PARAM_TEXT)); 572 } 573 574 public function test_clean_param_url() { 575 // Test PARAM_URL and PARAM_LOCALURL a bit. 576 $this->assertSame('http://google.com/', clean_param('http://google.com/', PARAM_URL)); 577 $this->assertSame('http://some.very.long.and.silly.domain/with/a/path/', clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_URL)); 578 $this->assertSame('http://localhost/', clean_param('http://localhost/', PARAM_URL)); 579 $this->assertSame('http://0.255.1.1/numericip.php', clean_param('http://0.255.1.1/numericip.php', PARAM_URL)); 580 $this->assertSame('/just/a/path', clean_param('/just/a/path', PARAM_URL)); 581 $this->assertSame('', clean_param('funny:thing', PARAM_URL)); 582 } 583 584 public function test_clean_param_localurl() { 585 global $CFG; 586 587 $this->resetAfterTest(); 588 589 // External, invalid. 590 $this->assertSame('', clean_param('funny:thing', PARAM_LOCALURL)); 591 $this->assertSame('', clean_param('http://google.com/', PARAM_LOCALURL)); 592 $this->assertSame('', clean_param('https://google.com/?test=true', PARAM_LOCALURL)); 593 $this->assertSame('', clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_LOCALURL)); 594 595 // Local absolute. 596 $this->assertSame(clean_param($CFG->wwwroot, PARAM_LOCALURL), $CFG->wwwroot); 597 $this->assertSame($CFG->wwwroot . '/with/something?else=true', 598 clean_param($CFG->wwwroot . '/with/something?else=true', PARAM_LOCALURL)); 599 600 // Local relative. 601 $this->assertSame('/just/a/path', clean_param('/just/a/path', PARAM_LOCALURL)); 602 $this->assertSame('course/view.php?id=3', clean_param('course/view.php?id=3', PARAM_LOCALURL)); 603 604 // Local absolute HTTPS. 605 $httpsroot = str_replace('http:', 'https:', $CFG->wwwroot); 606 $CFG->loginhttps = false; 607 $this->assertSame('', clean_param($httpsroot, PARAM_LOCALURL)); 608 $this->assertSame('', clean_param($httpsroot . '/with/something?else=true', PARAM_LOCALURL)); 609 $CFG->loginhttps = true; 610 $this->assertSame($httpsroot, clean_param($httpsroot, PARAM_LOCALURL)); 611 $this->assertSame($httpsroot . '/with/something?else=true', 612 clean_param($httpsroot . '/with/something?else=true', PARAM_LOCALURL)); 613 614 // Test open redirects are not possible. 615 $CFG->loginhttps = false; 616 $CFG->wwwroot = 'http://www.example.com'; 617 $this->assertSame('', clean_param('http://www.example.com.evil.net/hack.php', PARAM_LOCALURL)); 618 $CFG->loginhttps = true; 619 $this->assertSame('', clean_param('https://www.example.com.evil.net/hack.php', PARAM_LOCALURL)); 620 } 621 622 public function test_clean_param_file() { 623 $this->assertSame('correctfile.txt', clean_param('correctfile.txt', PARAM_FILE)); 624 $this->assertSame('badfile.txt', clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_FILE)); 625 $this->assertSame('..parentdirfile.txt', clean_param('../parentdirfile.txt', PARAM_FILE)); 626 $this->assertSame('....grandparentdirfile.txt', clean_param('../../grandparentdirfile.txt', PARAM_FILE)); 627 $this->assertSame('..winparentdirfile.txt', clean_param('..\winparentdirfile.txt', PARAM_FILE)); 628 $this->assertSame('....wingrandparentdir.txt', clean_param('..\..\wingrandparentdir.txt', PARAM_FILE)); 629 $this->assertSame('myfile.a.b.txt', clean_param('myfile.a.b.txt', PARAM_FILE)); 630 $this->assertSame('myfile..a..b.txt', clean_param('myfile..a..b.txt', PARAM_FILE)); 631 $this->assertSame('myfile.a..b...txt', clean_param('myfile.a..b...txt', PARAM_FILE)); 632 $this->assertSame('myfile.a.txt', clean_param('myfile.a.txt', PARAM_FILE)); 633 $this->assertSame('myfile...txt', clean_param('myfile...txt', PARAM_FILE)); 634 $this->assertSame('...jpg', clean_param('...jpg', PARAM_FILE)); 635 $this->assertSame('.a.b.', clean_param('.a.b.', PARAM_FILE)); 636 $this->assertSame('', clean_param('.', PARAM_FILE)); 637 $this->assertSame('', clean_param('..', PARAM_FILE)); 638 $this->assertSame('...', clean_param('...', PARAM_FILE)); 639 $this->assertSame('. . . .', clean_param('. . . .', PARAM_FILE)); 640 $this->assertSame('dontrtrim.me. .. .. . ', clean_param('dontrtrim.me. .. .. . ', PARAM_FILE)); 641 $this->assertSame(' . .dontltrim.me', clean_param(' . .dontltrim.me', PARAM_FILE)); 642 $this->assertSame('here is a tab.txt', clean_param("here is a tab\t.txt", PARAM_FILE)); 643 $this->assertSame('here is a linebreak.txt', clean_param("here is a line\r\nbreak.txt", PARAM_FILE)); 644 645 // The following behaviours have been maintained although they seem a little odd. 646 $this->assertSame('funnything', clean_param('funny:thing', PARAM_FILE)); 647 $this->assertSame('.currentdirfile.txt', clean_param('./currentdirfile.txt', PARAM_FILE)); 648 $this->assertSame('ctempwindowsfile.txt', clean_param('c:\temp\windowsfile.txt', PARAM_FILE)); 649 $this->assertSame('homeuserlinuxfile.txt', clean_param('/home/user/linuxfile.txt', PARAM_FILE)); 650 $this->assertSame('~myfile.txt', clean_param('~/myfile.txt', PARAM_FILE)); 651 } 652 653 public function test_clean_param_path() { 654 $this->assertSame('correctfile.txt', clean_param('correctfile.txt', PARAM_PATH)); 655 $this->assertSame('bad/file.txt', clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_PATH)); 656 $this->assertSame('/parentdirfile.txt', clean_param('../parentdirfile.txt', PARAM_PATH)); 657 $this->assertSame('/grandparentdirfile.txt', clean_param('../../grandparentdirfile.txt', PARAM_PATH)); 658 $this->assertSame('/winparentdirfile.txt', clean_param('..\winparentdirfile.txt', PARAM_PATH)); 659 $this->assertSame('/wingrandparentdir.txt', clean_param('..\..\wingrandparentdir.txt', PARAM_PATH)); 660 $this->assertSame('funnything', clean_param('funny:thing', PARAM_PATH)); 661 $this->assertSame('./here', clean_param('./././here', PARAM_PATH)); 662 $this->assertSame('./currentdirfile.txt', clean_param('./currentdirfile.txt', PARAM_PATH)); 663 $this->assertSame('c/temp/windowsfile.txt', clean_param('c:\temp\windowsfile.txt', PARAM_PATH)); 664 $this->assertSame('/home/user/linuxfile.txt', clean_param('/home/user/linuxfile.txt', PARAM_PATH)); 665 $this->assertSame('/home../user ./.linuxfile.txt', clean_param('/home../user ./.linuxfile.txt', PARAM_PATH)); 666 $this->assertSame('~/myfile.txt', clean_param('~/myfile.txt', PARAM_PATH)); 667 $this->assertSame('~/myfile.txt', clean_param('~/../myfile.txt', PARAM_PATH)); 668 $this->assertSame('/..b../.../myfile.txt', clean_param('/..b../.../myfile.txt', PARAM_PATH)); 669 $this->assertSame('..b../.../myfile.txt', clean_param('..b../.../myfile.txt', PARAM_PATH)); 670 $this->assertSame('/super/slashes/', clean_param('/super//slashes///', PARAM_PATH)); 671 } 672 673 public function test_clean_param_username() { 674 global $CFG; 675 $currentstatus = $CFG->extendedusernamechars; 676 677 // Run tests with extended character == false;. 678 $CFG->extendedusernamechars = false; 679 $this->assertSame('johndoe123', clean_param('johndoe123', PARAM_USERNAME) ); 680 $this->assertSame('john.doe', clean_param('john.doe', PARAM_USERNAME)); 681 $this->assertSame('john-doe', clean_param('john-doe', PARAM_USERNAME)); 682 $this->assertSame('john-doe', clean_param('john- doe', PARAM_USERNAME)); 683 $this->assertSame('john_doe', clean_param('john_doe', PARAM_USERNAME)); 684 $this->assertSame('john@doe', clean_param('john@doe', PARAM_USERNAME)); 685 $this->assertSame('johndoe', clean_param('john~doe', PARAM_USERNAME)); 686 $this->assertSame('johndoe', clean_param('john´doe', PARAM_USERNAME)); 687 $this->assertSame(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john_'); 688 $this->assertSame(clean_param(' john# $%&()+_^ ', PARAM_USERNAME), 'john_'); 689 $this->assertSame(clean_param('john#$%&() ', PARAM_USERNAME), 'john'); 690 $this->assertSame('johnd', clean_param('JOHNdóé ', PARAM_USERNAME)); 691 $this->assertSame(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýá?ý??doe ', PARAM_USERNAME), 'john.-_a_x-d@_doe'); 692 693 // Test success condition, if extendedusernamechars == ENABLE;. 694 $CFG->extendedusernamechars = true; 695 $this->assertSame('john_doe', clean_param('john_doe', PARAM_USERNAME)); 696 $this->assertSame('john@doe', clean_param('john@doe', PARAM_USERNAME)); 697 $this->assertSame(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john# $%&()+_^'); 698 $this->assertSame(clean_param(' john# $%&()+_^ ', PARAM_USERNAME), 'john# $%&()+_^'); 699 $this->assertSame('john~doe', clean_param('john~doe', PARAM_USERNAME)); 700 $this->assertSame('john´doe', clean_param('joHN´doe', PARAM_USERNAME)); 701 $this->assertSame('johndoe', clean_param('johnDOE', PARAM_USERNAME)); 702 $this->assertSame('johndóé', clean_param('johndóé ', PARAM_USERNAME)); 703 704 $CFG->extendedusernamechars = $currentstatus; 705 } 706 707 public function test_clean_param_stringid() { 708 // Test string identifiers validation. 709 // Valid strings. 710 $this->assertSame('validstring', clean_param('validstring', PARAM_STRINGID)); 711 $this->assertSame('mod/foobar:valid_capability', clean_param('mod/foobar:valid_capability', PARAM_STRINGID)); 712 $this->assertSame('CZ', clean_param('CZ', PARAM_STRINGID)); 713 $this->assertSame('application/vnd.ms-powerpoint', clean_param('application/vnd.ms-powerpoint', PARAM_STRINGID)); 714 $this->assertSame('grade2', clean_param('grade2', PARAM_STRINGID)); 715 // Invalid strings. 716 $this->assertSame('', clean_param('trailing ', PARAM_STRINGID)); 717 $this->assertSame('', clean_param('space bar', PARAM_STRINGID)); 718 $this->assertSame('', clean_param('0numeric', PARAM_STRINGID)); 719 $this->assertSame('', clean_param('*', PARAM_STRINGID)); 720 $this->assertSame('', clean_param(' ', PARAM_STRINGID)); 721 } 722 723 public function test_clean_param_timezone() { 724 // Test timezone validation. 725 $testvalues = array ( 726 'America/Jamaica' => 'America/Jamaica', 727 'America/Argentina/Cordoba' => 'America/Argentina/Cordoba', 728 'America/Port-au-Prince' => 'America/Port-au-Prince', 729 'America/Argentina/Buenos_Aires' => 'America/Argentina/Buenos_Aires', 730 'PST8PDT' => 'PST8PDT', 731 'Wrong.Value' => '', 732 'Wrong/.Value' => '', 733 'Wrong(Value)' => '', 734 '0' => '0', 735 '0.0' => '0.0', 736 '0.5' => '0.5', 737 '9.0' => '9.0', 738 '-9.0' => '-9.0', 739 '+9.0' => '+9.0', 740 '9.5' => '9.5', 741 '-9.5' => '-9.5', 742 '+9.5' => '+9.5', 743 '12.0' => '12.0', 744 '-12.0' => '-12.0', 745 '+12.0' => '+12.0', 746 '12.5' => '12.5', 747 '-12.5' => '-12.5', 748 '+12.5' => '+12.5', 749 '13.0' => '13.0', 750 '-13.0' => '-13.0', 751 '+13.0' => '+13.0', 752 '13.5' => '', 753 '+13.5' => '', 754 '-13.5' => '', 755 '0.2' => ''); 756 757 foreach ($testvalues as $testvalue => $expectedvalue) { 758 $actualvalue = clean_param($testvalue, PARAM_TIMEZONE); 759 $this->assertEquals($expectedvalue, $actualvalue); 760 } 761 } 762 763 public function test_validate_param() { 764 try { 765 $param = validate_param('11a', PARAM_INT); 766 $this->fail('invalid_parameter_exception expected'); 767 } catch (moodle_exception $ex) { 768 $this->assertInstanceOf('invalid_parameter_exception', $ex); 769 } 770 771 $param = validate_param('11', PARAM_INT); 772 $this->assertSame(11, $param); 773 774 try { 775 $param = validate_param(null, PARAM_INT, false); 776 $this->fail('invalid_parameter_exception expected'); 777 } catch (moodle_exception $ex) { 778 $this->assertInstanceOf('invalid_parameter_exception', $ex); 779 } 780 781 $param = validate_param(null, PARAM_INT, true); 782 $this->assertSame(null, $param); 783 784 try { 785 $param = validate_param(array(), PARAM_INT); 786 $this->fail('invalid_parameter_exception expected'); 787 } catch (moodle_exception $ex) { 788 $this->assertInstanceOf('invalid_parameter_exception', $ex); 789 } 790 try { 791 $param = validate_param(new stdClass, PARAM_INT); 792 $this->fail('invalid_parameter_exception expected'); 793 } catch (moodle_exception $ex) { 794 $this->assertInstanceOf('invalid_parameter_exception', $ex); 795 } 796 797 $param = validate_param('1.0', PARAM_FLOAT); 798 $this->assertSame(1.0, $param); 799 800 // Make sure valid floats do not cause exception. 801 validate_param(1.0, PARAM_FLOAT); 802 validate_param(10, PARAM_FLOAT); 803 validate_param('0', PARAM_FLOAT); 804 validate_param('119813454.545464564564546564545646556564465465456465465465645645465645645645', PARAM_FLOAT); 805 validate_param('011.1', PARAM_FLOAT); 806 validate_param('11', PARAM_FLOAT); 807 validate_param('+.1', PARAM_FLOAT); 808 validate_param('-.1', PARAM_FLOAT); 809 validate_param('1e10', PARAM_FLOAT); 810 validate_param('.1e+10', PARAM_FLOAT); 811 validate_param('1E-1', PARAM_FLOAT); 812 813 try { 814 $param = validate_param('1,2', PARAM_FLOAT); 815 $this->fail('invalid_parameter_exception expected'); 816 } catch (moodle_exception $ex) { 817 $this->assertInstanceOf('invalid_parameter_exception', $ex); 818 } 819 try { 820 $param = validate_param('', PARAM_FLOAT); 821 $this->fail('invalid_parameter_exception expected'); 822 } catch (moodle_exception $ex) { 823 $this->assertInstanceOf('invalid_parameter_exception', $ex); 824 } 825 try { 826 $param = validate_param('.', PARAM_FLOAT); 827 $this->fail('invalid_parameter_exception expected'); 828 } catch (moodle_exception $ex) { 829 $this->assertInstanceOf('invalid_parameter_exception', $ex); 830 } 831 try { 832 $param = validate_param('e10', PARAM_FLOAT); 833 $this->fail('invalid_parameter_exception expected'); 834 } catch (moodle_exception $ex) { 835 $this->assertInstanceOf('invalid_parameter_exception', $ex); 836 } 837 try { 838 $param = validate_param('abc', PARAM_FLOAT); 839 $this->fail('invalid_parameter_exception expected'); 840 } catch (moodle_exception $ex) { 841 $this->assertInstanceOf('invalid_parameter_exception', $ex); 842 } 843 } 844 845 public function test_shorten_text_no_tags_already_short_enough() { 846 // ......12345678901234567890123456. 847 $text = "short text already no tags"; 848 $this->assertSame($text, shorten_text($text)); 849 } 850 851 public function test_shorten_text_with_tags_already_short_enough() { 852 // .........123456...7890....12345678.......901234567. 853 $text = "<p>short <b>text</b> already</p><p>with tags</p>"; 854 $this->assertSame($text, shorten_text($text)); 855 } 856 857 public function test_shorten_text_no_tags_needs_shortening() { 858 // Default truncation is after 30 chars, but allowing 3 for the final '...'. 859 // ......12345678901234567890123456789023456789012345678901234. 860 $text = "long text without any tags blah de blah blah blah what"; 861 $this->assertSame('long text without any tags ...', shorten_text($text)); 862 } 863 864 public function test_shorten_text_with_tags_needs_shortening() { 865 // .......................................123456789012345678901234567890... 866 $text = "<div class='frog'><p><blockquote>Long text with tags that will ". 867 "be chopped off but <b>should be added back again</b></blockquote></p></div>"; 868 $this->assertEquals("<div class='frog'><p><blockquote>Long text with " . 869 "tags that ...</blockquote></p></div>", shorten_text($text)); 870 } 871 872 public function test_shorten_text_with_tags_and_html_comment() { 873 $text = "<div class='frog'><p><blockquote><!--[if !IE]><!-->Long text with ". 874 "tags that will<!--<![endif]--> ". 875 "be chopped off but <b>should be added back again</b></blockquote></p></div>"; 876 $this->assertEquals("<div class='frog'><p><blockquote><!--[if !IE]><!-->Long text with " . 877 "tags that ...<!--<![endif]--></blockquote></p></div>", shorten_text($text)); 878 } 879 880 public function test_shorten_text_with_entities() { 881 // Remember to allow 3 chars for the final '...'. 882 // ......123456789012345678901234567_____890... 883 $text = "some text which shouldn't break there"; 884 $this->assertSame("some text which shouldn't ...", shorten_text($text, 31)); 885 $this->assertSame("some text which shouldn't ...", shorten_text($text, 30)); 886 $this->assertSame("some text which shouldn't ...", shorten_text($text, 29)); 887 } 888 889 public function test_shorten_text_known_tricky_case() { 890 // This case caused a bug up to 1.9.5 891 // ..........123456789012345678901234567890123456789.....0_____1___2___... 892 $text = "<h3>standard 'break-out' sub groups in TGs?</h3> <<There are several"; 893 $this->assertSame("<h3>standard 'break-out' sub groups in ...</h3>", 894 shorten_text($text, 41)); 895 $this->assertSame("<h3>standard 'break-out' sub groups in TGs?...</h3>", 896 shorten_text($text, 42)); 897 $this->assertSame("<h3>standard 'break-out' sub groups in TGs?</h3> ...", 898 shorten_text($text, 43)); 899 } 900 901 public function test_shorten_text_no_spaces() { 902 // ..........123456789. 903 $text = "<h1>123456789</h1>"; // A string with no convenient breaks. 904 $this->assertSame("<h1>12345...</h1>", shorten_text($text, 8)); 905 } 906 907 public function test_shorten_text_utf8_european() { 908 // Text without tags. 909 // ......123456789012345678901234567. 910 $text = "Žluťoučký koníček přeskočil"; 911 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 912 $this->assertSame("Žluťoučký koníče...", shorten_text($text, 19, true)); 913 $this->assertSame("Žluťoučký ...", shorten_text($text, 19, false)); 914 // And try it with 2-less (that are, in bytes, the middle of a sequence). 915 $this->assertSame("Žluťoučký koní...", shorten_text($text, 17, true)); 916 $this->assertSame("Žluťoučký ...", shorten_text($text, 17, false)); 917 918 // .........123456789012345678...901234567....89012345. 919 $text = "<p>Žluťoučký koníček <b>přeskočil</b> potůček</p>"; 920 $this->assertSame($text, shorten_text($text, 60)); 921 $this->assertSame("<p>Žluťoučký koníček ...</p>", shorten_text($text, 21)); 922 $this->assertSame("<p>Žluťoučký koníče...</p>", shorten_text($text, 19, true)); 923 $this->assertSame("<p>Žluťoučký ...</p>", shorten_text($text, 19, false)); 924 // And try it with 2 fewer (that are, in bytes, the middle of a sequence). 925 $this->assertSame("<p>Žluťoučký koní...</p>", shorten_text($text, 17, true)); 926 $this->assertSame("<p>Žluťoučký ...</p>", shorten_text($text, 17, false)); 927 // And try over one tag (start/end), it does proper text len. 928 $this->assertSame("<p>Žluťoučký koníček <b>př...</b></p>", shorten_text($text, 23, true)); 929 $this->assertSame("<p>Žluťoučký koníček <b>přeskočil</b> pot...</p>", shorten_text($text, 34, true)); 930 // And in the middle of one tag. 931 $this->assertSame("<p>Žluťoučký koníček <b>přeskočil...</b></p>", shorten_text($text, 30, true)); 932 } 933 934 public function test_shorten_text_utf8_oriental() { 935 // Japanese 936 // text without tags 937 // ......123456789012345678901234. 938 $text = '言語設定言語設定abcdefghijkl'; 939 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 940 $this->assertSame("言語設定言語...", shorten_text($text, 9, true)); 941 $this->assertSame("言語設定言語...", shorten_text($text, 9, false)); 942 $this->assertSame("言語設定言語設定ab...", shorten_text($text, 13, true)); 943 $this->assertSame("言語設定言語設定...", shorten_text($text, 13, false)); 944 945 // Chinese 946 // text without tags 947 // ......123456789012345678901234. 948 $text = '简体中文简体中文abcdefghijkl'; 949 $this->assertSame($text, shorten_text($text)); // 30 chars by default. 950 $this->assertSame("简体中文简体...", shorten_text($text, 9, true)); 951 $this->assertSame("简体中文简体...", shorten_text($text, 9, false)); 952 $this->assertSame("简体中文简体中文ab...", shorten_text($text, 13, true)); 953 $this->assertSame("简体中文简体中文...", shorten_text($text, 13, false)); 954 } 955 956 public function test_shorten_text_multilang() { 957 // This is not necessaryily specific to multilang. The issue is really 958 // tags with attributes, where before we were generating invalid HTML 959 // output like shorten_text('<span id="x" class="y">A</span> B', 1) 960 // returning '<span id="x" ...</span>'. It is just that multilang 961 // requires the sort of HTML that is quite likely to trigger this. 962 // ........................................1... 963 $text = '<span lang="en" class="multilang">A</span>' . 964 '<span lang="fr" class="multilang">B</span>'; 965 $this->assertSame('<span lang="en" class="multilang">...</span>', 966 shorten_text($text, 1)); 967 } 968 969 public function test_usergetdate() { 970 global $USER, $CFG, $DB; 971 $this->resetAfterTest(); 972 973 $this->setAdminUser(); 974 975 $USER->timezone = 2;// Set the timezone to a known state. 976 977 $ts = 1261540267; // The time this function was created. 978 979 $arr = usergetdate($ts, 1); // Specify the timezone as an argument. 980 $arr = array_values($arr); 981 982 list($seconds, $minutes, $hours, $mday, $wday, $mon, $year, $yday, $weekday, $month) = $arr; 983 $this->assertSame(7, $seconds); 984 $this->assertSame(51, $minutes); 985 $this->assertSame(4, $hours); 986 $this->assertSame(23, $mday); 987 $this->assertSame(3, $wday); 988 $this->assertSame(12, $mon); 989 $this->assertSame(2009, $year); 990 $this->assertSame(356, $yday); 991 $this->assertSame('Wednesday', $weekday); 992 $this->assertSame('December', $month); 993 $arr = usergetdate($ts); // Gets the timezone from the $USER object. 994 $arr = array_values($arr); 995 996 list($seconds, $minutes, $hours, $mday, $wday, $mon, $year, $yday, $weekday, $month) = $arr; 997 $this->assertSame(7, $seconds); 998 $this->assertSame(51, $minutes); 999 $this->assertSame(5, $hours); 1000 $this->assertSame(23, $mday); 1001 $this->assertSame(3, $wday); 1002 $this->assertSame(12, $mon); 1003 $this->assertSame(2009, $year); 1004 $this->assertSame(356, $yday); 1005 $this->assertSame('Wednesday', $weekday); 1006 $this->assertSame('December', $month); 1007 } 1008 1009 public function test_mark_user_preferences_changed() { 1010 $this->resetAfterTest(); 1011 $otheruser = $this->getDataGenerator()->create_user(); 1012 $otheruserid = $otheruser->id; 1013 1014 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1015 mark_user_preferences_changed($otheruserid); 1016 1017 $this->assertEquals(get_cache_flag('userpreferenceschanged', $otheruserid, time()-10), 1); 1018 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1019 } 1020 1021 public function test_check_user_preferences_loaded() { 1022 global $DB; 1023 $this->resetAfterTest(); 1024 1025 $otheruser = $this->getDataGenerator()->create_user(); 1026 $otheruserid = $otheruser->id; 1027 1028 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1029 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1030 1031 $user = new stdClass(); 1032 $user->id = $otheruserid; 1033 1034 // Load. 1035 check_user_preferences_loaded($user); 1036 $this->assertTrue(isset($user->preference)); 1037 $this->assertTrue(is_array($user->preference)); 1038 $this->assertArrayHasKey('_lastloaded', $user->preference); 1039 $this->assertCount(1, $user->preference); 1040 1041 // Add preference via direct call. 1042 $DB->insert_record('user_preferences', array('name'=>'xxx', 'value'=>'yyy', 'userid'=>$user->id)); 1043 1044 // No cache reload yet. 1045 check_user_preferences_loaded($user); 1046 $this->assertCount(1, $user->preference); 1047 1048 // Forced reloading of cache. 1049 unset($user->preference); 1050 check_user_preferences_loaded($user); 1051 $this->assertCount(2, $user->preference); 1052 $this->assertSame('yyy', $user->preference['xxx']); 1053 1054 // Add preference via direct call. 1055 $DB->insert_record('user_preferences', array('name'=>'aaa', 'value'=>'bbb', 'userid'=>$user->id)); 1056 1057 // Test timeouts and modifications from different session. 1058 set_cache_flag('userpreferenceschanged', $user->id, 1, time() + 1000); 1059 $user->preference['_lastloaded'] = $user->preference['_lastloaded'] - 20; 1060 check_user_preferences_loaded($user); 1061 $this->assertCount(2, $user->preference); 1062 check_user_preferences_loaded($user, 10); 1063 $this->assertCount(3, $user->preference); 1064 $this->assertSame('bbb', $user->preference['aaa']); 1065 set_cache_flag('userpreferenceschanged', $user->id, null); 1066 } 1067 1068 public function test_set_user_preference() { 1069 global $DB, $USER; 1070 $this->resetAfterTest(); 1071 1072 $this->setAdminUser(); 1073 1074 $otheruser = $this->getDataGenerator()->create_user(); 1075 $otheruserid = $otheruser->id; 1076 1077 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1078 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1079 1080 $user = new stdClass(); 1081 $user->id = $otheruserid; 1082 1083 set_user_preference('aaa', 'bbb', $otheruserid); 1084 $this->assertSame('bbb', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'aaa'))); 1085 $this->assertSame('bbb', get_user_preferences('aaa', null, $otheruserid)); 1086 1087 set_user_preference('xxx', 'yyy', $user); 1088 $this->assertSame('yyy', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx'))); 1089 $this->assertSame('yyy', get_user_preferences('xxx', null, $otheruserid)); 1090 $this->assertTrue(is_array($user->preference)); 1091 $this->assertSame('bbb', $user->preference['aaa']); 1092 $this->assertSame('yyy', $user->preference['xxx']); 1093 1094 set_user_preference('xxx', null, $user); 1095 $this->assertFalse($DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx'))); 1096 $this->assertNull(get_user_preferences('xxx', null, $otheruserid)); 1097 1098 set_user_preference('ooo', true, $user); 1099 $prefs = get_user_preferences(null, null, $otheruserid); 1100 $this->assertSame($user->preference['aaa'], $prefs['aaa']); 1101 $this->assertSame($user->preference['ooo'], $prefs['ooo']); 1102 $this->assertSame('1', $prefs['ooo']); 1103 1104 set_user_preference('null', 0, $user); 1105 $this->assertSame('0', get_user_preferences('null', null, $otheruserid)); 1106 1107 $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid)); 1108 1109 $DB->delete_records('user_preferences', array('userid'=>$otheruserid)); 1110 set_cache_flag('userpreferenceschanged', $otheruserid, null); 1111 1112 // Test $USER default. 1113 set_user_preference('_test_user_preferences_pref', 'ok'); 1114 $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']); 1115 unset_user_preference('_test_user_preferences_pref'); 1116 $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref'])); 1117 1118 // Test 1333 char values (no need for unicode, there are already tests for that in DB tests). 1119 $longvalue = str_repeat('a', 1333); 1120 set_user_preference('_test_long_user_preference', $longvalue); 1121 $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference')); 1122 $this->assertEquals($longvalue, 1123 $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference'))); 1124 1125 // Test > 1333 char values, coding_exception expected. 1126 $longvalue = str_repeat('a', 1334); 1127 try { 1128 set_user_preference('_test_long_user_preference', $longvalue); 1129 $this->fail('Exception expected - longer than 1333 chars not allowed as preference value'); 1130 } catch (moodle_exception $ex) { 1131 $this->assertInstanceOf('coding_exception', $ex); 1132 } 1133 1134 // Test invalid params. 1135 try { 1136 set_user_preference('_test_user_preferences_pref', array()); 1137 $this->fail('Exception expected - array not valid preference value'); 1138 } catch (moodle_exception $ex) { 1139 $this->assertInstanceOf('coding_exception', $ex); 1140 } 1141 try { 1142 set_user_preference('_test_user_preferences_pref', new stdClass); 1143 $this->fail('Exception expected - class not valid preference value'); 1144 } catch (moodle_exception $ex) { 1145 $this->assertInstanceOf('coding_exception', $ex); 1146 } 1147 try { 1148 set_user_preference('_test_user_preferences_pref', 1, array('xx' => 1)); 1149 $this->fail('Exception expected - user instance expected'); 1150 } catch (moodle_exception $ex) { 1151 $this->assertInstanceOf('coding_exception', $ex); 1152 } 1153 try { 1154 set_user_preference('_test_user_preferences_pref', 1, 'abc'); 1155 $this->fail('Exception expected - user instance expected'); 1156 } catch (moodle_exception $ex) { 1157 $this->assertInstanceOf('coding_exception', $ex); 1158 } 1159 try { 1160 set_user_preference('', 1); 1161 $this->fail('Exception expected - invalid name accepted'); 1162 } catch (moodle_exception $ex) { 1163 $this->assertInstanceOf('coding_exception', $ex); 1164 } 1165 try { 1166 set_user_preference('1', 1); 1167 $this->fail('Exception expected - invalid name accepted'); 1168 } catch (moodle_exception $ex) { 1169 $this->assertInstanceOf('coding_exception', $ex); 1170 } 1171 } 1172 1173 public function test_get_extra_user_fields() { 1174 global $CFG, $USER, $DB; 1175 $this->resetAfterTest(); 1176 1177 $this->setAdminUser(); 1178 1179 // It would be really nice if there were a way to 'mock' has_capability 1180 // checks (either to return true or false) but as there is not, this 1181 // test doesn't test the capability check. Presumably, anyone running 1182 // unit tests will have the capability. 1183 $context = context_system::instance(); 1184 1185 // No fields. 1186 $CFG->showuseridentity = ''; 1187 $this->assertEquals(array(), get_extra_user_fields($context)); 1188 1189 // One field. 1190 $CFG->showuseridentity = 'frog'; 1191 $this->assertEquals(array('frog'), get_extra_user_fields($context)); 1192 1193 // Two fields. 1194 $CFG->showuseridentity = 'frog,zombie'; 1195 $this->assertEquals(array('frog', 'zombie'), get_extra_user_fields($context)); 1196 1197 // No fields, except. 1198 $CFG->showuseridentity = ''; 1199 $this->assertEquals(array(), get_extra_user_fields($context, array('frog'))); 1200 1201 // One field. 1202 $CFG->showuseridentity = 'frog'; 1203 $this->assertEquals(array(), get_extra_user_fields($context, array('frog'))); 1204 1205 // Two fields. 1206 $CFG->showuseridentity = 'frog,zombie'; 1207 $this->assertEquals(array('zombie'), get_extra_user_fields($context, array('frog'))); 1208 } 1209 1210 public function test_get_extra_user_fields_sql() { 1211 global $CFG, $USER, $DB; 1212 $this->resetAfterTest(); 1213 1214 $this->setAdminUser(); 1215 1216 $context = context_system::instance(); 1217 1218 // No fields. 1219 $CFG->showuseridentity = ''; 1220 $this->assertSame('', get_extra_user_fields_sql($context)); 1221 1222 // One field. 1223 $CFG->showuseridentity = 'frog'; 1224 $this->assertSame(', frog', get_extra_user_fields_sql($context)); 1225 1226 // Two fields with table prefix. 1227 $CFG->showuseridentity = 'frog,zombie'; 1228 $this->assertSame(', u1.frog, u1.zombie', get_extra_user_fields_sql($context, 'u1')); 1229 1230 // Two fields with field prefix. 1231 $CFG->showuseridentity = 'frog,zombie'; 1232 $this->assertSame(', frog AS u_frog, zombie AS u_zombie', 1233 get_extra_user_fields_sql($context, '', 'u_')); 1234 1235 // One field excluded. 1236 $CFG->showuseridentity = 'frog'; 1237 $this->assertSame('', get_extra_user_fields_sql($context, '', '', array('frog'))); 1238 1239 // Two fields, one excluded, table+field prefix. 1240 $CFG->showuseridentity = 'frog,zombie'; 1241 $this->assertEquals(', u1.zombie AS u_zombie', 1242 get_extra_user_fields_sql($context, 'u1', 'u_', array('frog'))); 1243 } 1244 1245 /** 1246 * Test some critical TZ/DST. 1247 * 1248 * This method tests some special TZ/DST combinations that were fixed 1249 * by MDL-38999. The tests are done by comparing the results of the 1250 * output using Moodle TZ/DST support and PHP native one. 1251 * 1252 * Note: If you don't trust PHP TZ/DST support, can verify the 1253 * harcoded expectations below with: 1254 * http://www.tools4noobs.com/online_tools/unix_timestamp_to_datetime/ 1255 */ 1256 public function test_some_moodle_special_dst() { 1257 $stamp = 1365386400; // 2013/04/08 02:00:00 GMT/UTC. 1258 1259 // In Europe/Tallinn it was 2013/04/08 05:00:00. 1260 $expectation = '2013/04/08 05:00:00'; 1261 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1262 $phpdt->setTimezone(new DateTimeZone('Europe/Tallinn')); 1263 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1264 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'Europe/Tallinn', false); // Moodle result. 1265 $this->assertSame($expectation, $phpres); 1266 $this->assertSame($expectation, $moodleres); 1267 1268 // In St. Johns it was 2013/04/07 23:30:00. 1269 $expectation = '2013/04/07 23:30:00'; 1270 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1271 $phpdt->setTimezone(new DateTimeZone('America/St_Johns')); 1272 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1273 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'America/St_Johns', false); // Moodle result. 1274 $this->assertSame($expectation, $phpres); 1275 $this->assertSame($expectation, $moodleres); 1276 1277 $stamp = 1383876000; // 2013/11/08 02:00:00 GMT/UTC. 1278 1279 // In Europe/Tallinn it was 2013/11/08 04:00:00. 1280 $expectation = '2013/11/08 04:00:00'; 1281 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1282 $phpdt->setTimezone(new DateTimeZone('Europe/Tallinn')); 1283 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1284 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'Europe/Tallinn', false); // Moodle result. 1285 $this->assertSame($expectation, $phpres); 1286 $this->assertSame($expectation, $moodleres); 1287 1288 // In St. Johns it was 2013/11/07 22:30:00. 1289 $expectation = '2013/11/07 22:30:00'; 1290 $phpdt = DateTime::createFromFormat('U', $stamp, new DateTimeZone('UTC')); 1291 $phpdt->setTimezone(new DateTimeZone('America/St_Johns')); 1292 $phpres = $phpdt->format('Y/m/d H:i:s'); // PHP result. 1293 $moodleres = userdate($stamp, '%Y/%m/%d %H:%M:%S', 'America/St_Johns', false); // Moodle result. 1294 $this->assertSame($expectation, $phpres); 1295 $this->assertSame($expectation, $moodleres); 1296 } 1297 1298 public function test_userdate() { 1299 global $USER, $CFG, $DB; 1300 $this->resetAfterTest(); 1301 1302 $this->setAdminUser(); 1303 1304 $testvalues = array( 1305 array( 1306 'time' => '1309514400', 1307 'usertimezone' => 'America/Moncton', 1308 'timezone' => '0.0', // No dst offset. 1309 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM' 1310 ), 1311 array( 1312 'time' => '1309514400', 1313 'usertimezone' => 'America/Moncton', 1314 'timezone' => '99', // Dst offset and timezone offset. 1315 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM' 1316 ), 1317 array( 1318 'time' => '1309514400', 1319 'usertimezone' => 'America/Moncton', 1320 'timezone' => 'America/Moncton', // Dst offset and timezone offset. 1321 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM' 1322 ), 1323 array( 1324 'time' => '1293876000 ', 1325 'usertimezone' => 'America/Moncton', 1326 'timezone' => '0.0', // No dst offset. 1327 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM' 1328 ), 1329 array( 1330 'time' => '1293876000 ', 1331 'usertimezone' => 'America/Moncton', 1332 'timezone' => '99', // No dst offset in jan, so just timezone offset. 1333 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM' 1334 ), 1335 array( 1336 'time' => '1293876000 ', 1337 'usertimezone' => 'America/Moncton', 1338 'timezone' => 'America/Moncton', // No dst offset in jan. 1339 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM' 1340 ), 1341 array( 1342 'time' => '1293876000 ', 1343 'usertimezone' => '2', 1344 'timezone' => '99', // Take user timezone. 1345 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM' 1346 ), 1347 array( 1348 'time' => '1293876000 ', 1349 'usertimezone' => '-2', 1350 'timezone' => '99', // Take user timezone. 1351 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM' 1352 ), 1353 array( 1354 'time' => '1293876000 ', 1355 'usertimezone' => '-10', 1356 'timezone' => '2', // Take this timezone. 1357 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM' 1358 ), 1359 array( 1360 'time' => '1293876000 ', 1361 'usertimezone' => '-10', 1362 'timezone' => '-2', // Take this timezone. 1363 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM' 1364 ), 1365 array( 1366 'time' => '1293876000 ', 1367 'usertimezone' => '-10', 1368 'timezone' => 'random/time', // This should show server time. 1369 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM' 1370 ), 1371 array( 1372 'time' => '1293876000 ', 1373 'usertimezone' => '20', // Fallback to server time zone. 1374 'timezone' => '99', // This should show user time. 1375 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM' 1376 ), 1377 ); 1378 1379 // Set default timezone to Australia/Perth, else time calculated 1380 // will not match expected values. 1381 $this->setTimezone(99, 'Australia/Perth'); 1382 1383 foreach ($testvalues as $vals) { 1384 $USER->timezone = $vals['usertimezone']; 1385 $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']); 1386 1387 // On different systems case of AM PM changes so compare case insensitive. 1388 $vals['expectedoutput'] = core_text::strtolower($vals['expectedoutput']); 1389 $actualoutput = core_text::strtolower($actualoutput); 1390 1391 $this->assertSame($vals['expectedoutput'], $actualoutput, 1392 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput} \ndata: " . var_export($vals, true)); 1393 } 1394 } 1395 1396 /** 1397 * Make sure the DST changes happen at the right time in Moodle. 1398 */ 1399 public function test_dst_changes() { 1400 // DST switching in Prague. 1401 // From 2AM to 3AM in 1989. 1402 $date = new DateTime('1989-03-26T01:59:00+01:00'); 1403 $this->assertSame('Sunday, 26 March 1989, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1404 $date = new DateTime('1989-03-26T02:01:00+01:00'); 1405 $this->assertSame('Sunday, 26 March 1989, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1406 // From 3AM to 2AM in 1989 - not the same as the west Europe. 1407 $date = new DateTime('1989-09-24T01:59:00+01:00'); 1408 $this->assertSame('Sunday, 24 September 1989, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1409 $date = new DateTime('1989-09-24T02:01:00+01:00'); 1410 $this->assertSame('Sunday, 24 September 1989, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1411 // From 2AM to 3AM in 2014. 1412 $date = new DateTime('2014-03-30T01:59:00+01:00'); 1413 $this->assertSame('Sunday, 30 March 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1414 $date = new DateTime('2014-03-30T02:01:00+01:00'); 1415 $this->assertSame('Sunday, 30 March 2014, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1416 // From 3AM to 2AM in 2014. 1417 $date = new DateTime('2014-10-26T01:59:00+01:00'); 1418 $this->assertSame('Sunday, 26 October 2014, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1419 $date = new DateTime('2014-10-26T02:01:00+01:00'); 1420 $this->assertSame('Sunday, 26 October 2014, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1421 // From 2AM to 3AM in 2020. 1422 $date = new DateTime('2020-03-29T01:59:00+01:00'); 1423 $this->assertSame('Sunday, 29 March 2020, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1424 $date = new DateTime('2020-03-29T02:01:00+01:00'); 1425 $this->assertSame('Sunday, 29 March 2020, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1426 // From 3AM to 2AM in 2020. 1427 $date = new DateTime('2020-10-25T01:59:00+01:00'); 1428 $this->assertSame('Sunday, 25 October 2020, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1429 $date = new DateTime('2020-10-25T02:01:00+01:00'); 1430 $this->assertSame('Sunday, 25 October 2020, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Europe/Prague')); 1431 1432 // DST switching in NZ. 1433 // From 3AM to 2AM in 2015. 1434 $date = new DateTime('2015-04-05T02:59:00+13:00'); 1435 $this->assertSame('Sunday, 5 April 2015, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland')); 1436 $date = new DateTime('2015-04-05T03:01:00+13:00'); 1437 $this->assertSame('Sunday, 5 April 2015, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland')); 1438 // From 2AM to 3AM in 2009. 1439 $date = new DateTime('2015-09-27T01:59:00+12:00'); 1440 $this->assertSame('Sunday, 27 September 2015, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland')); 1441 $date = new DateTime('2015-09-27T02:01:00+12:00'); 1442 $this->assertSame('Sunday, 27 September 2015, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Pacific/Auckland')); 1443 1444 // DST switching in Perth. 1445 // From 3AM to 2AM in 2009. 1446 $date = new DateTime('2008-03-30T01:59:00+08:00'); 1447 $this->assertSame('Sunday, 30 March 2008, 02:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth')); 1448 $date = new DateTime('2008-03-30T02:01:00+08:00'); 1449 $this->assertSame('Sunday, 30 March 2008, 02:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth')); 1450 // From 2AM to 3AM in 2009. 1451 $date = new DateTime('2008-10-26T01:59:00+08:00'); 1452 $this->assertSame('Sunday, 26 October 2008, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth')); 1453 $date = new DateTime('2008-10-26T02:01:00+08:00'); 1454 $this->assertSame('Sunday, 26 October 2008, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'Australia/Perth')); 1455 1456 // DST switching in US. 1457 // From 2AM to 3AM in 2014. 1458 $date = new DateTime('2014-03-09T01:59:00-05:00'); 1459 $this->assertSame('Sunday, 9 March 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York')); 1460 $date = new DateTime('2014-03-09T02:01:00-05:00'); 1461 $this->assertSame('Sunday, 9 March 2014, 03:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York')); 1462 // From 3AM to 2AM in 2014. 1463 $date = new DateTime('2014-11-02T01:59:00-04:00'); 1464 $this->assertSame('Sunday, 2 November 2014, 01:59', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York')); 1465 $date = new DateTime('2014-11-02T02:01:00-04:00'); 1466 $this->assertSame('Sunday, 2 November 2014, 01:01', userdate($date->getTimestamp(), '%A, %d %B %Y, %H:%M', 'America/New_York')); 1467 } 1468 1469 public function test_make_timestamp() { 1470 global $USER, $CFG, $DB; 1471 $this->resetAfterTest(); 1472 1473 $this->setAdminUser(); 1474 1475 $testvalues = array( 1476 array( 1477 'usertimezone' => 'America/Moncton', 1478 'year' => '2011', 1479 'month' => '7', 1480 'day' => '1', 1481 'hour' => '10', 1482 'minutes' => '00', 1483 'seconds' => '00', 1484 'timezone' => '0.0', 1485 'applydst' => false, // No dst offset. 1486 'expectedoutput' => '1309514400' // 6pm at UTC+0. 1487 ), 1488 array( 1489 'usertimezone' => 'America/Moncton', 1490 'year' => '2011', 1491 'month' => '7', 1492 'day' => '1', 1493 'hour' => '10', 1494 'minutes' => '00', 1495 'seconds' => '00', 1496 'timezone' => '99', // User default timezone. 1497 'applydst' => false, // Don't apply dst. 1498 'expectedoutput' => '1309528800' 1499 ), 1500 array( 1501 'usertimezone' => 'America/Moncton', 1502 'year' => '2011', 1503 'month' => '7', 1504 'day' => '1', 1505 'hour' => '10', 1506 'minutes' => '00', 1507 'seconds' => '00', 1508 'timezone' => '99', // User default timezone. 1509 'applydst' => true, // Apply dst. 1510 'expectedoutput' => '1309525200' 1511 ), 1512 array( 1513 'usertimezone' => 'America/Moncton', 1514 'year' => '2011', 1515 'month' => '7', 1516 'day' => '1', 1517 'hour' => '10', 1518 'minutes' => '00', 1519 'seconds' => '00', 1520 'timezone' => 'America/Moncton', // String timezone. 1521 'applydst' => true, // Apply dst. 1522 'expectedoutput' => '1309525200' 1523 ), 1524 array( 1525 'usertimezone' => '2', // No dst applyed. 1526 'year' => '2011', 1527 'month' => '7', 1528 'day' => '1', 1529 'hour' => '10', 1530 'minutes' => '00', 1531 'seconds' => '00', 1532 'timezone' => '99', // Take user timezone. 1533 'applydst' => true, // Apply dst. 1534 'expectedoutput' => '1309507200' 1535 ), 1536 array( 1537 'usertimezone' => '-2', // No dst applyed. 1538 'year' => '2011', 1539 'month' => '7', 1540 'day' => '1', 1541 'hour' => '10', 1542 'minutes' => '00', 1543 'seconds' => '00', 1544 'timezone' => '99', // Take usertimezone. 1545 'applydst' => true, // Apply dst. 1546 'expectedoutput' => '1309521600' 1547 ), 1548 array( 1549 'usertimezone' => '-10', // No dst applyed. 1550 'year' => '2011', 1551 'month' => '7', 1552 'day' => '1', 1553 'hour' => '10', 1554 'minutes' => '00', 1555 'seconds' => '00', 1556 'timezone' => '2', // Take this timezone. 1557 'applydst' => true, // Apply dst. 1558 'expectedoutput' => '1309507200' 1559 ), 1560 array( 1561 'usertimezone' => '-10', // No dst applyed. 1562 'year' => '2011', 1563 'month' => '7', 1564 'day' => '1', 1565 'hour' => '10', 1566 'minutes' => '00', 1567 'seconds' => '00', 1568 'timezone' => '-2', // Take this timezone. 1569 'applydst' => true, // Apply dst. 1570 'expectedoutput' => '1309521600' 1571 ), 1572 array( 1573 'usertimezone' => '-10', // No dst applyed. 1574 'year' => '2011', 1575 'month' => '7', 1576 'day' => '1', 1577 'hour' => '10', 1578 'minutes' => '00', 1579 'seconds' => '00', 1580 'timezone' => 'random/time', // This should show server time. 1581 'applydst' => true, // Apply dst. 1582 'expectedoutput' => '1309485600' 1583 ), 1584 array( 1585 'usertimezone' => '-14', // Server time. 1586 'year' => '2011', 1587 'month' => '7', 1588 'day' => '1', 1589 'hour' => '10', 1590 'minutes' => '00', 1591 'seconds' => '00', 1592 'timezone' => '99', // Get user time. 1593 'applydst' => true, // Apply dst. 1594 'expectedoutput' => '1309485600' 1595 ) 1596 ); 1597 1598 // Set default timezone to Australia/Perth, else time calculated 1599 // will not match expected values. 1600 $this->setTimezone(99, 'Australia/Perth'); 1601 1602 // Test make_timestamp with all testvals and assert if anything wrong. 1603 foreach ($testvalues as $vals) { 1604 $USER->timezone = $vals['usertimezone']; 1605 $actualoutput = make_timestamp( 1606 $vals['year'], 1607 $vals['month'], 1608 $vals['day'], 1609 $vals['hour'], 1610 $vals['minutes'], 1611 $vals['seconds'], 1612 $vals['timezone'], 1613 $vals['applydst'] 1614 ); 1615 1616 // On different systems case of AM PM changes so compare case insensitive. 1617 $vals['expectedoutput'] = core_text::strtolower($vals['expectedoutput']); 1618 $actualoutput = core_text::strtolower($actualoutput); 1619 1620 $this->assertSame($vals['expectedoutput'], $actualoutput, 1621 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput}, 1622 Please check if timezones are updated (Site adminstration -> location -> update timezone)"); 1623 } 1624 } 1625 1626 /** 1627 * Test get_string and most importantly the implementation of the lang_string 1628 * object. 1629 */ 1630 public function test_get_string() { 1631 global $COURSE; 1632 1633 // Make sure we are using English. 1634 $originallang = $COURSE->lang; 1635 $COURSE->lang = 'en'; 1636 1637 $yes = get_string('yes'); 1638 $yesexpected = 'Yes'; 1639 $this->assertInternalType('string', $yes); 1640 $this->assertSame($yesexpected, $yes); 1641 1642 $yes = get_string('yes', 'moodle'); 1643 $this->assertInternalType('string', $yes); 1644 $this->assertSame($yesexpected, $yes); 1645 1646 $yes = get_string('yes', 'core'); 1647 $this->assertInternalType('string', $yes); 1648 $this->assertSame($yesexpected, $yes); 1649 1650 $yes = get_string('yes', ''); 1651 $this->assertInternalType('string', $yes); 1652 $this->assertSame($yesexpected, $yes); 1653 1654 $yes = get_string('yes', null); 1655 $this->assertInternalType('string', $yes); 1656 $this->assertSame($yesexpected, $yes); 1657 1658 $yes = get_string('yes', null, 1); 1659 $this->assertInternalType('string', $yes); 1660 $this->assertSame($yesexpected, $yes); 1661 1662 $days = 1; 1663 $numdays = get_string('numdays', 'core', '1'); 1664 $numdaysexpected = $days.' days'; 1665 $this->assertInternalType('string', $numdays); 1666 $this->assertSame($numdaysexpected, $numdays); 1667 1668 $yes = get_string('yes', null, null, true); 1669 $this->assertInstanceOf('lang_string', $yes); 1670 $this->assertSame($yesexpected, (string)$yes); 1671 1672 // Test using a lang_string object as the $a argument for a normal 1673 // get_string call (returning string). 1674 $test = new lang_string('yes', null, null, true); 1675 $testexpected = get_string('numdays', 'core', get_string('yes')); 1676 $testresult = get_string('numdays', null, $test); 1677 $this->assertInternalType('string', $testresult); 1678 $this->assertSame($testexpected, $testresult); 1679 1680 // Test using a lang_string object as the $a argument for an object 1681 // get_string call (returning lang_string). 1682 $test = new lang_string('yes', null, null, true); 1683 $testexpected = get_string('numdays', 'core', get_string('yes')); 1684 $testresult = get_string('numdays', null, $test, true); 1685 $this->assertInstanceOf('lang_string', $testresult); 1686 $this->assertSame($testexpected, "$testresult"); 1687 1688 // Make sure that object properties that can't be converted don't cause 1689 // errors. 1690 // Level one: This is as deep as current language processing goes. 1691 $test = new stdClass; 1692 $test->one = 'here'; 1693 $string = get_string('yes', null, $test, true); 1694 $this->assertEquals($yesexpected, $string); 1695 1696 // Make sure that object properties that can't be converted don't cause 1697 // errors. 1698 // Level two: Language processing doesn't currently reach this deep. 1699 // only immediate scalar properties are worked with. 1700 $test = new stdClass; 1701 $test->one = new stdClass; 1702 $test->one->two = 'here'; 1703 $string = get_string('yes', null, $test, true); 1704 $this->assertEquals($yesexpected, $string); 1705 1706 // Make sure that object properties that can't be converted don't cause 1707 // errors. 1708 // Level three: It should never ever go this deep, but we're making sure 1709 // it doesn't cause any probs anyway. 1710 $test = new stdClass; 1711 $test->one = new stdClass; 1712 $test->one->two = new stdClass; 1713 $test->one->two->three = 'here'; 1714 $string = get_string('yes', null, $test, true); 1715 $this->assertEquals($yesexpected, $string); 1716 1717 // Make sure that object properties that can't be converted don't cause 1718 // errors and check lang_string properties. 1719 // Level one: This is as deep as current language processing goes. 1720 $test = new stdClass; 1721 $test->one = new lang_string('yes'); 1722 $string = get_string('yes', null, $test, true); 1723 $this->assertEquals($yesexpected, $string); 1724 1725 // Make sure that object properties that can't be converted don't cause 1726 // errors and check lang_string properties. 1727 // Level two: Language processing doesn't currently reach this deep. 1728 // only immediate scalar properties are worked with. 1729 $test = new stdClass; 1730 $test->one = new stdClass; 1731 $test->one->two = new lang_string('yes'); 1732 $string = get_string('yes', null, $test, true); 1733 $this->assertEquals($yesexpected, $string); 1734 1735 // Make sure that object properties that can't be converted don't cause 1736 // errors and check lang_string properties. 1737 // Level three: It should never ever go this deep, but we're making sure 1738 // it doesn't cause any probs anyway. 1739 $test = new stdClass; 1740 $test->one = new stdClass; 1741 $test->one->two = new stdClass; 1742 $test->one->two->three = new lang_string('yes'); 1743 $string = get_string('yes', null, $test, true); 1744 $this->assertEquals($yesexpected, $string); 1745 1746 // Make sure that array properties that can't be converted don't cause 1747 // errors. 1748 $test = array(); 1749 $test['one'] = new stdClass; 1750 $test['one']->two = 'here'; 1751 $string = get_string('yes', null, $test, true); 1752 $this->assertEquals($yesexpected, $string); 1753 1754 // Same thing but as above except using an object... this is allowed :P. 1755 $string = get_string('yes', null, null, true); 1756 $object = new stdClass; 1757 $object->$string = 'Yes'; 1758 $this->assertEquals($yesexpected, $string); 1759 $this->assertEquals($yesexpected, $object->$string); 1760 1761 // Reset the language. 1762 $COURSE->lang = $originallang; 1763 } 1764 1765 /** 1766 * @expectedException PHPUnit_Framework_Error_Warning 1767 */ 1768 public function test_get_string_limitation() { 1769 // This is one of the limitations to the lang_string class. It can't be 1770 // used as a key. 1771 $array = array(get_string('yes', null, null, true) => 'yes'); 1772 } 1773 1774 /** 1775 * Test localised float formatting. 1776 */ 1777 public function test_format_float() { 1778 1779 // Special case for null. 1780 $this->assertEquals('', format_float(null)); 1781 1782 // Default 1 decimal place. 1783 $this->assertEquals('5.4', format_float(5.43)); 1784 $this->assertEquals('5.0', format_float(5.001)); 1785 1786 // Custom number of decimal places. 1787 $this->assertEquals('5.43000', format_float(5.43, 5)); 1788 1789 // Option to strip ending zeros after rounding. 1790 $this->assertEquals('5.43', format_float(5.43, 5, true, true)); 1791 $this->assertEquals('5', format_float(5.0001, 3, true, true)); 1792 1793 // Tests with a localised decimal separator. 1794 $this->define_local_decimal_separator(); 1795 1796 // Localisation on (default). 1797 $this->assertEquals('5X43000', format_float(5.43, 5)); 1798 $this->assertEquals('5X43', format_float(5.43, 5, true, true)); 1799 1800 // Localisation off. 1801 $this->assertEquals('5.43000', format_float(5.43, 5, false)); 1802 $this->assertEquals('5.43', format_float(5.43, 5, false, true)); 1803 } 1804 1805 /** 1806 * Test localised float unformatting. 1807 */ 1808 public function test_unformat_float() { 1809 1810 // Tests without the localised decimal separator. 1811 1812 // Special case for null, empty or white spaces only strings. 1813 $this->assertEquals(null, unformat_float(null)); 1814 $this->assertEquals(null, unformat_float('')); 1815 $this->assertEquals(null, unformat_float(' ')); 1816 1817 // Regular use. 1818 $this->assertEquals(5.4, unformat_float('5.4')); 1819 $this->assertEquals(5.4, unformat_float('5.4', true)); 1820 1821 // No decimal. 1822 $this->assertEquals(5.0, unformat_float('5')); 1823 1824 // Custom number of decimal. 1825 $this->assertEquals(5.43267, unformat_float('5.43267')); 1826 1827 // Empty decimal. 1828 $this->assertEquals(100.0, unformat_float('100.00')); 1829 1830 // With the thousand separator. 1831 $this->assertEquals(1000.0, unformat_float('1 000')); 1832 $this->assertEquals(1000.32, unformat_float('1 000.32')); 1833 1834 // Negative number. 1835 $this->assertEquals(-100.0, unformat_float('-100')); 1836 1837 // Wrong value. 1838 $this->assertEquals(0.0, unformat_float('Wrong value')); 1839 // Wrong value in strict mode. 1840 $this->assertFalse(unformat_float('Wrong value', true)); 1841 1842 // Combining options. 1843 $this->assertEquals(-1023.862567, unformat_float(' -1 023.862567 ')); 1844 1845 // Bad decimal separator (should crop the decimal). 1846 $this->assertEquals(50.0, unformat_float('50,57')); 1847 // Bad decimal separator in strict mode (should return false). 1848 $this->assertFalse(unformat_float('50,57', true)); 1849 1850 // Tests with a localised decimal separator. 1851 $this->define_local_decimal_separator(); 1852 1853 // We repeat the tests above but with the current decimal separator. 1854 1855 // Regular use without and with the localised separator. 1856 $this->assertEquals (5.4, unformat_float('5.4')); 1857 $this->assertEquals (5.4, unformat_float('5X4')); 1858 1859 // Custom number of decimal. 1860 $this->assertEquals (5.43267, unformat_float('5X43267')); 1861 1862 // Empty decimal. 1863 $this->assertEquals (100.0, unformat_float('100X00')); 1864 1865 // With the thousand separator. 1866 $this->assertEquals (1000.32, unformat_float('1 000X32')); 1867 1868 // Bad different separator (should crop the decimal). 1869 $this->assertEquals (50.0, unformat_float('50Y57')); 1870 // Bad different separator in strict mode (should return false). 1871 $this->assertFalse (unformat_float('50Y57', true)); 1872 1873 // Combining options. 1874 $this->assertEquals (-1023.862567, unformat_float(' -1 023X862567 ')); 1875 // Combining options in strict mode. 1876 $this->assertEquals (-1023.862567, unformat_float(' -1 023X862567 ', true)); 1877 } 1878 1879 /** 1880 * Test deleting of users. 1881 */ 1882 public function test_delete_user() { 1883 global $DB, $CFG; 1884 1885 $this->resetAfterTest(); 1886 1887 $guest = $DB->get_record('user', array('id'=>$CFG->siteguest), '*', MUST_EXIST); 1888 $admin = $DB->get_record('user', array('id'=>$CFG->siteadmins), '*', MUST_EXIST); 1889 $this->assertEquals(0, $DB->count_records('user', array('deleted'=>1))); 1890 1891 $user = $this->getDataGenerator()->create_user(array('idnumber'=>'abc')); 1892 $user2 = $this->getDataGenerator()->create_user(array('idnumber'=>'xyz')); 1893 $usersharedemail1 = $this->getDataGenerator()->create_user(array('email' => 'sharedemail@example.invalid')); 1894 $usersharedemail2 = $this->getDataGenerator()->create_user(array('email' => 'sharedemail@example.invalid')); 1895 $useremptyemail1 = $this->getDataGenerator()->create_user(array('email' => '')); 1896 $useremptyemail2 = $this->getDataGenerator()->create_user(array('email' => '')); 1897 1898 // Delete user and capture event. 1899 $sink = $this->redirectEvents(); 1900 $result = delete_user($user); 1901 $events = $sink->get_events(); 1902 $sink->close(); 1903 $event = array_pop($events); 1904 1905 // Test user is deleted in DB. 1906 $this->assertTrue($result); 1907 $deluser = $DB->get_record('user', array('id'=>$user->id), '*', MUST_EXIST); 1908 $this->assertEquals(1, $deluser->deleted); 1909 $this->assertEquals(0, $deluser->picture); 1910 $this->assertSame('', $deluser->idnumber); 1911 $this->assertSame(md5($user->username), $deluser->email); 1912 $this->assertRegExp('/^'.preg_quote($user->email, '/').'\.\d*$/', $deluser->username); 1913 1914 $this->assertEquals(1, $DB->count_records('user', array('deleted'=>1))); 1915 1916 // Test Event. 1917 $this->assertInstanceOf('\core\event\user_deleted', $event); 1918 $this->assertSame($user->id, $event->objectid); 1919 $this->assertSame('user_deleted', $event->get_legacy_eventname()); 1920 $this->assertEventLegacyData($user, $event); 1921 $expectedlogdata = array(SITEID, 'user', 'delete', "view.php?id=$user->id", $user->firstname.' '.$user->lastname); 1922 $this->assertEventLegacyLogData($expectedlogdata, $event); 1923 $eventdata = $event->get_data(); 1924 $this->assertSame($eventdata['other']['username'], $user->username); 1925 $this->assertSame($eventdata['other']['email'], $user->email); 1926 $this->assertSame($eventdata['other']['idnumber'], $user->idnumber); 1927 $this->assertSame($eventdata['other']['picture'], $user->picture); 1928 $this->assertSame($eventdata['other']['mnethostid'], $user->mnethostid); 1929 $this->assertEquals($user, $event->get_record_snapshot('user', $event->objectid)); 1930 $this->assertEventContextNotUsed($event); 1931 1932 // Try invalid params. 1933 $record = new stdClass(); 1934 $record->grrr = 1; 1935 try { 1936 delete_user($record); 1937 $this->fail('Expecting exception for invalid delete_user() $user parameter'); 1938 } catch (moodle_exception $ex) { 1939 $this->assertInstanceOf('coding_exception', $ex); 1940 } 1941 $record->id = 1; 1942 try { 1943 delete_user($record); 1944 $this->fail('Expecting exception for invalid delete_user() $user parameter'); 1945 } catch (moodle_exception $ex) { 1946 $this->assertInstanceOf('coding_exception', $ex); 1947 } 1948 1949 $record = new stdClass(); 1950 $record->id = 666; 1951 $record->username = 'xx'; 1952 $this->assertFalse($DB->record_exists('user', array('id'=>666))); // Any non-existent id is ok. 1953 $result = delete_user($record); 1954 $this->assertFalse($result); 1955 1956 $result = delete_user($guest); 1957 $this->assertFalse($result); 1958 1959 $result = delete_user($admin); 1960 $this->assertFalse($result); 1961 1962 // Simultaneously deleting users with identical email addresses. 1963 $result1 = delete_user($usersharedemail1); 1964 $result2 = delete_user($usersharedemail2); 1965 1966 $usersharedemail1after = $DB->get_record('user', array('id' => $usersharedemail1->id)); 1967 $usersharedemail2after = $DB->get_record('user', array('id' => $usersharedemail2->id)); 1968 $this->assertTrue($result1); 1969 $this->assertTrue($result2); 1970 $this->assertStringStartsWith($usersharedemail1->email . '.', $usersharedemail1after->username); 1971 $this->assertStringStartsWith($usersharedemail2->email . '.', $usersharedemail2after->username); 1972 1973 // Simultaneously deleting users without email addresses. 1974 $result1 = delete_user($useremptyemail1); 1975 $result2 = delete_user($useremptyemail2); 1976 1977 $useremptyemail1after = $DB->get_record('user', array('id' => $useremptyemail1->id)); 1978 $useremptyemail2after = $DB->get_record('user', array('id' => $useremptyemail2->id)); 1979 $this->assertTrue($result1); 1980 $this->assertTrue($result2); 1981 $this->assertStringStartsWith($useremptyemail1->username . '.' . $useremptyemail1->id . '@unknownemail.invalid.', 1982 $useremptyemail1after->username); 1983 $this->assertStringStartsWith($useremptyemail2->username . '.' . $useremptyemail2->id . '@unknownemail.invalid.', 1984 $useremptyemail2after->username); 1985 1986 $this->resetDebugging(); 1987 } 1988 1989 /** 1990 * Test function convert_to_array() 1991 */ 1992 public function test_convert_to_array() { 1993 // Check that normal classes are converted to arrays the same way as (array) would do. 1994 $obj = new stdClass(); 1995 $obj->prop1 = 'hello'; 1996 $obj->prop2 = array('first', 'second', 13); 1997 $obj->prop3 = 15; 1998 $this->assertEquals(convert_to_array($obj), (array)$obj); 1999 2000 // Check that context object (with iterator) is converted to array properly. 2001 $obj = context_system::instance(); 2002 $ar = array( 2003 'id' => $obj->id, 2004 'contextlevel' => $obj->contextlevel, 2005 'instanceid' => $obj->instanceid, 2006 'path' => $obj->path, 2007 'depth' => $obj->depth 2008 ); 2009 $this->assertEquals(convert_to_array($obj), $ar); 2010 } 2011 2012 /** 2013 * Test the function date_format_string(). 2014 */ 2015 public function test_date_format_string() { 2016 global $CFG; 2017 2018 $this->resetAfterTest(); 2019 $this->setTimezone(99, 'Australia/Perth'); 2020 2021 $tests = array( 2022 array( 2023 'tz' => 99, 2024 'str' => '%A, %d %B %Y, %I:%M %p', 2025 'expected' => 'Saturday, 01 January 2011, 06:00 PM' 2026 ), 2027 array( 2028 'tz' => 0, 2029 'str' => '%A, %d %B %Y, %I:%M %p', 2030 'expected' => 'Saturday, 01 January 2011, 10:00 AM' 2031 ), 2032 array( 2033 // Note: this function expected the timestamp in weird format before, 2034 // since 2.9 it uses UTC. 2035 'tz' => 'Pacific/Auckland', 2036 'str' => '%A, %d %B %Y, %I:%M %p', 2037 'expected' => 'Saturday, 01 January 2011, 11:00 PM' 2038 ), 2039 // Following tests pass on Windows only because en lang pack does 2040 // not contain localewincharset, in real life lang pack maintainers 2041 // may use only characters that are present in localewincharset 2042 // in format strings! 2043 array( 2044 'tz' => 99, 2045 'str' => 'Žluťoučký koníček %A', 2046 'expected' => 'Žluťoučký koníček Saturday' 2047 ), 2048 array( 2049 'tz' => 99, 2050 'str' => '言語設定言語 %A', 2051 'expected' => '言語設定言語 Saturday' 2052 ), 2053 array( 2054 'tz' => 99, 2055 'str' => '简体中文简体 %A', 2056 'expected' => '简体中文简体 Saturday' 2057 ), 2058 ); 2059 2060 // Note: date_format_string() uses the timezone only to differenciate 2061 // the server time from the UTC time. It does not modify the timestamp. 2062 // Hence similar results for timezones <= 13. 2063 // On different systems case of AM PM changes so compare case insensitive. 2064 foreach ($tests as $test) { 2065 $str = date_format_string(1293876000, $test['str'], $test['tz']); 2066 $this->assertSame(core_text::strtolower($test['expected']), core_text::strtolower($str)); 2067 } 2068 } 2069 2070 public function test_get_config() { 2071 global $CFG; 2072 2073 $this->resetAfterTest(); 2074 2075 // Preparation. 2076 set_config('phpunit_test_get_config_1', 'test 1'); 2077 set_config('phpunit_test_get_config_2', 'test 2', 'mod_forum'); 2078 if (!is_array($CFG->config_php_settings)) { 2079 $CFG->config_php_settings = array(); 2080 } 2081 $CFG->config_php_settings['phpunit_test_get_config_3'] = 'test 3'; 2082 2083 if (!is_array($CFG->forced_plugin_settings)) { 2084 $CFG->forced_plugin_settings = array(); 2085 } 2086 if (!array_key_exists('mod_forum', $CFG->forced_plugin_settings)) { 2087 $CFG->forced_plugin_settings['mod_forum'] = array(); 2088 } 2089 $CFG->forced_plugin_settings['mod_forum']['phpunit_test_get_config_4'] = 'test 4'; 2090 $CFG->phpunit_test_get_config_5 = 'test 5'; 2091 2092 // Testing. 2093 $this->assertSame('test 1', get_config('core', 'phpunit_test_get_config_1')); 2094 $this->assertSame('test 2', get_config('mod_forum', 'phpunit_test_get_config_2')); 2095 $this->assertSame('test 3', get_config('core', 'phpunit_test_get_config_3')); 2096 $this->assertSame('test 4', get_config('mod_forum', 'phpunit_test_get_config_4')); 2097 $this->assertFalse(get_config('core', 'phpunit_test_get_config_5')); 2098 $this->assertFalse(get_config('core', 'phpunit_test_get_config_x')); 2099 $this->assertFalse(get_config('mod_forum', 'phpunit_test_get_config_x')); 2100 2101 // Test config we know to exist. 2102 $this->assertSame($CFG->dataroot, get_config('core', 'dataroot')); 2103 $this->assertSame($CFG->phpunit_dataroot, get_config('core', 'phpunit_dataroot')); 2104 $this->assertSame($CFG->dataroot, get_config('core', 'phpunit_dataroot')); 2105 $this->assertSame(get_config('core', 'dataroot'), get_config('core', 'phpunit_dataroot')); 2106 2107 // Test setting a config var that already exists. 2108 set_config('phpunit_test_get_config_1', 'test a'); 2109 $this->assertSame('test a', $CFG->phpunit_test_get_config_1); 2110 $this->assertSame('test a', get_config('core', 'phpunit_test_get_config_1')); 2111 2112 // Test cache invalidation. 2113 $cache = cache::make('core', 'config'); 2114 $this->assertInternalType('array', $cache->get('core')); 2115 $this->assertInternalType('array', $cache->get('mod_forum')); 2116 set_config('phpunit_test_get_config_1', 'test b'); 2117 $this->assertFalse($cache->get('core')); 2118 set_config('phpunit_test_get_config_4', 'test c', 'mod_forum'); 2119 $this->assertFalse($cache->get('mod_forum')); 2120 } 2121 2122 public function test_get_max_upload_sizes() { 2123 // Test with very low limits so we are not affected by php upload limits. 2124 // Test activity limit smallest. 2125 $sitebytes = 102400; 2126 $coursebytes = 51200; 2127 $modulebytes = 10240; 2128 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2129 2130 $this->assertSame('Activity upload limit (10KB)', $result['0']); 2131 $this->assertCount(2, $result); 2132 2133 // Test course limit smallest. 2134 $sitebytes = 102400; 2135 $coursebytes = 10240; 2136 $modulebytes = 51200; 2137 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2138 2139 $this->assertSame('Course upload limit (10KB)', $result['0']); 2140 $this->assertCount(2, $result); 2141 2142 // Test site limit smallest. 2143 $sitebytes = 10240; 2144 $coursebytes = 102400; 2145 $modulebytes = 51200; 2146 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2147 2148 $this->assertSame('Site upload limit (10KB)', $result['0']); 2149 $this->assertCount(2, $result); 2150 2151 // Test site limit not set. 2152 $sitebytes = 0; 2153 $coursebytes = 102400; 2154 $modulebytes = 51200; 2155 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2156 2157 $this->assertSame('Activity upload limit (50KB)', $result['0']); 2158 $this->assertCount(3, $result); 2159 2160 $sitebytes = 0; 2161 $coursebytes = 51200; 2162 $modulebytes = 102400; 2163 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes); 2164 2165 $this->assertSame('Course upload limit (50KB)', $result['0']); 2166 $this->assertCount(3, $result); 2167 2168 // Test custom bytes in range. 2169 $sitebytes = 102400; 2170 $coursebytes = 51200; 2171 $modulebytes = 51200; 2172 $custombytes = 10240; 2173 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2174 2175 $this->assertCount(3, $result); 2176 2177 // Test custom bytes in range but non-standard. 2178 $sitebytes = 102400; 2179 $coursebytes = 51200; 2180 $modulebytes = 51200; 2181 $custombytes = 25600; 2182 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2183 2184 $this->assertCount(4, $result); 2185 2186 // Test custom bytes out of range. 2187 $sitebytes = 102400; 2188 $coursebytes = 51200; 2189 $modulebytes = 51200; 2190 $custombytes = 102400; 2191 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2192 2193 $this->assertCount(3, $result); 2194 2195 // Test custom bytes out of range and non-standard. 2196 $sitebytes = 102400; 2197 $coursebytes = 51200; 2198 $modulebytes = 51200; 2199 $custombytes = 256000; 2200 $result = get_max_upload_sizes($sitebytes, $coursebytes, $modulebytes, $custombytes); 2201 2202 $this->assertCount(3, $result); 2203 2204 // Test site limit only. 2205 $sitebytes = 51200; 2206 $result = get_max_upload_sizes($sitebytes); 2207 2208 $this->assertSame('Site upload limit (50KB)', $result['0']); 2209 $this->assertSame('50KB', $result['51200']); 2210 $this->assertSame('10KB', $result['10240']); 2211 $this->assertCount(3, $result); 2212 2213 // Test no limit. 2214 $result = get_max_upload_sizes(); 2215 $this->assertArrayHasKey('0', $result); 2216 $this->assertArrayHasKey(get_max_upload_file_size(), $result); 2217 } 2218 2219 /** 2220 * Test function password_is_legacy_hash(). 2221 */ 2222 public function test_password_is_legacy_hash() { 2223 // Well formed md5s should be matched. 2224 foreach (array('some', 'strings', 'to_check!') as $string) { 2225 $md5 = md5($string); 2226 $this->assertTrue(password_is_legacy_hash($md5)); 2227 } 2228 // Strings that are not md5s should not be matched. 2229 foreach (array('', AUTH_PASSWORD_NOT_CACHED, 'IPW8WTcsWNgAWcUS1FBVHegzJnw5M2jOmYkmfc8z.xdBOyC4Caeum') as $notmd5) { 2230 $this->assertFalse(password_is_legacy_hash($notmd5)); 2231 } 2232 } 2233 2234 /** 2235 * Test function validate_internal_user_password(). 2236 */ 2237 public function test_validate_internal_user_password() { 2238 // Test bcrypt hashes. 2239 $validhashes = array( 2240 'pw' => '$2y$10$LOSDi5eaQJhutSRun.OVJ.ZSxQZabCMay7TO1KmzMkDMPvU40zGXK', 2241 'abc' => '$2y$10$VWTOhVdsBbWwtdWNDRHSpewjd3aXBQlBQf5rBY/hVhw8hciarFhXa', 2242 'C0mP1eX_&}<?@*&%` |\"' => '$2y$10$3PJf.q.9ywNJlsInPbqc8.IFeSsvXrGvQLKRFBIhVu1h1I3vpIry6', 2243 'ĩńťėŕňăţĩōŋāĹ' => '$2y$10$3A2Y8WpfRAnP3czJiSv6N.6Xp0T8hW3QZz2hUCYhzyWr1kGP1yUve' 2244 ); 2245 2246 foreach ($validhashes as $password => $hash) { 2247 $user = new stdClass(); 2248 $user->auth = 'manual'; 2249 $user->password = $hash; 2250 // The correct password should be validated. 2251 $this->assertTrue(validate_internal_user_password($user, $password)); 2252 // An incorrect password should not be validated. 2253 $this->assertFalse(validate_internal_user_password($user, 'badpw')); 2254 } 2255 } 2256 2257 /** 2258 * Test function hash_internal_user_password(). 2259 */ 2260 public function test_hash_internal_user_password() { 2261 $passwords = array('pw', 'abc123', 'C0mP1eX_&}<?@*&%` |\"', 'ĩńťėŕňăţĩōŋāĹ'); 2262 2263 // Check that some passwords that we convert to hashes can 2264 // be validated. 2265 foreach ($passwords as $password) { 2266 $hash = hash_internal_user_password($password); 2267 $fasthash = hash_internal_user_password($password, true); 2268 $user = new stdClass(); 2269 $user->auth = 'manual'; 2270 $user->password = $hash; 2271 $this->assertTrue(validate_internal_user_password($user, $password)); 2272 2273 // They should not be in md5 format. 2274 $this->assertFalse(password_is_legacy_hash($hash)); 2275 2276 // Check that cost factor in hash is correctly set. 2277 $this->assertRegExp('/\$10\$/', $hash); 2278 $this->assertRegExp('/\$04\$/', $fasthash); 2279 } 2280 } 2281 2282 /** 2283 * Test function update_internal_user_password(). 2284 */ 2285 public function test_update_internal_user_password() { 2286 global $DB; 2287 $this->resetAfterTest(); 2288 $passwords = array('password', '1234', 'changeme', '****'); 2289 foreach ($passwords as $password) { 2290 $user = $this->getDataGenerator()->create_user(array('auth'=>'manual')); 2291 update_internal_user_password($user, $password); 2292 // The user object should have been updated. 2293 $this->assertTrue(validate_internal_user_password($user, $password)); 2294 // The database field for the user should also have been updated to the 2295 // same value. 2296 $this->assertSame($user->password, $DB->get_field('user', 'password', array('id' => $user->id))); 2297 } 2298 2299 $user = $this->getDataGenerator()->create_user(array('auth'=>'manual')); 2300 // Manually set the user's password to the md5 of the string 'password'. 2301 $DB->set_field('user', 'password', '5f4dcc3b5aa765d61d8327deb882cf99', array('id' => $user->id)); 2302 2303 $sink = $this->redirectEvents(); 2304 // Update the password. 2305 update_internal_user_password($user, 'password'); 2306 $events = $sink->get_events(); 2307 $sink->close(); 2308 $event = array_pop($events); 2309 2310 // Password should have been updated to a bcrypt hash. 2311 $this->assertFalse(password_is_legacy_hash($user->password)); 2312 2313 // Verify event information. 2314 $this->assertInstanceOf('\core\event\user_password_updated', $event); 2315 $this->assertSame($user->id, $event->relateduserid); 2316 $this->assertEquals(context_user::instance($user->id), $event->get_context()); 2317 $this->assertEventContextNotUsed($event); 2318 2319 // Verify recovery of property 'auth'. 2320 unset($user->auth); 2321 update_internal_user_password($user, 'newpassword'); 2322 $this->assertDebuggingCalled('User record in update_internal_user_password() must include field auth', 2323 DEBUG_DEVELOPER); 2324 $this->assertEquals('manual', $user->auth); 2325 } 2326 2327 /** 2328 * Testing that if the password is not cached, that it does not update 2329 * the user table and fire event. 2330 */ 2331 public function test_update_internal_user_password_no_cache() { 2332 $this->resetAfterTest(); 2333 2334 $user = $this->getDataGenerator()->create_user(array('auth' => 'cas')); 2335 $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2336 2337 $sink = $this->redirectEvents(); 2338 update_internal_user_password($user, 'wonkawonka'); 2339 $this->assertEquals(0, $sink->count(), 'User updated event should not fire'); 2340 } 2341 2342 /** 2343 * Test if the user has a password hash, but now their auth method 2344 * says not to cache it. Then it should update. 2345 */ 2346 public function test_update_internal_user_password_update_no_cache() { 2347 $this->resetAfterTest(); 2348 2349 $user = $this->getDataGenerator()->create_user(array('password' => 'test')); 2350 $this->assertNotEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2351 $user->auth = 'cas'; // Change to a auth that does not store passwords. 2352 2353 $sink = $this->redirectEvents(); 2354 update_internal_user_password($user, 'wonkawonka'); 2355 $this->assertGreaterThanOrEqual(1, $sink->count(), 'User updated event should fire'); 2356 2357 $this->assertEquals(AUTH_PASSWORD_NOT_CACHED, $user->password); 2358 } 2359 2360 public function test_fullname() { 2361 global $CFG; 2362 2363 $this->resetAfterTest(); 2364 2365 // Create a user to test the name display on. 2366 $record = array(); 2367 $record['firstname'] = 'Scott'; 2368 $record['lastname'] = 'Fletcher'; 2369 $record['firstnamephonetic'] = 'スコット'; 2370 $record['lastnamephonetic'] = 'フレチャー'; 2371 $record['alternatename'] = 'No friends'; 2372 $user = $this->getDataGenerator()->create_user($record); 2373 2374 // Back up config settings for restore later. 2375 $originalcfg = new stdClass(); 2376 $originalcfg->fullnamedisplay = $CFG->fullnamedisplay; 2377 $originalcfg->alternativefullnameformat = $CFG->alternativefullnameformat; 2378 2379 // Testing existing fullnamedisplay settings. 2380 $CFG->fullnamedisplay = 'firstname'; 2381 $testname = fullname($user); 2382 $this->assertSame($user->firstname, $testname); 2383 2384 $CFG->fullnamedisplay = 'firstname lastname'; 2385 $expectedname = "$user->firstname $user->lastname"; 2386 $testname = fullname($user); 2387 $this->assertSame($expectedname, $testname); 2388 2389 $CFG->fullnamedisplay = 'lastname firstname'; 2390 $expectedname = "$user->lastname $user->firstname"; 2391 $testname = fullname($user); 2392 $this->assertSame($expectedname, $testname); 2393 2394 $expectedname = get_string('fullnamedisplay', null, $user); 2395 $CFG->fullnamedisplay = 'language'; 2396 $testname = fullname($user); 2397 $this->assertSame($expectedname, $testname); 2398 2399 // Test override parameter. 2400 $CFG->fullnamedisplay = 'firstname'; 2401 $expectedname = "$user->firstname $user->lastname"; 2402 $testname = fullname($user, true); 2403 $this->assertSame($expectedname, $testname); 2404 2405 // Test alternativefullnameformat setting. 2406 // Test alternativefullnameformat that has been set to nothing. 2407 $CFG->alternativefullnameformat = ''; 2408 $expectedname = "$user->firstname $user->lastname"; 2409 $testname = fullname($user, true); 2410 $this->assertSame($expectedname, $testname); 2411 2412 // Test alternativefullnameformat that has been set to 'language'. 2413 $CFG->alternativefullnameformat = 'language'; 2414 $expectedname = "$user->firstname $user->lastname"; 2415 $testname = fullname($user, true); 2416 $this->assertSame($expectedname, $testname); 2417 2418 // Test customising the alternativefullnameformat setting with all additional name fields. 2419 $CFG->alternativefullnameformat = 'firstname lastname firstnamephonetic lastnamephonetic middlename alternatename'; 2420 $expectedname = "$user->firstname $user->lastname $user->firstnamephonetic $user->lastnamephonetic $user->middlename $user->alternatename"; 2421 $testname = fullname($user, true); 2422 $this->assertSame($expectedname, $testname); 2423 2424 // Test additional name fields. 2425 $CFG->fullnamedisplay = 'lastname lastnamephonetic firstname firstnamephonetic'; 2426 $expectedname = "$user->lastname $user->lastnamephonetic $user->firstname $user->firstnamephonetic"; 2427 $testname = fullname($user); 2428 $this->assertSame($expectedname, $testname); 2429 2430 // Test for handling missing data. 2431 $user->middlename = null; 2432 // Parenthesis with no data. 2433 $CFG->fullnamedisplay = 'firstname (middlename) lastname'; 2434 $expectedname = "$user->firstname $user->lastname"; 2435 $testname = fullname($user); 2436 $this->assertSame($expectedname, $testname); 2437 2438 // Extra spaces due to no data. 2439 $CFG->fullnamedisplay = 'firstname middlename lastname'; 2440 $expectedname = "$user->firstname $user->lastname"; 2441 $testname = fullname($user); 2442 $this->assertSame($expectedname, $testname); 2443 2444 // Regular expression testing. 2445 // Remove some data from the user fields. 2446 $user->firstnamephonetic = ''; 2447 $user->lastnamephonetic = ''; 2448 2449 // Removing empty brackets and excess whitespace. 2450 // All of these configurations should resolve to just firstname lastname. 2451 $configarray = array(); 2452 $configarray[] = 'firstname lastname [firstnamephonetic lastnamephonetic]'; 2453 $configarray[] = 'firstname lastname \'middlename\''; 2454 $configarray[] = 'firstname "firstnamephonetic" lastname'; 2455 $configarray[] = 'firstname 「firstnamephonetic」 lastname 「lastnamephonetic」'; 2456 2457 foreach ($configarray as $config) { 2458 $CFG->fullnamedisplay = $config; 2459 $expectedname = "$user->firstname $user->lastname"; 2460 $testname = fullname($user); 2461 $this->assertSame($expectedname, $testname); 2462 } 2463 2464 // Check to make sure that other characters are left in place. 2465 $configarray = array(); 2466 $configarray['0'] = new stdClass(); 2467 $configarray['0']->config = 'lastname firstname, middlename'; 2468 $configarray['0']->expectedname = "$user->lastname $user->firstname,"; 2469 $configarray['1'] = new stdClass(); 2470 $configarray['1']->config = 'lastname firstname + alternatename'; 2471 $configarray['1']->expectedname = "$user->lastname $user->firstname + $user->alternatename"; 2472 $configarray['2'] = new stdClass(); 2473 $configarray['2']->config = 'firstname aka: alternatename'; 2474 $configarray['2']->expectedname = "$user->firstname aka: $user->alternatename"; 2475 $configarray['3'] = new stdClass(); 2476 $configarray['3']->config = 'firstname (alternatename)'; 2477 $configarray['3']->expectedname = "$user->firstname ($user->alternatename)"; 2478 $configarray['4'] = new stdClass(); 2479 $configarray['4']->config = 'firstname [alternatename]'; 2480 $configarray['4']->expectedname = "$user->firstname [$user->alternatename]"; 2481 $configarray['5'] = new stdClass(); 2482 $configarray['5']->config = 'firstname "lastname"'; 2483 $configarray['5']->expectedname = "$user->firstname \"$user->lastname\""; 2484 2485 foreach ($configarray as $config) { 2486 $CFG->fullnamedisplay = $config->config; 2487 $expectedname = $config->expectedname; 2488 $testname = fullname($user); 2489 $this->assertSame($expectedname, $testname); 2490 } 2491 2492 // Test debugging message displays when 2493 // fullnamedisplay setting is "normal". 2494 $CFG->fullnamedisplay = 'firstname lastname'; 2495 unset($user); 2496 $user = new stdClass(); 2497 $user->firstname = 'Stan'; 2498 $user->lastname = 'Lee'; 2499 $namedisplay = fullname($user); 2500 $this->assertDebuggingCalled(); 2501 2502 // Tidy up after we finish testing. 2503 $CFG->fullnamedisplay = $originalcfg->fullnamedisplay; 2504 $CFG->alternativefullnameformat = $originalcfg->alternativefullnameformat; 2505 } 2506 2507 public function test_get_all_user_name_fields() { 2508 $this->resetAfterTest(); 2509 2510 // Additional names in an array. 2511 $testarray = array('firstnamephonetic' => 'firstnamephonetic', 2512 'lastnamephonetic' => 'lastnamephonetic', 2513 'middlename' => 'middlename', 2514 'alternatename' => 'alternatename', 2515 'firstname' => 'firstname', 2516 'lastname' => 'lastname'); 2517 $this->assertEquals($testarray, get_all_user_name_fields()); 2518 2519 // Additional names as a string. 2520 $teststring = 'firstnamephonetic,lastnamephonetic,middlename,alternatename,firstname,lastname'; 2521 $this->assertEquals($teststring, get_all_user_name_fields(true)); 2522 2523 // Additional names as a string with an alias. 2524 $teststring = 't.firstnamephonetic,t.lastnamephonetic,t.middlename,t.alternatename,t.firstname,t.lastname'; 2525 $this->assertEquals($teststring, get_all_user_name_fields(true, 't')); 2526 2527 // Additional name fields with a prefix - object. 2528 $testarray = array('firstnamephonetic' => 'authorfirstnamephonetic', 2529 'lastnamephonetic' => 'authorlastnamephonetic', 2530 'middlename' => 'authormiddlename', 2531 'alternatename' => 'authoralternatename', 2532 'firstname' => 'authorfirstname', 2533 'lastname' => 'authorlastname'); 2534 $this->assertEquals($testarray, get_all_user_name_fields(false, null, 'author')); 2535 2536 // Additional name fields with an alias and a title - string. 2537 $teststring = 'u.firstnamephonetic AS authorfirstnamephonetic,u.lastnamephonetic AS authorlastnamephonetic,u.middlename AS authormiddlename,u.alternatename AS authoralternatename,u.firstname AS authorfirstname,u.lastname AS authorlastname'; 2538 $this->assertEquals($teststring, get_all_user_name_fields(true, 'u', null, 'author')); 2539 2540 // Test the order parameter of the function. 2541 // Returning an array. 2542 $testarray = array('firstname' => 'firstname', 2543 'lastname' => 'lastname', 2544 'firstnamephonetic' => 'firstnamephonetic', 2545 'lastnamephonetic' => 'lastnamephonetic', 2546 'middlename' => 'middlename', 2547 'alternatename' => 'alternatename' 2548 ); 2549 $this->assertEquals($testarray, get_all_user_name_fields(false, null, null, null, true)); 2550 2551 // Returning a string. 2552 $teststring = 'firstname,lastname,firstnamephonetic,lastnamephonetic,middlename,alternatename'; 2553 $this->assertEquals($teststring, get_all_user_name_fields(true, null, null, null, true)); 2554 } 2555 2556 public function test_order_in_string() { 2557 $this->resetAfterTest(); 2558 2559 // Return an array in an order as they are encountered in a string. 2560 $valuearray = array('second', 'firsthalf', 'first'); 2561 $formatstring = 'first firsthalf some other text (second)'; 2562 $expectedarray = array('0' => 'first', '6' => 'firsthalf', '33' => 'second'); 2563 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2564 2565 // Try again with a different order for the format. 2566 $valuearray = array('second', 'firsthalf', 'first'); 2567 $formatstring = 'firsthalf first second'; 2568 $expectedarray = array('0' => 'firsthalf', '10' => 'first', '16' => 'second'); 2569 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2570 2571 // Try again with yet another different order for the format. 2572 $valuearray = array('second', 'firsthalf', 'first'); 2573 $formatstring = 'start seconds away second firstquater first firsthalf'; 2574 $expectedarray = array('19' => 'second', '38' => 'first', '44' => 'firsthalf'); 2575 $this->assertEquals($expectedarray, order_in_string($valuearray, $formatstring)); 2576 } 2577 2578 public function test_complete_user_login() { 2579 global $USER, $DB; 2580 2581 $this->resetAfterTest(); 2582 $user = $this->getDataGenerator()->create_user(); 2583 $this->setUser(0); 2584 2585 $sink = $this->redirectEvents(); 2586 $loginuser = clone($user); 2587 $this->setCurrentTimeStart(); 2588 @complete_user_login($loginuser); // Hide session header errors. 2589 $this->assertSame($loginuser, $USER); 2590 $this->assertEquals($user->id, $USER->id); 2591 $events = $sink->get_events(); 2592 $sink->close(); 2593 2594 $this->assertCount(1, $events); 2595 $event = reset($events); 2596 $this->assertInstanceOf('\core\event\user_loggedin', $event); 2597 $this->assertEquals('user', $event->objecttable); 2598 $this->assertEquals($user->id, $event->objectid); 2599 $this->assertEquals(context_system::instance()->id, $event->contextid); 2600 $this->assertEventContextNotUsed($event); 2601 2602 $user = $DB->get_record('user', array('id'=>$user->id)); 2603 2604 $this->assertTimeCurrent($user->firstaccess); 2605 $this->assertTimeCurrent($user->lastaccess); 2606 2607 $this->assertTimeCurrent($USER->firstaccess); 2608 $this->assertTimeCurrent($USER->lastaccess); 2609 $this->assertTimeCurrent($USER->currentlogin); 2610 $this->assertSame(sesskey(), $USER->sesskey); 2611 $this->assertTimeCurrent($USER->preference['_lastloaded']); 2612 $this->assertObjectNotHasAttribute('password', $USER); 2613 $this->assertObjectNotHasAttribute('description', $USER); 2614 } 2615 2616 /** 2617 * Test require_logout. 2618 */ 2619 public function test_require_logout() { 2620 $this->resetAfterTest(); 2621 $user = $this->getDataGenerator()->create_user(); 2622 $this->setUser($user); 2623 2624 $this->assertTrue(isloggedin()); 2625 2626 // Logout user and capture event. 2627 $sink = $this->redirectEvents(); 2628 require_logout(); 2629 $events = $sink->get_events(); 2630 $sink->close(); 2631 $event = array_pop($events); 2632 2633 // Check if user is logged out. 2634 $this->assertFalse(isloggedin()); 2635 2636 // Test Event. 2637 $this->assertInstanceOf('\core\event\user_loggedout', $event); 2638 $this->assertSame($user->id, $event->objectid); 2639 $this->assertSame('user_logout', $event->get_legacy_eventname()); 2640 $this->assertEventLegacyData($user, $event); 2641 $expectedlogdata = array(SITEID, 'user', 'logout', 'view.php?id='.$event->objectid.'&course='.SITEID, $event->objectid, 0, 2642 $event->objectid); 2643 $this->assertEventLegacyLogData($expectedlogdata, $event); 2644 $this->assertEventContextNotUsed($event); 2645 } 2646 2647 /** 2648 * A data provider for testing email messageid 2649 */ 2650 public function generate_email_messageid_provider() { 2651 return array( 2652 'nopath' => array( 2653 'wwwroot' => 'http://www.example.com', 2654 'ids' => array( 2655 'a-custom-id' => '<a-custom-id@www.example.com>', 2656 'an-id-with-/-a-slash' => '<an-id-with-%2F-a-slash@www.example.com>', 2657 ), 2658 ), 2659 'path' => array( 2660 'wwwroot' => 'http://www.example.com/path/subdir', 2661 'ids' => array( 2662 'a-custom-id' => '<a-custom-id/path/subdir@www.example.com>', 2663 'an-id-with-/-a-slash' => '<an-id-with-%2F-a-slash/path/subdir@www.example.com>', 2664 ), 2665 ), 2666 ); 2667 } 2668 2669 /** 2670 * Test email message id generation 2671 * 2672 * @dataProvider generate_email_messageid_provider 2673 * 2674 * @param string $wwwroot The wwwroot 2675 * @param array $msgids An array of msgid local parts and the final result 2676 */ 2677 public function test_generate_email_messageid($wwwroot, $msgids) { 2678 global $CFG; 2679 2680 $this->resetAfterTest(); 2681 $CFG->wwwroot = $wwwroot; 2682 2683 foreach ($msgids as $local => $final) { 2684 $this->assertEquals($final, generate_email_messageid($local)); 2685 } 2686 } 2687 2688 /** 2689 * A data provider for testing email diversion 2690 */ 2691 public function diverted_emails_provider() { 2692 return array( 2693 'nodiverts' => array( 2694 'divertallemailsto' => null, 2695 'divertallemailsexcept' => null, 2696 array( 2697 'foo@example.com', 2698 'test@real.com', 2699 'fred.jones@example.com', 2700 'dev1@dev.com', 2701 'fred@example.com', 2702 'fred+verp@example.com', 2703 ), 2704 false, 2705 ), 2706 'alldiverts' => array( 2707 'divertallemailsto' => 'somewhere@elsewhere.com', 2708 'divertallemailsexcept' => null, 2709 array( 2710 'foo@example.com', 2711 'test@real.com', 2712 'fred.jones@example.com', 2713 'dev1@dev.com', 2714 'fred@example.com', 2715 'fred+verp@example.com', 2716 ), 2717 true, 2718 ), 2719 'alsodiverts' => array( 2720 'divertallemailsto' => 'somewhere@elsewhere.com', 2721 'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com', 2722 array( 2723 'foo@example.com', 2724 'test@real.com', 2725 'fred.jones@example.com', 2726 ), 2727 true, 2728 ), 2729 'divertsexceptions' => array( 2730 'divertallemailsto' => 'somewhere@elsewhere.com', 2731 'divertallemailsexcept' => '@dev.com, fred(\+.*)?@example.com', 2732 array( 2733 'dev1@dev.com', 2734 'fred@example.com', 2735 'fred+verp@example.com', 2736 ), 2737 false, 2738 ), 2739 ); 2740 } 2741 2742 /** 2743 * Test email diversion 2744 * 2745 * @dataProvider diverted_emails_provider 2746 * 2747 * @param string $divertallemailsto An optional email address 2748 * @param string $divertallemailsexcept An optional exclusion list 2749 * @param array $addresses An array of test addresses 2750 * @param boolean $expected Expected result 2751 */ 2752 public function test_email_should_be_diverted($divertallemailsto, $divertallemailsexcept, $addresses, $expected) { 2753 global $CFG; 2754 2755 $this->resetAfterTest(); 2756 $CFG->divertallemailsto = $divertallemailsto; 2757 $CFG->divertallemailsexcept = $divertallemailsexcept; 2758 2759 foreach ($addresses as $address) { 2760 $this->assertEquals($expected, email_should_be_diverted($address)); 2761 } 2762 } 2763 2764 public function test_email_to_user() { 2765 global $CFG; 2766 2767 $this->resetAfterTest(); 2768 2769 $user1 = $this->getDataGenerator()->create_user(); 2770 $user2 = $this->getDataGenerator()->create_user(); 2771 2772 $subject = 'subject'; 2773 $messagetext = 'message text'; 2774 $subject2 = 'subject 2'; 2775 $messagetext2 = 'message text 2'; 2776 2777 // Close the default email sink. 2778 $sink = $this->redirectEmails(); 2779 $sink->close(); 2780 2781 $CFG->noemailever = true; 2782 $this->assertNotEmpty($CFG->noemailever); 2783 email_to_user($user1, $user2, $subject, $messagetext); 2784 $this->assertDebuggingCalled('Not sending email due to $CFG->noemailever config setting'); 2785 2786 unset_config('noemailever'); 2787 2788 email_to_user($user1, $user2, $subject, $messagetext); 2789 $this->assertDebuggingCalled('Unit tests must not send real emails! Use $this->redirectEmails()'); 2790 2791 $sink = $this->redirectEmails(); 2792 email_to_user($user1, $user2, $subject, $messagetext); 2793 email_to_user($user2, $user1, $subject2, $messagetext2); 2794 $this->assertSame(2, $sink->count()); 2795 $result = $sink->get_messages(); 2796 $this->assertCount(2, $result); 2797 $sink->close(); 2798 2799 $this->assertSame($subject, $result[0]->subject); 2800 $this->assertSame($messagetext, trim($result[0]->body)); 2801 $this->assertSame($user1->email, $result[0]->to); 2802 $this->assertSame($user2->email, $result[0]->from); 2803 2804 $this->assertSame($subject2, $result[1]->subject); 2805 $this->assertSame($messagetext2, trim($result[1]->body)); 2806 $this->assertSame($user2->email, $result[1]->to); 2807 $this->assertSame($user1->email, $result[1]->from); 2808 2809 email_to_user($user1, $user2, $subject, $messagetext); 2810 $this->assertDebuggingCalled('Unit tests must not send real emails! Use $this->redirectEmails()'); 2811 2812 // Test $CFG->emailonlyfromnoreplyaddress. 2813 set_config('emailonlyfromnoreplyaddress', 1); 2814 $this->assertNotEmpty($CFG->emailonlyfromnoreplyaddress); 2815 $sink = $this->redirectEmails(); 2816 email_to_user($user1, $user2, $subject, $messagetext); 2817 unset_config('emailonlyfromnoreplyaddress'); 2818 email_to_user($user1, $user2, $subject, $messagetext); 2819 $result = $sink->get_messages(); 2820 $this->assertEquals($CFG->noreplyaddress, $result[0]->from); 2821 $this->assertNotEquals($CFG->noreplyaddress, $result[1]->from); 2822 $sink->close(); 2823 } 2824 2825 /** 2826 * Test setnew_password_and_mail. 2827 */ 2828 public function test_setnew_password_and_mail() { 2829 global $DB, $CFG; 2830 2831 $this->resetAfterTest(); 2832 2833 $user = $this->getDataGenerator()->create_user(); 2834 2835 // Update user password. 2836 $sink = $this->redirectEvents(); 2837 $sink2 = $this->redirectEmails(); // Make sure we are redirecting emails. 2838 setnew_password_and_mail($user); 2839 $events = $sink->get_events(); 2840 $sink->close(); 2841 $sink2->close(); 2842 $event = array_pop($events); 2843 2844 // Test updated value. 2845 $dbuser = $DB->get_record('user', array('id' => $user->id)); 2846 $this->assertSame($user->firstname, $dbuser->firstname); 2847 $this->assertNotEmpty($dbuser->password); 2848 2849 // Test event. 2850 $this->assertInstanceOf('\core\event\user_password_updated', $event); 2851 $this->assertSame($user->id, $event->relateduserid); 2852 $this->assertEquals(context_user::instance($user->id), $event->get_context()); 2853 $this->assertEventContextNotUsed($event); 2854 } 2855 2856 /** 2857 * Test remove_course_content deletes course contents 2858 * TODO Add asserts to verify other data related to course is deleted as well. 2859 */ 2860 public function test_remove_course_contents() { 2861 2862 $this->resetAfterTest(); 2863 2864 $course = $this->getDataGenerator()->create_course(); 2865 $user = $this->getDataGenerator()->create_user(); 2866 $gen = $this->getDataGenerator()->get_plugin_generator('core_notes'); 2867 $note = $gen->create_instance(array('courseid' => $course->id, 'userid' => $user->id)); 2868 2869 $this->assertNotEquals(false, note_load($note->id)); 2870 remove_course_contents($course->id, false); 2871 $this->assertFalse(note_load($note->id)); 2872 } 2873 2874 /** 2875 * Test function username_load_fields_from_object(). 2876 */ 2877 public function test_username_load_fields_from_object() { 2878 $this->resetAfterTest(); 2879 2880 // This object represents the information returned from an sql query. 2881 $userinfo = new stdClass(); 2882 $userinfo->userid = 1; 2883 $userinfo->username = 'loosebruce'; 2884 $userinfo->firstname = 'Bruce'; 2885 $userinfo->lastname = 'Campbell'; 2886 $userinfo->firstnamephonetic = 'ブルース'; 2887 $userinfo->lastnamephonetic = 'カンベッル'; 2888 $userinfo->middlename = ''; 2889 $userinfo->alternatename = ''; 2890 $userinfo->email = ''; 2891 $userinfo->picture = 23; 2892 $userinfo->imagealt = 'Michael Jordan draining another basket.'; 2893 $userinfo->idnumber = 3982; 2894 2895 // Just user name fields. 2896 $user = new stdClass(); 2897 $user = username_load_fields_from_object($user, $userinfo); 2898 $expectedarray = new stdClass(); 2899 $expectedarray->firstname = 'Bruce'; 2900 $expectedarray->lastname = 'Campbell'; 2901 $expectedarray->firstnamephonetic = 'ブルース'; 2902 $expectedarray->lastnamephonetic = 'カンベッル'; 2903 $expectedarray->middlename = ''; 2904 $expectedarray->alternatename = ''; 2905 $this->assertEquals($user, $expectedarray); 2906 2907 // User information for showing a picture. 2908 $user = new stdClass(); 2909 $additionalfields = explode(',', user_picture::fields()); 2910 $user = username_load_fields_from_object($user, $userinfo, null, $additionalfields); 2911 $user->id = $userinfo->userid; 2912 $expectedarray = new stdClass(); 2913 $expectedarray->id = 1; 2914 $expectedarray->firstname = 'Bruce'; 2915 $expectedarray->lastname = 'Campbell'; 2916 $expectedarray->firstnamephonetic = 'ブルース'; 2917 $expectedarray->lastnamephonetic = 'カンベッル'; 2918 $expectedarray->middlename = ''; 2919 $expectedarray->alternatename = ''; 2920 $expectedarray->email = ''; 2921 $expectedarray->picture = 23; 2922 $expectedarray->imagealt = 'Michael Jordan draining another basket.'; 2923 $this->assertEquals($user, $expectedarray); 2924 2925 // Alter the userinfo object to have a prefix. 2926 $userinfo->authorfirstname = 'Bruce'; 2927 $userinfo->authorlastname = 'Campbell'; 2928 $userinfo->authorfirstnamephonetic = 'ブルース'; 2929 $userinfo->authorlastnamephonetic = 'カンベッル'; 2930 $userinfo->authormiddlename = ''; 2931 $userinfo->authorpicture = 23; 2932 $userinfo->authorimagealt = 'Michael Jordan draining another basket.'; 2933 $userinfo->authoremail = 'test@example.com'; 2934 2935 2936 // Return an object with user picture information. 2937 $user = new stdClass(); 2938 $additionalfields = explode(',', user_picture::fields()); 2939 $user = username_load_fields_from_object($user, $userinfo, 'author', $additionalfields); 2940 $user->id = $userinfo->userid; 2941 $expectedarray = new stdClass(); 2942 $expectedarray->id = 1; 2943 $expectedarray->firstname = 'Bruce'; 2944 $expectedarray->lastname = 'Campbell'; 2945 $expectedarray->firstnamephonetic = 'ブルース'; 2946 $expectedarray->lastnamephonetic = 'カンベッル'; 2947 $expectedarray->middlename = ''; 2948 $expectedarray->alternatename = ''; 2949 $expectedarray->email = 'test@example.com'; 2950 $expectedarray->picture = 23; 2951 $expectedarray->imagealt = 'Michael Jordan draining another basket.'; 2952 $this->assertEquals($user, $expectedarray); 2953 } 2954 2955 /** 2956 * Test function count_words(). 2957 */ 2958 public function test_count_words() { 2959 $count = count_words("one two three'four"); 2960 $this->assertEquals(3, $count); 2961 2962 $count = count_words('one+two three’four'); 2963 $this->assertEquals(3, $count); 2964 2965 $count = count_words('one"two three-four'); 2966 $this->assertEquals(2, $count); 2967 2968 $count = count_words('one@two three_four'); 2969 $this->assertEquals(4, $count); 2970 2971 $count = count_words('one\two three/four'); 2972 $this->assertEquals(4, $count); 2973 2974 $count = count_words(' one ... two three...four '); 2975 $this->assertEquals(4, $count); 2976 2977 $count = count_words('one.2 3,four'); 2978 $this->assertEquals(4, $count); 2979 2980 $count = count_words('1³ £2 €3.45 $6,789'); 2981 $this->assertEquals(4, $count); 2982 2983 $count = count_words('one—two ブルース カンベッル'); 2984 $this->assertEquals(4, $count); 2985 2986 $count = count_words('one…two ブルース … カンベッル'); 2987 $this->assertEquals(4, $count); 2988 } 2989 /** 2990 * Tests the getremoteaddr() function. 2991 */ 2992 public function test_getremoteaddr() { 2993 $xforwardedfor = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : null; 2994 2995 $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; 2996 $noip = getremoteaddr('1.1.1.1'); 2997 $this->assertEquals('1.1.1.1', $noip); 2998 2999 $_SERVER['HTTP_X_FORWARDED_FOR'] = ''; 3000 $noip = getremoteaddr(); 3001 $this->assertEquals('0.0.0.0', $noip); 3002 3003 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1'; 3004 $singleip = getremoteaddr(); 3005 $this->assertEquals('127.0.0.1', $singleip); 3006 3007 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,127.0.0.2'; 3008 $twoip = getremoteaddr(); 3009 $this->assertEquals('127.0.0.1', $twoip); 3010 3011 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,127.0.0.2, 127.0.0.3'; 3012 $threeip = getremoteaddr(); 3013 $this->assertEquals('127.0.0.1', $threeip); 3014 3015 $_SERVER['HTTP_X_FORWARDED_FOR'] = '127.0.0.1:65535,127.0.0.2'; 3016 $portip = getremoteaddr(); 3017 $this->assertEquals('127.0.0.1', $portip); 3018 3019 $_SERVER['HTTP_X_FORWARDED_FOR'] = '0:0:0:0:0:0:0:1,127.0.0.2'; 3020 $portip = getremoteaddr(); 3021 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 3022 3023 $_SERVER['HTTP_X_FORWARDED_FOR'] = '0::1,127.0.0.2'; 3024 $portip = getremoteaddr(); 3025 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 3026 3027 $_SERVER['HTTP_X_FORWARDED_FOR'] = '[0:0:0:0:0:0:0:1]:65535,127.0.0.2'; 3028 $portip = getremoteaddr(); 3029 $this->assertEquals('0:0:0:0:0:0:0:1', $portip); 3030 3031 $_SERVER['HTTP_X_FORWARDED_FOR'] = $xforwardedfor; 3032 3033 } 3034 3035 /* 3036 * Test emulation of random_bytes() function. 3037 */ 3038 public function test_random_bytes_emulate() { 3039 $result = random_bytes_emulate(10); 3040 $this->assertSame(10, strlen($result)); 3041 $this->assertnotSame($result, random_bytes_emulate(10)); 3042 3043 $result = random_bytes_emulate(21); 3044 $this->assertSame(21, strlen($result)); 3045 $this->assertnotSame($result, random_bytes_emulate(21)); 3046 3047 $result = random_bytes_emulate(666); 3048 $this->assertSame(666, strlen($result)); 3049 3050 $this->assertDebuggingNotCalled(); 3051 3052 $result = random_bytes_emulate(0); 3053 $this->assertSame('', $result); 3054 $this->assertDebuggingCalled(); 3055 3056 $result = random_bytes_emulate(-1); 3057 $this->assertSame('', $result); 3058 $this->assertDebuggingCalled(); 3059 } 3060 3061 /** 3062 * Test function for creation of random strings. 3063 */ 3064 public function test_random_string() { 3065 $pool = 'a-zA-Z0-9'; 3066 3067 $result = random_string(10); 3068 $this->assertSame(10, strlen($result)); 3069 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3070 $this->assertNotSame($result, random_string(10)); 3071 3072 $result = random_string(21); 3073 $this->assertSame(21, strlen($result)); 3074 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3075 $this->assertNotSame($result, random_string(21)); 3076 3077 $result = random_string(666); 3078 $this->assertSame(666, strlen($result)); 3079 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3080 3081 $result = random_string(); 3082 $this->assertSame(15, strlen($result)); 3083 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3084 3085 $this->assertDebuggingNotCalled(); 3086 3087 $result = random_string(0); 3088 $this->assertSame('', $result); 3089 $this->assertDebuggingCalled(); 3090 3091 $result = random_string(-1); 3092 $this->assertSame('', $result); 3093 $this->assertDebuggingCalled(); 3094 } 3095 3096 /** 3097 * Test function for creation of complex random strings. 3098 */ 3099 public function test_complex_random_string() { 3100 $pool = preg_quote('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#%^&*()_+-=[];,./<>?:{} ', '/'); 3101 3102 $result = complex_random_string(10); 3103 $this->assertSame(10, strlen($result)); 3104 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3105 $this->assertNotSame($result, complex_random_string(10)); 3106 3107 $result = complex_random_string(21); 3108 $this->assertSame(21, strlen($result)); 3109 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3110 $this->assertNotSame($result, complex_random_string(21)); 3111 3112 $result = complex_random_string(666); 3113 $this->assertSame(666, strlen($result)); 3114 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3115 3116 $result = complex_random_string(); 3117 $this->assertEquals(28, strlen($result), '', 4); // Expected length is 24 - 32. 3118 $this->assertRegExp('/^[' . $pool . ']+$/', $result); 3119 3120 $this->assertDebuggingNotCalled(); 3121 3122 $result = complex_random_string(0); 3123 $this->assertSame('', $result); 3124 $this->assertDebuggingCalled(); 3125 3126 $result = complex_random_string(-1); 3127 $this->assertSame('', $result); 3128 $this->assertDebuggingCalled(); 3129 } 3130 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |