Merge "Import: Fix error reporting"
[lhc/web/wiklou.git] / tests / phpunit / includes / utils / IPTest.php
1 <?php
2 /**
3 * Tests for IP validity functions.
4 *
5 * Ported from /t/inc/IP.t by avar.
6 *
7 * @group IP
8 * @todo Test methods in this call should be split into a method and a
9 * dataprovider.
10 */
11
12 class IPTest extends PHPUnit_Framework_TestCase {
13 /**
14 * not sure it should be tested with boolean false. hashar 20100924
15 * @covers IP::isIPAddress
16 */
17 public function testisIPAddress() {
18 $this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' );
19 $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' );
20 $this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' );
21 $this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' );
22 $this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' );
23 $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' );
24 $this->assertFalse(
25 IP::isIPAddress( '2001:0DB8::A:1::' ),
26 'IPv6 with a double :: occurrence, last at end'
27 );
28 $this->assertFalse(
29 IP::isIPAddress( '::2001:0DB8::5:1' ),
30 'IPv6 with a double :: occurrence, firt at beginning'
31 );
32 $this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' );
33 $this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' );
34 $this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' );
35 $this->assertFalse( IP::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' );
36
37 $this->assertTrue( IP::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' );
38 $this->assertTrue( IP::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' );
39 $this->assertTrue( IP::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) );
40 $this->assertTrue( IP::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' );
41 $this->assertTrue( IP::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' );
42
43 $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac',
44 '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' );
45 foreach ( $validIPs as $ip ) {
46 $this->assertTrue( IP::isIPAddress( $ip ), "$ip is a valid IP address" );
47 }
48 }
49
50 /**
51 * @covers IP::isIPv6
52 */
53 public function testisIPv6() {
54 $this->assertFalse( IP::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' );
55 $this->assertFalse( IP::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
56 $this->assertFalse( IP::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' );
57 $this->assertFalse( IP::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' );
58
59 $this->assertTrue( IP::isIPv6( 'fc:100::' ) );
60 $this->assertTrue( IP::isIPv6( 'fc:100:a::' ) );
61 $this->assertTrue( IP::isIPv6( 'fc:100:a:d::' ) );
62 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1::' ) );
63 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e::' ) );
64 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac::' ) );
65
66 $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
67 $this->assertFalse(
68 IP::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ),
69 'IPv6 with 9 words ending with "::"'
70 );
71
72 $this->assertFalse( IP::isIPv6( ':::' ) );
73 $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
74
75 $this->assertTrue( IP::isIPv6( '::' ), 'IPv6 zero address' );
76 $this->assertTrue( IP::isIPv6( '::0' ) );
77 $this->assertTrue( IP::isIPv6( '::fc' ) );
78 $this->assertTrue( IP::isIPv6( '::fc:100' ) );
79 $this->assertTrue( IP::isIPv6( '::fc:100:a' ) );
80 $this->assertTrue( IP::isIPv6( '::fc:100:a:d' ) );
81 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1' ) );
82 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e' ) );
83 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e:ac' ) );
84
85 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
86 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
87
88 $this->assertFalse( IP::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' );
89 $this->assertFalse( IP::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' );
90 $this->assertFalse( IP::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' );
91
92 $this->assertTrue( IP::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' );
93 $this->assertTrue( IP::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
94 $this->assertTrue( IP::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) );
95 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
96 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
97 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
98 $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
99 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
100 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
101
102 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
103 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
104
105 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
106 }
107
108 /**
109 * @covers IP::isIPv4
110 */
111 public function testisIPv4() {
112 $this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' );
113 $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' );
114 $this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' );
115 $this->assertFalse( IP::isIPv4( 'abc' ) );
116 $this->assertFalse( IP::isIPv4( ':' ) );
117 $this->assertFalse( IP::isIPv4( '124.24.52' ), 'IPv4 not enough quads' );
118 $this->assertFalse( IP::isIPv4( '24.324.52.13' ), 'IPv4 out of range' );
119 $this->assertFalse( IP::isIPv4( '.24.52.13' ), 'IPv4 starts with period' );
120
121 $this->assertTrue( IP::isIPv4( '124.24.52.13' ) );
122 $this->assertTrue( IP::isIPv4( '1.24.52.13' ) );
123 $this->assertTrue( IP::isIPv4( '74.24.52.13/20', 'IPv4 range' ) );
124 }
125
126 /**
127 * @covers IP::isValid
128 */
129 public function testValidIPs() {
130 foreach ( range( 0, 255 ) as $i ) {
131 $a = sprintf( "%03d", $i );
132 $b = sprintf( "%02d", $i );
133 $c = sprintf( "%01d", $i );
134 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
135 $ip = "$f.$f.$f.$f";
136 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv4 address" );
137 }
138 }
139 foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) {
140 $a = sprintf( "%04x", $i );
141 $b = sprintf( "%03x", $i );
142 $c = sprintf( "%02x", $i );
143 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
144 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
145 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv6 address" );
146 }
147 }
148 // test with some abbreviations
149 $this->assertFalse( IP::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' );
150 $this->assertFalse( IP::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
151 $this->assertFalse( IP::isValid( 'fc:300' ), 'IPv6 with only 2 words' );
152 $this->assertFalse( IP::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' );
153
154 $this->assertTrue( IP::isValid( 'fc:100::' ) );
155 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e::' ) );
156 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e:ac::' ) );
157
158 $this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
159 $this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
160 $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
161 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
162 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
163 $this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
164 $this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
165
166 $this->assertFalse(
167 IP::isValid( 'fc:100:a:d:1:e:ac:0::' ),
168 'IPv6 with 8 words ending with "::"'
169 );
170 $this->assertFalse(
171 IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ),
172 'IPv6 with 9 words ending with "::"'
173 );
174 }
175
176 /**
177 * @covers IP::isValid
178 */
179 public function testInvalidIPs() {
180 // Out of range...
181 foreach ( range( 256, 999 ) as $i ) {
182 $a = sprintf( "%03d", $i );
183 $b = sprintf( "%02d", $i );
184 $c = sprintf( "%01d", $i );
185 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
186 $ip = "$f.$f.$f.$f";
187 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv4 address" );
188 }
189 }
190 foreach ( range( 'g', 'z' ) as $i ) {
191 $a = sprintf( "%04s", $i );
192 $b = sprintf( "%03s", $i );
193 $c = sprintf( "%02s", $i );
194 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
195 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
196 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv6 address" );
197 }
198 }
199 // Have CIDR
200 $ipCIDRs = array(
201 '212.35.31.121/32',
202 '212.35.31.121/18',
203 '212.35.31.121/24',
204 '::ff:d:321:5/96',
205 'ff::d3:321:5/116',
206 'c:ff:12:1:ea:d:321:5/120',
207 );
208 foreach ( $ipCIDRs as $i ) {
209 $this->assertFalse( IP::isValid( $i ),
210 "$i is an invalid IP address because it is a block" );
211 }
212 // Incomplete/garbage
213 $invalid = array(
214 'www.xn--var-xla.net',
215 '216.17.184.G',
216 '216.17.184.1.',
217 '216.17.184',
218 '216.17.184.',
219 '256.17.184.1'
220 );
221 foreach ( $invalid as $i ) {
222 $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" );
223 }
224 }
225
226 /**
227 * @covers IP::isValidBlock
228 */
229 public function testValidBlocks() {
230 $valid = array(
231 '116.17.184.5/32',
232 '0.17.184.5/30',
233 '16.17.184.1/24',
234 '30.242.52.14/1',
235 '10.232.52.13/8',
236 '30.242.52.14/0',
237 '::e:f:2001/96',
238 '::c:f:2001/128',
239 '::10:f:2001/70',
240 '::fe:f:2001/1',
241 '::6d:f:2001/8',
242 '::fe:f:2001/0',
243 );
244 foreach ( $valid as $i ) {
245 $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" );
246 }
247 }
248
249 /**
250 * @covers IP::isValidBlock
251 */
252 public function testInvalidBlocks() {
253 $invalid = array(
254 '116.17.184.5/33',
255 '0.17.184.5/130',
256 '16.17.184.1/-1',
257 '10.232.52.13/*',
258 '7.232.52.13/ab',
259 '11.232.52.13/',
260 '::e:f:2001/129',
261 '::c:f:2001/228',
262 '::10:f:2001/-1',
263 '::6d:f:2001/*',
264 '::86:f:2001/ab',
265 '::23:f:2001/',
266 );
267 foreach ( $invalid as $i ) {
268 $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" );
269 }
270 }
271
272 /**
273 * Improve IP::sanitizeIP() code coverage
274 * @todo Most probably incomplete
275 */
276 public function testSanitizeIP() {
277 $this->assertNull( IP::sanitizeIP( '' ) );
278 $this->assertNull( IP::sanitizeIP( ' ' ) );
279 }
280
281 /**
282 * @covers IP::toHex
283 * @dataProvider provideToHex
284 */
285 public function testToHex( $expected, $input ) {
286 $result = IP::toHex( $input );
287 $this->assertTrue( $result === false || is_string( $result ) );
288 $this->assertEquals( $expected, $result );
289 }
290
291 /**
292 * Provider for IP::testToHex()
293 */
294 public static function provideToHex() {
295 return array(
296 array( '00000001', '0.0.0.1' ),
297 array( '01020304', '1.2.3.4' ),
298 array( '7F000001', '127.0.0.1' ),
299 array( '80000000', '128.0.0.0' ),
300 array( 'DEADCAFE', '222.173.202.254' ),
301 array( 'FFFFFFFF', '255.255.255.255' ),
302 array( false, 'IN.VA.LI.D' ),
303 array( 'v6-00000000000000000000000000000001', '::1' ),
304 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
305 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
306 array( false, 'IN:VA::LI:D' ),
307 array( false, ':::1' )
308 );
309 }
310
311 /**
312 * @covers IP::isPublic
313 */
314 public function testPrivateIPs() {
315 $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' );
316 foreach ( $private as $p ) {
317 $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" );
318 }
319 $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' );
320 foreach ( $public as $p ) {
321 $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" );
322 }
323 }
324
325 // Private wrapper used to test CIDR Parsing.
326 private function assertFalseCIDR( $CIDR, $msg = '' ) {
327 $ff = array( false, false );
328 $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg );
329 }
330
331 // Private wrapper to test network shifting using only dot notation
332 private function assertNet( $expected, $CIDR ) {
333 $parse = IP::parseCIDR( $CIDR );
334 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
335 }
336
337 /**
338 * @covers IP::hexToQuad
339 */
340 public function testHexToQuad() {
341 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) );
342 $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) );
343 $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) );
344 $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) );
345 // hex not left-padded...
346 $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) );
347 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) );
348 $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) );
349 $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) );
350 }
351
352 /**
353 * @covers IP::hexToOctet
354 */
355 public function testHexToOctet() {
356 $this->assertEquals( '0:0:0:0:0:0:0:1',
357 IP::hexToOctet( '00000000000000000000000000000001' ) );
358 $this->assertEquals( '0:0:0:0:0:0:FF:3',
359 IP::hexToOctet( '00000000000000000000000000FF0003' ) );
360 $this->assertEquals( '0:0:0:0:0:0:FF00:6',
361 IP::hexToOctet( '000000000000000000000000FF000006' ) );
362 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF',
363 IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) );
364 $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
365 IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
366 // hex not left-padded...
367 $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) );
368 $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) );
369 $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) );
370 $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) );
371 $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) );
372 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) );
373 }
374
375 /**
376 * IP::parseCIDR() returns an array containing a signed IP address
377 * representing the network mask and the bit mask.
378 * @covers IP::parseCIDR
379 */
380 public function testCIDRParsing() {
381 $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
382 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
383
384 // Verify if statement
385 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
386 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
387 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
388 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
389
390 // Check internal logic
391 # 0 mask always result in array(0,0)
392 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) );
393 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) );
394 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) );
395
396 // @todo FIXME: Add more tests.
397
398 # This part test network shifting
399 $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
400 $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
401 $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
402 $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
403 $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
404 $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
405 $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
406 $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
407 $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
408 }
409
410 /**
411 * @covers IP::canonicalize
412 */
413 public function testIPCanonicalizeOnValidIp() {
414 $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ),
415 'Canonicalization of a valid IP returns it unchanged' );
416 }
417
418 /**
419 * @covers IP::canonicalize
420 */
421 public function testIPCanonicalizeMappedAddress() {
422 $this->assertEquals(
423 '192.0.2.152',
424 IP::canonicalize( '::ffff:192.0.2.152' )
425 );
426 $this->assertEquals(
427 '192.0.2.152',
428 IP::canonicalize( '::192.0.2.152' )
429 );
430 }
431
432 /**
433 * Issues there are most probably from IP::toHex() or IP::parseRange()
434 * @covers IP::isInRange
435 * @dataProvider provideIPsAndRanges
436 */
437 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
438 $this->assertEquals(
439 $expected,
440 IP::isInRange( $addr, $range ),
441 $message
442 );
443 }
444
445 /** Provider for testIPIsInRange() */
446 public static function provideIPsAndRanges() {
447 # Format: (expected boolean, address, range, optional message)
448 return array(
449 # IPv4
450 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
451 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
452 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
453
454 array( false, '0.0.0.0', '192.0.2.0/24' ),
455 array( false, '255.255.255', '192.0.2.0/24' ),
456
457 # IPv6
458 array( false, '::1', '2001:DB8::/32' ),
459 array( false, '::', '2001:DB8::/32' ),
460 array( false, 'FE80::1', '2001:DB8::/32' ),
461
462 array( true, '2001:DB8::', '2001:DB8::/32' ),
463 array( true, '2001:0DB8::', '2001:DB8::/32' ),
464 array( true, '2001:DB8::1', '2001:DB8::/32' ),
465 array( true, '2001:0DB8::1', '2001:DB8::/32' ),
466 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
467 '2001:DB8::/32' ),
468
469 array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
470 );
471 }
472
473 /**
474 * Test for IP::splitHostAndPort().
475 * @dataProvider provideSplitHostAndPort
476 */
477 public function testSplitHostAndPort( $expected, $input, $description ) {
478 $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description );
479 }
480
481 /**
482 * Provider for IP::splitHostAndPort()
483 */
484 public static function provideSplitHostAndPort() {
485 return array(
486 array( false, '[', 'Unclosed square bracket' ),
487 array( false, '[::', 'Unclosed square bracket 2' ),
488 array( array( '::', false ), '::', 'Bare IPv6 0' ),
489 array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
490 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
491 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
492 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
493 array( false, '::x', 'Double colon but no IPv6' ),
494 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
495 array( false, 'x:x', 'Hostname and invalid port' ),
496 array( array( 'x', false ), 'x', 'Plain hostname' )
497 );
498 }
499
500 /**
501 * Test for IP::combineHostAndPort()
502 * @dataProvider provideCombineHostAndPort
503 */
504 public function testCombineHostAndPort( $expected, $input, $description ) {
505 list( $host, $port, $defaultPort ) = $input;
506 $this->assertEquals(
507 $expected,
508 IP::combineHostAndPort( $host, $port, $defaultPort ),
509 $description );
510 }
511
512 /**
513 * Provider for IP::combineHostAndPort()
514 */
515 public static function provideCombineHostAndPort() {
516 return array(
517 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
518 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
519 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
520 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
521 );
522 }
523
524 /**
525 * Test for IP::sanitizeRange()
526 * @dataProvider provideIPCIDRs
527 */
528 public function testSanitizeRange( $input, $expected, $description ) {
529 $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
530 }
531
532 /**
533 * Provider for IP::testSanitizeRange()
534 */
535 public static function provideIPCIDRs() {
536 return array(
537 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
538 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
539 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
540 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
541 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
542 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
543 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
544 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
545 );
546 }
547
548 /**
549 * Test for IP::prettifyIP()
550 * @dataProvider provideIPsToPrettify
551 */
552 public function testPrettifyIP( $ip, $prettified ) {
553 $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" );
554 }
555
556 /**
557 * Provider for IP::testPrettifyIP()
558 */
559 public static function provideIPsToPrettify() {
560 return array(
561 array( '0:0:0:0:0:0:0:0', '::' ),
562 array( '0:0:0::0:0:0', '::' ),
563 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
564 array( '0:0::f', '::f' ),
565 array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
566 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
567 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
568 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
569 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
570 array( '0:0:0:0:0:0:0:0/16', '::/16' ),
571 array( '0:0:0::0:0:0/64', '::/64' ),
572 array( '0:0::f/52', '::f/52' ),
573 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
574 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
575 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
576 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
577 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),
578 );
579 }
580 }