MDL-24419 (3): Add new parameter to format_float for shorter display
[moodle.git] / lib / tests / moodlelib_test.php
CommitLineData
a3d5830a
PS
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 &copy; 2006 The Open University
23 * @author T.J.Hunt@open.ac.uk
24 * @author nicolas@moodle.com
25 */
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
30require_once($CFG->libdir . '/moodlelib.php');
31
32
4b027431 33class moodlelib_testcase extends advanced_testcase {
a3d5830a
PS
34
35 public static $includecoverage = array('lib/moodlelib.php');
36
37 var $user_agents = array(
38 'MSIE' => array(
39 '5.0' => array('Windows 98' => 'Mozilla/4.0 (compatible; MSIE 5.00; Windows 98)'),
40 '5.5' => array('Windows 2000' => 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)'),
41 '6.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'),
42 '7.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)'),
43 '8.0' => array('Windows Vista' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)'),
44 '9.0' => array('Windows 7' => 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))'),
45
46 ),
47 'Firefox' => array(
48 '1.0.6' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6'),
49 '1.5' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5'),
50 '1.5.0.1' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1'),
51 '2.0' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1',
52 'Ubuntu Linux AMD64' => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1) Gecko/20060601 Firefox/2.0 (Ubuntu-edgy)'),
53 '3.0.6' => array('SUSE' => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.6) Gecko/2009012700 SUSE/3.0.6-1.4 Firefox/3.0.6'),
54 ),
55 'Safari' => array(
56 '312' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312'),
57 '412' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412')
58 ),
59 'Safari iOS' => array(
60 '528' => array('iPhone' => 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; cs-cz) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7D11 Safari/528.16'),
61 '533' => array('iPad' => 'Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5'),
62 ),
63 'WebKit Android' => array(
64 '525' => array('G1 Phone' => 'Mozilla/5.0 (Linux; U; Android 1.1; en-gb; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 – G1 Phone'),
65 '530' => array('Nexus' => 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17 –Nexus'),
66 ),
67 'Chrome' => array(
68 '8' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10'),
69 ),
70 'Opera' => array(
71 '8.51' => array('Windows XP' => 'Opera/8.51 (Windows NT 5.1; U; en)'),
72 '9.0' => array('Windows XP' => 'Opera/9.0 (Windows NT 5.1; U; en)',
73 'Debian Linux' => 'Opera/9.01 (X11; Linux i686; U; en)')
74 )
75 );
76
77 function test_cleanremoteaddr() {
78 //IPv4
79 $this->assertEquals(cleanremoteaddr('1023.121.234.1'), null);
80 $this->assertEquals(cleanremoteaddr('123.121.234.01 '), '123.121.234.1');
81
82 //IPv6
83 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:0:0'), null);
84 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:abh'), null);
85 $this->assertEquals(cleanremoteaddr('0:0:0:::0:0:1'), null);
86 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:0:0', true), '::');
87 $this->assertEquals(cleanremoteaddr('0:0:0:0:0:0:1:1', true), '::1:1');
88 $this->assertEquals(cleanremoteaddr('abcd:00ef:0:0:0:0:0:0', true), 'abcd:ef::');
89 $this->assertEquals(cleanremoteaddr('1:0:0:0:0:0:0:1', true), '1::1');
90 $this->assertEquals(cleanremoteaddr('::10:1', false), '0:0:0:0:0:0:10:1');
91 $this->assertEquals(cleanremoteaddr('01:1::', false), '1:1:0:0:0:0:0:0');
92 $this->assertEquals(cleanremoteaddr('10::10', false), '10:0:0:0:0:0:0:10');
93 $this->assertEquals(cleanremoteaddr('::ffff:192.168.1.1', true), '::ffff:c0a8:11');
94 }
95
96 function test_address_in_subnet() {
97 /// 1: xxx.xxx.xxx.xxx/nn or xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/nnn (number of bits in net mask)
98 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.1/32'));
99 $this->assertFalse(address_in_subnet('123.121.23.1', '123.121.23.0/32'));
100 $this->assertTrue(address_in_subnet('10.10.10.100', '123.121.23.45/0'));
101 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/24'));
102 $this->assertFalse(address_in_subnet('123.121.34.1', '123.121.234.0/24'));
103 $this->assertTrue(address_in_subnet('123.121.234.1', '123.121.234.0/30'));
104 $this->assertFalse(address_in_subnet('123.121.23.8', '123.121.23.0/30'));
105 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128'));
106 $this->assertFalse(address_in_subnet('bab:baba::baba', 'bab:baba::cece/128'));
107 $this->assertTrue(address_in_subnet('baba:baba::baba', 'cece:cece::cece/0'));
108 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba/128'));
109 $this->assertTrue(address_in_subnet('baba:baba::00ba', 'baba:baba::/120'));
110 $this->assertFalse(address_in_subnet('baba:baba::aba', 'baba:baba::/120'));
111 $this->assertTrue(address_in_subnet('baba::baba:00ba', 'baba::baba:0/112'));
112 $this->assertFalse(address_in_subnet('baba::aba:00ba', 'baba::baba:0/112'));
113 $this->assertFalse(address_in_subnet('aba::baba:0000', 'baba::baba:0/112'));
114
115 // fixed input
116 $this->assertTrue(address_in_subnet('123.121.23.1 ', ' 123.121.23.0 / 24'));
117 $this->assertTrue(address_in_subnet('::ffff:10.1.1.1', ' 0:0:0:000:0:ffff:a1:10 / 126'));
118
119 // incorrect input
120 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/-2'));
121 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/64'));
122 $this->assertFalse(address_in_subnet('123.121.234.x', '123.121.234.1/24'));
123 $this->assertFalse(address_in_subnet('123.121.234.0', '123.121.234.xx/24'));
124 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.1/xx0'));
125 $this->assertFalse(address_in_subnet('::1', '::aa:0/xx0'));
126 $this->assertFalse(address_in_subnet('::1', '::aa:0/-5'));
127 $this->assertFalse(address_in_subnet('::1', '::aa:0/130'));
128 $this->assertFalse(address_in_subnet('x:1', '::aa:0/130'));
129 $this->assertFalse(address_in_subnet('::1', '::ax:0/130'));
130
131
132 /// 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)
133 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12-14'));
134 $this->assertTrue(address_in_subnet('123.121.234.13', '123.121.234.12-14'));
135 $this->assertTrue(address_in_subnet('123.121.234.14', '123.121.234.12-14'));
136 $this->assertFalse(address_in_subnet('123.121.234.1', '123.121.234.12-14'));
137 $this->assertFalse(address_in_subnet('123.121.234.20', '123.121.234.12-14'));
138 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.234.12-14'));
139 $this->assertFalse(address_in_subnet('123.12.234.12', '123.121.234.12-14'));
140 $this->assertTrue(address_in_subnet('baba:baba::baba', 'baba:baba::baba-babe'));
141 $this->assertTrue(address_in_subnet('baba:baba::babc', 'baba:baba::baba-babe'));
142 $this->assertTrue(address_in_subnet('baba:baba::babe', 'baba:baba::baba-babe'));
143 $this->assertFalse(address_in_subnet('bab:baba::bab0', 'bab:baba::baba-babe'));
144 $this->assertFalse(address_in_subnet('bab:baba::babf', 'bab:baba::baba-babe'));
145 $this->assertFalse(address_in_subnet('bab:baba::bfbe', 'bab:baba::baba-babe'));
146 $this->assertFalse(address_in_subnet('bfb:baba::babe', 'bab:baba::baba-babe'));
147
148 // fixed input
149 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12 - 14 '));
150 $this->assertTrue(address_in_subnet('bab:baba::babe', 'bab:baba::baba - babe '));
151
152 // incorrect input
153 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-234.14'));
154 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12-256'));
155 $this->assertFalse(address_in_subnet('123.121.234.12', '123.121.234.12--256'));
156
157
158 /// 3: xxx.xxx or xxx.xxx. or xxx:xxx:xxxx or xxx:xxx:xxxx. (incomplete address, a bit non-technical ;-)
159 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.12'));
160 $this->assertFalse(address_in_subnet('123.121.23.12', '123.121.23.13'));
161 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234.'));
162 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121.234'));
163 $this->assertTrue(address_in_subnet('123.121.234.12', '123.121'));
164 $this->assertTrue(address_in_subnet('123.121.234.12', '123'));
165 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234.'));
166 $this->assertFalse(address_in_subnet('123.121.234.1', '12.121.234'));
167 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba::bab'));
168 $this->assertFalse(address_in_subnet('baba:baba::ba', 'baba:baba::bc'));
169 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:baba'));
170 $this->assertTrue(address_in_subnet('baba:baba::bab', 'baba:'));
171 $this->assertFalse(address_in_subnet('bab:baba::bab', 'baba:'));
172
173
174 /// multiple subnets
175 $this->assertTrue(address_in_subnet('123.121.234.12', '::1/64, 124., 123.121.234.10-30'));
176 $this->assertTrue(address_in_subnet('124.121.234.12', '::1/64, 124., 123.121.234.10-30'));
177 $this->assertTrue(address_in_subnet('::2', '::1/64, 124., 123.121.234.10-30'));
178 $this->assertFalse(address_in_subnet('12.121.234.12', '::1/64, 124., 123.121.234.10-30'));
179
180
181 /// other incorrect input
182 $this->assertFalse(address_in_subnet('123.123.123.123', ''));
183 }
184
185 /**
186 * Modifies $_SERVER['HTTP_USER_AGENT'] manually to check if check_browser_version
187 * works as expected.
188 */
189 function test_check_browser_version()
190 {
191 global $CFG;
192
193 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['412']['Mac OS X'];
194 $this->assertTrue(check_browser_version('Safari'));
195 $this->assertTrue(check_browser_version('WebKit'));
196 $this->assertTrue(check_browser_version('Safari', '312'));
197 $this->assertFalse(check_browser_version('Safari', '500'));
198 $this->assertFalse(check_browser_version('Chrome'));
199 $this->assertFalse(check_browser_version('Safari iOS'));
200
201 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari iOS']['528']['iPhone'];
202 $this->assertTrue(check_browser_version('Safari iOS'));
203 $this->assertTrue(check_browser_version('WebKit'));
204 $this->assertTrue(check_browser_version('Safari iOS', '527'));
205 $this->assertFalse(check_browser_version('Safari iOS', 590));
206 $this->assertFalse(check_browser_version('Safari', '312'));
207 $this->assertFalse(check_browser_version('Safari', '500'));
208 $this->assertFalse(check_browser_version('Chrome'));
209
210 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['WebKit Android']['530']['Nexus'];
211 $this->assertTrue(check_browser_version('WebKit'));
212 $this->assertTrue(check_browser_version('WebKit Android', '527'));
213 $this->assertFalse(check_browser_version('WebKit Android', 590));
214 $this->assertFalse(check_browser_version('Safari'));
215 $this->assertFalse(check_browser_version('Chrome'));
216
217 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
218 $this->assertTrue(check_browser_version('Chrome'));
219 $this->assertTrue(check_browser_version('WebKit'));
220 $this->assertTrue(check_browser_version('Chrome', 8));
221 $this->assertFalse(check_browser_version('Chrome', 10));
222 $this->assertFalse(check_browser_version('Safari', '1'));
223
224 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
225 $this->assertTrue(check_browser_version('Opera'));
226 $this->assertTrue(check_browser_version('Opera', '8.0'));
227 $this->assertFalse(check_browser_version('Opera', '10.0'));
228
229 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['6.0']['Windows XP SP2'];
230 $this->assertTrue(check_browser_version('MSIE'));
231 $this->assertTrue(check_browser_version('MSIE', '5.0'));
232 $this->assertFalse(check_browser_version('MSIE', '7.0'));
233
234 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['5.0']['Windows 98'];
235 $this->assertFalse(check_browser_version('MSIE'));
236 $this->assertTrue(check_browser_version('MSIE', 0));
237 $this->assertTrue(check_browser_version('MSIE', '5.0'));
238 $this->assertFalse(check_browser_version('MSIE', '7.0'));
239
240 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['9.0']['Windows 7'];
241 $this->assertTrue(check_browser_version('MSIE'));
242 $this->assertTrue(check_browser_version('MSIE', 0));
243 $this->assertTrue(check_browser_version('MSIE', '5.0'));
244 $this->assertTrue(check_browser_version('MSIE', '9.0'));
245 $this->assertFalse(check_browser_version('MSIE', '10'));
246
247 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
248 $this->assertTrue(check_browser_version('Firefox'));
249 $this->assertTrue(check_browser_version('Firefox', '1.5'));
250 $this->assertFalse(check_browser_version('Firefox', '3.0'));
251 }
252
253 function test_get_browser_version_classes() {
254 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['412']['Mac OS X'];
255 $this->assertEquals(array('safari'), get_browser_version_classes());
256
257 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
258 $this->assertEquals(array('safari'), get_browser_version_classes());
259
260 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari iOS']['528']['iPhone'];
261 $this->assertEquals(array('safari', 'ios'), get_browser_version_classes());
262
263 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['WebKit Android']['530']['Nexus'];
264 $this->assertEquals(array('safari', 'android'), get_browser_version_classes());
265
266 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Chrome']['8']['Mac OS X'];
267 $this->assertEquals(array('safari'), get_browser_version_classes());
268
269 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
270 $this->assertEquals(array('opera'), get_browser_version_classes());
271
272 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['6.0']['Windows XP SP2'];
273 $this->assertEquals(array('ie', 'ie6'), get_browser_version_classes());
274
275 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['7.0']['Windows XP SP2'];
276 $this->assertEquals(array('ie', 'ie7'), get_browser_version_classes());
277
278 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['8.0']['Windows Vista'];
279 $this->assertEquals(array('ie', 'ie8'), get_browser_version_classes());
280
281 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
282 $this->assertEquals(array('gecko', 'gecko18'), get_browser_version_classes());
283
284 $_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['3.0.6']['SUSE'];
285 $this->assertEquals(array('gecko', 'gecko19'), get_browser_version_classes());
286 }
287
288 function test_get_device_type() {
289 // IE8 (common pattern ~1.5% of IE7/8 users have embedded IE6 agent))
290 $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; BT Openworld BB; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Hotbar 10.2.197.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727)';
291 $this->assertEquals('default', get_device_type());
292 // Genuine IE6
293 $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/4.0 (compatible; MSIE 6.0; AOL 9.0; Windows NT 5.1; SV1; FunWebProducts; .NET CLR 1.0.3705; Media Center PC 2.8)';
294 $this->assertEquals('legacy', get_device_type());
295 }
296
297 function test_fix_utf8() {
298 // make sure valid data including other types is not changed
299 $this->assertSame(null, fix_utf8(null));
300 $this->assertSame(1, fix_utf8(1));
301 $this->assertSame(1.1, fix_utf8(1.1));
302 $this->assertSame(true, fix_utf8(true));
303 $this->assertSame('', fix_utf8(''));
304 $array = array('do', 're', 'mi');
305 $this->assertSame($array, fix_utf8($array));
306 $object = new stdClass();
307 $object->a = 'aa';
308 $object->b = 'bb';
309 $this->assertEquals($object, fix_utf8($object));
310
311 // valid utf8 string
312 $this->assertSame("žlutý koníček přeskočil potůček \n\t\r\0", fix_utf8("žlutý koníček přeskočil potůček \n\t\r\0"));
313
314 // invalid utf8 string
315 $this->assertSame('aaabbb', fix_utf8('aaa'.chr(130).'bbb'));
316 }
317
318 function test_optional_param() {
319 global $CFG;
320
321 $_POST['username'] = 'post_user';
322 $_GET['username'] = 'get_user';
323 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_POST['username']);
324
325 unset($_POST['username']);
326 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_GET['username']);
327
328 unset($_GET['username']);
329 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), 'default_user');
330
331 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
332 $_POST['username'] = 'post_user';
333 try {
334 optional_param('username', 'default_user', null);
335 $this->fail('coding_exception expected');
336 } catch (coding_exception $ex) {
337 $this->assertTrue(true);
338 }
339 try {
340 @optional_param('username', 'default_user');
341 $this->fail('coding_exception expected');
342 } catch (coding_exception $ex) {
343 $this->assertTrue(true);
344 }
345 try {
346 @optional_param('username');
347 $this->fail('coding_exception expected');
348 } catch (coding_exception $ex) {
349 $this->assertTrue(true);
350 }
351 try {
352 optional_param('', 'default_user', PARAM_RAW);
353 $this->fail('coding_exception expected');
354 } catch (coding_exception $ex) {
355 $this->assertTrue(true);
356 }
357
358 // make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3
359 $debugging = isset($CFG->debug) ? $CFG->debug : null;
360 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
361 $CFG->debug = DEBUG_DEVELOPER;
362 $CFG->debugdisplay = true;
363
364 ob_start();
365 $this->assertSame(optional_param('username', 'default_user', PARAM_RAW), $_POST['username']);
366 $d = ob_end_clean();
367 $this->assertTrue($d !== '');
368
369 if ($debugging !== null) {
370 $CFG->debug = $debugging;
371 } else {
372 unset($CFG->debug);
373 }
374 if ($debugdisplay !== null) {
375 $CFG->debugdisplay = $debugdisplay;
376 } else {
377 unset($CFG->debugdisplay);
378 }
379 }
380
381 function test_optional_param_array() {
382 global $CFG;
383
384 $_POST['username'] = array('a'=>'post_user');
385 $_GET['username'] = array('a'=>'get_user');
386 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), $_POST['username']);
387
388 unset($_POST['username']);
389 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), $_GET['username']);
390
391 unset($_GET['username']);
392 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), array('a'=>'default_user'));
393
394 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
395 $_POST['username'] = array('a'=>'post_user');
396 try {
397 optional_param_array('username', array('a'=>'default_user'), null);
398 $this->fail('coding_exception expected');
399 } catch (coding_exception $ex) {
400 $this->assertTrue(true);
401 }
402 try {
403 @optional_param_array('username', array('a'=>'default_user'));
404 $this->fail('coding_exception expected');
405 } catch (coding_exception $ex) {
406 $this->assertTrue(true);
407 }
408 try {
409 @optional_param_array('username');
410 $this->fail('coding_exception expected');
411 } catch (coding_exception $ex) {
412 $this->assertTrue(true);
413 }
414 try {
415 optional_param_array('', array('a'=>'default_user'), PARAM_RAW);
416 $this->fail('coding_exception expected');
417 } catch (coding_exception $ex) {
418 $this->assertTrue(true);
419 }
420
421 // do not allow nested arrays
422 try {
423 $_POST['username'] = array('a'=>array('b'=>'post_user'));
424 optional_param_array('username', array('a'=>'default_user'), PARAM_RAW);
425 $this->fail('coding_exception expected');
426 } catch (coding_exception $ex) {
427 $this->assertTrue(true);
428 }
429
430 // do not allow non-arrays
431 $debugging = isset($CFG->debug) ? $CFG->debug : null;
432 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
433 $CFG->debug = DEBUG_DEVELOPER;
434 $CFG->debugdisplay = true;
435
436 ob_start();
437 $_POST['username'] = 'post_user';
438 $this->assertSame(optional_param_array('username', array('a'=>'default_user'), PARAM_RAW), array('a'=>'default_user'));
439 $d = ob_end_clean();
440 $this->assertTrue($d !== '');
441
442 // make sure array keys are sanitised
443 ob_start();
444 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user');
445 $this->assertSame(optional_param_array('username', array(), PARAM_RAW), array('a1_-'=>'post_user'));
446 $d = ob_end_clean();
447 $this->assertTrue($d !== '');
448
449 if ($debugging !== null) {
450 $CFG->debug = $debugging;
451 } else {
452 unset($CFG->debug);
453 }
454 if ($debugdisplay !== null) {
455 $CFG->debugdisplay = $debugdisplay;
456 } else {
457 unset($CFG->debugdisplay);
458 }
459 }
460
461 function test_required_param() {
462 global $CFG;
463
464 $_POST['username'] = 'post_user';
465 $_GET['username'] = 'get_user';
466 $this->assertSame(required_param('username', PARAM_RAW), 'post_user');
467
468 unset($_POST['username']);
469 $this->assertSame(required_param('username', PARAM_RAW), 'get_user');
470
471 unset($_GET['username']);
472 try {
473 $this->assertSame(required_param('username', PARAM_RAW), 'default_user');
474 $this->fail('moodle_exception expected');
475 } catch (moodle_exception $ex) {
476 $this->assertTrue(true);
477 }
478
479 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
480 $_POST['username'] = 'post_user';
481 try {
482 @required_param('username');
483 $this->fail('coding_exception expected');
484 } catch (coding_exception $ex) {
485 $this->assertTrue(true);
486 }
487 try {
488 required_param('username', '');
489 $this->fail('coding_exception expected');
490 } catch (coding_exception $ex) {
491 $this->assertTrue(true);
492 }
493 try {
494 required_param('', PARAM_RAW);
495 $this->fail('coding_exception expected');
496 } catch (coding_exception $ex) {
497 $this->assertTrue(true);
498 }
499
500 // make sure warning is displayed if array submitted - TODO: throw exception in Moodle 2.3
501 $debugging = isset($CFG->debug) ? $CFG->debug : null;
502 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
503 $CFG->debug = DEBUG_DEVELOPER;
504 $CFG->debugdisplay = true;
505
506 ob_start();
507 $this->assertSame(required_param('username', PARAM_RAW), $_POST['username']);
508 $d = ob_end_clean();
509 $this->assertTrue($d !== '');
510
511 if ($debugging !== null) {
512 $CFG->debug = $debugging;
513 } else {
514 unset($CFG->debug);
515 }
516 if ($debugdisplay !== null) {
517 $CFG->debugdisplay = $debugdisplay;
518 } else {
519 unset($CFG->debugdisplay);
520 }
521 }
522
523 function test_required_param_array() {
524 global $CFG;
525
526 $_POST['username'] = array('a'=>'post_user');
527 $_GET['username'] = array('a'=>'get_user');
528 $this->assertSame(required_param_array('username', PARAM_RAW), $_POST['username']);
529
530 unset($_POST['username']);
531 $this->assertSame(required_param_array('username', PARAM_RAW), $_GET['username']);
532
533 // make sure exception is triggered when some params are missing, hide error notices here - new in 2.2
534 $_POST['username'] = array('a'=>'post_user');
535 try {
536 required_param_array('username', null);
537 $this->fail('coding_exception expected');
538 } catch (coding_exception $ex) {
539 $this->assertTrue(true);
540 }
541 try {
542 @required_param_array('username');
543 $this->fail('coding_exception expected');
544 } catch (coding_exception $ex) {
545 $this->assertTrue(true);
546 }
547 try {
548 required_param_array('', PARAM_RAW);
549 $this->fail('coding_exception expected');
550 } catch (coding_exception $ex) {
551 $this->assertTrue(true);
552 }
553
554 // do not allow nested arrays
555 try {
556 $_POST['username'] = array('a'=>array('b'=>'post_user'));
557 required_param_array('username', PARAM_RAW);
558 $this->fail('coding_exception expected');
559 } catch (coding_exception $ex) {
560 $this->assertTrue(true);
561 }
562
563 // do not allow non-arrays
564 try {
565 $_POST['username'] = 'post_user';
566 required_param_array('username', PARAM_RAW);
567 $this->fail('moodle_exception expected');
568 } catch (moodle_exception $ex) {
569 $this->assertTrue(true);
570 }
571
572 // do not allow non-arrays
573 $debugging = isset($CFG->debug) ? $CFG->debug : null;
574 $debugdisplay = isset($CFG->debugdisplay) ? $CFG->debugdisplay : null;
575 $CFG->debug = DEBUG_DEVELOPER;
576 $CFG->debugdisplay = true;
577
578 // make sure array keys are sanitised
579 ob_start();
580 $_POST['username'] = array('abc123_;-/*-+ '=>'arrggh', 'a1_-'=>'post_user');
581 $this->assertSame(required_param_array('username', PARAM_RAW), array('a1_-'=>'post_user'));
582 $d = ob_end_clean();
583 $this->assertTrue($d !== '');
584
585 if ($debugging !== null) {
586 $CFG->debug = $debugging;
587 } else {
588 unset($CFG->debug);
589 }
590 if ($debugdisplay !== null) {
591 $CFG->debugdisplay = $debugdisplay;
592 } else {
593 unset($CFG->debugdisplay);
594 }
595 }
596
597 function test_clean_param() {
598 // forbid objects and arrays
599 try {
600 clean_param(array('x', 'y'), PARAM_RAW);
601 $this->fail('coding_exception expected');
602 } catch (coding_exception $ex) {
603 $this->assertTrue(true);
604 }
605 try {
606 $param = new stdClass();
607 $param->id = 1;
608 clean_param($param, PARAM_RAW);
609 $this->fail('coding_exception expected');
610 } catch (coding_exception $ex) {
611 $this->assertTrue(true);
612 }
613
614 // require correct type
615 try {
616 clean_param('x', 'xxxxxx');
617 $this->fail('moodle_exception expected');
618 } catch (moodle_exception $ex) {
619 $this->assertTrue(true);
620 }
621 try {
622 @clean_param('x');
623 $this->fail('moodle_exception expected');
624 } catch (moodle_exception $ex) {
625 $this->assertTrue(true);
626 }
627
628 }
629
630 function test_clean_param_array() {
631 $this->assertSame(clean_param_array(null, PARAM_RAW), array());
632 $this->assertSame(clean_param_array(array('a', 'b'), PARAM_RAW), array('a', 'b'));
633 $this->assertSame(clean_param_array(array('a', array('b')), PARAM_RAW, true), array('a', array('b')));
634
635 // require correct type
636 try {
637 clean_param_array(array('x'), 'xxxxxx');
638 $this->fail('moodle_exception expected');
639 } catch (moodle_exception $ex) {
640 $this->assertTrue(true);
641 }
642 try {
643 @clean_param_array(array('x'));
644 $this->fail('moodle_exception expected');
645 } catch (moodle_exception $ex) {
646 $this->assertTrue(true);
647 }
648
649 try {
650 clean_param_array(array('x', array('y')), PARAM_RAW);
651 $this->fail('coding_exception expected');
652 } catch (coding_exception $ex) {
653 $this->assertTrue(true);
654 }
655
656 // test recursive
657 }
658
659 function test_clean_param_raw() {
660 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_RAW),
661 '#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)');
662 }
663
664 function test_clean_param_trim() {
665 $this->assertEquals(clean_param(" Frog toad \r\n ", PARAM_RAW_TRIMMED), 'Frog toad');
666 }
667
668 function test_clean_param_clean() {
669 // PARAM_CLEAN is an ugly hack, do not use in new code (skodak)
670 // instead use more specific type, or submit sothing that can be verified properly
671 $this->assertEquals(clean_param('xx<script>', PARAM_CLEAN), 'xx');
672 }
673
674 function test_clean_param_alpha() {
675 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHA),
676 'DSFMOSDJ');
677 }
678
679 function test_clean_param_alphanum() {
680 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHANUM),
681 '978942897DSFMOSDJ');
682 }
683
684 function test_clean_param_alphaext() {
685 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_ALPHAEXT),
686 'DSFMOSDJ');
687 }
688
689 function test_clean_param_sequence() {
690 $this->assertEquals(clean_param('#()*#,9789\'".,<42897></?$(*DSFMO#$*)(SDJ)($*)', PARAM_SEQUENCE),
691 ',9789,42897');
692 }
693
694 function test_clean_param_component() {
695 // please note the cleaning of component names is very strict, no guessing here
696 $this->assertSame(clean_param('mod_forum', PARAM_COMPONENT), 'mod_forum');
697 $this->assertSame(clean_param('block_online_users', PARAM_COMPONENT), 'block_online_users');
698 $this->assertSame(clean_param('block_blond_online_users', PARAM_COMPONENT), 'block_blond_online_users');
699 $this->assertSame(clean_param('mod_something2', PARAM_COMPONENT), 'mod_something2');
700 $this->assertSame(clean_param('forum', PARAM_COMPONENT), 'forum');
701 $this->assertSame(clean_param('user', PARAM_COMPONENT), 'user');
702 $this->assertSame(clean_param('rating', PARAM_COMPONENT), 'rating');
703 $this->assertSame(clean_param('mod_2something', PARAM_COMPONENT), '');
704 $this->assertSame(clean_param('2mod_something', PARAM_COMPONENT), '');
705 $this->assertSame(clean_param('mod_something_xx', PARAM_COMPONENT), '');
706 $this->assertSame(clean_param('auth_something__xx', PARAM_COMPONENT), '');
707 $this->assertSame(clean_param('mod_Something', PARAM_COMPONENT), '');
708 $this->assertSame(clean_param('mod_somethíng', PARAM_COMPONENT), '');
709 $this->assertSame(clean_param('auth_xx-yy', PARAM_COMPONENT), '');
710 $this->assertSame(clean_param('_auth_xx', PARAM_COMPONENT), '');
711 $this->assertSame(clean_param('a2uth_xx', PARAM_COMPONENT), '');
712 $this->assertSame(clean_param('auth_xx_', PARAM_COMPONENT), '');
713 $this->assertSame(clean_param('auth_xx.old', PARAM_COMPONENT), '');
714 $this->assertSame(clean_param('_user', PARAM_COMPONENT), '');
715 $this->assertSame(clean_param('2rating', PARAM_COMPONENT), '');
716 $this->assertSame(clean_param('user_', PARAM_COMPONENT), '');
717 }
718
719 function test_clean_param_plugin() {
720 // please note the cleaning of plugin names is very strict, no guessing here
721 $this->assertSame(clean_param('forum', PARAM_PLUGIN), 'forum');
722 $this->assertSame(clean_param('forum2', PARAM_PLUGIN), 'forum2');
723 $this->assertSame(clean_param('online_users', PARAM_PLUGIN), 'online_users');
724 $this->assertSame(clean_param('blond_online_users', PARAM_PLUGIN), 'blond_online_users');
725 $this->assertSame(clean_param('online__users', PARAM_PLUGIN), '');
726 $this->assertSame(clean_param('forum ', PARAM_PLUGIN), '');
727 $this->assertSame(clean_param('forum.old', PARAM_PLUGIN), '');
728 $this->assertSame(clean_param('xx-yy', PARAM_PLUGIN), '');
729 $this->assertSame(clean_param('2xx', PARAM_PLUGIN), '');
730 $this->assertSame(clean_param('Xx', PARAM_PLUGIN), '');
731 $this->assertSame(clean_param('_xx', PARAM_PLUGIN), '');
732 $this->assertSame(clean_param('xx_', PARAM_PLUGIN), '');
733 }
734
735 function test_clean_param_area() {
736 // please note the cleaning of area names is very strict, no guessing here
737 $this->assertSame(clean_param('something', PARAM_AREA), 'something');
738 $this->assertSame(clean_param('something2', PARAM_AREA), 'something2');
739 $this->assertSame(clean_param('some_thing', PARAM_AREA), 'some_thing');
740 $this->assertSame(clean_param('some_thing_xx', PARAM_AREA), 'some_thing_xx');
741 $this->assertSame(clean_param('_something', PARAM_AREA), '');
742 $this->assertSame(clean_param('something_', PARAM_AREA), '');
743 $this->assertSame(clean_param('2something', PARAM_AREA), '');
744 $this->assertSame(clean_param('Something', PARAM_AREA), '');
745 $this->assertSame(clean_param('some-thing', PARAM_AREA), '');
746 $this->assertSame(clean_param('somethííng', PARAM_AREA), '');
747 $this->assertSame(clean_param('something.x', PARAM_AREA), '');
748 }
749
750 function test_clean_param_text() {
751 $this->assertEquals(PARAM_TEXT, PARAM_MULTILANG);
752 //standard
753 $this->assertEquals(clean_param('xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>', PARAM_TEXT), 'xx<lang lang="en">aa</lang><lang lang="yy">pp</lang>');
754 $this->assertEquals(clean_param('<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>', PARAM_TEXT), '<span lang="en" class="multilang">aa</span><span lang="xy" class="multilang">bb</span>');
755 $this->assertEquals(clean_param('xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>', PARAM_TEXT), 'xx<lang lang="en">aa'."\n".'</lang><lang lang="yy">pp</lang>');
756 //malformed
757 $this->assertEquals(clean_param('<span lang="en" class="multilang">aa</span>', PARAM_TEXT), '<span lang="en" class="multilang">aa</span>');
758 $this->assertEquals(clean_param('<span lang="en" class="nothing" class="multilang">aa</span>', PARAM_TEXT), 'aa');
759 $this->assertEquals(clean_param('<lang lang="en" class="multilang">aa</lang>', PARAM_TEXT), 'aa');
760 $this->assertEquals(clean_param('<lang lang="en!!">aa</lang>', PARAM_TEXT), 'aa');
761 $this->assertEquals(clean_param('<span lang="en==" class="multilang">aa</span>', PARAM_TEXT), 'aa');
762 $this->assertEquals(clean_param('a<em>b</em>c', PARAM_TEXT), 'abc');
763 $this->assertEquals(clean_param('a><xx >c>', PARAM_TEXT), 'a>c>'); // standard strip_tags() behaviour
764 $this->assertEquals(clean_param('a<b', PARAM_TEXT), 'a');
765 $this->assertEquals(clean_param('a>b', PARAM_TEXT), 'a>b');
766 $this->assertEquals(clean_param('<lang lang="en">a>a</lang>', PARAM_TEXT), '<lang lang="en">a>a</lang>'); // standard strip_tags() behaviour
767 $this->assertEquals(clean_param('<lang lang="en">a<a</lang>', PARAM_TEXT), 'a');
768 $this->assertEquals(clean_param('<lang lang="en">a<br>a</lang>', PARAM_TEXT), '<lang lang="en">aa</lang>');
769 }
770
771 function test_clean_param_url() {
772 // Test PARAM_URL and PARAM_LOCALURL a bit
773 $this->assertEquals(clean_param('http://google.com/', PARAM_URL), 'http://google.com/');
774 $this->assertEquals(clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_URL), 'http://some.very.long.and.silly.domain/with/a/path/');
775 $this->assertEquals(clean_param('http://localhost/', PARAM_URL), 'http://localhost/');
776 $this->assertEquals(clean_param('http://0.255.1.1/numericip.php', PARAM_URL), 'http://0.255.1.1/numericip.php');
777 $this->assertEquals(clean_param('/just/a/path', PARAM_URL), '/just/a/path');
778 $this->assertEquals(clean_param('funny:thing', PARAM_URL), '');
779 }
780
781 function test_clean_param_localurl() {
782 global $CFG;
783 $this->assertEquals(clean_param('http://google.com/', PARAM_LOCALURL), '');
784 $this->assertEquals(clean_param('http://some.very.long.and.silly.domain/with/a/path/', PARAM_LOCALURL), '');
785 $this->assertEquals(clean_param($CFG->wwwroot, PARAM_LOCALURL), $CFG->wwwroot);
786 $this->assertEquals(clean_param('/just/a/path', PARAM_LOCALURL), '/just/a/path');
787 $this->assertEquals(clean_param('funny:thing', PARAM_LOCALURL), '');
788 $this->assertEquals(clean_param('course/view.php?id=3', PARAM_LOCALURL), 'course/view.php?id=3');
789 }
790
791 function test_clean_param_file() {
792 $this->assertEquals(clean_param('correctfile.txt', PARAM_FILE), 'correctfile.txt');
793 $this->assertEquals(clean_param('b\'a<d`\\/fi:l>e.t"x|t', PARAM_FILE), 'badfile.txt');
794 $this->assertEquals(clean_param('../parentdirfile.txt', PARAM_FILE), 'parentdirfile.txt');
795 //The following behaviours have been maintained although they seem a little odd
796 $this->assertEquals(clean_param('funny:thing', PARAM_FILE), 'funnything');
797 $this->assertEquals(clean_param('./currentdirfile.txt', PARAM_FILE), '.currentdirfile.txt');
798 $this->assertEquals(clean_param('c:\temp\windowsfile.txt', PARAM_FILE), 'ctempwindowsfile.txt');
799 $this->assertEquals(clean_param('/home/user/linuxfile.txt', PARAM_FILE), 'homeuserlinuxfile.txt');
800 $this->assertEquals(clean_param('~/myfile.txt', PARAM_FILE), '~myfile.txt');
801 }
802
803 function test_clean_param_username() {
804 global $CFG;
805 $currentstatus = $CFG->extendedusernamechars;
806
807 // Run tests with extended character == FALSE;
808 $CFG->extendedusernamechars = FALSE;
809 $this->assertEquals(clean_param('johndoe123', PARAM_USERNAME), 'johndoe123' );
810 $this->assertEquals(clean_param('john.doe', PARAM_USERNAME), 'john.doe');
811 $this->assertEquals(clean_param('john-doe', PARAM_USERNAME), 'john-doe');
812 $this->assertEquals(clean_param('john- doe', PARAM_USERNAME), 'john-doe');
813 $this->assertEquals(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
814 $this->assertEquals(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
815 $this->assertEquals(clean_param('john~doe', PARAM_USERNAME), 'johndoe');
816 $this->assertEquals(clean_param('john´doe', PARAM_USERNAME), 'johndoe');
817 $this->assertEquals(clean_param('john#$%&() ', PARAM_USERNAME), 'john');
818 $this->assertEquals(clean_param('JOHNdóé ', PARAM_USERNAME), 'johnd');
819 $this->assertEquals(clean_param('john.,:;-_/|\ñÑ[]A_X-,D {} ~!@#$%^&*()_+ ?><[] ščřžžý ?ýá\9e?\9eý??\9adoe ', PARAM_USERNAME), 'john.-_a_x-d@_doe');
820
821
822 // Test success condition, if extendedusernamechars == ENABLE;
823 $CFG->extendedusernamechars = TRUE;
824 $this->assertEquals(clean_param('john_doe', PARAM_USERNAME), 'john_doe');
825 $this->assertEquals(clean_param('john@doe', PARAM_USERNAME), 'john@doe');
826 $this->assertEquals(clean_param('john# $%&()+_^', PARAM_USERNAME), 'john#$%&()+_^');
827 $this->assertEquals(clean_param('john~doe', PARAM_USERNAME), 'john~doe');
828 $this->assertEquals(clean_param('joHN´doe', PARAM_USERNAME), 'john´doe');
829 $this->assertEquals(clean_param('johnDOE', PARAM_USERNAME), 'johndoe');
830 $this->assertEquals(clean_param('johndóé ', PARAM_USERNAME), 'johndóé');
831
832 $CFG->extendedusernamechars = $currentstatus;
833 }
834
835 function test_clean_param_stringid() {
836 // Test string identifiers validation
837 // valid strings:
838 $this->assertEquals(clean_param('validstring', PARAM_STRINGID), 'validstring');
839 $this->assertEquals(clean_param('mod/foobar:valid_capability', PARAM_STRINGID), 'mod/foobar:valid_capability');
840 $this->assertEquals(clean_param('CZ', PARAM_STRINGID), 'CZ');
841 $this->assertEquals(clean_param('application/vnd.ms-powerpoint', PARAM_STRINGID), 'application/vnd.ms-powerpoint');
842 $this->assertEquals(clean_param('grade2', PARAM_STRINGID), 'grade2');
843 // invalid strings:
844 $this->assertEquals(clean_param('trailing ', PARAM_STRINGID), '');
845 $this->assertEquals(clean_param('space bar', PARAM_STRINGID), '');
846 $this->assertEquals(clean_param('0numeric', PARAM_STRINGID), '');
847 $this->assertEquals(clean_param('*', PARAM_STRINGID), '');
848 $this->assertEquals(clean_param(' ', PARAM_STRINGID), '');
849 }
850
851 function test_clean_param_timezone() {
852 // Test timezone validation
853 $testvalues = array (
854 'America/Jamaica' => 'America/Jamaica',
855 'America/Argentina/Cordoba' => 'America/Argentina/Cordoba',
856 'America/Port-au-Prince' => 'America/Port-au-Prince',
857 'America/Argentina/Buenos_Aires' => 'America/Argentina/Buenos_Aires',
858 'PST8PDT' => 'PST8PDT',
859 'Wrong.Value' => '',
860 'Wrong/.Value' => '',
861 'Wrong(Value)' => '',
862 '0' => '0',
863 '0.0' => '0.0',
864 '0.5' => '0.5',
865 '-12.5' => '-12.5',
866 '+12.5' => '+12.5',
867 '13.5' => '',
868 '-13.5' => '',
869 '0.2' => '');
870
871 foreach ($testvalues as $testvalue => $expectedvalue) {
872 $actualvalue = clean_param($testvalue, PARAM_TIMEZONE);
873 $this->assertEquals($actualvalue, $expectedvalue);
874 }
875 }
876
877 function test_validate_param() {
878 try {
879 $param = validate_param('11a', PARAM_INT);
880 $this->fail('invalid_parameter_exception expected');
881 } catch (invalid_parameter_exception $ex) {
882 $this->assertTrue(true);
883 }
884 try {
885 $param = validate_param('11', PARAM_INT);
886 $this->assertEquals($param, 11);
887 } catch (invalid_parameter_exception $ex) {
888 $this->fail('invalid_parameter_exception not expected');
889 }
890 try {
891 $param = validate_param(null, PARAM_INT, false);
892 $this->fail('invalid_parameter_exception expected');
893 } catch (invalid_parameter_exception $ex) {
894 $this->assertTrue(true);
895 }
896 try {
897 $param = validate_param(null, PARAM_INT, true);
898 $this->assertTrue($param===null);
899 } catch (invalid_parameter_exception $ex) {
900 $this->fail('invalid_parameter_exception expected');
901 }
902 try {
903 $param = validate_param(array(), PARAM_INT);
904 $this->fail('invalid_parameter_exception expected');
905 } catch (invalid_parameter_exception $ex) {
906 $this->assertTrue(true);
907 }
908 try {
909 $param = validate_param(new stdClass, PARAM_INT);
910 $this->fail('invalid_parameter_exception expected');
911 } catch (invalid_parameter_exception $ex) {
912 $this->assertTrue(true);
913 }
914 }
915
916 function test_shorten_text() {
917 $text = "short text already no tags";
918 $this->assertEquals($text, shorten_text($text));
919
920 $text = "<p>short <b>text</b> already</p><p>with tags</p>";
921 $this->assertEquals($text, shorten_text($text));
922
923 $text = "long text without any tags blah de blah blah blah what";
924 $this->assertEquals('long text without any tags ...', shorten_text($text));
925
926 $text = "<div class='frog'><p><blockquote>Long text with tags that will ".
927 "be chopped off but <b>should be added back again</b></blockquote></p></div>";
928 $this->assertEquals("<div class='frog'><p><blockquote>Long text with " .
929 "tags that ...</blockquote></p></div>", shorten_text($text));
930
931 $text = "some text which shouldn't &nbsp; break there";
932 $this->assertEquals("some text which shouldn't &nbsp; ...",
933 shorten_text($text, 31));
934 $this->assertEquals("some text which shouldn't ...",
935 shorten_text($text, 30));
936
937 // This case caused a bug up to 1.9.5
938 $text = "<h3>standard 'break-out' sub groups in TGs?</h3>&nbsp;&lt;&lt;There are several";
939 $this->assertEquals("<h3>standard 'break-out' sub groups in ...</h3>",
940 shorten_text($text, 43));
941
942 $text = "<h1>123456789</h1>";//a string with no convenient breaks
943 $this->assertEquals("<h1>12345...</h1>",
944 shorten_text($text, 8));
945
946 // ==== this must work with UTF-8 too! ======
947
948 // text without tags
949 $text = "Žluťoučký koníček přeskočil";
950 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
951 $this->assertEquals("Žluťoučký koníče...", shorten_text($text, 19, true));
952 $this->assertEquals("Žluťoučký ...", shorten_text($text, 19, false));
953 // And try it with 2-less (that are, in bytes, the middle of a sequence)
954 $this->assertEquals("Žluťoučký koní...", shorten_text($text, 17, true));
955 $this->assertEquals("Žluťoučký ...", shorten_text($text, 17, false));
956
957 $text = "<p>Žluťoučký koníček <b>přeskočil</b> potůček</p>";
958 $this->assertEquals($text, shorten_text($text, 60));
959 $this->assertEquals("<p>Žluťoučký koníček ...</p>", shorten_text($text, 21));
960 $this->assertEquals("<p>Žluťoučký koníče...</p>", shorten_text($text, 19, true));
961 $this->assertEquals("<p>Žluťoučký ...</p>", shorten_text($text, 19, false));
962 // And try it with 2-less (that are, in bytes, the middle of a sequence)
963 $this->assertEquals("<p>Žluťoučký koní...</p>", shorten_text($text, 17, true));
964 $this->assertEquals("<p>Žluťoučký ...</p>", shorten_text($text, 17, false));
965 // And try over one tag (start/end), it does proper text len
966 $this->assertEquals("<p>Žluťoučký koníček <b>př...</b></p>", shorten_text($text, 23, true));
967 $this->assertEquals("<p>Žluťoučký koníček <b>přeskočil</b> pot...</p>", shorten_text($text, 34, true));
968 // And in the middle of one tag
969 $this->assertEquals("<p>Žluťoučký koníček <b>přeskočil...</b></p>", shorten_text($text, 30, true));
970
971 // Japanese
972 $text = '言語設定言語設定abcdefghijkl';
973 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
974 $this->assertEquals("言語設定言語...", shorten_text($text, 9, true));
975 $this->assertEquals("言語設定言語...", shorten_text($text, 9, false));
976 $this->assertEquals("言語設定言語設定ab...", shorten_text($text, 13, true));
977 $this->assertEquals("言語設定言語設定...", shorten_text($text, 13, false));
978
979 // Chinese
980 $text = '简体中文简体中文abcdefghijkl';
981 $this->assertEquals($text, shorten_text($text)); // 30 chars by default
982 $this->assertEquals("简体中文简体...", shorten_text($text, 9, true));
983 $this->assertEquals("简体中文简体...", shorten_text($text, 9, false));
984 $this->assertEquals("简体中文简体中文ab...", shorten_text($text, 13, true));
985 $this->assertEquals("简体中文简体中文...", shorten_text($text, 13, false));
986
987 }
988
989 function test_usergetdate() {
990 global $USER, $CFG, $DB;
991
992 //Check if forcetimezone is set then save it and set it to use user timezone
993 $cfgforcetimezone = null;
994 if (isset($CFG->forcetimezone)) {
995 $cfgforcetimezone = $CFG->forcetimezone;
996 $CFG->forcetimezone = 99; //get user default timezone.
997 }
998
999 $olduser = $USER;
1000 $USER = $DB->get_record('user', array('id'=>2)); //admin
1001
1002 $userstimezone = $USER->timezone;
1003 $USER->timezone = 2;//set the timezone to a known state
1004
1005 // The string version of date comes from server locale setting and does
1006 // not respect user language, so it is necessary to reset that.
1007 $oldlocale = setlocale(LC_TIME, '0');
1008 setlocale(LC_TIME, 'en_AU.UTF-8');
1009
1010 $ts = 1261540267; //the time this function was created
1011
1012 $arr = usergetdate($ts,1);//specify the timezone as an argument
1013 $arr = array_values($arr);
1014
1015 list($seconds,$minutes,$hours,$mday,$wday,$mon,$year,$yday,$weekday,$month) = $arr;
03764014
EL
1016 $this->assertSame($seconds, 7);
1017 $this->assertSame($minutes, 51);
1018 $this->assertSame($hours, 4);
1019 $this->assertSame($mday, 23);
1020 $this->assertSame($wday, 3);
1021 $this->assertSame($mon, 12);
1022 $this->assertSame($year, 2009);
1023 $this->assertSame($yday, 356);
1024 $this->assertSame($weekday, 'Wednesday');
1025 $this->assertSame($month, 'December');
a3d5830a
PS
1026 $arr = usergetdate($ts);//gets the timezone from the $USER object
1027 $arr = array_values($arr);
1028
1029 list($seconds,$minutes,$hours,$mday,$wday,$mon,$year,$yday,$weekday,$month) = $arr;
03764014
EL
1030 $this->assertSame($seconds, 7);
1031 $this->assertSame($minutes, 51);
1032 $this->assertSame($hours, 5);
1033 $this->assertSame($mday, 23);
1034 $this->assertSame($wday, 3);
1035 $this->assertSame($mon, 12);
1036 $this->assertSame($year, 2009);
1037 $this->assertSame($yday, 356);
1038 $this->assertSame($weekday, 'Wednesday');
1039 $this->assertSame($month, 'December');
a3d5830a
PS
1040 //set the timezone back to what it was
1041 $USER->timezone = $userstimezone;
1042
1043 //restore forcetimezone if changed.
1044 if (!is_null($cfgforcetimezone)) {
1045 $CFG->forcetimezone = $cfgforcetimezone;
1046 }
1047
1048 setlocale(LC_TIME, $oldlocale);
1049
1050 $USER = $olduser;
1051 }
1052
1053 public function test_normalize_component() {
1054
1055 // moodle core
1056 $this->assertEquals(normalize_component('moodle'), array('core', null));
1057 $this->assertEquals(normalize_component('core'), array('core', null));
1058
1059 // moodle core subsystems
1060 $this->assertEquals(normalize_component('admin'), array('core', 'admin'));
1061 $this->assertEquals(normalize_component('core_admin'), array('core', 'admin'));
1062
1063 // activity modules and their subplugins
1064 $this->assertEquals(normalize_component('workshop'), array('mod', 'workshop'));
1065 $this->assertEquals(normalize_component('mod_workshop'), array('mod', 'workshop'));
1066 $this->assertEquals(normalize_component('workshopform_accumulative'), array('workshopform', 'accumulative'));
1067 $this->assertEquals(normalize_component('quiz'), array('mod', 'quiz'));
1068 $this->assertEquals(normalize_component('quiz_grading'), array('quiz', 'grading'));
1069 $this->assertEquals(normalize_component('data'), array('mod', 'data'));
1070 $this->assertEquals(normalize_component('datafield_checkbox'), array('datafield', 'checkbox'));
1071
1072 // other plugin types
1073 $this->assertEquals(normalize_component('auth_mnet'), array('auth', 'mnet'));
1074 $this->assertEquals(normalize_component('enrol_self'), array('enrol', 'self'));
1075 $this->assertEquals(normalize_component('block_html'), array('block', 'html'));
1076 $this->assertEquals(normalize_component('block_mnet_hosts'), array('block', 'mnet_hosts'));
1077 $this->assertEquals(normalize_component('local_amos'), array('local', 'amos'));
1078
1079 // unknown components are supposed to be activity modules
1080 $this->assertEquals(normalize_component('whothefuckwouldcomewithsuchastupidnameofcomponent'),
1081 array('mod', 'whothefuckwouldcomewithsuchastupidnameofcomponent'));
1082 $this->assertEquals(normalize_component('whothefuck_wouldcomewithsuchastupidnameofcomponent'),
1083 array('mod', 'whothefuck_wouldcomewithsuchastupidnameofcomponent'));
1084 $this->assertEquals(normalize_component('whothefuck_would_come_withsuchastupidnameofcomponent'),
1085 array('mod', 'whothefuck_would_come_withsuchastupidnameofcomponent'));
1086 }
1087
1088 protected function get_fake_preference_test_userid() {
1089 global $DB;
1090
1091 // we need some nonexistent user id
1092 $id = 2147483647 - 666;
1093 if ($DB->get_records('user', array('id'=>$id))) {
1094 //weird!
1095 return false;
1096 }
1097 return $id;
1098 }
1099
1100 public function test_mark_user_preferences_changed() {
1101 $this->resetAfterTest(true);
1102 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1103 $this->fail('Can not find unused user id for the preferences test');
1104 return;
1105 }
1106
1107 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1108 mark_user_preferences_changed($otheruserid);
1109
1110 $this->assertEquals(get_cache_flag('userpreferenceschanged', $otheruserid, time()-10), 1);
1111 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1112 }
1113
1114 public function test_check_user_preferences_loaded() {
1115 global $DB;
1116 $this->resetAfterTest(true);
1117
1118 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1119 $this->fail('Can not find unused user id for the preferences test');
1120 return;
1121 }
1122
1123 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1124 set_cache_flag('userpreferenceschanged', $otheruserid, NULL);
1125
1126 $user = new stdClass();
1127 $user->id = $otheruserid;
1128
1129 // load
1130 check_user_preferences_loaded($user);
1131 $this->assertTrue(isset($user->preference));
1132 $this->assertTrue(is_array($user->preference));
1133 $this->assertTrue(isset($user->preference['_lastloaded']));
1134 $this->assertEquals(count($user->preference), 1);
1135
1136 // add preference via direct call
1137 $DB->insert_record('user_preferences', array('name'=>'xxx', 'value'=>'yyy', 'userid'=>$user->id));
1138
1139 // no cache reload yet
1140 check_user_preferences_loaded($user);
1141 $this->assertEquals(count($user->preference), 1);
1142
1143 // forced reloading of cache
1144 unset($user->preference);
1145 check_user_preferences_loaded($user);
1146 $this->assertEquals(count($user->preference), 2);
1147 $this->assertEquals($user->preference['xxx'], 'yyy');
1148
1149 // add preference via direct call
1150 $DB->insert_record('user_preferences', array('name'=>'aaa', 'value'=>'bbb', 'userid'=>$user->id));
1151
1152 // test timeouts and modifications from different session
1153 set_cache_flag('userpreferenceschanged', $user->id, 1, time() + 1000);
1154 $user->preference['_lastloaded'] = $user->preference['_lastloaded'] - 20;
1155 check_user_preferences_loaded($user);
1156 $this->assertEquals(count($user->preference), 2);
1157 check_user_preferences_loaded($user, 10);
1158 $this->assertEquals(count($user->preference), 3);
1159 $this->assertEquals($user->preference['aaa'], 'bbb');
1160 set_cache_flag('userpreferenceschanged', $user->id, null);
1161 }
1162
1163 public function test_set_user_preference() {
1164 global $DB, $USER;
1165 $this->resetAfterTest(true);
1166
1167 $olduser = $USER;
1168 $USER = $DB->get_record('user', array('id'=>2)); //admin
1169
1170 if (!$otheruserid = $this->get_fake_preference_test_userid()) {
1171 $this->fail('Can not find unused user id for the preferences test');
1172 return;
1173 }
1174
1175 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1176 set_cache_flag('userpreferenceschanged', $otheruserid, null);
1177
1178 $user = new stdClass();
1179 $user->id = $otheruserid;
1180
1181 set_user_preference('aaa', 'bbb', $otheruserid);
1182 $this->assertEquals('bbb', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'aaa')));
1183 $this->assertEquals('bbb', get_user_preferences('aaa', null, $otheruserid));
1184
1185 set_user_preference('xxx', 'yyy', $user);
1186 $this->assertEquals('yyy', $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
1187 $this->assertEquals('yyy', get_user_preferences('xxx', null, $otheruserid));
1188 $this->assertTrue(is_array($user->preference));
1189 $this->assertEquals($user->preference['aaa'], 'bbb');
1190 $this->assertEquals($user->preference['xxx'], 'yyy');
1191
1192 set_user_preference('xxx', NULL, $user);
1193 $this->assertSame(false, $DB->get_field('user_preferences', 'value', array('userid'=>$otheruserid, 'name'=>'xxx')));
1194 $this->assertSame(null, get_user_preferences('xxx', null, $otheruserid));
1195
1196 set_user_preference('ooo', true, $user);
1197 $prefs = get_user_preferences(null, null, $otheruserid);
1198 $this->assertSame($prefs['aaa'], $user->preference['aaa']);
1199 $this->assertSame($prefs['ooo'], $user->preference['ooo']);
1200 $this->assertSame($prefs['ooo'], '1');
1201
1202 set_user_preference('null', 0, $user);
1203 $this->assertSame('0', get_user_preferences('null', null, $otheruserid));
1204
1205 $this->assertSame('lala', get_user_preferences('undefined', 'lala', $otheruserid));
1206
1207 $DB->delete_records('user_preferences', array('userid'=>$otheruserid));
1208 set_cache_flag('userpreferenceschanged', $otheruserid, null);
1209
1210 // test $USER default
1211 set_user_preference('_test_user_preferences_pref', 'ok');
1212 $this->assertSame('ok', $USER->preference['_test_user_preferences_pref']);
1213 unset_user_preference('_test_user_preferences_pref');
1214 $this->assertTrue(!isset($USER->preference['_test_user_preferences_pref']));
1215
1216 // Test 1333 char values (no need for unicode, there are already tests for that in DB tests)
1217 $longvalue = str_repeat('a', 1333);
1218 set_user_preference('_test_long_user_preference', $longvalue);
1219 $this->assertEquals($longvalue, get_user_preferences('_test_long_user_preference'));
1220 $this->assertEquals($longvalue,
1221 $DB->get_field('user_preferences', 'value', array('userid' => $USER->id, 'name' => '_test_long_user_preference')));
1222
1223 // Test > 1333 char values, coding_exception expected
1224 $longvalue = str_repeat('a', 1334);
1225 try {
1226 set_user_preference('_test_long_user_preference', $longvalue);
1227 $this->assertFail('Exception expected - longer than 1333 chars not allowed as preference value');
1228 } catch (Exception $e) {
1229 $this->assertTrue($e instanceof coding_exception);
1230 }
1231
1232 //test invalid params
1233 try {
1234 set_user_preference('_test_user_preferences_pref', array());
1235 $this->assertFail('Exception expected - array not valid preference value');
1236 } catch (Exception $ex) {
1237 $this->assertTrue(true);
1238 }
1239 try {
1240 set_user_preference('_test_user_preferences_pref', new stdClass);
1241 $this->assertFail('Exception expected - class not valid preference value');
1242 } catch (Exception $ex) {
1243 $this->assertTrue(true);
1244 }
1245 try {
1246 set_user_preference('_test_user_preferences_pref', 1, array('xx'=>1));
1247 $this->assertFail('Exception expected - user instance expected');
1248 } catch (Exception $ex) {
1249 $this->assertTrue(true);
1250 }
1251 try {
1252 set_user_preference('_test_user_preferences_pref', 1, 'abc');
1253 $this->assertFail('Exception expected - user instance expected');
1254 } catch (Exception $ex) {
1255 $this->assertTrue(true);
1256 }
1257 try {
1258 set_user_preference('', 1);
1259 $this->assertFail('Exception expected - invalid name accepted');
1260 } catch (Exception $ex) {
1261 $this->assertTrue(true);
1262 }
1263 try {
1264 set_user_preference('1', 1);
1265 $this->assertFail('Exception expected - invalid name accepted');
1266 } catch (Exception $ex) {
1267 $this->assertTrue(true);
1268 }
1269
1270 $USER = $olduser;
1271 }
1272
1273 public function test_get_extra_user_fields() {
1274 global $CFG, $USER, $DB;
1275 $oldshowuseridentity = $CFG->showuseridentity;
1276
1277 $olduser = $USER;
1278 $USER = $DB->get_record('user', array('id'=>2)); //admin
1279
1280 // It would be really nice if there were a way to 'mock' has_capability
1281 // checks (either to return true or false) but as there is not, this
1282 // test doesn't test the capability check. Presumably, anyone running
1283 // unit tests will have the capability.
1284 $context = context_system::instance();
1285
1286 // No fields
1287 $CFG->showuseridentity = '';
1288 $this->assertEquals(array(), get_extra_user_fields($context));
1289
1290 // One field
1291 $CFG->showuseridentity = 'frog';
1292 $this->assertEquals(array('frog'), get_extra_user_fields($context));
1293
1294 // Two fields
1295 $CFG->showuseridentity = 'frog,zombie';
1296 $this->assertEquals(array('frog', 'zombie'), get_extra_user_fields($context));
1297
1298 // No fields, except
1299 $CFG->showuseridentity = '';
1300 $this->assertEquals(array(), get_extra_user_fields($context, array('frog')));
1301
1302 // One field
1303 $CFG->showuseridentity = 'frog';
1304 $this->assertEquals(array(), get_extra_user_fields($context, array('frog')));
1305
1306 // Two fields
1307 $CFG->showuseridentity = 'frog,zombie';
1308 $this->assertEquals(array('zombie'), get_extra_user_fields($context, array('frog')));
1309
1310 // As long as this test passes, the value will be set back. This is only
1311 // in-memory anyhow
1312 $CFG->showuseridentity = $oldshowuseridentity;
1313
1314 $USER = $olduser;
1315 }
1316
1317 public function test_get_extra_user_fields_sql() {
1318 global $CFG, $USER, $DB;
1319
1320 $olduser = $USER;
1321 $USER = $DB->get_record('user', array('id'=>2)); //admin
1322
1323 $oldshowuseridentity = $CFG->showuseridentity;
1324 $context = context_system::instance();
1325
1326 // No fields
1327 $CFG->showuseridentity = '';
1328 $this->assertEquals('', get_extra_user_fields_sql($context));
1329
1330 // One field
1331 $CFG->showuseridentity = 'frog';
1332 $this->assertEquals(', frog', get_extra_user_fields_sql($context));
1333
1334 // Two fields with table prefix
1335 $CFG->showuseridentity = 'frog,zombie';
1336 $this->assertEquals(', u1.frog, u1.zombie', get_extra_user_fields_sql($context, 'u1'));
1337
1338 // Two fields with field prefix
1339 $CFG->showuseridentity = 'frog,zombie';
1340 $this->assertEquals(', frog AS u_frog, zombie AS u_zombie',
1341 get_extra_user_fields_sql($context, '', 'u_'));
1342
1343 // One field excluded
1344 $CFG->showuseridentity = 'frog';
1345 $this->assertEquals('', get_extra_user_fields_sql($context, '', '', array('frog')));
1346
1347 // Two fields, one excluded, table+field prefix
1348 $CFG->showuseridentity = 'frog,zombie';
1349 $this->assertEquals(', u1.zombie AS u_zombie',
1350 get_extra_user_fields_sql($context, 'u1', 'u_', array('frog')));
1351
1352 // As long as this test passes, the value will be set back. This is only
1353 // in-memory anyhow
1354 $CFG->showuseridentity = $oldshowuseridentity;
1355 $USER = $olduser;
1356 }
1357
1358 public function test_userdate() {
1359 global $USER, $CFG, $DB;
1360
1361 $olduser = $USER;
1362 $USER = $DB->get_record('user', array('id'=>2)); //admin
1363
1364 $testvalues = array(
1365 array(
1366 'time' => '1309514400',
1367 'usertimezone' => 'America/Moncton',
1368 'timezone' => '0.0', //no dst offset
1369 'expectedoutput' => 'Friday, 1 July 2011, 10:00 AM'
1370 ),
1371 array(
1372 'time' => '1309514400',
1373 'usertimezone' => 'America/Moncton',
1374 'timezone' => '99', //dst offset and timezone offset.
1375 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM'
1376 ),
1377 array(
1378 'time' => '1309514400',
1379 'usertimezone' => 'America/Moncton',
1380 'timezone' => 'America/Moncton', //dst offset and timezone offset.
1381 'expectedoutput' => 'Friday, 1 July 2011, 7:00 AM'
1382 ),
1383 array(
1384 'time' => '1293876000 ',
1385 'usertimezone' => 'America/Moncton',
1386 'timezone' => '0.0', //no dst offset
1387 'expectedoutput' => 'Saturday, 1 January 2011, 10:00 AM'
1388 ),
1389 array(
1390 'time' => '1293876000 ',
1391 'usertimezone' => 'America/Moncton',
1392 'timezone' => '99', //no dst offset in jan, so just timezone offset.
1393 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM'
1394 ),
1395 array(
1396 'time' => '1293876000 ',
1397 'usertimezone' => 'America/Moncton',
1398 'timezone' => 'America/Moncton', //no dst offset in jan
1399 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 AM'
1400 ),
1401 array(
1402 'time' => '1293876000 ',
1403 'usertimezone' => '2',
1404 'timezone' => '99', //take user timezone
1405 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
1406 ),
1407 array(
1408 'time' => '1293876000 ',
1409 'usertimezone' => '-2',
1410 'timezone' => '99', //take user timezone
1411 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM'
1412 ),
1413 array(
1414 'time' => '1293876000 ',
1415 'usertimezone' => '-10',
1416 'timezone' => '2', //take this timezone
1417 'expectedoutput' => 'Saturday, 1 January 2011, 12:00 PM'
1418 ),
1419 array(
1420 'time' => '1293876000 ',
1421 'usertimezone' => '-10',
1422 'timezone' => '-2', //take this timezone
1423 'expectedoutput' => 'Saturday, 1 January 2011, 8:00 AM'
1424 ),
1425 array(
1426 'time' => '1293876000 ',
1427 'usertimezone' => '-10',
1428 'timezone' => 'random/time', //this should show server time
1429 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM'
1430 ),
1431 array(
1432 'time' => '1293876000 ',
1433 'usertimezone' => '14', //server time zone
1434 'timezone' => '99', //this should show user time
1435 'expectedoutput' => 'Saturday, 1 January 2011, 6:00 PM'
1436 ),
1437 );
1438
1439 //Check if forcetimezone is set then save it and set it to use user timezone
1440 $cfgforcetimezone = null;
1441 if (isset($CFG->forcetimezone)) {
1442 $cfgforcetimezone = $CFG->forcetimezone;
1443 $CFG->forcetimezone = 99; //get user default timezone.
1444 }
1445 //store user default timezone to restore later
1446 $userstimezone = $USER->timezone;
1447
1448 // The string version of date comes from server locale setting and does
1449 // not respect user language, so it is necessary to reset that.
1450 $oldlocale = setlocale(LC_TIME, '0');
1451 setlocale(LC_TIME, 'en_AU.UTF-8');
1452
1453 //set default timezone to Australia/Perth, else time calculated
1454 //will not match expected values. Before that save system defaults.
1455 $systemdefaulttimezone = date_default_timezone_get();
1456 date_default_timezone_set('Australia/Perth');
1457
1458 foreach ($testvalues as $vals) {
1459 $USER->timezone = $vals['usertimezone'];
1460 $actualoutput = userdate($vals['time'], '%A, %d %B %Y, %I:%M %p', $vals['timezone']);
1461
1462 //On different systems case of AM PM changes so compare case insensitive
1463 $vals['expectedoutput'] = textlib::strtolower($vals['expectedoutput']);
1464 $actualoutput = textlib::strtolower($actualoutput);
1465
1466 $this->assertEquals($vals['expectedoutput'], $actualoutput,
1467 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
1468 Please check if timezones are updated (Site adminstration -> location -> update timezone)");
1469 }
1470
1471 //restore user timezone back to what it was
1472 $USER->timezone = $userstimezone;
1473
1474 //restore forcetimezone
1475 if (!is_null($cfgforcetimezone)) {
1476 $CFG->forcetimezone = $cfgforcetimezone;
1477 }
1478
1479 //restore system default values.
1480 date_default_timezone_set($systemdefaulttimezone);
1481 setlocale(LC_TIME, $oldlocale);
1482
1483 $USER = $olduser;
1484 }
1485
1486 public function test_make_timestamp() {
1487 global $USER, $CFG, $DB;
1488
1489 $olduser = $USER;
1490 $USER = $DB->get_record('user', array('id'=>2)); //admin
1491
1492 $testvalues = array(
1493 array(
1494 'usertimezone' => 'America/Moncton',
1495 'year' => '2011',
1496 'month' => '7',
1497 'day' => '1',
1498 'hour' => '10',
1499 'minutes' => '00',
1500 'seconds' => '00',
1501 'timezone' => '0.0', //no dst offset
1502 'applydst' => false,
1503 'expectedoutput' => '1309528800'
1504 ),
1505 array(
1506 'usertimezone' => 'America/Moncton',
1507 'year' => '2011',
1508 'month' => '7',
1509 'day' => '1',
1510 'hour' => '10',
1511 'minutes' => '00',
1512 'seconds' => '00',
1513 'timezone' => '99', //user default timezone
1514 'applydst' => false, //don't apply dst
1515 'expectedoutput' => '1309528800'
1516 ),
1517 array(
1518 'usertimezone' => 'America/Moncton',
1519 'year' => '2011',
1520 'month' => '7',
1521 'day' => '1',
1522 'hour' => '10',
1523 'minutes' => '00',
1524 'seconds' => '00',
1525 'timezone' => '99', //user default timezone
1526 'applydst' => true, //apply dst
1527 'expectedoutput' => '1309525200'
1528 ),
1529 array(
1530 'usertimezone' => 'America/Moncton',
1531 'year' => '2011',
1532 'month' => '7',
1533 'day' => '1',
1534 'hour' => '10',
1535 'minutes' => '00',
1536 'seconds' => '00',
1537 'timezone' => 'America/Moncton', //string timezone
1538 'applydst' => true, //apply dst
1539 'expectedoutput' => '1309525200'
1540 ),
1541 array(
1542 'usertimezone' => '2',//no dst applyed
1543 'year' => '2011',
1544 'month' => '7',
1545 'day' => '1',
1546 'hour' => '10',
1547 'minutes' => '00',
1548 'seconds' => '00',
1549 'timezone' => '99', //take user timezone
1550 'applydst' => true, //apply dst
1551 'expectedoutput' => '1309507200'
1552 ),
1553 array(
1554 'usertimezone' => '-2',//no dst applyed
1555 'year' => '2011',
1556 'month' => '7',
1557 'day' => '1',
1558 'hour' => '10',
1559 'minutes' => '00',
1560 'seconds' => '00',
1561 'timezone' => '99', //take usertimezone
1562 'applydst' => true, //apply dst
1563 'expectedoutput' => '1309521600'
1564 ),
1565 array(
1566 'usertimezone' => '-10',//no dst applyed
1567 'year' => '2011',
1568 'month' => '7',
1569 'day' => '1',
1570 'hour' => '10',
1571 'minutes' => '00',
1572 'seconds' => '00',
1573 'timezone' => '2', //take this timezone
1574 'applydst' => true, //apply dst
1575 'expectedoutput' => '1309507200'
1576 ),
1577 array(
1578 'usertimezone' => '-10',//no dst applyed
1579 'year' => '2011',
1580 'month' => '7',
1581 'day' => '1',
1582 'hour' => '10',
1583 'minutes' => '00',
1584 'seconds' => '00',
1585 'timezone' => '-2', //take this timezone
1586 'applydst' => true, //apply dst,
1587 'expectedoutput' => '1309521600'
1588 ),
1589 array(
1590 'usertimezone' => '-10',//no dst applyed
1591 'year' => '2011',
1592 'month' => '7',
1593 'day' => '1',
1594 'hour' => '10',
1595 'minutes' => '00',
1596 'seconds' => '00',
1597 'timezone' => 'random/time', //This should show server time
1598 'applydst' => true, //apply dst,
1599 'expectedoutput' => '1309485600'
1600 ),
1601 array(
1602 'usertimezone' => '14',//server time
1603 'year' => '2011',
1604 'month' => '7',
1605 'day' => '1',
1606 'hour' => '10',
1607 'minutes' => '00',
1608 'seconds' => '00',
1609 'timezone' => '99', //get user time
1610 'applydst' => true, //apply dst,
1611 'expectedoutput' => '1309485600'
1612 )
1613 );
1614
1615 //Check if forcetimezone is set then save it and set it to use user timezone
1616 $cfgforcetimezone = null;
1617 if (isset($CFG->forcetimezone)) {
1618 $cfgforcetimezone = $CFG->forcetimezone;
1619 $CFG->forcetimezone = 99; //get user default timezone.
1620 }
1621
1622 //store user default timezone to restore later
1623 $userstimezone = $USER->timezone;
1624
1625 // The string version of date comes from server locale setting and does
1626 // not respect user language, so it is necessary to reset that.
1627 $oldlocale = setlocale(LC_TIME, '0');
1628 setlocale(LC_TIME, 'en_AU.UTF-8');
1629
1630 //set default timezone to Australia/Perth, else time calulated
1631 //will not match expected values. Before that save system defaults.
1632 $systemdefaulttimezone = date_default_timezone_get();
1633 date_default_timezone_set('Australia/Perth');
1634
1635 //Test make_timestamp with all testvals and assert if anything wrong.
1636 foreach ($testvalues as $vals) {
1637 $USER->timezone = $vals['usertimezone'];
1638 $actualoutput = make_timestamp(
1639 $vals['year'],
1640 $vals['month'],
1641 $vals['day'],
1642 $vals['hour'],
1643 $vals['minutes'],
1644 $vals['seconds'],
1645 $vals['timezone'],
1646 $vals['applydst']
1647 );
1648
1649 //On different systems case of AM PM changes so compare case insenitive
1650 $vals['expectedoutput'] = textlib::strtolower($vals['expectedoutput']);
1651 $actualoutput = textlib::strtolower($actualoutput);
1652
1653 $this->assertEquals($vals['expectedoutput'], $actualoutput,
1654 "Expected: {$vals['expectedoutput']} => Actual: {$actualoutput},
1655 Please check if timezones are updated (Site adminstration -> location -> update timezone)");
1656 }
1657
1658 //restore user timezone back to what it was
1659 $USER->timezone = $userstimezone;
1660
1661 //restore forcetimezone
1662 if (!is_null($cfgforcetimezone)) {
1663 $CFG->forcetimezone = $cfgforcetimezone;
1664 }
1665
1666 //restore system default values.
1667 date_default_timezone_set($systemdefaulttimezone);
1668 setlocale(LC_TIME, $oldlocale);
1669
1670 $USER = $olduser;
1671 }
1672
1673 /**
1674 * Test get_string and most importantly the implementation of the lang_string
1675 * object.
1676 */
1677 public function test_get_string() {
1678 global $COURSE;
1679
1680 // Make sure we are using English
1681 $originallang = $COURSE->lang;
1682 $COURSE->lang = 'en';
1683
1684 $yes = get_string('yes');
1685 $yesexpected = 'Yes';
1686 $this->assertEquals(getType($yes), 'string');
1687 $this->assertEquals($yes, $yesexpected);
1688
1689 $yes = get_string('yes', 'moodle');
1690 $this->assertEquals(getType($yes), 'string');
1691 $this->assertEquals($yes, $yesexpected);
1692
1693 $yes = get_string('yes', 'core');
1694 $this->assertEquals(getType($yes), 'string');
1695 $this->assertEquals($yes, $yesexpected);
1696
1697 $yes = get_string('yes', '');
1698 $this->assertEquals(getType($yes), 'string');
1699 $this->assertEquals($yes, $yesexpected);
1700
1701 $yes = get_string('yes', null);
1702 $this->assertEquals(getType($yes), 'string');
1703 $this->assertEquals($yes, $yesexpected);
1704
1705 $yes = get_string('yes', null, 1);
1706 $this->assertEquals(getType($yes), 'string');
1707 $this->assertEquals($yes, $yesexpected);
1708
1709 $days = 1;
1710 $numdays = get_string('numdays', 'core', '1');
1711 $numdaysexpected = $days.' days';
1712 $this->assertEquals(getType($numdays), 'string');
1713 $this->assertEquals($numdays, $numdaysexpected);
1714
1715 $yes = get_string('yes', null, null, true);
1716 $this->assertEquals(get_class($yes), 'lang_string');
1717 $this->assertEquals((string)$yes, $yesexpected);
1718
1719 // Test using a lang_string object as the $a argument for a normal
1720 // get_string call (returning string)
1721 $test = new lang_string('yes', null, null, true);
1722 $testexpected = get_string('numdays', 'core', get_string('yes'));
1723 $testresult = get_string('numdays', null, $test);
1724 $this->assertEquals(getType($testresult), 'string');
1725 $this->assertEquals($testresult, $testexpected);
1726
1727 // Test using a lang_string object as the $a argument for an object
1728 // get_string call (returning lang_string)
1729 $test = new lang_string('yes', null, null, true);
1730 $testexpected = get_string('numdays', 'core', get_string('yes'));
1731 $testresult = get_string('numdays', null, $test, true);
1732 $this->assertEquals(get_class($testresult), 'lang_string');
1733 $this->assertEquals("$testresult", $testexpected);
1734
1735 // Make sure that object properties that can't be converted don't cause
1736 // errors
1737 // Level one: This is as deep as current language processing goes
1738 $test = new stdClass;
1739 $test->one = 'here';
1740 $string = get_string('yes', null, $test, true);
1741 $this->assertEquals($string, $yesexpected);
1742
1743 // Make sure that object properties that can't be converted don't cause
1744 // errors.
1745 // Level two: Language processing doesn't currently reach this deep.
1746 // only immediate scalar properties are worked with.
1747 $test = new stdClass;
1748 $test->one = new stdClass;
1749 $test->one->two = 'here';
1750 $string = get_string('yes', null, $test, true);
1751 $this->assertEquals($string, $yesexpected);
1752
1753 // Make sure that object properties that can't be converted don't cause
1754 // errors.
1755 // Level three: It should never ever go this deep, but we're making sure
1756 // it doesn't cause any probs anyway.
1757 $test = new stdClass;
1758 $test->one = new stdClass;
1759 $test->one->two = new stdClass;
1760 $test->one->two->three = 'here';
1761 $string = get_string('yes', null, $test, true);
1762 $this->assertEquals($string, $yesexpected);
1763
1764 // Make sure that object properties that can't be converted don't cause
1765 // errors and check lang_string properties.
1766 // Level one: This is as deep as current language processing goes
1767 $test = new stdClass;
1768 $test->one = new lang_string('yes');
1769 $string = get_string('yes', null, $test, true);
1770 $this->assertEquals($string, $yesexpected);
1771
1772 // Make sure that object properties that can't be converted don't cause
1773 // errors and check lang_string properties.
1774 // Level two: Language processing doesn't currently reach this deep.
1775 // only immediate scalar properties are worked with.
1776 $test = new stdClass;
1777 $test->one = new stdClass;
1778 $test->one->two = new lang_string('yes');
1779 $string = get_string('yes', null, $test, true);
1780 $this->assertEquals($string, $yesexpected);
1781
1782 // Make sure that object properties that can't be converted don't cause
1783 // errors and check lang_string properties.
1784 // Level three: It should never ever go this deep, but we're making sure
1785 // it doesn't cause any probs anyway.
1786 $test = new stdClass;
1787 $test->one = new stdClass;
1788 $test->one->two = new stdClass;
1789 $test->one->two->three = new lang_string('yes');
1790 $string = get_string('yes', null, $test, true);
1791 $this->assertEquals($string, $yesexpected);
1792
1793 // Make sure that array properties that can't be converted don't cause
1794 // errors
1795 $test = array();
1796 $test['one'] = new stdClass;
1797 $test['one']->two = 'here';
1798 $string = get_string('yes', null, $test, true);
1799 $this->assertEquals($string, $yesexpected);
1800
1801 // Same thing but as above except using an object... this is allowed :P
1802 $string = get_string('yes', null, null, true);
1803 $object = new stdClass;
1804 $object->$string = 'Yes';
1805 $this->assertEquals($string, $yesexpected);
1806 $this->assertEquals($object->$string, $yesexpected);
1807
1808 // Reset the language
1809 $COURSE->lang = $originallang;
1810 }
1811
1812 /**
1813 * @expectedException PHPUnit_Framework_Error_Warning
1814 * @return void
1815 */
1816 public function test_get_string_limitation() {
1817 // This is one of the limitations to the lang_string class. It can't be
1818 // used as a key
1819 $array = array(get_string('yes', null, null, true) => 'yes');
1820 }
637da99e 1821
1822 /**
1823 * Test localised float formatting.
1824 */
1825 public function test_format_float() {
1826 global $SESSION, $CFG;
1827
1828 // Special case for null
1829 $this->assertEquals('', format_float(null));
1830
1831 // Default 1 decimal place
1832 $this->assertEquals('5.4', format_float(5.43));
1833 $this->assertEquals('5.0', format_float(5.001));
1834
1835 // Custom number of decimal places
1836 $this->assertEquals('5.43000', format_float(5.43, 5));
1837
1838 // Option to strip ending zeros after rounding
1839 $this->assertEquals('5.43', format_float(5.43, 5, true, true));
1840 $this->assertEquals('5', format_float(5.0001, 3, true, true));
1841
1842 // It is not possible to directly change the result of get_string in
1843 // a unit test. Instead, we create a language pack for language 'xx' in
1844 // dataroot and make langconfig.php with the string we need to change.
1845 // The example separator used here is 'X'; on PHP 5.3 and before this
1846 // must be a single byte character due to PHP bug/limitation in
1847 // number_format, so you can't use UTF-8 characters.
1848 $SESSION->lang = 'xx';
1849 $langconfig = "<?php\n\$string['decsep'] = 'X';";
1850 $langfolder = $CFG->dataroot . '/lang/xx';
1851 check_dir_exists($langfolder);
1852 file_put_contents($langfolder . '/langconfig.php', $langconfig);
1853
1854 // Localisation on (default)
1855 $this->assertEquals('5X43000', format_float(5.43, 5));
1856 $this->assertEquals('5X43', format_float(5.43, 5, true, true));
1857
1858 // Localisation off
1859 $this->assertEquals('5.43000', format_float(5.43, 5, false));
1860 $this->assertEquals('5.43', format_float(5.43, 5, false, true));
1861 }
a3d5830a 1862}