3 * Tests for IP validity functions.
5 * Ported from /t/inc/IP.t by avar.
8 * @todo Test methods in this call should be split into a method and a
12 class IPTest
extends PHPUnit_Framework_TestCase
{
14 * @covers IP::isIPAddress
15 * @dataProvider provideInvalidIPs
17 public function isNotIPAddress( $val, $desc ) {
18 $this->assertFalse( IP
::isIPAddress( $val ), $desc );
22 * Provide a list of things that aren't IP addresses
24 public function provideInvalidIPs() {
26 array( false, 'Boolean false is not an IP' ),
27 array( true, 'Boolean true is not an IP' ),
28 array( '', 'Empty string is not an IP' ),
29 array( 'abc', 'Garbage IP string' ),
30 array( ':', 'Single ":" is not an IP' ),
31 array( '2001:0DB8::A:1::1', 'IPv6 with a double :: occurrence' ),
32 array( '2001:0DB8::A:1::', 'IPv6 with a double :: occurrence, last at end' ),
33 array( '::2001:0DB8::5:1', 'IPv6 with a double :: occurrence, firt at beginning' ),
34 array( '124.24.52', 'IPv4 not enough quads' ),
35 array( '24.324.52.13', 'IPv4 out of range' ),
36 array( '.24.52.13', 'IPv4 starts with period' ),
37 array( 'fc:100:300', 'IPv6 with only 3 words' ),
42 * @covers IP::isIPAddress
44 public function testisIPAddress() {
45 $this->assertTrue( IP
::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' );
46 $this->assertTrue( IP
::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' );
47 $this->assertTrue( IP
::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) );
48 $this->assertTrue( IP
::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' );
49 $this->assertTrue( IP
::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' );
51 $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac',
52 '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' );
53 foreach ( $validIPs as $ip ) {
54 $this->assertTrue( IP
::isIPAddress( $ip ), "$ip is a valid IP address" );
61 public function testisIPv6() {
62 $this->assertFalse( IP
::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' );
63 $this->assertFalse( IP
::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
64 $this->assertFalse( IP
::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' );
65 $this->assertFalse( IP
::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' );
67 $this->assertTrue( IP
::isIPv6( 'fc:100::' ) );
68 $this->assertTrue( IP
::isIPv6( 'fc:100:a::' ) );
69 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d::' ) );
70 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1::' ) );
71 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e::' ) );
72 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e:ac::' ) );
74 $this->assertFalse( IP
::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' );
76 IP
::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ),
77 'IPv6 with 9 words ending with "::"'
80 $this->assertFalse( IP
::isIPv6( ':::' ) );
81 $this->assertFalse( IP
::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
83 $this->assertTrue( IP
::isIPv6( '::' ), 'IPv6 zero address' );
84 $this->assertTrue( IP
::isIPv6( '::0' ) );
85 $this->assertTrue( IP
::isIPv6( '::fc' ) );
86 $this->assertTrue( IP
::isIPv6( '::fc:100' ) );
87 $this->assertTrue( IP
::isIPv6( '::fc:100:a' ) );
88 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d' ) );
89 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1' ) );
90 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1:e' ) );
91 $this->assertTrue( IP
::isIPv6( '::fc:100:a:d:1:e:ac' ) );
93 $this->assertFalse( IP
::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
94 $this->assertFalse( IP
::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
96 $this->assertFalse( IP
::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' );
97 $this->assertFalse( IP
::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' );
98 $this->assertFalse( IP
::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' );
100 $this->assertTrue( IP
::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' );
101 $this->assertTrue( IP
::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
102 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) );
103 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
104 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' );
105 $this->assertTrue( IP
::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
106 $this->assertTrue( IP
::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' );
107 $this->assertTrue( IP
::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
108 $this->assertTrue( IP
::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
110 $this->assertFalse( IP
::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' );
111 $this->assertFalse( IP
::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' );
113 $this->assertTrue( IP
::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
118 * @dataProvider provideInvalidIPv4Addresses
120 public function testisNotIPv4( $bogusIP, $desc ) {
121 $this->assertFalse( IP
::isIPv4( $bogusIP ), $desc );
124 public function provideInvalidIPv4Addresses() {
126 array( false, 'Boolean false is not an IP' ),
127 array( true, 'Boolean true is not an IP' ),
128 array( '', 'Empty string is not an IP' ),
129 array( 'abc', 'Letters are not an IP' ),
130 array( ':', 'A colon is not an IP' ),
131 array( '124.24.52', 'IPv4 not enough quads' ),
132 array( '24.324.52.13', 'IPv4 out of range' ),
133 array( '.24.52.13', 'IPv4 starts with period' ),
139 * @dataProvider provideValidIPv4Address
141 public function testIsIPv4( $ip, $desc ) {
142 $this->assertTrue( IP
::isIPv4( $ip ), $desc );
146 * Provide some IPv4 addresses and ranges
148 public function provideValidIPv4Address() {
150 array( '124.24.52.13', 'Valid IPv4 address' ),
151 array( '1.24.52.13', 'Another valid IPv4 address' ),
152 array( '74.24.52.13/20', 'An IPv4 range' ),
157 * @covers IP::isValid
159 public function testValidIPs() {
160 foreach ( range( 0, 255 ) as $i ) {
161 $a = sprintf( "%03d", $i );
162 $b = sprintf( "%02d", $i );
163 $c = sprintf( "%01d", $i );
164 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
166 $this->assertTrue( IP
::isValid( $ip ), "$ip is a valid IPv4 address" );
169 foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) {
170 $a = sprintf( "%04x", $i );
171 $b = sprintf( "%03x", $i );
172 $c = sprintf( "%02x", $i );
173 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
174 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
175 $this->assertTrue( IP
::isValid( $ip ), "$ip is a valid IPv6 address" );
178 // test with some abbreviations
179 $this->assertFalse( IP
::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' );
180 $this->assertFalse( IP
::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' );
181 $this->assertFalse( IP
::isValid( 'fc:300' ), 'IPv6 with only 2 words' );
182 $this->assertFalse( IP
::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' );
184 $this->assertTrue( IP
::isValid( 'fc:100::' ) );
185 $this->assertTrue( IP
::isValid( 'fc:100:a:d:1:e::' ) );
186 $this->assertTrue( IP
::isValid( 'fc:100:a:d:1:e:ac::' ) );
188 $this->assertTrue( IP
::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' );
189 $this->assertTrue( IP
::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' );
190 $this->assertTrue( IP
::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' );
191 $this->assertTrue( IP
::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' );
192 $this->assertTrue( IP
::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' );
193 $this->assertTrue( IP
::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' );
194 $this->assertTrue( IP
::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' );
197 IP
::isValid( 'fc:100:a:d:1:e:ac:0::' ),
198 'IPv6 with 8 words ending with "::"'
201 IP
::isValid( 'fc:100:a:d:1:e:ac:0:1::' ),
202 'IPv6 with 9 words ending with "::"'
207 * @covers IP::isValid
209 public function testInvalidIPs() {
211 foreach ( range( 256, 999 ) as $i ) {
212 $a = sprintf( "%03d", $i );
213 $b = sprintf( "%02d", $i );
214 $c = sprintf( "%01d", $i );
215 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
217 $this->assertFalse( IP
::isValid( $ip ), "$ip is not a valid IPv4 address" );
220 foreach ( range( 'g', 'z' ) as $i ) {
221 $a = sprintf( "%04s", $i );
222 $b = sprintf( "%03s", $i );
223 $c = sprintf( "%02s", $i );
224 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) {
225 $ip = "$f:$f:$f:$f:$f:$f:$f:$f";
226 $this->assertFalse( IP
::isValid( $ip ), "$ip is not a valid IPv6 address" );
236 'c:ff:12:1:ea:d:321:5/120',
238 foreach ( $ipCIDRs as $i ) {
239 $this->assertFalse( IP
::isValid( $i ),
240 "$i is an invalid IP address because it is a block" );
242 // Incomplete/garbage
244 'www.xn--var-xla.net',
251 foreach ( $invalid as $i ) {
252 $this->assertFalse( IP
::isValid( $i ), "$i is an invalid IP address" );
257 * Provide some valid IP blocks
259 public function provideValidBlocks() {
261 array( '116.17.184.5/32' ),
262 array( '0.17.184.5/30' ),
263 array( '16.17.184.1/24' ),
264 array( '30.242.52.14/1' ),
265 array( '10.232.52.13/8' ),
266 array( '30.242.52.14/0' ),
267 array( '::e:f:2001/96' ),
268 array( '::c:f:2001/128' ),
269 array( '::10:f:2001/70' ),
270 array( '::fe:f:2001/1' ),
271 array( '::6d:f:2001/8' ),
272 array( '::fe:f:2001/0' ),
277 * @covers IP::isValidBlock
278 * @dataProvider provideValidBlocks
280 public function testValidBlocks( $block ) {
281 $this->assertTrue( IP
::isValidBlock( $block ), "$block is a valid IP block" );
285 * @covers IP::isValidBlock
286 * @dataProvider provideInvalidBlocks
288 public function testInvalidBlocks( $invalid ) {
289 $this->assertFalse( IP
::isValidBlock( $invalid ), "$invalid is not a valid IP block" );
292 public function provideInvalidBlocks() {
294 array( '116.17.184.5/33' ),
295 array( '0.17.184.5/130' ),
296 array( '16.17.184.1/-1' ),
297 array( '10.232.52.13/*' ),
298 array( '7.232.52.13/ab' ),
299 array( '11.232.52.13/' ),
300 array( '::e:f:2001/129' ),
301 array( '::c:f:2001/228' ),
302 array( '::10:f:2001/-1' ),
303 array( '::6d:f:2001/*' ),
304 array( '::86:f:2001/ab' ),
305 array( '::23:f:2001/' ),
310 * @covers IP::sanitizeIP
311 * @dataProvider provideSanitizeIP
313 public function testSanitizeIP( $expected, $input ) {
314 $result = IP
::sanitizeIP( $input );
315 $this->assertEquals( $expected, $result );
319 * Provider for IP::testSanitizeIP()
321 public static function provideSanitizeIP() {
323 array( '0.0.0.0', '0.0.0.0' ),
324 array( '0.0.0.0', '00.00.00.00' ),
325 array( '0.0.0.0', '000.000.000.000' ),
326 array( '141.0.11.253', '141.000.011.253' ),
327 array( '1.2.4.5', '1.2.4.5' ),
328 array( '1.2.4.5', '01.02.04.05' ),
329 array( '1.2.4.5', '001.002.004.005' ),
330 array( '10.0.0.1', '010.0.000.1' ),
331 array( '80.72.250.4', '080.072.250.04' ),
332 array( 'Foo.1000.00', 'Foo.1000.00' ),
333 array( 'Bar.01', 'Bar.01' ),
334 array( 'Bar.010', 'Bar.010' ),
342 * @dataProvider provideToHex
344 public function testToHex( $expected, $input ) {
345 $result = IP
::toHex( $input );
346 $this->assertTrue( $result === false ||
is_string( $result ) );
347 $this->assertEquals( $expected, $result );
351 * Provider for IP::testToHex()
353 public static function provideToHex() {
355 array( '00000001', '0.0.0.1' ),
356 array( '01020304', '1.2.3.4' ),
357 array( '7F000001', '127.0.0.1' ),
358 array( '80000000', '128.0.0.0' ),
359 array( 'DEADCAFE', '222.173.202.254' ),
360 array( 'FFFFFFFF', '255.255.255.255' ),
361 array( '8D000BFD', '141.000.11.253' ),
362 array( false, 'IN.VA.LI.D' ),
363 array( 'v6-00000000000000000000000000000001', '::1' ),
364 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
365 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
366 array( false, 'IN:VA::LI:D' ),
367 array( false, ':::1' )
372 * @covers IP::isPublic
373 * @dataProvider provideIsPublic
375 public function testIsPublic( $expected, $input ) {
376 $result = IP
::isPublic( $input );
377 $this->assertEquals( $expected, $result );
381 * Provider for IP::testIsPublic()
383 public static function provideIsPublic() {
385 array( false, 'fc00::3' ), # RFC 4193 (local)
386 array( false, 'fc00::ff' ), # RFC 4193 (local)
387 array( false, '127.1.2.3' ), # loopback
388 array( false, '::1' ), # loopback
389 array( false, 'fe80::1' ), # link-local
390 array( false, '169.254.1.1' ), # link-local
391 array( false, '10.0.0.1' ), # RFC 1918 (private)
392 array( false, '172.16.0.1' ), # RFC 1918 (private)
393 array( false, '192.168.0.1' ), # RFC 1918 (private)
394 array( true, '2001:5c0:1000:a::133' ), # public
395 array( true, 'fc::3' ), # public
396 array( true, '00FC::' ) # public
400 // Private wrapper used to test CIDR Parsing.
401 private function assertFalseCIDR( $CIDR, $msg = '' ) {
402 $ff = array( false, false );
403 $this->assertEquals( $ff, IP
::parseCIDR( $CIDR ), $msg );
406 // Private wrapper to test network shifting using only dot notation
407 private function assertNet( $expected, $CIDR ) {
408 $parse = IP
::parseCIDR( $CIDR );
409 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
413 * @covers IP::hexToQuad
414 * @dataProvider provideIPsAndHexes
416 public function testHexToQuad( $ip, $hex ) {
417 $this->assertEquals( $ip, IP
::hexToQuad( $hex ) );
421 * Provide some IP addresses and their equivalent hex representations
423 public function provideIPsandHexes() {
425 array( '0.0.0.1', '00000001' ),
426 array( '255.0.0.0', 'FF000000' ),
427 array( '255.255.255.255', 'FFFFFFFF' ),
428 array( '10.188.222.255', '0ABCDEFF' ),
429 // hex not left-padded...
430 array( '0.0.0.0', '0' ),
431 array( '0.0.0.1', '1' ),
432 array( '0.0.0.255', 'FF' ),
433 array( '0.0.255.0', 'FF00' ),
438 * @covers IP::hexToOctet
439 * @dataProvider provideOctetsAndHexes
441 public function testHexToOctet( $octet, $hex ) {
442 $this->assertEquals( $octet, IP
::hexToOctet( $hex ) );
446 * Provide some hex and octet representations of the same IPs
448 public function provideOctetsAndHexes() {
450 array( '0:0:0:0:0:0:0:1', '00000000000000000000000000000001' ),
451 array( '0:0:0:0:0:0:FF:3', '00000000000000000000000000FF0003' ),
452 array( '0:0:0:0:0:0:FF00:6', '000000000000000000000000FF000006' ),
453 array( '0:0:0:0:0:0:FCCF:FAFF', '000000000000000000000000FCCFFAFF' ),
454 array( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF', 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ),
455 // hex not left-padded...
456 array( '0:0:0:0:0:0:0:0', '0' ),
457 array( '0:0:0:0:0:0:0:1', '1' ),
458 array( '0:0:0:0:0:0:0:FF', 'FF' ),
459 array( '0:0:0:0:0:0:0:FFD0', 'FFD0' ),
460 array( '0:0:0:0:0:0:FA00:0', 'FA000000' ),
461 array( '0:0:0:0:0:0:FCCF:FAFF', 'FCCFFAFF' ),
466 * IP::parseCIDR() returns an array containing a signed IP address
467 * representing the network mask and the bit mask.
468 * @covers IP::parseCIDR
470 public function testCIDRParsing() {
471 $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
472 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
474 // Verify if statement
475 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
476 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
477 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
478 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
480 // Check internal logic
481 # 0 mask always result in array(0,0)
482 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '192.0.0.2/0' ) );
483 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '0.0.0.0/0' ) );
484 $this->assertEquals( array( 0, 0 ), IP
::parseCIDR( '255.255.255.255/0' ) );
486 // @todo FIXME: Add more tests.
488 # This part test network shifting
489 $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
490 $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
491 $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
492 $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
493 $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
494 $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
495 $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
496 $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
497 $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
501 * @covers IP::canonicalize
503 public function testIPCanonicalizeOnValidIp() {
504 $this->assertEquals( '192.0.2.152', IP
::canonicalize( '192.0.2.152' ),
505 'Canonicalization of a valid IP returns it unchanged' );
509 * @covers IP::canonicalize
511 public function testIPCanonicalizeMappedAddress() {
514 IP
::canonicalize( '::ffff:192.0.2.152' )
518 IP
::canonicalize( '::192.0.2.152' )
523 * Issues there are most probably from IP::toHex() or IP::parseRange()
524 * @covers IP::isInRange
525 * @dataProvider provideIPsAndRanges
527 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
530 IP
::isInRange( $addr, $range ),
535 /** Provider for testIPIsInRange() */
536 public static function provideIPsAndRanges() {
537 # Format: (expected boolean, address, range, optional message)
540 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
541 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
542 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
544 array( false, '0.0.0.0', '192.0.2.0/24' ),
545 array( false, '255.255.255', '192.0.2.0/24' ),
548 array( false, '::1', '2001:DB8::/32' ),
549 array( false, '::', '2001:DB8::/32' ),
550 array( false, 'FE80::1', '2001:DB8::/32' ),
552 array( true, '2001:DB8::', '2001:DB8::/32' ),
553 array( true, '2001:0DB8::', '2001:DB8::/32' ),
554 array( true, '2001:DB8::1', '2001:DB8::/32' ),
555 array( true, '2001:0DB8::1', '2001:DB8::/32' ),
556 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
559 array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
564 * Test for IP::splitHostAndPort().
565 * @dataProvider provideSplitHostAndPort
567 public function testSplitHostAndPort( $expected, $input, $description ) {
568 $this->assertEquals( $expected, IP
::splitHostAndPort( $input ), $description );
572 * Provider for IP::splitHostAndPort()
574 public static function provideSplitHostAndPort() {
576 array( false, '[', 'Unclosed square bracket' ),
577 array( false, '[::', 'Unclosed square bracket 2' ),
578 array( array( '::', false ), '::', 'Bare IPv6 0' ),
579 array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
580 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
581 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
582 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
583 array( false, '::x', 'Double colon but no IPv6' ),
584 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
585 array( false, 'x:x', 'Hostname and invalid port' ),
586 array( array( 'x', false ), 'x', 'Plain hostname' )
591 * Test for IP::combineHostAndPort()
592 * @dataProvider provideCombineHostAndPort
594 public function testCombineHostAndPort( $expected, $input, $description ) {
595 list( $host, $port, $defaultPort ) = $input;
598 IP
::combineHostAndPort( $host, $port, $defaultPort ),
603 * Provider for IP::combineHostAndPort()
605 public static function provideCombineHostAndPort() {
607 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
608 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
609 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
610 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
615 * Test for IP::sanitizeRange()
616 * @dataProvider provideIPCIDRs
618 public function testSanitizeRange( $input, $expected, $description ) {
619 $this->assertEquals( $expected, IP
::sanitizeRange( $input ), $description );
623 * Provider for IP::testSanitizeRange()
625 public static function provideIPCIDRs() {
627 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
628 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
629 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
630 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
631 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
632 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
633 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
634 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
639 * Test for IP::prettifyIP()
640 * @dataProvider provideIPsToPrettify
642 public function testPrettifyIP( $ip, $prettified ) {
643 $this->assertEquals( $prettified, IP
::prettifyIP( $ip ), "Prettify of $ip" );
647 * Provider for IP::testPrettifyIP()
649 public static function provideIPsToPrettify() {
651 array( '0:0:0:0:0:0:0:0', '::' ),
652 array( '0:0:0::0:0:0', '::' ),
653 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
654 array( '0:0::f', '::f' ),
655 array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
656 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
657 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
658 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
659 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
660 array( '0:0:0:0:0:0:0:0/16', '::/16' ),
661 array( '0:0:0::0:0:0/64', '::/64' ),
662 array( '0:0::f/52', '::f/52' ),
663 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
664 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
665 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
666 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
667 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),