AccessLogParserTest   A
last analyzed

Complexity

Total Complexity 5

Size/Duplication

Total Lines 576
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 29
Bugs 7 Features 14
Metric Value
wmc 5
c 29
b 7
f 14
lcom 0
cbo 2
dl 0
loc 576
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A testParseLine() 0 7 1
A testParseLineCachedPattern() 0 16 1
A testParseLineNoMatches() 0 5 1
B getTestParseLineData() 0 502 1
A getTestParseLineNoMatchesData() 0 7 1
1
<?php
2
3
/*
4
 * (c) Mantas Varatiejus <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace MVar\Apache2LogParser\Tests;
11
12
use MVar\Apache2LogParser\AccessLogParser;
13
14
/**
15
 * @covers \MVar\Apache2LogParser\AccessLogParser
16
 */
17
class AccessLogParserTest extends \PHPUnit_Framework_TestCase
18
{
19
    /**
20
     * Test for parseLine().
21
     *
22
     * @param string $format
23
     * @param string $logLine
24
     * @param array  $expectedResult
25
     *
26
     * @dataProvider getTestParseLineData()
27
     */
28
    public function testParseLine($format, $logLine, $expectedResult)
29
    {
30
        $parser = new AccessLogParser($format);
31
        $result = $parser->parseLine($logLine);
32
33
        $this->assertEquals($expectedResult, $result);
34
    }
35
36
    /**
37
     * Test for parseLine() if pattern is cached.
38
     */
39
    public function testParseLineCachedPattern()
40
    {
41
        /** @var \PHPUnit_Framework_MockObject_MockObject|AccessLogParser $parser */
42
        $parser = $this->getMock(
43
            '\\MVar\\Apache2LogParser\\AccessLogParser',
44
            ['getCallbackPatterns'],
45
            ['%%']
46
        );
47
48
        $parser->expects($this->once())->method('getCallbackPatterns');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in MVar\Apache2LogParser\AccessLogParser.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
49
50
        $parser->parseLine('%');
0 ignored issues
show
Bug introduced by
The method parseLine does only exist in MVar\Apache2LogParser\AccessLogParser, but not in PHPUnit_Framework_MockObject_MockObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
51
52
        // Pattern should be cached
53
        $parser->parseLine('%');
54
    }
55
56
    /**
57
     * Test for parseLine() in case of invalid line.
58
     *
59
     * @param string $format
60
     * @param string $logLine
61
     *
62
     * @dataProvider getTestParseLineNoMatchesData()
63
     * @expectedException \MVar\Apache2LogParser\Exception\NoMatchesException
64
     * @expectedExceptionMessage line does not match
65
     */
66
    public function testParseLineNoMatches($format, $logLine)
67
    {
68
        $parser = new AccessLogParser($format);
69
        $parser->parseLine($logLine);
70
    }
71
72
    /**
73
     * Data provider for testParseLine().
74
     *
75
     * @return array[]
76
     */
77
    public function getTestParseLineData()
78
    {
79
        return [
80
            [
81
                AccessLogParser::FORMAT_COMMON,
82
                '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326',
83
                [
84
                    'remote_host' => '127.0.0.1',
85
                    'identity' => '-',
86
                    'remote_user' => 'frank',
87
                    'time' => '10/Oct/2000:13:55:36 -0700',
88
                    'request_line' => 'GET /apache_pb.gif HTTP/1.0',
89
                    'request' => [
90
                        'method' => 'GET',
91
                        'path' => '/apache_pb.gif',
92
                        'protocol' => 'HTTP/1.0'
93
                    ],
94
                    'response_code' => '200',
95
                    'bytes_sent' => '2326',
96
                ],
97
            ],
98
            [
99
                AccessLogParser::FORMAT_COMBINED,
100
                '127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 ' .
101
                    '"http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"',
102
                [
103
                    'remote_host' => '127.0.0.1',
104
                    'identity' => '-',
105
                    'remote_user' => 'frank',
106
                    'time' => '10/Oct/2000:13:55:36 -0700',
107
                    'request_line' => 'GET /apache_pb.gif HTTP/1.0',
108
                    'request' => [
109
                        'method' => 'GET',
110
                        'path' => '/apache_pb.gif',
111
                        'protocol' => 'HTTP/1.0',
112
                    ],
113
                    'response_code' => '200',
114
                    'bytes_sent' => '2326',
115
                    'request_headers' => [
116
                        'Referer' => 'http://www.example.com/start.html',
117
                        'User-Agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
118
                    ],
119
                ],
120
            ],
121
            [
122
                AccessLogParser::FORMAT_COMBINED,
123
                '127.0.0.1 - - [28/Dec/2013:19:03:49 +0200] "GET /test-page/ HTTP/1.1" ' .
124
                    '200 8359 "-" "Symfony2 BrowserKit"',
125
                [
126
                    'remote_host' => '127.0.0.1',
127
                    'identity' => '-',
128
                    'remote_user' => '-',
129
                    'time' => '28/Dec/2013:19:03:49 +0200',
130
                    'request_line' => 'GET /test-page/ HTTP/1.1',
131
                    'request' => [
132
                        'method' => 'GET',
133
                        'path' => '/test-page/',
134
                        'protocol' => 'HTTP/1.1',
135
                    ],
136
                    'response_code' => '200',
137
                    'bytes_sent' => '8359',
138
                    'request_headers' => [
139
                        'Referer' => '-',
140
                        'User-Agent' => 'Symfony2 BrowserKit',
141
                    ],
142
                ],
143
            ],
144
            [
145
                AccessLogParser::FORMAT_COMBINED,
146
                '66.249.78.230 - - [29/Dec/2013:16:07:58 +0200] "GET /robots.txt HTTP/1.1" ' .
147
                    '200 408 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"',
148
                [
149
                    'remote_host' => '66.249.78.230',
150
                    'identity' => '-',
151
                    'remote_user' => '-',
152
                    'time' => '29/Dec/2013:16:07:58 +0200',
153
                    'request_line' => 'GET /robots.txt HTTP/1.1',
154
                    'request' => [
155
                        'method' => 'GET',
156
                        'path' => '/robots.txt',
157
                        'protocol' => 'HTTP/1.1',
158
                    ],
159
                    'response_code' => '200',
160
                    'bytes_sent' => '408',
161
                    'request_headers' => [
162
                        'Referer' => '-',
163
                        'User-Agent' => 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
164
                    ],
165
                ],
166
            ],
167
            [
168
                AccessLogParser::FORMAT_COMBINED,
169
                '71.82.1.1 - - [29/Dec/2013:17:37:40 +0200] "GET / HTTP/1.1" 200 2577 "http://example.com/test/" ' .
170
                    '"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"',
171
                [
172
                    'remote_host' => '71.82.1.1',
173
                    'identity' => '-',
174
                    'remote_user' => '-',
175
                    'time' => '29/Dec/2013:17:37:40 +0200',
176
                    'request_line' => 'GET / HTTP/1.1',
177
                    'request' => [
178
                        'method' => 'GET',
179
                        'path' => '/',
180
                        'protocol' => 'HTTP/1.1',
181
                    ],
182
                    'response_code' => '200',
183
                    'bytes_sent' => '2577',
184
                    'request_headers' => [
185
                        'Referer' => 'http://example.com/test/',
186
                        'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
187
                    ],
188
                ],
189
            ],
190
            [
191
                AccessLogParser::FORMAT_COMBINED,
192
                // HTTP error 408 "Request Timeout"
193
                '192.168.25.1 - - [25/Jun/2012:14:00:14 -0700] "-" 408 0 "-" "-"',
194
                [
195
                    'remote_host' => '192.168.25.1',
196
                    'identity' => '-',
197
                    'remote_user' => '-',
198
                    'time' => '25/Jun/2012:14:00:14 -0700',
199
                    'request_line' => '-',
200
                    'response_code' => '408',
201
                    'request_headers' => [
202
                        'Referer' => '-',
203
                        'User-Agent' => '-',
204
                    ],
205
                ]
206
            ],
207
            [
208
                AccessLogParser::FORMAT_COMBINED,
209
                // HTTP error 414 "Request URI too long"
210
                '192.168.139.1 - - [10/Oct/2013:00:26:32 +0300] "GET /' . str_repeat('a', 7995) . '" 414 540 "-" "-"',
211
                [
212
                    'remote_host' => '192.168.139.1',
213
                    'identity' => '-',
214
                    'remote_user' => '-',
215
                    'time' => '10/Oct/2013:00:26:32 +0300',
216
                    'request_line' => 'GET /' . str_repeat('a', 7995),
217
                    'request' => [
218
                        'method' => 'GET',
219
                        'path' => '/' . str_repeat('a', 7995),
220
                    ],
221
                    'response_code' => '414',
222
                    'bytes_sent' => '540',
223
                    'request_headers' => [
224
                        'Referer' => '-',
225
                        'User-Agent' => '-',
226
                    ],
227
                ]
228
            ],
229
            [
230
                AccessLogParser::FORMAT_COMBINED,
231
                // When no bytes were sent
232
                '74.86.158.106 - - [09/Jan/2014:04:11:40 -0800] "HEAD / HTTP/1.1" 200 - "-" ' .
233
                    '"Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)"',
234
                [
235
                    'remote_host' => '74.86.158.106',
236
                    'identity' => '-',
237
                    'remote_user' => '-',
238
                    'time' => '09/Jan/2014:04:11:40 -0800',
239
                    'request_line' => 'HEAD / HTTP/1.1',
240
                    'request' => [
241
                        'method' => 'HEAD',
242
                        'path' => '/',
243
                        'protocol' => 'HTTP/1.1',
244
                    ],
245
                    'response_code' => '200',
246
                    'bytes_sent' => '-',
247
                    'request_headers' => [
248
                        'Referer' => '-',
249
                        'User-Agent' => 'Mozilla/5.0+(compatible; UptimeRobot/2.0; http://www.uptimerobot.com/)',
250
                    ],
251
                ],
252
            ],
253
            [
254
                AccessLogParser::FORMAT_COMBINED,
255
                '12.34.56.78 - - [06/Feb/2014:02:00:18 -0800] "GET / HTTP/1.1" 200 2151 "" "-"',
256
                [
257
                    'remote_host' => '12.34.56.78',
258
                    'identity' => '-',
259
                    'remote_user' => '-',
260
                    'time' => '06/Feb/2014:02:00:18 -0800',
261
                    'request_line' => 'GET / HTTP/1.1',
262
                    'request' => [
263
                        'method' => 'GET',
264
                        'path' => '/',
265
                        'protocol' => 'HTTP/1.1',
266
                    ],
267
                    'response_code' => '200',
268
                    'bytes_sent' => '2151',
269
                    'request_headers' => [
270
                        'User-Agent' => '-',
271
                    ],
272
                ],
273
            ],
274
            [
275
                AccessLogParser::FORMAT_COMBINED,
276
                '12.34.56.78 - - [20/May/2014:17:21:57 -0700] "GET /test/ HTTP/1.1" 200 1680 ' .
277
                    '"http://search.yahoo.com/search?p=what color" "Mozilla/5.0"',
278
                [
279
                    'remote_host' => '12.34.56.78',
280
                    'identity' => '-',
281
                    'remote_user' => '-',
282
                    'time' => '20/May/2014:17:21:57 -0700',
283
                    'request_line' => 'GET /test/ HTTP/1.1',
284
                    'request' => [
285
                        'method' => 'GET',
286
                        'path' => '/test/',
287
                        'protocol' => 'HTTP/1.1',
288
                    ],
289
                    'response_code' => '200',
290
                    'bytes_sent' => '1680',
291
                    'request_headers' => [
292
                        'User-Agent' => 'Mozilla/5.0',
293
                        'Referer' => 'http://search.yahoo.com/search?p=what color',
294
                    ],
295
                ],
296
            ],
297
            [
298
                AccessLogParser::FORMAT_VHOST_COMBINED,
299
                '127.0.1.1:80 127.0.0.1 - - [26/Jun/2012:10:41:10 -0700] "OPTIONS * HTTP/1.0" 200 126 "-" ' .
300
                    '"Apache/2.2.22 (Ubuntu) (internal dummy connection)"',
301
                [
302
                    'canonical_server_name' => '127.0.1.1',
303
                    'server_port' => '80',
304
                    'remote_host' => '127.0.0.1',
305
                    'identity' => '-',
306
                    'remote_user' => '-',
307
                    'time' => '26/Jun/2012:10:41:10 -0700',
308
                    'request_line' => 'OPTIONS * HTTP/1.0',
309
                    'request' => [
310
                        'method' => 'OPTIONS',
311
                        'path' => '*',
312
                        'protocol' => 'HTTP/1.0',
313
                    ],
314
                    'response_code' => '200',
315
                    'bytes_sent' => '126',
316
                    'request_headers' => [
317
                        'Referer' => '-',
318
                        'User-Agent' => 'Apache/2.2.22 (Ubuntu) (internal dummy connection)',
319
                    ],
320
                ],
321
            ],
322
            [
323
                // Test for percent sign
324
                '%% test',
325
                '% test',
326
                [],
327
            ],
328
            [
329
                // Test for full port support
330
                '%{canonical}p %{local}p %{remote}p test',
331
                '123 456 789 test',
332
                [
333
                    'canonical_port' => 123,
334
                    'local_port' => 456,
335
                    'remote_port' => 789,
336
                ],
337
            ],
338
            [
339
                // Test for status code of the original request
340
                '%s',
341
                '201',
342
                [
343
                    'original_status_code' => 201,
344
                ],
345
            ],
346
            [
347
                // Test for Size of response in bytes, excluding HTTP headers. In CLF format
348
                '%b',
349
                '-',
350
                [
351
                    'response_body_size' => 0,
352
                ],
353
            ],
354
            [
355
                // Test for predefined User-Agent format
356
                AccessLogParser::FORMAT_AGENT,
357
                'Symfony2 BrowserKit',
358
                [
359
                    'request_headers' => [
360
                        'User-Agent' => 'Symfony2 BrowserKit',
361
                    ],
362
                ],
363
            ],
364
            [
365
                // Test for request method
366
                '%m',
367
                'POST',
368
                [
369
                    'request_method' => 'POST',
370
                ],
371
            ],
372
            [
373
                // Test for request serve time
374
                '%D %T',
375
                '123 456',
376
                [
377
                    'request_time_us' => '123',
378
                    'request_time_s' => '456',
379
                ],
380
            ],
381
            [
382
                // Test for URL path
383
                '%U',
384
                '/path',
385
                [
386
                    'request_path' => '/path',
387
                ],
388
            ],
389
            [
390
                // Test for URL path and query string
391
                '%U%q',
392
                '/path?googleguy=googley',
393
                [
394
                    'request_path' => '/path',
395
                    'query_string' => '?googleguy=googley',
396
                ],
397
            ],
398
            [
399
                // Test for bytes received and transferred
400
                '%I %S',
401
                '123 456',
402
                [
403
                    'bytes_received' => '123',
404
                    'bytes_transferred' => '456',
405
                ],
406
            ],
407
            [
408
                // Test for predefined referer log format
409
                AccessLogParser::FORMAT_REFERER,
410
                'http://www.example.com/ -> /my-page/',
411
                [
412
                    'request_headers' => [
413
                        'Referer' => 'http://www.example.com/',
414
                    ],
415
                    'request_path' => '/my-page/',
416
                ],
417
            ],
418
            [
419
                // Test for request protocol
420
                '%H',
421
                'HTTP/1.0',
422
                [
423
                    'request_protocol' => 'HTTP/1.0',
424
                ],
425
            ],
426
            [
427
                // Test for local IP address
428
                '%A',
429
                '192.168.5.128',
430
                [
431
                    'local_ip' => '192.168.5.128',
432
                ],
433
            ],
434
            [
435
                // Test for client IP address
436
                '%a',
437
                '192.168.5.1',
438
                [
439
                    'client_ip' => '192.168.5.1',
440
                ],
441
            ],
442
            [
443
                // Test for real client IP address (e.g. when proxy is used)
444
                '%{c}a',
445
                '192.168.5.55',
446
                [
447
                    'peer_ip' => '192.168.5.55',
448
                ],
449
            ],
450
            [
451
                // Test for cookies
452
                '"%{cookie1}C" "%{cookie_2}C"',
453
                '"cookie1 contents" "cookie_2 contents"',
454
                [
455
                    'cookies' => [
456
                        'cookie1' => 'cookie1 contents',
457
                        'cookie_2' => 'cookie_2 contents',
458
                    ],
459
                ],
460
            ],
461
            [
462
                // Test for filename
463
                '"%f"',
464
                '"/home/user/public_html/favicon.ico"',
465
                [
466
                    'filename' => '/home/user/public_html/favicon.ico',
467
                ],
468
            ],
469
            [
470
                // Test for connection status
471
                '%X',
472
                '+',
473
                [
474
                    'connection_status' => '+',
475
                ],
476
            ],
477
            [
478
                // Test for environment variables
479
                '"%{CUSTOM_VARIABLE}e"',
480
                '"custom variable contents"',
481
                [
482
                    'env_vars' => [
483
                        'CUSTOM_VARIABLE' => 'custom variable contents',
484
                    ],
485
                ],
486
            ],
487
            [
488
                // Test for response headers
489
                '%{Content-Length}o',
490
                '1553',
491
                [
492
                    'response_headers' => [
493
                        'Content-Length' => '1553',
494
                    ],
495
                ],
496
            ],
497
            [
498
                // Test for response headers
499
                '%{Content-Length}o "%{Content-Encoding}o"',
500
                '1553 "gzip"',
501
                [
502
                    'response_headers' => [
503
                        'Content-Length' => '1553',
504
                        'Content-Encoding' => 'gzip',
505
                    ],
506
                ],
507
            ],
508
            [
509
                // Test for module notes
510
                '%{outstream}n/%{instream}n (%{ratio}n%%)',
511
                '512/1024 (50%)',
512
                [
513
                    'mod_vars' => [
514
                        'outstream' => '512',
515
                        'instream' => '1024',
516
                        'ratio' => '50',
517
                    ],
518
                ],
519
            ],
520
            [
521
                // Test for the server name
522
                '%V',
523
                'www.domain.tld',
524
                [
525
                    'server_name' => 'www.domain.tld',
526
                ],
527
            ],
528
            [
529
                // Test for number of keep-alive requests handled on this connection
530
                '%k',
531
                '2',
532
                [
533
                    'keepalive_requests' => '2',
534
                ],
535
            ],
536
            [
537
                // Test for process and thread ID
538
                '%P %{pid}P %{tid}P %{hextid}P',
539
                '229 12 34 56',
540
                [
541
                    'process_id' => '229',
542
                    'pid' => '12',
543
                    'tid' => '34',
544
                    'hextid' => '56',
545
                ],
546
            ],
547
            [
548
                // Test for the request log ID
549
                '%L',
550
                '55',
551
                [
552
                    'log_id' => '55',
553
                ],
554
            ],
555
            [
556
                // Test for the handler generating the response
557
                '%R',
558
                'application/x-httpd-php',
559
                [
560
                    'response_handler' => 'application/x-httpd-php',
561
                ],
562
            ],
563
            // Check if format string quoting works correctly
564
            ['%z/%z', '%z/%z', []],
565
            ['{%{test}z}', '{%{test}z}', []],
566
            ['{%{test}z}*', '{%{test}z}*', []],
567
            ['{%{test}z}/%z', '{%{test}z}/%z', []],
568
            ['{%{test}z}/%z-%>z', '{%{test}z}/%z-%>z', []],
569
            ['{%{test}z}/%z-(%>z)', '{%{test}z}/%z-(%>z)', []],
570
            // Also do not quote directives with modifiers
571
            ['%>{test}z', '%>{test}z', []],
572
            ['%<{test}z', '%<{test}z', []],
573
            ['%200{test}z', '%200{test}z', []],
574
            ['%!200{test}z', '%!200{test}z', []],
575
            ['%200,201{test}z', '%200,201{test}z', []],
576
            ['%!200,201{test}z', '%!200,201{test}z', []],
577
        ];
578
    }
579
580
    /**
581
     * Data provider for testParseLineNoMatches().
582
     *
583
     * @return array[]
584
     */
585
    public function getTestParseLineNoMatchesData()
586
    {
587
        return [
588
            ['%b', 'abc'],
589
            ['%B', '-'],
590
        ];
591
    }
592
}
593