Pass phpcs-strict on some test files (11/11)
[mediawiki.git] / tests / phpunit / includes / utils / IPTest.php
blob1267268364c6879f755debcc907577b411137cbf
1 <?php
2 /**
3 * Tests for IP validity functions.
5 * Ported from /t/inc/IP.t by avar.
7 * @group IP
8 * @todo Test methods in this call should be split into a method and a
9 * dataprovider.
12 class IPTest extends MediaWikiTestCase {
13 /**
14 * not sure it should be tested with boolean false. hashar 20100924
15 * @covers IP::isIPAddress
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'
28 $this->assertFalse(
29 IP::isIPAddress( '::2001:0DB8::5:1' ),
30 'IPv6 with a double :: occurrence, firt at beginning'
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' );
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 "::"' );
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" );
50 /**
51 * @covers IP::isIPv6
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' );
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::' ) );
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 "::"'
72 $this->assertFalse( IP::isIPv6( ':::' ) );
73 $this->assertFalse( IP::isIPv6( '::0:' ), 'IPv6 ending in a lone ":"' );
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' ) );
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' );
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' );
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' );
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' );
105 $this->assertTrue( IP::isIPv6( 'fc:100:a:d:1:e:ac:0' ) );
109 * @covers IP::isIPv4
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' );
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' ) );
127 * @covers IP::isValid
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" );
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" );
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' );
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::' ) );
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' );
166 $this->assertFalse(
167 IP::isValid( 'fc:100:a:d:1:e:ac:0::' ),
168 'IPv6 with 8 words ending with "::"'
170 $this->assertFalse(
171 IP::isValid( 'fc:100:a:d:1:e:ac:0:1::' ),
172 'IPv6 with 9 words ending with "::"'
177 * @covers IP::isValid
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" );
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" );
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',
208 foreach ( $ipCIDRs as $i ) {
209 $this->assertFalse( IP::isValid( $i ),
210 "$i is an invalid IP address because it is a block" );
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'
221 foreach ( $invalid as $i ) {
222 $this->assertFalse( IP::isValid( $i ), "$i is an invalid IP address" );
227 * @covers IP::isValidBlock
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',
244 foreach ( $valid as $i ) {
245 $this->assertTrue( IP::isValidBlock( $i ), "$i is a valid IP block" );
250 * @covers IP::isValidBlock
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/',
267 foreach ( $invalid as $i ) {
268 $this->assertFalse( IP::isValidBlock( $i ), "$i is not a valid IP block" );
273 * Improve IP::sanitizeIP() code coverage
274 * @todo Most probably incomplete
276 public function testSanitizeIP() {
277 $this->assertNull( IP::sanitizeIP( '' ) );
278 $this->assertNull( IP::sanitizeIP( ' ' ) );
282 * @covers IP::toUnsigned
283 * @dataProvider provideToUnsigned
285 public function testToUnsigned( $expected, $input ) {
286 $result = IP::toUnsigned( $input );
287 $this->assertTrue( $result === false || is_string( $result ) || is_int( $result ) );
288 $this->assertEquals( $expected, $result );
292 * Provider for IP::testToUnsigned()
294 public static function provideToUnsigned() {
295 return array(
296 array( 1, '0.0.0.1' ),
297 array( 16909060, '1.2.3.4' ),
298 array( 2130706433, '127.0.0.1' ),
299 array( '2147483648', '128.0.0.0' ),
300 array( 2130706440, '127.0.0.08' ),
301 array( 2130706441, '127.0.0.09' ),
302 array( '3735931646', '222.173.202.254' ),
303 array( pow( 2, 32 ) - 1, '255.255.255.255' ),
304 array( false, 'IN.VA.LI.D' ),
305 array( 1, '::1' ),
306 array( '42540766452641154071740215577757643572', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
307 array( '42540766452641154071740215577757643572', '2001:db8:85a3::8a2e:0370:7334' ),
308 array( false, 'IN:VA::LI:D' ),
309 array( false, ':::1' )
314 * @covers IP::toHex
315 * @dataProvider provideToHex
317 public function testToHex( $expected, $input ) {
318 $result = IP::toHex( $input );
319 $this->assertTrue( $result === false || is_string( $result ) );
320 $this->assertEquals( $expected, $result );
324 * Provider for IP::testToHex()
326 public static function provideToHex() {
327 return array(
328 array( '00000001', '0.0.0.1' ),
329 array( '01020304', '1.2.3.4' ),
330 array( '7F000001', '127.0.0.1' ),
331 array( '80000000', '128.0.0.0' ),
332 array( 'DEADCAFE', '222.173.202.254' ),
333 array( 'FFFFFFFF', '255.255.255.255' ),
334 array( false, 'IN.VA.LI.D' ),
335 array( 'v6-00000000000000000000000000000001', '::1' ),
336 array( 'v6-20010DB885A3000000008A2E03707334', '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ),
337 array( 'v6-20010DB885A3000000008A2E03707334', '2001:db8:85a3::8a2e:0370:7334' ),
338 array( false, 'IN:VA::LI:D' ),
339 array( false, ':::1' )
344 * @covers IP::isPublic
346 public function testPrivateIPs() {
347 $private = array( 'fc00::3', 'fc00::ff', '::1', '10.0.0.1', '172.16.0.1', '192.168.0.1' );
348 foreach ( $private as $p ) {
349 $this->assertFalse( IP::isPublic( $p ), "$p is not a public IP address" );
351 $public = array( '2001:5c0:1000:a::133', 'fc::3', '00FC::' );
352 foreach ( $public as $p ) {
353 $this->assertTrue( IP::isPublic( $p ), "$p is a public IP address" );
357 // Private wrapper used to test CIDR Parsing.
358 private function assertFalseCIDR( $CIDR, $msg = '' ) {
359 $ff = array( false, false );
360 $this->assertEquals( $ff, IP::parseCIDR( $CIDR ), $msg );
363 // Private wrapper to test network shifting using only dot notation
364 private function assertNet( $expected, $CIDR ) {
365 $parse = IP::parseCIDR( $CIDR );
366 $this->assertEquals( $expected, long2ip( $parse[0] ), "network shifting $CIDR" );
370 * @covers IP::hexToQuad
372 public function testHexToQuad() {
373 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '00000001' ) );
374 $this->assertEquals( '255.0.0.0', IP::hexToQuad( 'FF000000' ) );
375 $this->assertEquals( '255.255.255.255', IP::hexToQuad( 'FFFFFFFF' ) );
376 $this->assertEquals( '10.188.222.255', IP::hexToQuad( '0ABCDEFF' ) );
377 // hex not left-padded...
378 $this->assertEquals( '0.0.0.0', IP::hexToQuad( '0' ) );
379 $this->assertEquals( '0.0.0.1', IP::hexToQuad( '1' ) );
380 $this->assertEquals( '0.0.0.255', IP::hexToQuad( 'FF' ) );
381 $this->assertEquals( '0.0.255.0', IP::hexToQuad( 'FF00' ) );
385 * @covers IP::hexToOctet
387 public function testHexToOctet() {
388 $this->assertEquals( '0:0:0:0:0:0:0:1',
389 IP::hexToOctet( '00000000000000000000000000000001' ) );
390 $this->assertEquals( '0:0:0:0:0:0:FF:3',
391 IP::hexToOctet( '00000000000000000000000000FF0003' ) );
392 $this->assertEquals( '0:0:0:0:0:0:FF00:6',
393 IP::hexToOctet( '000000000000000000000000FF000006' ) );
394 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF',
395 IP::hexToOctet( '000000000000000000000000FCCFFAFF' ) );
396 $this->assertEquals( 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
397 IP::hexToOctet( 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' ) );
398 // hex not left-padded...
399 $this->assertEquals( '0:0:0:0:0:0:0:0', IP::hexToOctet( '0' ) );
400 $this->assertEquals( '0:0:0:0:0:0:0:1', IP::hexToOctet( '1' ) );
401 $this->assertEquals( '0:0:0:0:0:0:0:FF', IP::hexToOctet( 'FF' ) );
402 $this->assertEquals( '0:0:0:0:0:0:0:FFD0', IP::hexToOctet( 'FFD0' ) );
403 $this->assertEquals( '0:0:0:0:0:0:FA00:0', IP::hexToOctet( 'FA000000' ) );
404 $this->assertEquals( '0:0:0:0:0:0:FCCF:FAFF', IP::hexToOctet( 'FCCFFAFF' ) );
408 * IP::parseCIDR() returns an array containing a signed IP address
409 * representing the network mask and the bit mask.
410 * @covers IP::parseCIDR
412 public function testCIDRParsing() {
413 $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
414 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
416 // Verify if statement
417 $this->assertFalseCIDR( '256.0.0.0/32', "invalid net" );
418 $this->assertFalseCIDR( '192.0.2.0/AA', "mask not numeric" );
419 $this->assertFalseCIDR( '192.0.2.0/-1', "mask < 0" );
420 $this->assertFalseCIDR( '192.0.2.0/33', "mask > 32" );
422 // Check internal logic
423 # 0 mask always result in array(0,0)
424 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '192.0.0.2/0' ) );
425 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '0.0.0.0/0' ) );
426 $this->assertEquals( array( 0, 0 ), IP::parseCIDR( '255.255.255.255/0' ) );
428 // @todo FIXME: Add more tests.
430 # This part test network shifting
431 $this->assertNet( '192.0.0.0', '192.0.0.2/24' );
432 $this->assertNet( '192.168.5.0', '192.168.5.13/24' );
433 $this->assertNet( '10.0.0.160', '10.0.0.161/28' );
434 $this->assertNet( '10.0.0.0', '10.0.0.3/28' );
435 $this->assertNet( '10.0.0.0', '10.0.0.3/30' );
436 $this->assertNet( '10.0.0.4', '10.0.0.4/30' );
437 $this->assertNet( '172.17.32.0', '172.17.35.48/21' );
438 $this->assertNet( '10.128.0.0', '10.135.0.0/9' );
439 $this->assertNet( '134.0.0.0', '134.0.5.1/8' );
443 * @covers IP::canonicalize
445 public function testIPCanonicalizeOnValidIp() {
446 $this->assertEquals( '192.0.2.152', IP::canonicalize( '192.0.2.152' ),
447 'Canonicalization of a valid IP returns it unchanged' );
451 * @covers IP::canonicalize
453 public function testIPCanonicalizeMappedAddress() {
454 $this->assertEquals(
455 '192.0.2.152',
456 IP::canonicalize( '::ffff:192.0.2.152' )
458 $this->assertEquals(
459 '192.0.2.152',
460 IP::canonicalize( '::192.0.2.152' )
465 * Issues there are most probably from IP::toHex() or IP::parseRange()
466 * @covers IP::isInRange
467 * @dataProvider provideIPsAndRanges
469 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
470 $this->assertEquals(
471 $expected,
472 IP::isInRange( $addr, $range ),
473 $message
477 /** Provider for testIPIsInRange() */
478 public static function provideIPsAndRanges() {
479 # Format: (expected boolean, address, range, optional message)
480 return array(
481 # IPv4
482 array( true, '192.0.2.0', '192.0.2.0/24', 'Network address' ),
483 array( true, '192.0.2.77', '192.0.2.0/24', 'Simple address' ),
484 array( true, '192.0.2.255', '192.0.2.0/24', 'Broadcast address' ),
486 array( false, '0.0.0.0', '192.0.2.0/24' ),
487 array( false, '255.255.255', '192.0.2.0/24' ),
489 # IPv6
490 array( false, '::1', '2001:DB8::/32' ),
491 array( false, '::', '2001:DB8::/32' ),
492 array( false, 'FE80::1', '2001:DB8::/32' ),
494 array( true, '2001:DB8::', '2001:DB8::/32' ),
495 array( true, '2001:0DB8::', '2001:DB8::/32' ),
496 array( true, '2001:DB8::1', '2001:DB8::/32' ),
497 array( true, '2001:0DB8::1', '2001:DB8::/32' ),
498 array( true, '2001:0DB8:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF',
499 '2001:DB8::/32' ),
501 array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
506 * Test for IP::splitHostAndPort().
507 * @dataProvider provideSplitHostAndPort
509 public function testSplitHostAndPort( $expected, $input, $description ) {
510 $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description );
514 * Provider for IP::splitHostAndPort()
516 public static function provideSplitHostAndPort() {
517 return array(
518 array( false, '[', 'Unclosed square bracket' ),
519 array( false, '[::', 'Unclosed square bracket 2' ),
520 array( array( '::', false ), '::', 'Bare IPv6 0' ),
521 array( array( '::1', false ), '::1', 'Bare IPv6 1' ),
522 array( array( '::', false ), '[::]', 'Bracketed IPv6 0' ),
523 array( array( '::1', false ), '[::1]', 'Bracketed IPv6 1' ),
524 array( array( '::1', 80 ), '[::1]:80', 'Bracketed IPv6 with port' ),
525 array( false, '::x', 'Double colon but no IPv6' ),
526 array( array( 'x', 80 ), 'x:80', 'Hostname and port' ),
527 array( false, 'x:x', 'Hostname and invalid port' ),
528 array( array( 'x', false ), 'x', 'Plain hostname' )
533 * Test for IP::combineHostAndPort()
534 * @dataProvider provideCombineHostAndPort
536 public function testCombineHostAndPort( $expected, $input, $description ) {
537 list( $host, $port, $defaultPort ) = $input;
538 $this->assertEquals(
539 $expected,
540 IP::combineHostAndPort( $host, $port, $defaultPort ),
541 $description );
545 * Provider for IP::combineHostAndPort()
547 public static function provideCombineHostAndPort() {
548 return array(
549 array( '[::1]', array( '::1', 2, 2 ), 'IPv6 default port' ),
550 array( '[::1]:2', array( '::1', 2, 3 ), 'IPv6 non-default port' ),
551 array( 'x', array( 'x', 2, 2 ), 'Normal default port' ),
552 array( 'x:2', array( 'x', 2, 3 ), 'Normal non-default port' ),
557 * Test for IP::sanitizeRange()
558 * @dataProvider provideIPCIDRs
560 public function testSanitizeRange( $input, $expected, $description ) {
561 $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
565 * Provider for IP::testSanitizeRange()
567 public static function provideIPCIDRs() {
568 return array(
569 array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
570 array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
571 array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
572 array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
573 array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
574 array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
575 array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
576 array( '0:c1:A2:3:4:5:c6:7', '0:C1:A2:3:4:5:C6:7', 'IPv6 non range' ),
581 * Test for IP::prettifyIP()
582 * @dataProvider provideIPsToPrettify
584 public function testPrettifyIP( $ip, $prettified ) {
585 $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" );
589 * Provider for IP::testPrettifyIP()
591 public static function provideIPsToPrettify() {
592 return array(
593 array( '0:0:0:0:0:0:0:0', '::' ),
594 array( '0:0:0::0:0:0', '::' ),
595 array( '0:0:0:1:0:0:0:0', '0:0:0:1::' ),
596 array( '0:0::f', '::f' ),
597 array( '0::0:0:0:33:fef:b', '::33:fef:b' ),
598 array( '3f:535:0:0:0:0:e:fbb', '3f:535::e:fbb' ),
599 array( '0:0:fef:0:0:0:e:fbb', '0:0:fef::e:fbb' ),
600 array( 'abbc:2004::0:0:0:0', 'abbc:2004::' ),
601 array( 'cebc:2004:f:0:0:0:0:0', 'cebc:2004:f::' ),
602 array( '0:0:0:0:0:0:0:0/16', '::/16' ),
603 array( '0:0:0::0:0:0/64', '::/64' ),
604 array( '0:0::f/52', '::f/52' ),
605 array( '::0:0:33:fef:b/52', '::33:fef:b/52' ),
606 array( '3f:535:0:0:0:0:e:fbb/48', '3f:535::e:fbb/48' ),
607 array( '0:0:fef:0:0:0:e:fbb/96', '0:0:fef::e:fbb/96' ),
608 array( 'abbc:2004:0:0::0:0/40', 'abbc:2004::/40' ),
609 array( 'aebc:2004:f:0:0:0:0:0/80', 'aebc:2004:f::/80' ),