Merge branch 'MDL-64012' of https://github.com/timhunt/moodle
[moodle.git] / lib / tests / collator_test.php
blob7fb9eddb158bff8e4bd290c7aead6da006342383
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.
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/>.
17 /**
18 * Collator unit tests.
20 * @package core
21 * @category phpunit
22 * @copyright 2011 Sam Hemelryk
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
28 /**
29 * Unit tests for our utf-8 aware collator which is used for sorting.
31 * @package core
32 * @category phpunit
33 * @copyright 2011 Sam Hemelryk
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 class core_collator_testcase extends advanced_testcase {
38 /**
39 * @var string The initial lang, stored because we change it during testing
41 protected $initiallang = null;
43 /**
44 * @var string The last error that has occurred
46 protected $error = null;
48 /**
49 * Prepares things for this test case.
51 protected function setUp() {
52 global $SESSION;
53 if (isset($SESSION->lang)) {
54 $this->initiallang = $SESSION->lang;
56 $SESSION->lang = 'en'; // Make sure we test en language to get consistent results, hopefully all systems have this locale.
57 if (extension_loaded('intl')) {
58 $this->error = 'Collation aware sorting not supported';
59 } else {
60 $this->error = 'Collation aware sorting not supported, PHP extension "intl" is not available.';
62 parent::setUp();
65 /**
66 * Cleans things up after this test case has run.
68 protected function tearDown() {
69 global $SESSION;
70 parent::tearDown();
71 if ($this->initiallang !== null) {
72 $SESSION->lang = $this->initiallang;
73 $this->initiallang = null;
74 } else {
75 unset($SESSION->lang);
79 /**
80 * Tests the static asort method.
82 public function test_asort() {
83 $arr = array('b' => 'ab', 1 => 'aa', 0 => 'cc');
84 $result = core_collator::asort($arr);
85 $this->assertSame(array('aa', 'ab', 'cc'), array_values($arr));
86 $this->assertSame(array(1, 'b', 0), array_keys($arr));
87 $this->assertTrue($result);
89 $arr = array('b' => 'ab', 1 => 'aa', 0 => 'cc');
90 $result = core_collator::asort($arr, core_collator::SORT_STRING);
91 $this->assertSame(array('aa', 'ab', 'cc'), array_values($arr));
92 $this->assertSame(array(1, 'b', 0), array_keys($arr));
93 $this->assertTrue($result);
95 $arr = array('b' => 'aac', 1 => 'Aac', 0 => 'cc');
96 $result = core_collator::asort($arr, (core_collator::SORT_STRING | core_collator::CASE_SENSITIVE));
97 $this->assertSame(array('Aac', 'aac', 'cc'), array_values($arr));
98 $this->assertSame(array(1, 'b', 0), array_keys($arr));
99 $this->assertTrue($result);
101 $arr = array('b' => 'a1', 1 => 'a10', 0 => 'a3b');
102 $result = core_collator::asort($arr);
103 $this->assertSame(array('a1', 'a10', 'a3b'), array_values($arr));
104 $this->assertSame(array('b', 1, 0), array_keys($arr));
105 $this->assertTrue($result);
107 $arr = array('b' => 'a1', 1 => 'a10', 0 => 'a3b');
108 $result = core_collator::asort($arr, core_collator::SORT_NATURAL);
109 $this->assertSame(array('a1', 'a3b', 'a10'), array_values($arr));
110 $this->assertSame(array('b', 0, 1), array_keys($arr));
111 $this->assertTrue($result);
113 $arr = array('b' => '1.1.1', 1 => '1.2', 0 => '1.20.2');
114 $result = core_collator::asort($arr, core_collator::SORT_NATURAL);
115 $this->assertSame(array_values($arr), array('1.1.1', '1.2', '1.20.2'));
116 $this->assertSame(array_keys($arr), array('b', 1, 0));
117 $this->assertTrue($result);
119 $arr = array('b' => '-1', 1 => 1000, 0 => -1.2, 3 => 1, 4 => false);
120 $result = core_collator::asort($arr, core_collator::SORT_NUMERIC);
121 $this->assertSame(array(-1.2, '-1', false, 1, 1000), array_values($arr));
122 $this->assertSame(array(0, 'b', 4, 3, 1), array_keys($arr));
123 $this->assertTrue($result);
125 $arr = array('b' => array(1), 1 => array(2, 3), 0 => 1);
126 $result = core_collator::asort($arr, core_collator::SORT_REGULAR);
127 $this->assertSame(array(1, array(1), array(2, 3)), array_values($arr));
128 $this->assertSame(array(0, 'b', 1), array_keys($arr));
129 $this->assertTrue($result);
131 // Test sorting of array of arrays - first element should be used for actual comparison.
132 $arr = array(0=>array('bb', 'z'), 1=>array('ab', 'a'), 2=>array('zz', 'x'));
133 $result = core_collator::asort($arr, core_collator::SORT_REGULAR);
134 $this->assertSame(array(1, 0, 2), array_keys($arr));
135 $this->assertTrue($result);
137 $arr = array('a' => 'áb', 'b' => 'ab', 1 => 'aa', 0=>'cc', 'x' => 'Áb');
138 $result = core_collator::asort($arr);
139 $this->assertSame(array('aa', 'ab', 'áb', 'Áb', 'cc'), array_values($arr), $this->error);
140 $this->assertSame(array(1, 'b', 'a', 'x', 0), array_keys($arr), $this->error);
141 $this->assertTrue($result);
143 $a = array(2=>'b', 1=>'c');
144 $c =& $a;
145 $b =& $a;
146 core_collator::asort($b);
147 $this->assertSame($a, $b);
148 $this->assertSame($c, $b);
152 * Tests the static asort_objects_by_method method.
154 public function test_asort_objects_by_method() {
155 $objects = array(
156 'b' => new string_test_class('ab'),
157 1 => new string_test_class('aa'),
158 0 => new string_test_class('cc')
160 $result = core_collator::asort_objects_by_method($objects, 'get_protected_name');
161 $this->assertSame(array(1, 'b', 0), array_keys($objects));
162 $this->assertSame(array('aa', 'ab', 'cc'), $this->get_ordered_names($objects, 'get_protected_name'));
163 $this->assertTrue($result);
165 $objects = array(
166 'b' => new string_test_class('a20'),
167 1 => new string_test_class('a1'),
168 0 => new string_test_class('a100')
170 $result = core_collator::asort_objects_by_method($objects, 'get_protected_name', core_collator::SORT_NATURAL);
171 $this->assertSame(array(1, 'b', 0), array_keys($objects));
172 $this->assertSame(array('a1', 'a20', 'a100'), $this->get_ordered_names($objects, 'get_protected_name'));
173 $this->assertTrue($result);
177 * Tests the static asort_objects_by_method method.
179 public function test_asort_objects_by_property() {
180 $objects = array(
181 'b' => new string_test_class('ab'),
182 1 => new string_test_class('aa'),
183 0 => new string_test_class('cc')
185 $result = core_collator::asort_objects_by_property($objects, 'publicname');
186 $this->assertSame(array(1, 'b', 0), array_keys($objects));
187 $this->assertSame(array('aa', 'ab', 'cc'), $this->get_ordered_names($objects, 'publicname'));
188 $this->assertTrue($result);
190 $objects = array(
191 'b' => new string_test_class('a20'),
192 1 => new string_test_class('a1'),
193 0 => new string_test_class('a100')
195 $result = core_collator::asort_objects_by_property($objects, 'publicname', core_collator::SORT_NATURAL);
196 $this->assertSame(array(1, 'b', 0), array_keys($objects));
197 $this->assertSame(array('a1', 'a20', 'a100'), $this->get_ordered_names($objects, 'publicname'));
198 $this->assertTrue($result);
202 * Tests the sorting of an array of arrays by key.
204 public function test_asort_array_of_arrays_by_key() {
205 $array = array(
206 'a' => array('name' => 'bravo'),
207 'b' => array('name' => 'charlie'),
208 'c' => array('name' => 'alpha')
210 $this->assertSame(array('a', 'b', 'c'), array_keys($array));
211 $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
212 $this->assertSame(array('c', 'a', 'b'), array_keys($array));
214 $array = array(
215 'a' => array('name' => 'b'),
216 'b' => array('name' => 1),
217 'c' => array('name' => 0)
219 $this->assertSame(array('a', 'b', 'c'), array_keys($array));
220 $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
221 $this->assertSame(array('c', 'b', 'a'), array_keys($array));
223 $array = array(
224 'a' => array('name' => 'áb'),
225 'b' => array('name' => 'ab'),
226 1 => array('name' => 'aa'),
227 'd' => array('name' => 'cc'),
228 0 => array('name' => 'Áb')
230 $this->assertSame(array('a', 'b', 1, 'd', 0), array_keys($array));
231 $this->assertTrue(core_collator::asort_array_of_arrays_by_key($array, 'name'));
232 $this->assertSame(array(1, 'b', 'a', 0, 'd'), array_keys($array));
233 $this->assertSame(array(
234 1 => array('name' => 'aa'),
235 'b' => array('name' => 'ab'),
236 'a' => array('name' => 'áb'),
237 0 => array('name' => 'Áb'),
238 'd' => array('name' => 'cc')
239 ), $array);
244 * Returns an array of sorted names.
245 * @param array $objects
246 * @param string $methodproperty
247 * @return array
249 protected function get_ordered_names($objects, $methodproperty = 'get_protected_name') {
250 $return = array();
251 foreach ($objects as $object) {
252 if ($methodproperty == 'publicname') {
253 $return[] = $object->publicname;
254 } else {
255 $return[] = $object->$methodproperty();
258 return $return;
262 * Tests the static ksort method.
264 public function test_ksort() {
265 $arr = array('b' => 'ab', 1 => 'aa', 0 => 'cc');
266 $result = core_collator::ksort($arr);
267 $this->assertSame(array(0, 1, 'b'), array_keys($arr));
268 $this->assertSame(array('cc', 'aa', 'ab'), array_values($arr));
269 $this->assertTrue($result);
271 $obj = new stdClass();
272 $arr = array('1.1.1'=>array(), '1.2'=>$obj, '1.20.2'=>null);
273 $result = core_collator::ksort($arr, core_collator::SORT_NATURAL);
274 $this->assertSame(array('1.1.1', '1.2', '1.20.2'), array_keys($arr));
275 $this->assertSame(array(array(), $obj, null), array_values($arr));
276 $this->assertTrue($result);
278 $a = array(2=>'b', 1=>'c');
279 $c =& $a;
280 $b =& $a;
281 core_collator::ksort($b);
282 $this->assertSame($a, $b);
283 $this->assertSame($c, $b);
290 * Simple class used to work with the unit test.
292 * @package core
293 * @category phpunit
294 * @copyright 2011 Sam Hemelryk
295 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
297 class string_test_class extends stdClass {
299 * @var string A public property
301 public $publicname;
303 * @var string A protected property
305 protected $protectedname;
307 * @var string A private property
309 private $privatename;
311 * Constructs the test instance.
312 * @param string $name
314 public function __construct($name) {
315 $this->publicname = $name;
316 $this->protectedname = $name;
317 $this->privatename = $name;
320 * Returns the protected property.
321 * @return string
323 public function get_protected_name() {
324 return $this->protectedname;
327 * Returns the protected property.
328 * @return string
330 public function get_private_name() {
331 return $this->publicname;