6 require_once 'application/Utils.php';
7 require_once 'tests/utils/ReferenceSessionIdHashes.php';
9 // Initialize reference data before PHPUnit starts a session
10 ReferenceSessionIdHashes
::genAllHashes();
14 * Unitary tests for Shaarli utilities
16 class UtilsTest
extends PHPUnit_Framework_TestCase
19 protected static $sidHashes = null;
22 protected static $testLogFile = 'tests.log';
24 // Expected log date format
25 protected static $dateFormat = 'Y/m/d H:i:s';
28 * @var string Save the current timezone.
30 protected static $defaultTimeZone;
34 * Assign reference data
36 public static function setUpBeforeClass()
38 self
::$sidHashes = ReferenceSessionIdHashes
::getHashes();
39 self
::$defaultTimeZone = date_default_timezone_get();
40 // Timezone without DST for test consistency
41 date_default_timezone_set('Africa/Nairobi');
47 public static function tearDownAfterClass()
49 date_default_timezone_set(self
::$defaultTimeZone);
53 * Resets test data before each test
55 protected function setUp()
57 if (file_exists(self
::$testLogFile)) {
58 unlink(self
::$testLogFile);
63 * Returns a list of the elements from the last logged entry
65 * @return list (date, ip address, message)
67 protected function getLastLogEntry()
69 $logFile = file(self
::$testLogFile);
70 return explode(' - ', trim(array_pop($logFile), PHP_EOL
));
74 * Log a message to a file - IPv4 client address
76 public function testLogmIp4()
78 $logMessage = 'IPv4 client connected';
79 logm(self
::$testLogFile, '127.0.0.1', $logMessage);
80 list($date, $ip, $message) = $this->getLastLogEntry();
82 $this->assertInstanceOf(
84 DateTime
::createFromFormat(self
::$dateFormat, $date)
87 filter_var($ip, FILTER_VALIDATE_IP
, FILTER_FLAG_IPV4
) !== false
89 $this->assertEquals($logMessage, $message);
93 * Log a message to a file - IPv6 client address
95 public function testLogmIp6()
97 $logMessage = 'IPv6 client connected';
98 logm(self
::$testLogFile, '2001:db8::ff00:42:8329', $logMessage);
99 list($date, $ip, $message) = $this->getLastLogEntry();
101 $this->assertInstanceOf(
103 DateTime
::createFromFormat(self
::$dateFormat, $date)
106 filter_var($ip, FILTER_VALIDATE_IP
, FILTER_FLAG_IPV6
) !== false
108 $this->assertEquals($logMessage, $message);
112 * Represent a link by its hash
114 public function testSmallHash()
116 $this->assertEquals('CyAAJw', smallHash('http://test.io'));
117 $this->assertEquals(6, strlen(smallHash('https://github.com')));
121 * Look for a substring at the beginning of a string
123 public function testStartsWithCaseInsensitive()
125 $this->assertTrue(startsWith('Lorem ipsum', 'lorem', false));
126 $this->assertTrue(startsWith('Lorem ipsum', 'LoReM i', false));
130 * Look for a substring at the beginning of a string (case-sensitive)
132 public function testStartsWithCaseSensitive()
134 $this->assertTrue(startsWith('Lorem ipsum', 'Lorem', true));
135 $this->assertFalse(startsWith('Lorem ipsum', 'lorem', true));
136 $this->assertFalse(startsWith('Lorem ipsum', 'LoReM i', true));
140 * Look for a substring at the beginning of a string (Unicode)
142 public function testStartsWithSpecialChars()
144 $this->assertTrue(startsWith('å!ùµ', 'å!', false));
145 $this->assertTrue(startsWith('µ$åù', 'µ$', true));
149 * Look for a substring at the end of a string
151 public function testEndsWithCaseInsensitive()
153 $this->assertTrue(endsWith('Lorem ipsum
', 'ipsum
', false));
154 $this->assertTrue(endsWith('Lorem ipsum
', 'm IpsUM
', false));
158 * Look for a substring at the end of a string (case-sensitive)
160 public function testEndsWithCaseSensitive()
162 $this->assertTrue(endsWith('lorem Ipsum
', 'Ipsum
', true));
163 $this->assertFalse(endsWith('lorem Ipsum
', 'ipsum
', true));
164 $this->assertFalse(endsWith('lorem Ipsum
', 'M IPsuM
', true));
168 * Look for a substring at the end of a string (Unicode)
170 public function testEndsWithSpecialChars()
172 $this->assertTrue(endsWith('å
!ùµ
', 'ùµ
', false));
173 $this->assertTrue(endsWith('µ$åù
', 'åù
', true));
177 * Check valid date strings, according to a DateTime format
179 public function testCheckValidDateFormat()
181 $this->assertTrue(checkDateFormat('Ymd
', '20150627'));
182 $this->assertTrue(checkDateFormat('Y
-m
-d
', '2015-06-27'));
186 * Check erroneous date strings, according to a DateTime format
188 public function testCheckInvalidDateFormat()
190 $this->assertFalse(checkDateFormat('Ymd
', '2015'));
191 $this->assertFalse(checkDateFormat('Y
-m
-d
', '2015-06'));
192 $this->assertFalse(checkDateFormat('Ymd
', 'DeLorean
'));
196 * Test generate location with valid data.
198 public function testGenerateLocation() {
199 $ref = 'http
://localhost/?test';
200 $this->assertEquals($ref, generateLocation($ref, 'localhost'));
201 $ref = 'http://localhost:8080/?test';
202 $this->assertEquals($ref, generateLocation($ref, 'localhost:8080'));
203 $ref = '?localreferer#hash';
204 $this->assertEquals($ref, generateLocation($ref, 'localhost:8080'));
208 * Test generate location - anti loop.
210 public function testGenerateLocationLoop() {
211 $ref = 'http://localhost/?test';
212 $this->assertEquals('?', generateLocation($ref, 'localhost', array('test')));
216 * Test generate location - from other domain.
218 public function testGenerateLocationOut() {
219 $ref = 'http://somewebsite.com/?test';
220 $this->assertEquals('?', generateLocation($ref, 'localhost'));
224 * Test is_session_id_valid with a valid ID - TEST ALL THE HASHES!
226 * This tests extensively covers all hash algorithms / bit representations
228 public function testIsAnyHashSessionIdValid()
230 foreach (self
::$sidHashes as $algo => $bpcs) {
231 foreach ($bpcs as $bpc => $hash) {
232 $this->assertTrue(is_session_id_valid($hash));
238 * Test is_session_id_valid with a valid ID - SHA-1 hashes
240 public function testIsSha1SessionIdValid()
242 $this->assertTrue(is_session_id_valid(sha1('shaarli')));
246 * Test is_session_id_valid with a valid ID - SHA-256 hashes
248 public function testIsSha256SessionIdValid()
250 $this->assertTrue(is_session_id_valid(hash('sha256', 'shaarli')));
254 * Test is_session_id_valid with a valid ID - SHA-512 hashes
256 public function testIsSha512SessionIdValid()
258 $this->assertTrue(is_session_id_valid(hash('sha512', 'shaarli')));
262 * Test is_session_id_valid with invalid IDs.
264 public function testIsSessionIdInvalid()
266 $this->assertFalse(is_session_id_valid(''));
267 $this->assertFalse(is_session_id_valid(array()));
269 is_session_id_valid('c0ZqcWF3VFE2NmJBdm1HMVQ0ZHJ3UmZPbTFsNGhkNHI=')
274 * Test generateSecretApi.
276 public function testGenerateSecretApi()
278 $this->assertEquals(12, strlen(generate_api_secret('foo', 'bar')));
282 * Test generateSecretApi with invalid parameters.
284 public function testGenerateSecretApiInvalid()
286 $this->assertFalse(generate_api_secret('', ''));
287 $this->assertFalse(generate_api_secret(false, false));
291 * Test normalize_spaces.
293 public function testNormalizeSpace()
295 $str = ' foo bar is important ';
296 $this->assertEquals('foo bar is important', normalize_spaces($str));
297 $this->assertEquals('foo', normalize_spaces('foo'));
298 $this->assertEquals('', normalize_spaces(''));
299 $this->assertEquals(null, normalize_spaces(null));
303 * Test arrays_combine
305 public function testCartesianProductGenerator()
307 $arr = [['ab', 'cd'], ['ef', 'gh'], ['ij', 'kl'], ['m']];
309 ['ab', 'ef', 'ij', 'm'],
310 ['ab', 'ef', 'kl', 'm'],
311 ['ab', 'gh', 'ij', 'm'],
312 ['ab', 'gh', 'kl', 'm'],
313 ['cd', 'ef', 'ij', 'm'],
314 ['cd', 'ef', 'kl', 'm'],
315 ['cd', 'gh', 'ij', 'm'],
316 ['cd', 'gh', 'kl', 'm'],
318 $this->assertEquals($expected, iterator_to_array(cartesian_product_generator($arr)));
322 * Test date_format() with invalid parameter.
324 public function testDateFormatInvalid()
326 $this->assertFalse(format_date([]));
327 $this->assertFalse(format_date(null));