3 * Tests for IP validity functions. Ported from /t/inc/IP.t by avar.
7 class IPTest
extends MediaWikiTestCase
{
9 * not sure it should be tested with boolean false. hashar 20100924
10 * @covers IP::isIPAddress
12 public function testisIPAddress() {
13 $this->assertFalse( IP
::isIPAddress( false ), 'Boolean false is not an IP' );
14 $this->assertFalse( IP
::isIPAddress( true ), 'Boolean true is not an IP' );
15 $this->assertFalse( IP
::isIPAddress( "" ), 'Empty string is not an IP' );
16 $this->assertFalse( IP
::isIPAddress( 'abc' ), 'Garbage IP string' );
17 $this->assertFalse( IP
::isIPAddress( ':' ), 'Single ":" is not an IP' );
18 $this->assertFalse( IP
::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' );
19 $this->assertFalse( IP
::isIPAddress( '2001:0DB8::A:1::' ), 'IPv6 with a double :: occurrence, last at end' );
20 $this->assertFalse( IP
::isIPAddress( '::2001:0DB8::5:1' ), 'IPv6 with a double :: occurrence, firt at beginning' );
21 $this->assertFalse( IP
::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' );
22 $this->assertFalse( IP
::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' );
23 $this->assertFalse( IP
::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' );
24 $this->assertFalse( IP
::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' );
26 $this->assertTrue( IP
::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' );
27 $this->assertTrue( IP
::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' );
28 $this->assertTrue( IP
::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) );
29 $this->assertTrue( IP
::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' );
30 $this->assertTrue( IP
::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' );
32 $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac',
33 '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' );
34 foreach ( $validIPs as $ip ) {
35 $this->assertTrue( IP
::isIPAddress( $ip ), "$ip is a valid IP address" );
42 public function testisIPv6() {
43 $this->assertFalse( IP
::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' );
44 $this->assertFalse( IP
::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
45 $this->assertFalse( IP
::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' );
46 $this->assertFalse( IP
::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' );
48 $this->assertTrue( IP
::isIPv6( 'fc:100::' ) );
49 $this->assertTrue( IP
::isIPv6( 'fc:100:a::' ) );
50 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d::' ) );
51 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1::' ) );
52 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e::' ) );
53 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e:ac::' ) );
55 $this->assertFalse( IP
::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
56 $this->assertFalse( IP
::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' );
58 $this->assertFalse( IP
::isIPv6( ':::' ) );
59 $this->assertFalse( IP
::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
61 $this->assertTrue( IP
::isIPv6( '::' ), 'IPv6 zero address' );
62 $this->assertTrue( IP
::isIPv6( '::0' ) );
63 $this->assertTrue( IP
::isIPv6( '::fc' ) );
64 $this->assertTrue( IP
::isIPv6( '::fc:100' ) );
65 $this->assertTrue( IP
::isIPv6( '::fc:100:a' ) );
66 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d' ) );
67 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1' ) );
68 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1:e' ) );
69 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1:e:ac' ) );
71 $this->assertFalse( IP
::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
72 $this->assertFalse( IP
::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
74 $this->assertFalse( IP
::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' );
75 $this->assertFalse( IP
::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' );
76 $this->assertFalse( IP
::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' );
78 $this->assertTrue( IP
::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' );
79 $this->assertTrue( IP
::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
80 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) );
81 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
82 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
83 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
84 $this->assertTrue( IP
::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
85 $this->assertTrue( IP
::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
86 $this->assertTrue( IP
::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
88 $this->assertFalse( IP
::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
89 $this->assertFalse( IP
::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
91 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
97 public function testisIPv4() {
98 $this->assertFalse( IP
::isIPv4( false ), 'Boolean false is not an IP' );
99 $this->assertFalse( IP
::isIPv4( true ), 'Boolean true is not an IP' );
100 $this->assertFalse( IP
::isIPv4( "" ), 'Empty string is not an IP' );
101 $this->assertFalse( IP
::isIPv4( 'abc' ) );
102 $this->assertFalse( IP
::isIPv4( ':' ) );
103 $this->assertFalse( IP
::isIPv4( '124.24.52' ), 'IPv4 not enough quads' );
104 $this->assertFalse( IP
::isIPv4( '24.324.52.13' ), 'IPv4 out of range' );
105 $this->assertFalse( IP
::isIPv4( '.24.52.13' ), 'IPv4 starts with period' );
107 $this->assertTrue( IP
::isIPv4( '124.24.52.13' ) );
108 $this->assertTrue( IP
::isIPv4( '1.24.52.13' ) );
109 $this->assertTrue( IP
::isIPv4( '74.24.52.13/20', 'IPv4 range' ) );
113 * @covers IP::isValid
115 public function testValidIPs() {
116 foreach ( range( 0, 255 ) as $i ) {
117 $a = sprintf( "%03d", $i );
118 $b = sprintf( "%02d", $i );
119 $c = sprintf( "%01d", $i );
120 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
122 $this->assertTrue( IP
::isValid( $ip ), "$ip is a valid IPv4 address" );
125 foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) {
126 $a = sprintf( "%04x", $i );
127 $b = sprintf( "%03x", $i );
128 $c = sprintf( "%02x", $i );
129 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
130 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
131 $this->assertTrue( IP
::isValid( $ip ), "$ip is a valid IPv6 address" );
134 // test with some abbreviations
135 $this->assertFalse( IP
::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' );
136 $this->assertFalse( IP
::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
137 $this->assertFalse( IP
::isValid( 'fc:300' ), 'IPv6 with only 2 words' );
138 $this->assertFalse( IP
::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' );
140 $this->assertTrue( IP
::isValid( 'fc:100::' ) );
141 $this->assertTrue( IP
::isValid( 'fc:100:a:d:1:e::' ) );
142 $this->assertTrue( IP
::isValid( 'fc:100:a:d:1:e:ac::' ) );
144 $this->assertTrue( IP
::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
145 $this->assertTrue( IP
::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
146 $this->assertTrue( IP
::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
147 $this->assertTrue( IP
::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
148 $this->assertTrue( IP
::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
149 $this->assertTrue( IP
::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
150 $this->assertTrue( IP
::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
152 $this->assertFalse( IP
::isValid( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
153 $this->assertFalse( IP
::isValid( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' );
157 * @covers IP::isValid
159 public function testInvalidIPs() {
161 foreach ( range( 256, 999 ) as $i ) {
162 $a = sprintf( "%03d", $i );
163 $b = sprintf( "%02d", $i );
164 $c = sprintf( "%01d", $i );
165 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
167 $this->assertFalse( IP
::isValid( $ip ), "$ip is not a valid IPv4 address" );
170 foreach ( range( 'g', 'z' ) as $i ) {
171 $a = sprintf( "%04s", $i );
172 $b = sprintf( "%03s", $i );
173 $c = sprintf( "%02s", $i );
174 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
175 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
176 $this->assertFalse( IP
::isValid( $ip ), "$ip is not a valid IPv6 address" );
186 'c:ff:12:1:ea:d:321:5/120',
188 foreach ( $ipCIDRs as $i ) {
189 $this->assertFalse( IP
::isValid( $i ),
190 "$i is an invalid IP address because it is a block" );
192 // Incomplete/garbage
194 'www.xn--var-xla.net',
201 foreach ( $invalid as $i ) {
202 $this->assertFalse( IP
::isValid( $i ), "$i is an invalid IP address" );
207 * @covers IP::isValidBlock
209 public function testValidBlocks() {
224 foreach ( $valid as $i ) {
225 $this->assertTrue( IP
::isValidBlock( $i ), "$i is a valid IP block" );
230 * @covers IP::isValidBlock
232 public function testInvalidBlocks() {
247 foreach ( $invalid as $i ) {
248 $this->assertFalse( IP
::isValidBlock( $i ), "$i is not a valid IP block" );
253 * Improve IP::sanitizeIP() code coverage
254 * @todo Most probably incomplete
256 public function testSanitizeIP() {
257 $this->assertNull( IP
::sanitizeIP( '' ) );
258 $this->assertNull( IP
::sanitizeIP( ' ' ) );
262 * @covers IP::toUnsigned
263 * @dataProvider provideToUnsigned
265 public function testToUnsigned( $expected, $input ) {
266 $result = IP
::toUnsigned( $input );
267 $this->assertTrue( $result === false ||
is_string( $result ) ||
is_int( $result ) );
268 $this->assertEquals( $expected, $result );
272 * Provider for IP::testToUnsigned()
274 public static function provideToUnsigned() {
276 array( 1, '0.0.0.1' ),
277 array( 16909060, '1.2.3.4' ),
278 array( 2130706433, '127.0.0.1' ),
279 array( '2147483648', '128.0.0.0' ),
280 array( '3735931646', '222.173.202.254' ),
281 array( pow( 2, 32 ) - 1, '255.255.255.255' ),
282 array( false, 'IN.VA.LI.D' ),
284 array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
285 array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ),
286 array( false, 'IN:VA::LI:D' ),
287 array( false, ':::1' )
293 * @dataProvider provideToHex
295 public function testToHex( $expected, $input ) {
296 $result = IP
::toHex( $input );
297 $this->assertTrue( $result === false ||
is_string( $result ) );
298 $this->assertEquals( $expected, $result );
302 * Provider for IP::testToHex()
304 public static function provideToHex() {
306 array( '00000001', '0.0.0.1' ),
307 array( '01020304', '1.2.3.4' ),
308 array( '7F000001', '127.0.0.1' ),
309 array( '80000000', '128.0.0.0' ),
310 array( 'DEADCAFE', '222.173.202.254' ),
311 array( 'FFFFFFFF', '255.255.255.255' ),
312 array( false, 'IN.VA.LI.D' ),
313 array( 'v6-00000000000000000000000000000001', '::1' ),
314 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
315 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
316 array( false, 'IN:VA::LI:D' ),
317 array( false, ':::1' )
322 * @covers IP::isPublic
324 public function testPrivateIPs() {
325 $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' );
326 foreach ( $private as $p ) {
327 $this->assertFalse( IP
::isPublic( $p ), "$p is not a public IP address" );
329 $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' );
330 foreach ( $public as $p ) {
331 $this->assertTrue( IP
::isPublic( $p ), "$p is a public IP address" );
335 // Private wrapper used to test CIDR Parsing.
336 private function assertFalseCIDR( $CIDR, $msg = '' ) {
337 $ff = array( false, false );
338 $this->assertEquals( $ff, IP
::parseCIDR( $CIDR ), $msg );
341 // Private wrapper to test network shifting using only dot notation
342 private function assertNet( $expected, $CIDR ) {
343 $parse = IP
::parseCIDR( $CIDR );
344 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
348 * @covers IP::hexToQuad
350 public function testHexToQuad() {
351 $this->assertEquals( '0.0.0.1', IP
::hexToQuad( '00000001' ) );
352 $this->assertEquals( '255.0.0.0', IP
::hexToQuad( 'FF000000' ) );
353 $this->assertEquals( '255.255.255.255', IP
::hexToQuad( 'FFFFFFFF' ) );
354 $this->assertEquals( '10.188.222.255', IP
::hexToQuad( '0ABCDEFF' ) );
355 // hex not left-padded...
356 $this->assertEquals( '0.0.0.0', IP
::hexToQuad( '0' ) );
357 $this->assertEquals( '0.0.0.1', IP
::hexToQuad( '1' ) );
358 $this->assertEquals( '0.0.0.255', IP
::hexToQuad( 'FF' ) );
359 $this->assertEquals( '0.0.255.0', IP
::hexToQuad( 'FF00' ) );
363 * @covers IP::hexToOctet
365 public function testHexToOctet() {
366 $this->assertEquals( '0:0:0:0:0:0:0:1',
367 IP
::hexToOctet( '00000000000000000000000000000001' ) );
368 $this->assertEquals( '0:0:0:0:0:0:FF:3',
369 IP
::hexToOctet( '00000000000000000000000000FF0003' ) );
370 $this->assertEquals( '0:0:0:0:0:0:FF00:6',
371 IP
::hexToOctet( '000000000000000000000000FF000006' ) );
372 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF',
373 IP
::hexToOctet( '000000000000000000000000FCCFFAFF' ) );
374 $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
375 IP
::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
376 // hex not left-padded...
377 $this->assertEquals( '0:0:0:0:0:0:0:0', IP
::hexToOctet( '0' ) );
378 $this->assertEquals( '0:0:0:0:0:0:0:1', IP
::hexToOctet( '1' ) );
379 $this->assertEquals( '0:0:0:0:0:0:0:FF', IP
::hexToOctet( 'FF' ) );
380 $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP
::hexToOctet( 'FFD0' ) );
381 $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP
::hexToOctet( 'FA000000' ) );
382 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP
::hexToOctet( 'FCCFFAFF' ) );
386 * IP::parseCIDR() returns an array containing a signed IP address
387 * representing the network mask and the bit mask.
388 * @covers IP::parseCIDR
390 function testCIDRParsing() {
391 $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
392 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
394 // Verify if statement
395 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
396 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
397 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
398 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
400 // Check internal logic
401 # 0 mask always result in array(0,0)
402 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '192.0.0.2/0' ) );
403 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '0.0.0.0/0' ) );
404 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '255.255.255.255/0' ) );
406 // @todo FIXME: Add more tests.
408 # This part test network shifting
409 $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
410 $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
411 $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
412 $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
413 $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
414 $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
415 $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
416 $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
417 $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
421 * @covers IP::canonicalize
423 public function testIPCanonicalizeOnValidIp() {
424 $this->assertEquals( '192.0.2.152', IP
::canonicalize( '192.0.2.152' ),
425 'Canonicalization of a valid IP returns it unchanged' );
429 * @covers IP::canonicalize
431 public function testIPCanonicalizeMappedAddress() {
434 IP
::canonicalize( '::ffff:192.0.2.152' )
438 IP
::canonicalize( '::192.0.2.152' )
443 * Issues there are most probably from IP::toHex() or IP::parseRange()
444 * @covers IP::isInRange
445 * @dataProvider provideIPsAndRanges
447 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
450 IP
::isInRange( $addr, $range ),
455 /** Provider for testIPIsInRange() */
456 public static function provideIPsAndRanges() {
457 # Format: (expected boolean, address, range, optional message)
460 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
461 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
462 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
464 array( false, '0.0.0.0', '192.0.2.0/24' ),
465 array( false, '255.255.255', '192.0.2.0/24' ),
468 array( false, '::1', '2001:DB8::/32' ),
469 array( false, '::', '2001:DB8::/32' ),
470 array( false, 'FE80::1', '2001:DB8::/32' ),
472 array( true, '2001:DB8::', '2001:DB8::/32' ),
473 array( true, '2001:0DB8::', '2001:DB8::/32' ),
474 array( true, '2001:DB8::1', '2001:DB8::/32' ),
475 array( true, '2001:0DB8::1', '2001:DB8::/32' ),
476 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
479 array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
484 * Test for IP::splitHostAndPort().
485 * @dataProvider provideSplitHostAndPort
487 function testSplitHostAndPort( $expected, $input, $description ) {
488 $this->assertEquals( $expected, IP
::splitHostAndPort( $input ), $description );
492 * Provider for IP::splitHostAndPort()
494 public static function provideSplitHostAndPort() {
496 array( false, '[', 'Unclosed square bracket' ),
497 array( false, '[::', 'Unclosed square bracket 2' ),
498 array( array( '::', false ), '::', 'Bare IPv6 0' ),
499 array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
500 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
501 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
502 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
503 array( false, '::x', 'Double colon but no IPv6' ),
504 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
505 array( false, 'x:x', 'Hostname and invalid port' ),
506 array( array( 'x', false ), 'x', 'Plain hostname' )
511 * Test for IP::combineHostAndPort()
512 * @dataProvider provideCombineHostAndPort
514 function testCombineHostAndPort( $expected, $input, $description ) {
515 list( $host, $port, $defaultPort ) = $input;
518 IP
::combineHostAndPort( $host, $port, $defaultPort ),
523 * Provider for IP::combineHostAndPort()
525 public static function provideCombineHostAndPort() {
527 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
528 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
529 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
530 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
535 * Test for IP::sanitizeRange()
536 * @dataProvider provideIPCIDRs
538 function testSanitizeRange( $input, $expected, $description ) {
539 $this->assertEquals( $expected, IP
::sanitizeRange( $input ), $description );
543 * Provider for IP::testSanitizeRange()
545 public static function provideIPCIDRs() {
547 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
548 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
549 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
550 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
551 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
552 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
553 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
554 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
559 * Test for IP::prettifyIP()
560 * @dataProvider provideIPsToPrettify
562 function testPrettifyIP( $ip, $prettified ) {
563 $this->assertEquals( $prettified, IP
::prettifyIP( $ip ), "Prettify of $ip" );
567 * Provider for IP::testPrettifyIP()
569 public static function provideIPsToPrettify() {
571 array( '0:0:0:0:0:0:0:0', '::' ),
572 array( '0:0:0::0:0:0', '::' ),
573 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
574 array( '0:0::f', '::f' ),
575 array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
576 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
577 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
578 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
579 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
580 array( '0:0:0:0:0:0:0:0/16', '::/16' ),
581 array( '0:0:0::0:0:0/64', '::/64' ),
582 array( '0:0::f/52', '::f/52' ),
583 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
584 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
585 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
586 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
587 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),