FlattenExceptionTest   A
last analyzed

Complexity

Total Complexity 18

Size/Duplication

Total Lines 184
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 101
dl 0
loc 184
rs 10
c 0
b 0
f 0
wmc 18

14 Methods

Rating   Name   Duplication   Size   Complexity  
A testMessage() 0 4 1
A testTooBigArray() 0 25 4
A testPrevious() 0 9 1
A createException() 0 3 1
A testRecursionInArguments() 0 11 1
A testTraceAsString() 0 4 1
A testClass() 0 3 1
A testArguments() 0 63 2
A testTrace() 0 10 1
A testToString() 0 6 1
A testFile() 0 4 1
A testLine() 0 4 1
A testCode() 0 4 1
A testClosureSerialize() 0 6 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Debug\Tests\Unit;
6
7
use Closure;
8
use Exception;
9
use PHPUnit\Framework\TestCase;
10
use RuntimeException;
11
use Yiisoft\Yii\Debug\FlattenException;
12
13
final class FlattenExceptionTest extends TestCase
14
{
15
    public function testMessage(): void
16
    {
17
        $flattened = new FlattenException(new Exception('test'));
18
        $this->assertEquals('test', $flattened->getMessage());
19
    }
20
21
    public function testCode(): void
22
    {
23
        $flattened = new FlattenException(new Exception('test', 100));
24
        $this->assertEquals(100, $flattened->getCode());
25
    }
26
27
    public function testFile(): void
28
    {
29
        $flattened = new FlattenException(new Exception('test', 100));
30
        $this->assertEquals(__FILE__, $flattened->getFile());
31
    }
32
33
    public function testLine(): void
34
    {
35
        $flattened = new FlattenException(new Exception('test', 100));
36
        $this->assertEquals(__LINE__ - 1, $flattened->getLine());
37
    }
38
39
    public function testTrace(): void
40
    {
41
        $i = (new Exception('test'));
42
        $flattened = new FlattenException($i);
43
44
        $trace = $flattened->getTrace();
45
        $this->assertEquals(__NAMESPACE__, $trace[0]['namespace']);
46
        $this->assertEquals(self::class, $trace[0]['class']);
47
        $this->assertEquals('FlattenExceptionTest', $trace[0]['short_class']);
48
        $this->assertEquals(__FUNCTION__, $trace[0]['function']);
49
    }
50
51
    public function testPrevious(): void
52
    {
53
        $exception2 = new Exception();
54
        $exception = new Exception('test', 0, $exception2);
55
56
        $flattened = new FlattenException($exception);
57
        $flattened2 = new FlattenException($exception2);
58
59
        $this->assertSame($flattened2->getTrace(), $flattened->getPrevious()->getTrace());
60
    }
61
62
    public function testTraceAsString(): void
63
    {
64
        $exception = $this->createException('test');
65
        $this->assertEquals($exception->getTraceAsString(), (new FlattenException($exception))->getTraceAsString());
66
    }
67
68
    public function testToString(): void
69
    {
70
        $exception = new Exception();
71
        $this->assertEquals($exception->__toString(), (new FlattenException($exception))->__toString(), 'empty');
72
        $exception = new Exception('test');
73
        $this->assertEquals($exception->__toString(), (new FlattenException($exception))->__toString());
74
    }
75
76
    public function testClass(): void
77
    {
78
        $this->assertEquals('Exception', (new FlattenException(new Exception()))->getClass());
79
    }
80
81
    public function testArguments(): void
82
    {
83
        $this->markTestSkipped('Should be fixed');
84
85
        $dh = opendir(__DIR__);
86
        $fh = tmpfile();
87
88
        $incomplete = unserialize('O:14:"BogusTestClass":0:{}');
89
90
        $exception = $this->createException([
91
            (object)['foo' => 1],
92
            new RuntimeException('test'),
93
            $incomplete,
94
            $dh,
95
            $fh,
96
            function () {
97
            },
98
            [1, 2],
99
            ['foo' => 123],
100
            null,
101
            true,
102
            false,
103
            0,
104
            0.0,
105
            '0',
106
            '',
107
            INF,
108
            NAN,
109
        ]);
110
111
        $flattened = new FlattenException($exception);
112
        $trace = $flattened->getTrace();
113
        $args = $trace[0]['args'];
114
        $array = $args[0][1];
115
116
        closedir($dh);
117
        fclose($fh);
118
119
        $i = 0;
120
        $this->assertSame(['object', 'stdClass'], $array[$i++]);
121
        $this->assertSame(['object', RuntimeException::class], $array[$i++]);
122
        $this->assertSame(['incomplete-object', 'BogusTestClass'], $array[$i++]);
123
        $this->assertSame(['resource', 'stream'], $array[$i++]);
124
        $this->assertSame(['resource', 'stream'], $array[$i++]);
125
126
        $args = $array[$i++];
127
        $this->assertSame($args[0], 'object');
128
        $this->assertTrue(Closure::class === $args[1] || is_subclass_of($args[1], '\\' . Closure::class), 'Expect object class name to be Closure or a subclass of Closure.');
129
130
        $this->assertSame(['array', [['integer', 1], ['integer', 2]]], $array[$i++]);
131
        $this->assertSame(['array', ['foo' => ['integer', 123]]], $array[$i++]);
132
        $this->assertSame(['null', null], $array[$i++]);
133
        $this->assertSame(['boolean', true], $array[$i++]);
134
        $this->assertSame(['boolean', false], $array[$i++]);
135
        $this->assertSame(['integer', 0], $array[$i++]);
136
        $this->assertSame(['float', 0.0], $array[$i++]);
137
        $this->assertSame(['string', '0'], $array[$i++]);
138
        $this->assertSame(['string', ''], $array[$i++]);
139
        $this->assertSame(['float', INF], $array[$i++]);
140
141
        // assertEquals() does not like NAN values.
142
        $this->assertEquals('float', $array[$i][0]);
143
        $this->assertNan($array[$i++][1]);
144
    }
145
146
    public function testClosureSerialize(): void
147
    {
148
        $exception = $this->createException(fn () => 1 + 1);
149
150
        $flattened = new FlattenException($exception);
151
        $this->assertStringContainsString(Closure::class, serialize($flattened));
152
    }
153
154
    public function testRecursionInArguments(): void
155
    {
156
        $this->markTestSkipped('Should be fixed');
157
158
        $a = ['foo'];
159
        $a[] = [2, &$a];
160
        $exception = $this->createException($a);
161
162
        $flattened = new FlattenException($exception);
163
        $trace = $flattened->getTrace();
164
        $this->assertStringContainsString('*DEEP NESTED ARRAY*', serialize($trace));
165
    }
166
167
    public function testTooBigArray(): void
168
    {
169
        $this->markTestSkipped('Should be fixed');
170
171
        $a = [];
172
        for ($i = 0; $i < 20; ++$i) {
173
            for ($j = 0; $j < 50; ++$j) {
174
                for ($k = 0; $k < 10; ++$k) {
175
                    $a[$i][$j][$k] = 'value';
176
                }
177
            }
178
        }
179
        $a[20] = 'value';
180
        $a[21] = 'value1';
181
        $exception = $this->createException($a);
182
183
        $flattened = new FlattenException($exception);
184
        $trace = $flattened->getTrace();
185
186
        $this->assertSame($trace[0]['args'][0], ['array', ['array', '*SKIPPED over 10000 entries*']]);
187
188
        $serializeTrace = serialize($trace);
189
190
        $this->assertStringContainsString('*SKIPPED over 10000 entries*', $serializeTrace);
191
        $this->assertStringNotContainsString('*value1*', $serializeTrace);
192
    }
193
194
    private function createException($foo): Exception
0 ignored issues
show
Unused Code introduced by
The parameter $foo is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

194
    private function createException(/** @scrutinizer ignore-unused */ $foo): Exception

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
    {
196
        return new Exception();
197
    }
198
}
199