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