Merge "DatabaseMssql: Don't duplicate body of makeList()"
[mediawiki.git] / tests / phpunit / includes / utils / IPTest.php
blob09c1587de8daea10a14de6ee6791d934d529711c
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 PHPUnit_Framework_TestCase {
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::toHex
283 * @dataProvider provideToHex
285 public function testToHex( $expected, $input ) {
286 $result = IP::toHex( $input );
287 $this->assertTrue( $result === false || is_string( $result ) );
288 $this->assertEquals( $expected, $result );
292 * Provider for IP::testToHex()
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' )
312 * @covers IP::isPublic
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" );
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" );
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 );
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" );
338 * @covers IP::hexToQuad
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' ) );
353 * @covers IP::hexToOctet
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' ) );
376 * IP::parseCIDR() returns an array containing a signed IP address
377 * representing the network mask and the bit mask.
378 * @covers IP::parseCIDR
380 public function testCIDRParsing() {
381 $this->assertFalseCIDR( '192.0.2.0', "missing mask" );
382 $this->assertFalseCIDR( '192.0.2.0/', "missing bitmask" );
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" );
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' ) );
396 // @todo FIXME: Add more tests.
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' );
411 * @covers IP::canonicalize
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' );
419 * @covers IP::canonicalize
421 public function testIPCanonicalizeMappedAddress() {
422 $this->assertEquals(
423 '192.0.2.152',
424 IP::canonicalize( '::ffff:192.0.2.152' )
426 $this->assertEquals(
427 '192.0.2.152',
428 IP::canonicalize( '::192.0.2.152' )
433 * Issues there are most probably from IP::toHex() or IP::parseRange()
434 * @covers IP::isInRange
435 * @dataProvider provideIPsAndRanges
437 public function testIPIsInRange( $expected, $addr, $range, $message = '' ) {
438 $this->assertEquals(
439 $expected,
440 IP::isInRange( $addr, $range ),
441 $message
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' ),
454 array( false, '0.0.0.0', '192.0.2.0/24' ),
455 array( false, '255.255.255', '192.0.2.0/24' ),
457 # IPv6
458 array( false, '::1', '2001:DB8::/32' ),
459 array( false, '::', '2001:DB8::/32' ),
460 array( false, 'FE80::1', '2001:DB8::/32' ),
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' ),
469 array( false, '2001:0DB8:F::', '2001:DB8::/96' ),
474 * Test for IP::splitHostAndPort().
475 * @dataProvider provideSplitHostAndPort
477 public function testSplitHostAndPort( $expected, $input, $description ) {
478 $this->assertEquals( $expected, IP::splitHostAndPort( $input ), $description );
482 * Provider for IP::splitHostAndPort()
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' )
501 * Test for IP::combineHostAndPort()
502 * @dataProvider provideCombineHostAndPort
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 );
513 * Provider for IP::combineHostAndPort()
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' ),
525 * Test for IP::sanitizeRange()
526 * @dataProvider provideIPCIDRs
528 public function testSanitizeRange( $input, $expected, $description ) {
529 $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
533 * Provider for IP::testSanitizeRange()
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' ),
549 * Test for IP::prettifyIP()
550 * @dataProvider provideIPsToPrettify
552 public function testPrettifyIP( $ip, $prettified ) {
553 $this->assertEquals( $prettified, IP::prettifyIP( $ip ), "Prettify of $ip" );
557 * Provider for IP::testPrettifyIP()
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' ),