IncidentsTableTest   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 569
Duplicated Lines 0 %

Importance

Changes 11
Bugs 0 Features 1
Metric Value
eloc 312
dl 0
loc 569
rs 10
c 11
b 0
f 1
wmc 15

11 Methods

Rating   Name   Duplication   Size   Complexity  
A testGetClosestReport() 0 16 1
A testGetStackHash() 0 32 1
A testGetReportDetails() 0 46 1
A testGetSimpleVersion() 0 39 1
B testGetSchematizedIncident() 0 97 1
A setUp() 0 4 1
A testGetServer() 0 28 1
A testGetIdentifyingLocation() 0 76 1
A testStripversion() 0 3 1
B testCreateIncidentFromBugReport() 0 107 5
A versionsStripping() 0 82 1
1
<?php
2
3
namespace App\Test\TestCase\Model\Table;
4
5
use App\Model\Table\IncidentsTable;
6
use Cake\ORM\TableRegistry;
7
use Cake\TestSuite\TestCase;
8
use ReflectionMethod;
9
10
use function count;
11
use function file_get_contents;
12
use function json_decode;
13
use function json_encode;
14
15
use const DS;
16
17
class IncidentsTableTest extends TestCase
18
{
19
    /**
20
     * Fixtures.
21
     *
22
     * @var array
23
     */
24
    public $fixtures = [
25
        'app.Notifications',
26
        'app.Developers',
27
        'app.Reports',
28
        'app.Incidents',
29
    ];
30
31
    public function setUp(): void
32
    {
33
        parent::setUp();
34
        $this->Incidents = TableRegistry::getTableLocator()->get('Incidents');
35
    }
36
37
    public function testGetStackHash(): void
38
    {
39
        //$method = new ReflectionMethod('Incident', 'getStackHash');
40
        //$method->setAccessible(true);
41
42
        $stacktrace1 = [
43
            [
44
                'filename' => 'file1',
45
                'line' => 300,
46
            ],
47
            [
48
                'filename' => 'file2',
49
                'line' => 200,
50
            ],
51
        ];
52
53
        $stacktrace2 = [
54
            [
55
                'line' => 300,
56
                'filename' => 'file1',
57
            ],
58
            [
59
                'line' => 200,
60
                'filename' => 'file2',
61
            ],
62
        ];
63
64
        $result = $this->Incidents->getStackHash($stacktrace1);
65
        $this->assertEquals('a441639902837d88db25214812c0cd83', $result);
66
67
        $result = $this->Incidents->getStackHash($stacktrace2);
68
        $this->assertEquals('a441639902837d88db25214812c0cd83', $result);
69
    }
70
71
    public function testGetServer(): void
72
    {
73
        $method = new ReflectionMethod($this->Incidents, 'getServer');
74
        $method->setAccessible(true);
75
76
        $result = $method->invoke(
77
            $this->Incidents,
78
            'some random/data Apache/2.1.7;other.random/data'
79
        );
80
        $this->assertEquals('Apache/2.1', $result);
81
82
        $result = $method->invoke(
83
            $this->Incidents,
84
            'some random/data Nginx/1.0.7;other.random/data'
85
        );
86
        $this->assertEquals('Nginx/1.0', $result);
87
88
        $result = $method->invoke(
89
            $this->Incidents,
90
            'some random/data Lighttpd/4.6.7;other.random/data'
91
        );
92
        $this->assertEquals('Lighttpd/4.6', $result);
93
94
        $result = $method->invoke(
95
            $this->Incidents,
96
            'some random/data DoesNotExist/3.5;other.random/data'
97
        );
98
        $this->assertEquals('UNKNOWN', $result);
99
    }
100
101
    public function testGetSimpleVersion(): void
102
    {
103
        $method = new ReflectionMethod($this->Incidents, 'getSimpleVersion');
104
        $method->setAccessible(true);
105
106
        $result = $method->invoke(
107
            $this->Incidents,
108
            '15.3.12.17',
109
            1
110
        );
111
        $this->assertEquals('15', $result);
112
113
        $result = $method->invoke(
114
            $this->Incidents,
115
            '15.3.12.17',
116
            2
117
        );
118
        $this->assertEquals('15.3', $result);
119
120
        $result = $method->invoke(
121
            $this->Incidents,
122
            '15.3.12.17',
123
            3
124
        );
125
        $this->assertEquals('15.3.12', $result);
126
127
        $result = $method->invoke(
128
            $this->Incidents,
129
            '15.3.12.17',
130
            'wrong argument'
131
        );
132
        $this->assertEquals('15', $result);
133
134
        $result = $method->invoke(
135
            $this->Incidents,
136
            '15.3.12.17',
137
            -1
138
        );
139
        $this->assertEquals('15', $result);
140
    }
141
142
    public function testGetIdentifyingLocation(): void
143
    {
144
        $method = new ReflectionMethod($this->Incidents, 'getIdentifyingLocation');
145
        $method->setAccessible(true);
146
147
        $stacktrace = [
148
            [
149
                'filename' => 'file1',
150
                'line' => 300,
151
            ],
152
            [
153
                'filename' => 'file2',
154
                'line' => 200,
155
            ],
156
        ];
157
158
        $stacktrace_script = [
159
            [
160
                'scriptname' => 'script1',
161
                'line' => 300,
162
            ],
163
            [
164
                'filename' => 'file2',
165
                'line' => 200,
166
            ],
167
        ];
168
169
        $stacktrace_uri = [
170
            [
171
                'uri' => 'sql.php',
172
                'line' => 5,
173
            ],
174
            [
175
                'filename' => 'file2',
176
                'line' => 200,
177
            ],
178
        ];
179
180
        $result = $method->invoke(
181
            $this->Incidents,
182
            $stacktrace_script
183
        );
184
        $this->assertEquals(['script1', 300], $result);
185
186
        $result = $method->invoke(
187
            $this->Incidents,
188
            $stacktrace
189
        );
190
        $this->assertEquals(['file1', 300], $result);
191
192
        $stacktrace[0]['filename'] = 'tracekit/tracekit.js';
193
        $result = $method->invoke(
194
            $this->Incidents,
195
            $stacktrace
196
        );
197
        $this->assertEquals(['file2', 200], $result);
198
199
        $stacktrace[0]['filename'] = 'error_report.js';
200
        $result = $method->invoke(
201
            $this->Incidents,
202
            $stacktrace
203
        );
204
        $this->assertEquals(['file2', 200], $result);
205
206
        $stacktrace[1] = null;
207
        $result = $method->invoke(
208
            $this->Incidents,
209
            $stacktrace
210
        );
211
        $this->assertEquals(['error_report.js', 300], $result);
212
213
        $result = $method->invoke(
214
            $this->Incidents,
215
            $stacktrace_uri
216
        );
217
        $this->assertEquals(['file2', 200], $result);
218
    }
219
220
    public function testGetSchematizedIncident(): void
221
    {
222
        $method = new ReflectionMethod($this->Incidents, 'getSchematizedIncidents');
223
        $method->setAccessible(true);
224
225
        // Case-1: JavaScript Report
226
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
227
        $bugReport = json_decode($bugReport, true);
228
229
        $result = $method->invoke(
230
            $this->Incidents,
231
            $bugReport
232
        );
233
234
        $expected = [
235
            [
236
                'pma_version' => '4.5.4.1',
237
                'php_version' => '5.2',
238
                'steps' => '<script>test steps',
239
                'error_message' => 'a is not defined',
240
                'error_name' => 'ReferenceError',
241
                'browser' => 'FIREFOX 17',
242
                'user_os' => 'Windows',
243
                'locale' => 'en',
244
                'script_name' => 'tbl_relation.php',
245
                'configuration_storage' => 'enabled',
246
                'server_software' => 'NginX/1.17',
247
                'stackhash' => '9db5408094f1e76ef7161b7bbf3ddfe4',
248
                'full_report' => json_encode($bugReport),
249
                'stacktrace' => json_encode($bugReport['exception']['stack']),
250
                'exception_type' => 0,
251
            ],
252
        ];
253
254
        $this->assertEquals($expected, $result);
255
256
        // Case-2: php Report
257
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_php.json');
258
        $bugReport = json_decode($bugReport, true);
259
260
        $result = $method->invoke(
261
            $this->Incidents,
262
            $bugReport
263
        );
264
265
        $expected = [
266
            [
267
                'pma_version' => '4.5.4.1',
268
                'php_version' => '5.5',
269
                'error_message' => 'Undefined variable: haha',
270
                'error_name' => 'Notice',
271
                'browser' => 'CHROME 27',
272
                'user_os' => 'Linux',
273
                'locale' => 'en',
274
                'script_name' => './libraries/Config.class.php',
275
                'configuration_storage' => 'disabled',
276
                'server_software' => 'Apache/2.4',
277
                'stackhash' => '5063bbe81a2daa6a6ad39c5cd315701c',
278
                'full_report' => json_encode($bugReport),
279
                'stacktrace' => json_encode($bugReport['errors'][0]['stackTrace']),
280
                'exception_type' => 1,
281
            ],
282
            [
283
                'pma_version' => '4.5.4.1',
284
                'php_version' => '5.5',
285
                'error_message' => 'Undefined variable: hihi',
286
                'error_name' => 'Notice',
287
                'browser' => 'CHROME 27',
288
                'user_os' => 'Linux',
289
                'locale' => 'en',
290
                'script_name' => './libraries/Util.class.php',
291
                'configuration_storage' => 'disabled',
292
                'server_software' => 'Apache/2.4',
293
                'stackhash' => 'e911a21765eae766463612e033773716',
294
                'full_report' => json_encode($bugReport),
295
                'stacktrace' => json_encode($bugReport['errors'][1]['stackTrace']),
296
                'exception_type' => 1,
297
            ],
298
            [
299
                'pma_version' => '4.5.4.1',
300
                'php_version' => '5.5',
301
                'error_message' => 'Undefined variable: hehe',
302
                'error_name' => 'Notice',
303
                'browser' => 'CHROME 27',
304
                'user_os' => 'Linux',
305
                'locale' => 'en',
306
                'script_name' => './index.php',
307
                'configuration_storage' => 'disabled',
308
                'server_software' => 'Apache/2.4',
309
                'stackhash' => '37848b23bdd6e737273516b9575fe407',
310
                'full_report' => json_encode($bugReport),
311
                'stacktrace' => json_encode($bugReport['errors'][2]['stackTrace']),
312
                'exception_type' => 1,
313
            ],
314
        ];
315
316
        $this->assertEquals($expected, $result);
317
    }
318
319
    public function testGetReportDetails(): void
320
    {
321
        $method = new ReflectionMethod($this->Incidents, 'getReportDetails');
322
        $method->setAccessible(true);
323
324
        // case-1: JavaScript BugReport
325
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
326
        $bugReport = json_decode($bugReport, true);
327
328
        $result = $method->invoke(
329
            $this->Incidents,
330
            $bugReport
331
        );
332
333
        $expected = [
334
            'error_message' => 'a is not defined',
335
            'error_name' => 'ReferenceError',
336
            'status' => 'new',
337
            'location' => 'error.js',
338
            'linenumber' => (int) 312,
339
            'pma_version' => '4.5.4.1',
340
            'exception_type' => 0,
341
        ];
342
343
        $this->assertEquals($expected, $result);
344
345
        // case-2: php BugReport
346
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_php.json');
347
        $bugReport = json_decode($bugReport, true);
348
349
        $result = $method->invoke(
350
            $this->Incidents,
351
            $bugReport,
352
            1
353
        );
354
355
        $expected = [
356
            'error_message' => 'Undefined variable: hihi',
357
            'error_name' => 'Notice',
358
            'status' => 'new',
359
            'location' => './libraries/Util.class.php',
360
            'linenumber' => (int) 557,
361
            'pma_version' => '4.5.4.1',
362
            'exception_type' => 1,
363
        ];
364
        $this->assertEquals($expected, $result);
365
    }
366
367
    public function testGetClosestReport(): void
368
    {
369
        $method = new ReflectionMethod($this->Incidents, 'getClosestReport');
370
        $method->setAccessible(true);
371
372
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
373
        $bugReport = json_decode($bugReport, true);
374
375
        $returnedReport = null;
376
377
        $result = $method->invoke(
378
            $this->Incidents,
379
            $bugReport
380
        );
381
382
        $this->assertEquals($returnedReport, $result);
383
    }
384
385
    public function testCreateIncidentFromBugReport(): void
386
    {
387
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
388
        $bugReport = json_decode($bugReport, true);
389
390
        // Case-1: 'js' report
391
392
        // Case-1.1: closest report = null
393
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
394
        $this->assertEquals(1, count($result['incidents']));
395
396
        // One new report added (no closest report found)
397
        $this->assertEquals(1, count($result['reports']));
398
399
        // Case-1.2: closest report = some report.
400
        // Previously(in Case-1.1) inserted Reports serve as ClosestReports.
401
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
402
        $this->assertEquals(1, count($result['incidents']));
403
404
        // No new report added (closest report found)
405
        $this->assertEquals(0, count($result['reports']));
406
407
        $incident = $this->Incidents->get($result['incidents'][0]);
408
        // check the incident has been reported under the same 'Report'
409
        $result = TableRegistry::getTableLocator()->get('Incidents')->find('all', ['conditions' => ['report_id = ' . $incident->report_id]]);
410
        $result = $result->enableHydration(false)->toArray();
411
        $this->assertEquals(2, count($result));
412
413
        // Case-2: for 'php' reports
414
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_php.json');
415
        $bugReport = json_decode($bugReport, true);
416
        // Case-2.1: closest report = null.
417
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
418
        $this->assertEquals(3, count($result['incidents']));
419
420
        // Three (one for each incident) new report added (no closest report found)
421
        $this->assertEquals(3, count($result['reports']));
422
423
        // Case-2.2: closest report = some report.
424
        // Previously(in Case-2.1) inserted Reports serve as ClosestReports.
425
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
426
        $this->assertEquals(3, count($result['incidents']));
427
428
        // No new report added (closest report found)
429
        $this->assertEquals(0, count($result['reports']));
430
431
        // check the incidents have been reported under the same 'Report's
432
        $incident = $this->Incidents->get($result['incidents'][0]);
433
        $result = TableRegistry::getTableLocator()->get('Incidents')->find('all', ['conditions' => ['report_id = ' . $incident->report_id]]);
434
        $result = $result->enableHydration(false)->toArray();
435
        $this->assertEquals(2, count($result));
436
437
        // Case 3.1: Long PHP report submission
438
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_php.json');
439
        $bugReport = json_decode($bugReport, true);
440
441
        // Forcefully inflate the report by inflating $bugReport['errors']
442
        for ($i = 0; $i < 2000; $i++) {
443
            $bugReport['errors'][] = $bugReport['errors'][0];
444
        }
445
446
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
447
        $this->assertEquals(40, count($result['incidents']));
448
        // No new report added (closest report found)
449
        $this->assertEquals(0, count($result['reports']));
450
451
        // Case 3.2: Long JS report submission
452
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
453
        $bugReport = json_decode($bugReport, true);
454
455
        // Forcefully inflate the report by inflating $bugReport['exception']['stack']
456
        for ($i = 0; $i < 1500; $i++) {
457
            $bugReport['exception']['stack'][] = $bugReport['exception']['stack'][0];
458
        }
459
460
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
461
        $this->assertEquals(1, count($result['incidents']));
462
        // No new report added (closest report found)
463
        $this->assertEquals(0, count($result['reports']));
464
465
        // Case 3.3: Long error_message in PHP report submission
466
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_php.json');
467
        $bugReport = json_decode($bugReport, true);
468
469
        // Forcefully inflate error message
470
        for ($i = 0; $i < 6; $i++) {
471
            $bugReport['errors'][0]['msg'] .= $bugReport['errors'][0]['msg'];
472
        }
473
474
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
475
        $this->assertEquals(3, count($result['incidents']));
476
        // No new report added (closest report found)
477
        $this->assertEquals(0, count($result['reports']));
478
479
        // Case 3.4: Long error_message in JS report submission
480
        $bugReport = file_get_contents(TESTS . 'Fixture' . DS . 'report_js.json');
481
        $bugReport = json_decode($bugReport, true);
482
483
        // Forcefully inflate error message
484
        for ($i = 0; $i < 8; $i++) {
485
            $bugReport['exception']['message'] .= $bugReport['exception']['message'];
486
        }
487
488
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
489
        $this->assertEquals(1, count($result['incidents']));
490
        // No new report added (closest report found)
491
        $this->assertEquals(0, count($result['reports']));
492
    }
493
494
    /**
495
     * @dataProvider versionsStripping
496
     * @param string $version  The version
497
     * @param string $expected The expected version
498
     */
499
    public function testStripversion(string $version, string $expected): void
500
    {
501
        $this->assertEquals($expected, IncidentsTable::getStrippedPmaVersion($version));
502
    }
503
504
    public function versionsStripping(): array
505
    {
506
        return [
507
            [
508
                '1.2.3',
509
                '1.2.3',
510
            ],
511
            [
512
                '1.2.3-rc1',
513
                '1.2.3-rc1',
514
            ],
515
            [
516
                '4.1-dev',
517
                '4.1-dev',
518
            ],
519
            [
520
                '4.1.6deb0ubuntu1ppa1',
521
                '4.1.6',
522
            ],
523
            [
524
                '4.2.3deb1.trusty~ppa.1',
525
                '4.2.3',
526
            ],
527
            [
528
                '4.2.9deb0.1',
529
                '4.2.9',
530
            ],
531
            [
532
                '4.5.4.1deb2ubuntu2',
533
                '4.5.4.1',
534
            ],
535
            [
536
                '4.5.4+deb2ubuntu2',
537
                '4.5.4',
538
            ],
539
            [
540
                '5.1.1-dev+20210325.2ece069cf6',
541
                '5.1.1-dev',
542
            ],
543
            [
544
                '5.1.1+20210325.2ece069cf6',
545
                '5.1.1',
546
            ],
547
            [
548
                '5.1.1+ubuntu1',
549
                '5.1.1',
550
            ],
551
            [
552
                '5.1.1-dev+ubuntu1',// Impossible in theory
553
                '5.1.1-dev',
554
            ],
555
            [
556
                '5.1.1-rc1+ubuntu1',
557
                '5.1.1-rc1',
558
            ],
559
            [
560
                '5.1.1-rc2-deb2',
561
                '5.1.1-rc2',
562
            ],
563
            [
564
                'zpzefz5.1.1efe',
565
                'zpzefz5.1.1efe',
566
            ],
567
            [
568
                'beta5.1foo',
569
                'beta5.1foo',
570
            ],
571
            [
572
                '4.9.0.1',
573
                '4.9.0.1',
574
            ],
575
            [
576
                '4.9.0.1deb1',
577
                '4.9.0.1',
578
            ],
579
            [// https://bugzilla.redhat.com/show_bug.cgi?id=1932174#c7
580
                '5.1.0-3.el7.remi',
581
                '5.1.0',
582
            ],
583
            [// https://bugzilla.redhat.com/show_bug.cgi?id=1932174#c7
584
                '5.1.0-3.fc34',
585
                '5.1.0',
586
            ],
587
        ];
588
    }
589
}
590