Completed
Push — next ( aa6b76...a5d913 )
by Jonathan
02:53
created

WhipTest::testRemoteAddrMethod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 6
rs 9.4286
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
/*
3
The MIT License (MIT)
4
5
Copyright (c) 2015 Vectorface, Inc.
6
7
Permission is hereby granted, free of charge, to any person obtaining a copy
8
of this software and associated documentation files (the "Software"), to deal
9
in the Software without restriction, including without limitation the rights
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
copies of the Software, and to permit persons to whom the Software is
12
furnished to do so, subject to the following conditions:
13
14
The above copyright notice and this permission notice shall be included in
15
all copies or substantial portions of the Software.
16
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
THE SOFTWARE.
24
*/
25
namespace Vectorface\WhipTests;
26
27
use PHPUnit_Framework_TestCase;
28
use Vectorface\Whip\Whip;
29
use Vectorface\Whip\IpRange\IpWhitelist;
30
use Psr\Http\Message\ServerRequestInterface;
31
32
/**
33
 * Test class for testing Whip.
34
 * @backupGlobals enabled
35
 * @copyright Vectorface, Inc 2015
36
 * @author Daniel Bruce <[email protected]>
37
 */
38
class WhipTest extends PHPUnit_Framework_TestCase
39
{
40
    /**
41
     * Tests that an invalid source format is rejected.
42
     * @expectedException \InvalidArgumentException
43
     */
44
    public function testInvalidSource()
45
    {
46
        new Whip(Whip::REMOTE_ADDR, [], new \stdClass());
47
    }
48
    /**
49
     * Tests that we get back the right IP when there using superglobals.
50
     */
51
    public function testSuperglobal()
0 ignored issues
show
Coding Style introduced by
testSuperglobal uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
52
    {
53
        $_SERVER = array('REMOTE_ADDR' => '24.24.24.24');
54
        $lookup = new Whip(Whip::REMOTE_ADDR);
55
        $this->assertEquals('24.24.24.24', $lookup->getValidIpAddress());
56
    }
57
58
    /**
59
     * Tests that we get back 127.0.0.1 when there is no superglobal information
60
     * at all.
61
     */
62
    public function testEmptySuperglobal()
0 ignored issues
show
Coding Style introduced by
testEmptySuperglobal uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
63
    {
64
        $_SERVER = array();
65
        $lookup = new Whip();
66
        $this->assertFalse($lookup->getIpAddress());
67
    }
68
69
    /**
70
     * Tests that we can use a PSR-7 ServerRequestInterface compatible class.
71
     */
72
    public function testPsr7Request()
73
    {
74
        $stub = $this->getMockBuilder("Psr\Http\Message\ServerRequestInterface")
75
            ->getMock();
76
77
        $stub->method('getServerParams')
78
            ->willReturn(array('REMOTE_ADDR' => '127.0.0.1'));
79
        $stub->method('getHeaders')
80
            ->willReturn(array('X-Forwarded-For' => array('192.168.1.1,32.32.32.32')));
81
82
        $lookup = new Whip(
83
            Whip::PROXY_HEADERS,
84
            array(
85
                Whip::PROXY_HEADERS => array(
86
                    IpWhitelist::IPV4 => array(
87
                        '127.0.0.1'
88
                    )
89
                )
90
            ),
91
            $stub
92
        );
93
94
        $this->assertTrue($stub instanceof ServerRequestInterface);
95
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
96
    }
97
98
    /**
99
     * Tests that we get false when no valid IP address could be found.
100
     */
101
    public function testNoAddresFoundDueToBitmask()
102
    {
103
        $lookup = new Whip(Whip::PROXY_HEADERS);
104
        $lookup->setSource(array('REMOTE_ADDR' => '127.0.0.1'));
105
        $this->assertFalse($lookup->getIpAddress());
106
    }
107
108
    /**
109
     * Tests the standard REMOTE_ADDR method.
110
     */
111
    public function testRemoteAddrMethod()
112
    {
113
        $lookup = new Whip(Whip::REMOTE_ADDR);
114
        $lookup->setSOurce(array('REMOTE_ADDR' => '24.24.24.24'));
115
        $this->assertEquals('24.24.24.24', $lookup->getValidIpAddress());
116
    }
117
118
    /**
119
     * Tests that an invalid IPv4 address returns false.
120
     */
121
    public function testInvalidIPv4Address()
122
    {
123
        $lookup = new Whip(Whip::REMOTE_ADDR);
124
        $lookup->setSource(array('REMOTE_ADDR' => '127.0.0.256'));
125
        $this->assertFalse($lookup->getValidIpAddress());
126
    }
127
128
    /**
129
     * Tests a valid IPv6 address.
130
     */
131
    public function testValidIPv6Address()
132
    {
133
        $lookup = new Whip(Whip::REMOTE_ADDR);
134
        $lookup->setSource(array('REMOTE_ADDR' => '::1'));
135
        $this->assertEquals('::1', $lookup->getValidIpAddress());
136
    }
137
138
    /**
139
     * Tests that we accept whitelisted proxy methods when the IP matches, even
140
     * if the IP listed is a comma separated list.
141
     */
142
    public function testValidWhitelistedProxyMethod()
143
    {
144
        $lookup = new Whip(
145
            Whip::PROXY_HEADERS,
146
            array(
147
                Whip::PROXY_HEADERS => array(
148
                    IpWhitelist::IPV4 => array(
149
                        '127.0.0.1'
150
                    ),
151
                    IpWhitelist::IPV6 => array(
152
                        '::1'
153
                    )
154
                )
155
            ),
156
            array(
157
                'REMOTE_ADDR' => '127.0.0.1',
158
                'HTTP_X_FORWARDED_FOR' => '192.168.1.1,32.32.32.32'
159
            )
160
        );
161
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
162
163
         /* Repeat test for IPv6 */
164
        $lookup->setSource(array(
165
            'REMOTE_ADDR' => '::1',
166
            'HTTP_X_FORWARDED_FOR' => '192.168.1.1,32.32.32.32'
167
        ));
168
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
169
    }
170
171
    /**
172
     * Tests that we accept proxy method based on a whitelisted IP using the
173
     * dashed range notation.
174
     */
175 View Code Duplication
    public function testValidWhitelistedProxyMethodWithDashNotation()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
    {
177
        $lookup = new Whip(
178
            Whip::PROXY_HEADERS,
179
            array(
180
                Whip::PROXY_HEADERS => array(
181
                    IpWhitelist::IPV4 => array(
182
                        '127.0.0.0-127.0.255.255',
183
                    ),
184
                    IpWhitelist::IPV6 => array(
185
                        '::1'
186
                    )
187
                )
188
            ),
189
            array(
190
                'REMOTE_ADDR' => '127.0.0.1',
191
                'HTTP_X_FORWARDED_FOR' => '32.32.32.32'
192
            )
193
        );
194
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
195
    }
196
197
    /**
198
     * Tests that we accept proxy method based on a whitelisted IP using the
199
     * wildcard asterix notation.
200
     */
201 View Code Duplication
    public function testValidWhitelistedProxyMethodWithWildcardNotation()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
    {
203
        $lookup = new Whip(
204
            Whip::PROXY_HEADERS,
205
            array(
206
                Whip::PROXY_HEADERS => array(
207
                    IpWhitelist::IPV4 => array(
208
                        '127.0.*'
209
                    ),
210
                    IpWhitelist::IPV6 => array(
211
                        '::1'
212
                    )
213
                )
214
            ),
215
            array(
216
                'REMOTE_ADDR' => '127.0.0.1',
217
                'HTTP_X_FORWARDED_FOR' => '32.32.32.32'
218
            )
219
        );
220
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
221
    }
222
223
    /**
224
     * Tests that we accept proxy method based on a whitelisted IP using the
225
     * CIDR address notation.
226
     */
227 View Code Duplication
    public function testValidWhitelistedProxyMethodWithCIDRdNotation()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
228
    {
229
        $lookup = new Whip(
230
            Whip::PROXY_HEADERS,
231
            array(
232
                Whip::PROXY_HEADERS => array(
233
                    IpWhitelist::IPV4 => array(
234
                        '127.0.0.0/24'
235
                    ),
236
                    IpWhitelist::IPV6 => array(
237
                        '::1'
238
                    )
239
                )
240
            ),
241
            array(
242
                'REMOTE_ADDR' => '127.0.0.1',
243
                'HTTP_X_FORWARDED_FOR' => '32.32.32.32'
244
            )
245
        );
246
        $this->assertEquals('32.32.32.32', $lookup->getIpAddress());
247
    }
248
249
    /**
250
     * Tests that we get false if there is a valid IP in a proxy header but
251
     * we reject it due to REMOTE_ADDR not being in the whitelist.
252
     */
253 View Code Duplication
    public function testValidIpRejectedDueToWhitelist()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
254
    {
255
        $lookup = new Whip(
256
            Whip::PROXY_HEADERS,
257
            array(
258
                Whip::PROXY_HEADERS => array(
259
                    IpWhitelist::IPV4 => array(
260
                        '127.0.0.1/24'
261
                    ),
262
                    IpWhitelist::IPV6 => array(
263
                        '::1'
264
                    )
265
                )
266
            ),
267
            array(
268
                'REMOTE_ADDR' => '24.24.24.24',
269
                'HTTP_X_FORWARDED_FOR' => '32.32.32.32'
270
            )
271
        );
272
        $this->assertFalse($lookup->getIpAddress());
273
    }
274
275
    /**
276
     * Tests that we reject a proxy listed IPv6 address that does not fall within
277
     * the allowed subnet.
278
     */
279
    public function testIPv6AddressRejectedDueToWhitelist()
280
    {
281
        $lookup = new Whip(
282
            Whip::PROXY_HEADERS,
283
            array(
284
                Whip::PROXY_HEADERS => array(
285
                    IpWhitelist::IPV6 => array(
286
                        '2400:cb00::/32'
287
                    )
288
                )
289
            ),
290
            array(
291
                'REMOTE_ADDR' => '::1',
292
                'HTTP_X_FORWARDED_FOR' => '::1'
293
            )
294
        );
295
        $this->assertFalse($lookup->getIpAddress());
296
    }
297
298
    /**
299
     * Tests that we reject a proxy listed IPv6 address that does not fall within
300
     * the allowed subnet.
301
     */
302
    public function testIPv6AddressFoundInWhitelist()
303
    {
304
        $lookup = new Whip(
305
            Whip::PROXY_HEADERS,
306
            array(
307
                Whip::PROXY_HEADERS => array(
308
                    IpWhitelist::IPV6 => array(
309
                        '::1/32'
310
                    )
311
                )
312
            ),
313
            array(
314
                'REMOTE_ADDR' => '::1',
315
                'HTTP_X_FORWARDED_FOR' => '::1'
316
            )
317
        );
318
        $this->assertEquals('::1', $lookup->getIpAddress());
319
    }
320
321
    /**
322
     * Test that an IPv4 address is rejected because the whitelist is empty for
323
     * IPv4.
324
     */
325
    public function testIPv4AddressRejectedDueToEmptyWhitelist()
326
    {
327
        $lookup = new Whip(
328
            Whip::PROXY_HEADERS,
329
            array(
330
                Whip::PROXY_HEADERS => array(
331
                    IpWhitelist::IPV6 => array(
332
                        '::1/32'
333
                    )
334
                )
335
            ),
336
            array(
337
                'REMOTE_ADDR' => '127.0.0.1',
338
                'HTTP_X_FORWARDED_FOR' => '24.24.24.24'
339
            )
340
        );
341
        $this->assertFalse($lookup->getIpAddress());
342
    }
343
344
    /**
345
     * Test that an IPv6 address is rejected because the whitelist is empty for
346
     * IPv6.
347
     */
348
    public function testIPv6AddressRejectedDueToEmptyWhitelist()
349
    {
350
        $lookup = new Whip(
351
            Whip::PROXY_HEADERS,
352
            array(
353
                Whip::PROXY_HEADERS => array(
354
                    IpWhitelist::IPV4 => array(
355
                        '127.0.0.0/24'
356
                    )
357
                )
358
            ),
359
            array(
360
                'REMOTE_ADDR' => '::1',
361
                'HTTP_X_FORWARDED_FOR' => '::1'
362
            )
363
        );
364
        $this->assertFalse($lookup->getIpAddress());
365
    }
366
367
    /**
368
     * Test a custom header with a whitelisted IP.
369
     */
370 View Code Duplication
    public function testCustomHeader()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
371
    {
372
        $lookup = new Whip(
373
            Whip::CUSTOM_HEADERS | Whip::REMOTE_ADDR,
374
            array(
375
                Whip::CUSTOM_HEADERS => array(
376
                    IpWhitelist::IPV4 => array(
377
                        '127.0.0.1',
378
                        '::1'
379
                    )
380
                )
381
            ),
382
            array(
383
                'REMOTE_ADDR' => '127.0.0.1',
384
                'HTTP_CUSTOM_SECRET_HEADER' => '32.32.32.32'
385
            )
386
        );
387
        $this->assertEquals(
388
            '32.32.32.32',
389
            $lookup->addCustomHeader('HTTP_CUSTOM_SECRET_HEADER')->getIpAddress()
390
        );
391
    }
392
393
    /**
394
     * Test HTTP_X_REAL_IP header.
395
     */
396
    public function testHttpXRealIpHeader()
397
    {
398
        $lookup = new Whip(
399
            Whip::PROXY_HEADERS | Whip::REMOTE_ADDR,
400
            array(),
401
            array(
402
                'REMOTE_ADDR' => '127.0.0.1',
403
                'HTTP_X_REAL_IP' => '24.24.24.24'
404
            )
405
        );
406
        $this->assertEquals('24.24.24.24', $lookup->getIpAddress());
407
    }
408
409
    /**
410
     * Tests that if we specify the source array, it overrides any values found
411
     * in the $_SERVER array.
412
     */
413 View Code Duplication
    public function testSourceArrayOverridesServerSuperglobal()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
414
    {
415
        $source = array(
416
            'REMOTE_ADDR' => '24.24.24.24'
417
        );
418
        $lookup = new Whip(Whip::REMOTE_ADDR, [], array('REMOTE_ADDR' => '127.0.0.1'));
419
        $this->assertNotEquals($source['REMOTE_ADDR'], $lookup->getIpAddress());
420
        $this->assertEquals($source['REMOTE_ADDR'], $lookup->getIpAddress($source));
421
    }
422
423
    /**
424
     * Tests that if we specify the source array through Whip::setSource, the
425
     * class will override any values found in $_SERVER.
426
     */
427 View Code Duplication
    public function testSetSourceArrayOverridesServerSuperglobal()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
428
    {
429
        $source = array(
430
            'REMOTE_ADDR' => '24.24.24.24'
431
        );
432
        $lookup = new Whip(Whip::REMOTE_ADDR, [], array('REMOTE_ADDR' => '127.0.0.1'));
433
        $this->assertNotEquals($source['REMOTE_ADDR'], $lookup->getIpAddress());
434
        $lookup->setSource($source);
435
        $this->assertEquals($source['REMOTE_ADDR'], $lookup->getIpAddress());
436
    }
437
}
438