MediaWiki
REL1_22
|
00001 <?php 00012 class IPTest extends MediaWikiTestCase { 00017 public function testisIPAddress() { 00018 $this->assertFalse( IP::isIPAddress( false ), 'Boolean false is not an IP' ); 00019 $this->assertFalse( IP::isIPAddress( true ), 'Boolean true is not an IP' ); 00020 $this->assertFalse( IP::isIPAddress( "" ), 'Empty string is not an IP' ); 00021 $this->assertFalse( IP::isIPAddress( 'abc' ), 'Garbage IP string' ); 00022 $this->assertFalse( IP::isIPAddress( ':' ), 'Single ":" is not an IP' ); 00023 $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::1' ), 'IPv6 with a double :: occurrence' ); 00024 $this->assertFalse( IP::isIPAddress( '2001:0DB8::A:1::' ), 'IPv6 with a double :: occurrence, last at end' ); 00025 $this->assertFalse( IP::isIPAddress( '::2001:0DB8::5:1' ), 'IPv6 with a double :: occurrence, firt at beginning' ); 00026 $this->assertFalse( IP::isIPAddress( '124.24.52' ), 'IPv4 not enough quads' ); 00027 $this->assertFalse( IP::isIPAddress( '24.324.52.13' ), 'IPv4 out of range' ); 00028 $this->assertFalse( IP::isIPAddress( '.24.52.13' ), 'IPv4 starts with period' ); 00029 $this->assertFalse( IP::isIPAddress( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00030 00031 $this->assertTrue( IP::isIPAddress( '::' ), 'RFC 4291 IPv6 Unspecified Address' ); 00032 $this->assertTrue( IP::isIPAddress( '::1' ), 'RFC 4291 IPv6 Loopback Address' ); 00033 $this->assertTrue( IP::isIPAddress( '74.24.52.13/20', 'IPv4 range' ) ); 00034 $this->assertTrue( IP::isIPAddress( 'fc:100:a:d:1:e:ac:0/24' ), 'IPv6 range' ); 00035 $this->assertTrue( IP::isIPAddress( 'fc::100:a:d:1:e:ac/96' ), 'IPv6 range with "::"' ); 00036 00037 $validIPs = array( 'fc:100::', 'fc:100:a:d:1:e:ac::', 'fc::100', '::fc:100:a:d:1:e:ac', 00038 '::fc', 'fc::100:a:d:1:e:ac', 'fc:100:a:d:1:e:ac:0', '124.24.52.13', '1.24.52.13' ); 00039 foreach ( $validIPs as $ip ) { 00040 $this->assertTrue( IP::isIPAddress( $ip ), "$ip is a valid IP address" ); 00041 } 00042 } 00043 00047 public function testisIPv6() { 00048 $this->assertFalse( IP::isIPv6( ':fc:100::' ), 'IPv6 starting with lone ":"' ); 00049 $this->assertFalse( IP::isIPv6( 'fc:100:::' ), 'IPv6 ending with a ":::"' ); 00050 $this->assertFalse( IP::isIPv6( 'fc:300' ), 'IPv6 with only 2 words' ); 00051 $this->assertFalse( IP::isIPv6( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00052 00053 $this->assertTrue( IP::isIPv6( 'fc:100::' ) ); 00054 $this->assertTrue( IP::isIPv6( 'fc:100:a::' ) ); 00055 $this->assertTrue( IP::isIPv6( 'fc:100:a:d::' ) ); 00056 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1::' ) ); 00057 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e::' ) ); 00058 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac::' ) ); 00059 00060 $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' ); 00061 $this->assertFalse( IP::isIPv6( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' ); 00062 00063 $this->assertFalse( IP::isIPv6( ':::' ) ); 00064 $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' ); 00065 00066 $this->assertTrue( IP::isIPv6( '::' ), 'IPv6 zero address' ); 00067 $this->assertTrue( IP::isIPv6( '::0' ) ); 00068 $this->assertTrue( IP::isIPv6( '::fc' ) ); 00069 $this->assertTrue( IP::isIPv6( '::fc:100' ) ); 00070 $this->assertTrue( IP::isIPv6( '::fc:100:a' ) ); 00071 $this->assertTrue( IP::isIPv6( '::fc:100:a:d' ) ); 00072 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1' ) ); 00073 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e' ) ); 00074 $this->assertTrue( IP::isIPv6( '::fc:100:a:d:1:e:ac' ) ); 00075 00076 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' ); 00077 $this->assertFalse( IP::isIPv6( '::fc:100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' ); 00078 00079 $this->assertFalse( IP::isIPv6( ':fc::100' ), 'IPv6 starting with lone ":"' ); 00080 $this->assertFalse( IP::isIPv6( 'fc::100:' ), 'IPv6 ending with lone ":"' ); 00081 $this->assertFalse( IP::isIPv6( 'fc:::100' ), 'IPv6 with ":::" in the middle' ); 00082 00083 $this->assertTrue( IP::isIPv6( 'fc::100' ), 'IPv6 with "::" and 2 words' ); 00084 $this->assertTrue( IP::isIPv6( 'fc::100:a' ), 'IPv6 with "::" and 3 words' ); 00085 $this->assertTrue( IP::isIPv6( 'fc::100:a:d', 'IPv6 with "::" and 4 words' ) ); 00086 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' ); 00087 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e' ), 'IPv6 with "::" and 6 words' ); 00088 $this->assertTrue( IP::isIPv6( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' ); 00089 $this->assertTrue( IP::isIPv6( '2001::df' ), 'IPv6 with "::" and 2 words' ); 00090 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' ); 00091 $this->assertTrue( IP::isIPv6( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' ); 00092 00093 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0' ), 'IPv6 with "::" and 8 words' ); 00094 $this->assertFalse( IP::isIPv6( 'fc::100:a:d:1:e:ac:0:1' ), 'IPv6 with 9 words' ); 00095 00096 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) ); 00097 } 00098 00102 public function testisIPv4() { 00103 $this->assertFalse( IP::isIPv4( false ), 'Boolean false is not an IP' ); 00104 $this->assertFalse( IP::isIPv4( true ), 'Boolean true is not an IP' ); 00105 $this->assertFalse( IP::isIPv4( "" ), 'Empty string is not an IP' ); 00106 $this->assertFalse( IP::isIPv4( 'abc' ) ); 00107 $this->assertFalse( IP::isIPv4( ':' ) ); 00108 $this->assertFalse( IP::isIPv4( '124.24.52' ), 'IPv4 not enough quads' ); 00109 $this->assertFalse( IP::isIPv4( '24.324.52.13' ), 'IPv4 out of range' ); 00110 $this->assertFalse( IP::isIPv4( '.24.52.13' ), 'IPv4 starts with period' ); 00111 00112 $this->assertTrue( IP::isIPv4( '124.24.52.13' ) ); 00113 $this->assertTrue( IP::isIPv4( '1.24.52.13' ) ); 00114 $this->assertTrue( IP::isIPv4( '74.24.52.13/20', 'IPv4 range' ) ); 00115 } 00116 00120 public function testValidIPs() { 00121 foreach ( range( 0, 255 ) as $i ) { 00122 $a = sprintf( "%03d", $i ); 00123 $b = sprintf( "%02d", $i ); 00124 $c = sprintf( "%01d", $i ); 00125 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00126 $ip = "$f.$f.$f.$f"; 00127 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv4 address" ); 00128 } 00129 } 00130 foreach ( range( 0x0, 0xFFFF, 0xF ) as $i ) { 00131 $a = sprintf( "%04x", $i ); 00132 $b = sprintf( "%03x", $i ); 00133 $c = sprintf( "%02x", $i ); 00134 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00135 $ip = "$f:$f:$f:$f:$f:$f:$f:$f"; 00136 $this->assertTrue( IP::isValid( $ip ), "$ip is a valid IPv6 address" ); 00137 } 00138 } 00139 // test with some abbreviations 00140 $this->assertFalse( IP::isValid( ':fc:100::' ), 'IPv6 starting with lone ":"' ); 00141 $this->assertFalse( IP::isValid( 'fc:100:::' ), 'IPv6 ending with a ":::"' ); 00142 $this->assertFalse( IP::isValid( 'fc:300' ), 'IPv6 with only 2 words' ); 00143 $this->assertFalse( IP::isValid( 'fc:100:300' ), 'IPv6 with only 3 words' ); 00144 00145 $this->assertTrue( IP::isValid( 'fc:100::' ) ); 00146 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e::' ) ); 00147 $this->assertTrue( IP::isValid( 'fc:100:a:d:1:e:ac::' ) ); 00148 00149 $this->assertTrue( IP::isValid( 'fc::100' ), 'IPv6 with "::" and 2 words' ); 00150 $this->assertTrue( IP::isValid( 'fc::100:a' ), 'IPv6 with "::" and 3 words' ); 00151 $this->assertTrue( IP::isValid( '2001::df' ), 'IPv6 with "::" and 2 words' ); 00152 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df' ), 'IPv6 with "::" and 5 words' ); 00153 $this->assertTrue( IP::isValid( '2001:5c0:1400:a::df:2' ), 'IPv6 with "::" and 6 words' ); 00154 $this->assertTrue( IP::isValid( 'fc::100:a:d:1' ), 'IPv6 with "::" and 5 words' ); 00155 $this->assertTrue( IP::isValid( 'fc::100:a:d:1:e:ac' ), 'IPv6 with "::" and 7 words' ); 00156 00157 $this->assertFalse( IP::isValid( 'fc:100:a:d:1:e:ac:0::' ), 'IPv6 with 8 words ending with "::"' ); 00158 $this->assertFalse( IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ), 'IPv6 with 9 words ending with "::"' ); 00159 } 00160 00164 public function testInvalidIPs() { 00165 // Out of range... 00166 foreach ( range( 256, 999 ) as $i ) { 00167 $a = sprintf( "%03d", $i ); 00168 $b = sprintf( "%02d", $i ); 00169 $c = sprintf( "%01d", $i ); 00170 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00171 $ip = "$f.$f.$f.$f"; 00172 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv4 address" ); 00173 } 00174 } 00175 foreach ( range( 'g', 'z' ) as $i ) { 00176 $a = sprintf( "%04s", $i ); 00177 $b = sprintf( "%03s", $i ); 00178 $c = sprintf( "%02s", $i ); 00179 foreach ( array_unique( array( $a, $b, $c ) ) as $f ) { 00180 $ip = "$f:$f:$f:$f:$f:$f:$f:$f"; 00181 $this->assertFalse( IP::isValid( $ip ), "$ip is not a valid IPv6 address" ); 00182 } 00183 } 00184 // Have CIDR 00185 $ipCIDRs = array( 00186 '212.35.31.121/32', 00187 '212.35.31.121/18', 00188 '212.35.31.121/24', 00189 '::ff:d:321:5/96', 00190 'ff::d3:321:5/116', 00191 'c:ff:12:1:ea:d:321:5/120', 00192 ); 00193 foreach ( $ipCIDRs as $i ) { 00194 $this->assertFalse( IP::isValid( $i ), 00195 "$i is an invalid IP address because it is a block" ); 00196 } 00197 // Incomplete/garbage 00198 $invalid = array( 00199 'www.xn--var-xla.net', 00200 '216.17.184.G', 00201 '216.17.184.1.', 00202 '216.17.184', 00203 '216.17.184.', 00204 '256.17.184.1' 00205 ); 00206 foreach ( $invalid as $i ) { 00207 $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" ); 00208 } 00209 } 00210 00214 public function testValidBlocks() { 00215 $valid = array( 00216 '116.17.184.5/32', 00217 '0.17.184.5/30', 00218 '16.17.184.1/24', 00219 '30.242.52.14/1', 00220 '10.232.52.13/8', 00221 '30.242.52.14/0', 00222 '::e:f:2001/96', 00223 '::c:f:2001/128', 00224 '::10:f:2001/70', 00225 '::fe:f:2001/1', 00226 '::6d:f:2001/8', 00227 '::fe:f:2001/0', 00228 ); 00229 foreach ( $valid as $i ) { 00230 $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" ); 00231 } 00232 } 00233 00237 public function testInvalidBlocks() { 00238 $invalid = array( 00239 '116.17.184.5/33', 00240 '0.17.184.5/130', 00241 '16.17.184.1/-1', 00242 '10.232.52.13/*', 00243 '7.232.52.13/ab', 00244 '11.232.52.13/', 00245 '::e:f:2001/129', 00246 '::c:f:2001/228', 00247 '::10:f:2001/-1', 00248 '::6d:f:2001/*', 00249 '::86:f:2001/ab', 00250 '::23:f:2001/', 00251 ); 00252 foreach ( $invalid as $i ) { 00253 $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" ); 00254 } 00255 } 00256 00261 public function testSanitizeIP() { 00262 $this->assertNull( IP::sanitizeIP( '' ) ); 00263 $this->assertNull( IP::sanitizeIP( ' ' ) ); 00264 } 00265 00270 public function testToUnsigned( $expected, $input ) { 00271 $result = IP::toUnsigned( $input ); 00272 $this->assertTrue( $result === false || is_string( $result ) || is_int( $result ) ); 00273 $this->assertEquals( $expected, $result ); 00274 } 00275 00279 public static function provideToUnsigned() { 00280 return array( 00281 array( 1, '0.0.0.1' ), 00282 array( 16909060, '1.2.3.4' ), 00283 array( 2130706433, '127.0.0.1' ), 00284 array( '2147483648', '128.0.0.0' ), 00285 array( '3735931646', '222.173.202.254' ), 00286 array( pow( 2, 32 ) - 1, '255.255.255.255' ), 00287 array( false, 'IN.VA.LI.D' ), 00288 array( 1, '::1' ), 00289 array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ), 00290 array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ), 00291 array( false, 'IN:VA::LI:D' ), 00292 array( false, ':::1' ) 00293 ); 00294 } 00295 00300 public function testToHex( $expected, $input ) { 00301 $result = IP::toHex( $input ); 00302 $this->assertTrue( $result === false || is_string( $result ) ); 00303 $this->assertEquals( $expected, $result ); 00304 } 00305 00309 public static function provideToHex() { 00310 return array( 00311 array( '00000001', '0.0.0.1' ), 00312 array( '01020304', '1.2.3.4' ), 00313 array( '7F000001', '127.0.0.1' ), 00314 array( '80000000', '128.0.0.0' ), 00315 array( 'DEADCAFE', '222.173.202.254' ), 00316 array( 'FFFFFFFF', '255.255.255.255' ), 00317 array( false, 'IN.VA.LI.D' ), 00318 array( 'v6-00000000000000000000000000000001', '::1' ), 00319 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ), 00320 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ), 00321 array( false, 'IN:VA::LI:D' ), 00322 array( false, ':::1' ) 00323 ); 00324 } 00325 00329 public function testPrivateIPs() { 00330 $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' ); 00331 foreach ( $private as $p ) { 00332 $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" ); 00333 } 00334 $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' ); 00335 foreach ( $public as $p ) { 00336 $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" ); 00337 } 00338 } 00339 00340 // Private wrapper used to test CIDR Parsing. 00341 private function assertFalseCIDR( $CIDR, $msg = '' ) { 00342 $ff = array( false, false ); 00343 $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg ); 00344 } 00345 00346 // Private wrapper to test network shifting using only dot notation 00347 private function assertNet( $expected, $CIDR ) { 00348 $parse = IP::parseCIDR( $CIDR ); 00349 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" ); 00350 } 00351 00355 public function testHexToQuad() { 00356 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) ); 00357 $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) ); 00358 $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) ); 00359 $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) ); 00360 // hex not left-padded... 00361 $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) ); 00362 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) ); 00363 $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) ); 00364 $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) ); 00365 } 00366 00370 public function testHexToOctet() { 00371 $this->assertEquals( '0:0:0:0:0:0:0:1', 00372 IP::hexToOctet( '00000000000000000000000000000001' ) ); 00373 $this->assertEquals( '0:0:0:0:0:0:FF:3', 00374 IP::hexToOctet( '00000000000000000000000000FF0003' ) ); 00375 $this->assertEquals( '0:0:0:0:0:0:FF00:6', 00376 IP::hexToOctet( '000000000000000000000000FF000006' ) ); 00377 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', 00378 IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) ); 00379 $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF', 00380 IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) ); 00381 // hex not left-padded... 00382 $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) ); 00383 $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) ); 00384 $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) ); 00385 $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) ); 00386 $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) ); 00387 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) ); 00388 } 00389 00395 public function testCIDRParsing() { 00396 $this->assertFalseCIDR( '192.0.2.0', "missing mask" ); 00397 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" ); 00398 00399 // Verify if statement 00400 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" ); 00401 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" ); 00402 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" ); 00403 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" ); 00404 00405 // Check internal logic 00406 # 0 mask always result in array(0,0) 00407 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) ); 00408 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) ); 00409 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) ); 00410 00411 // @todo FIXME: Add more tests. 00412 00413 # This part test network shifting 00414 $this->assertNet( '192.0.0.0', '192.0.0.2/24' ); 00415 $this->assertNet( '192.168.5.0', '192.168.5.13/24' ); 00416 $this->assertNet( '10.0.0.160', '10.0.0.161/28' ); 00417 $this->assertNet( '10.0.0.0', '10.0.0.3/28' ); 00418 $this->assertNet( '10.0.0.0', '10.0.0.3/30' ); 00419 $this->assertNet( '10.0.0.4', '10.0.0.4/30' ); 00420 $this->assertNet( '172.17.32.0', '172.17.35.48/21' ); 00421 $this->assertNet( '10.128.0.0', '10.135.0.0/9' ); 00422 $this->assertNet( '134.0.0.0', '134.0.5.1/8' ); 00423 } 00424 00428 public function testIPCanonicalizeOnValidIp() { 00429 $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ), 00430 'Canonicalization of a valid IP returns it unchanged' ); 00431 } 00432 00436 public function testIPCanonicalizeMappedAddress() { 00437 $this->assertEquals( 00438 '192.0.2.152', 00439 IP::canonicalize( '::ffff:192.0.2.152' ) 00440 ); 00441 $this->assertEquals( 00442 '192.0.2.152', 00443 IP::canonicalize( '::192.0.2.152' ) 00444 ); 00445 } 00446 00452 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) { 00453 $this->assertEquals( 00454 $expected, 00455 IP::isInRange( $addr, $range ), 00456 $message 00457 ); 00458 } 00459 00461 public static function provideIPsAndRanges() { 00462 # Format: (expected boolean, address, range, optional message) 00463 return array( 00464 # IPv4 00465 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ), 00466 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ), 00467 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ), 00468 00469 array( false, '0.0.0.0', '192.0.2.0/24' ), 00470 array( false, '255.255.255', '192.0.2.0/24' ), 00471 00472 # IPv6 00473 array( false, '::1', '2001:DB8::/32' ), 00474 array( false, '::', '2001:DB8::/32' ), 00475 array( false, 'FE80::1', '2001:DB8::/32' ), 00476 00477 array( true, '2001:DB8::', '2001:DB8::/32' ), 00478 array( true, '2001:0DB8::', '2001:DB8::/32' ), 00479 array( true, '2001:DB8::1', '2001:DB8::/32' ), 00480 array( true, '2001:0DB8::1', '2001:DB8::/32' ), 00481 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF', 00482 '2001:DB8::/32' ), 00483 00484 array( false, '2001:0DB8:F::', '2001:DB8::/96' ), 00485 ); 00486 } 00487 00492 public function testSplitHostAndPort( $expected, $input, $description ) { 00493 $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description ); 00494 } 00495 00499 public static function provideSplitHostAndPort() { 00500 return array( 00501 array( false, '[', 'Unclosed square bracket' ), 00502 array( false, '[::', 'Unclosed square bracket 2' ), 00503 array( array( '::', false ), '::', 'Bare IPv6 0' ), 00504 array( array( '::1', false ), '::1', 'Bare IPv6 1' ), 00505 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ), 00506 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ), 00507 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ), 00508 array( false, '::x', 'Double colon but no IPv6' ), 00509 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ), 00510 array( false, 'x:x', 'Hostname and invalid port' ), 00511 array( array( 'x', false ), 'x', 'Plain hostname' ) 00512 ); 00513 } 00514 00519 public function testCombineHostAndPort( $expected, $input, $description ) { 00520 list( $host, $port, $defaultPort ) = $input; 00521 $this->assertEquals( 00522 $expected, 00523 IP::combineHostAndPort( $host, $port, $defaultPort ), 00524 $description ); 00525 } 00526 00530 public static function provideCombineHostAndPort() { 00531 return array( 00532 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ), 00533 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ), 00534 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ), 00535 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ), 00536 ); 00537 } 00538 00543 public function testSanitizeRange( $input, $expected, $description ) { 00544 $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description ); 00545 } 00546 00550 public static function provideIPCIDRs() { 00551 return array( 00552 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ), 00553 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ), 00554 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ), 00555 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ), 00556 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ), 00557 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ), 00558 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ), 00559 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ), 00560 ); 00561 } 00562 00567 public function testPrettifyIP( $ip, $prettified ) { 00568 $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" ); 00569 } 00570 00574 public static function provideIPsToPrettify() { 00575 return array( 00576 array( '0:0:0:0:0:0:0:0', '::' ), 00577 array( '0:0:0::0:0:0', '::' ), 00578 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ), 00579 array( '0:0::f', '::f' ), 00580 array( '0::0:0:0:33:fef:b', '::33:fef:b' ), 00581 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ), 00582 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ), 00583 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ), 00584 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ), 00585 array( '0:0:0:0:0:0:0:0/16', '::/16' ), 00586 array( '0:0:0::0:0:0/64', '::/64' ), 00587 array( '0:0::f/52', '::f/52' ), 00588 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ), 00589 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ), 00590 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ), 00591 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ), 00592 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ), 00593 ); 00594 } 00595 }