8000 [PhpUnitBridge] Use serialized trace when using serialized deprecation · symfony/symfony@6bc77b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6bc77b7

Browse files
l-vogreg0ire
authored andcommitted
[PhpUnitBridge] Use serialized trace when using serialized deprecation
1 parent 179b76e commit 6bc77b7

File tree

3 files changed

+138
-18
lines changed

3 files changed

+138
-18
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,19 @@ public static function collectDeprecations($outputFile)
106106
return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context);
107107
}
108108

109-
$deprecations[] = [error_reporting(), $msg, $file];
109+
$trace = debug_backtrace();
110+
$filesStack = [];
111+
foreach ($trace as $line) {
112+
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
113+
continue;
114+
}
115+
116+
if (isset($line['file'])) {
117+
$filesStack[] = $line['file'];
118+
}
119+
}
120+
121+
$deprecations[] = [error_reporting(), $msg, $file, $filesStack];
110122

111123
return null;
112124
});

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class Deprecation
4343
*/
4444
private static $internalPaths = [];
4545

46+
private $originalFilesStack;
47+
4648
/**
4749
* @param string $message
4850
* @param string $file
@@ -63,6 +65,7 @@ public function __construct($message, array $trace, $file)
6365
$this->message = $parsedMsg['deprecation'];
6466
$this->originClass = $parsedMsg['class'];
6567
$this->originMethod = $parsedMsg 8000 ['method'];
68+
$this->originalFilesStack = $parsedMsg['files_stack'];
6669
// If the deprecation has been triggered via
6770
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
6871
// then we need to use the serialized information to determine
@@ -164,6 +167,24 @@ public function isMuted()
164167
return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR);
165168
}
166169

170+
private function getOriginalFilesStack(): array
171+
{
172+
if (null === $this->originalFilesStack) {
173+
$this->originalFilesStack = [];
174+
foreach ($this->trace as $line) {
175+
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
176+
continue;
177+
}
178+
if (!isset($line['file'])) {
179+
continue;
180+
}
181+
$this->originalFilesStack[] = $line['file'];
182+
}
183+
}
184+
185+
return $this->originalFilesStack;
186+
}
187+
167188
/**
168189
* Tells whether both the calling package and the called package are vendor
169190
* packages.
@@ -180,14 +201,8 @@ public function getType()
180201
return self::TYPE_UNDETERMINED;
181202
}
182203
$erroringFile = $erroringPackage = null;
183-
foreach ($this->trace as $line) {
184-
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
185-
continue;
186-
}
187-
if (!isset($line['file'])) {
188-
continue;
189-
}
190-
$file = $line['file'];
204+
205+
foreach ($this->getOriginalFilesStack() as $file) {
191206
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
192207
continue;
193208
}

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,32 @@
1111

1212
namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler;
1313

14+
use Composer\Autoload\ClassLoader;
1415
use PHPUnit\Framework\TestCase;
1516
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
1617
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation;
1718
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV5;
1819

1920
class DeprecationTest extends TestCase
2021
{
22+
public static function setUpBeforeClass(): void
23+
{
24+
$vendorDir = self::getVendorDir();
25+
26+
mkdir($vendorDir.'/myfakevendor/myfakepackage1', 0777, true);
27+
mkdir($vendorDir.'/myfakevendor/myfakepackage2');
28+
touch($vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php');
29+
touch($vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile2.php');
30+
touch($vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php');
31+
}
32+
33+
private static function getVendorDir(): string
34+
{
35+
$reflection = new \ReflectionClass(ClassLoader::class);
36+
37+
return \dirname($reflection->getFileName(), 2);
38+
}
39+
2140
public function testItCanDetermineTheClassWhereTheDeprecationHappened()
2241
{
2342
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
@@ -119,19 +138,19 @@ public function testItTakesMutesDeprecationFromPhpUnitFiles()
119138
$this->assertTrue($deprecation->isMuted());
120139
}
121140

122-
public function providerIsSelf(): array
141+
public function providerGetTypeDetectsSelf(): array
123142
{
124143
return [
125-
'not_from_vendors_file' => [true, '', 'MyClass1', ''],
126-
'nonexistent_file' => [false, '', 'MyClass1', 'dummy_vendor_path'],
144+
'not_from_vendors_file' => [Deprecation::TYPE_SELF, '', 'MyClass1', ''],
145+
'nonexistent_file' => [Deprecation::TYPE_UNDETERMINED, '', 'MyClass1', 'dummy_vendor_path'],
127146
'serialized_trace_without_triggering_file' => [
128-
true,
147+
Deprecation::TYPE_SELF,
129148
serialize(['class' => '', 'method' => '', 'deprecation' => '', 'files_stack' => []]),
130149
SymfonyTestsListenerForV5::class,
131150
'',
132151
],
133152
'serialized_trace_with_not_from_vendors_triggering_file' => [
134-
true,
153+
Deprecation::TYPE_SELF,
135154
serialize([
136155
'class' => '',
137156
'method' => '',
@@ -143,7 +162,7 @@ public function providerIsSelf(): array
143162
'',
144163
],
145164
'serialized_trace_with_nonexistent_triggering_file' => [
146-
false,
165+
Deprecation::TYPE_UNDETERMINED,
147166
serialize([
148167
'class' => '',
149168
'method' => '',
@@ -158,16 +177,72 @@ public function providerIsSelf(): array
158177
}
159178

160179
/**
161-
* @dataProvider providerIsSelf
180+
* @dataProvider providerGetTypeDetectsSelf
162181
*/
163-
public function testIsSelf(bool $expectedIsSelf, string $message, string $traceClass, string $file): void
182+
public function testGetTypeDetectsSelf(string $expectedType, string $message, string $traceClass, string $file): void
164183
{
165184
$trace = [
166185
['class' => 'MyClass1', 'function' => 'myMethod'],
167186
['class' => $traceClass, 'function' => 'myMethod'],
168187
];
169188
$deprecation = new Deprecation($message, $trace, $file);
170-
$this->assertEquals($expectedIsSelf, $deprecation->getType() === Deprecation::TYPE_SELF);
189+
$this->assertEquals($expectedType, $deprecation->getType());
190+
}
191+
192+
public function providerGetTypeUsesRightTrace(): array
193+
{
194+
$vendorDir = self::getVendorDir();
195+
196+
return [
197+
'no_file_in_stack' => [Deprecation::TYPE_DIRECT, '', [['function' => 'myfunc1'], ['function' => 'myfunc2']]],
198+
'files_in_stack_from_various_packages' => [
199+
Deprecation::TYPE_INDIRECT,
200+
'',
201+
[
202+
['function' => 'myfunc1', 'file' => $vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php'],
203+
['function' => 'myfunc2', 'file' => $vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php'],
204+
],
205+
],
206+
'serialized_stack_files_from_same_package' => [
207+
Deprecation::TYPE_DIRECT,
208+
serialize([
209+
'deprecation' => 'My deprecation message',
210+
'class' => 'MyClass',
211+
'method' => 'myMethod',
212+
'files_stack' => [
213+
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php',
214+
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile2.php',
215+
],
216+
]),
217+
[['function' => 'myfunc1'], ['class' => SymfonyTestsListenerForV5::class, 'method' => 'mymethod']],
218+
],
219+
'serialized_stack_files_from_various_packages' => [
220+
Deprecation::TYPE_INDIRECT,
221+
serialize([
222+
'deprecation' => 'My deprecation message',
223+
'class' => 'MyClass',
224+
'method' => 'myMethod',
225+
'files_stack' => [
226+
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php',
227+
$vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php',
228+
],
229+
]),
230+
[['function' => 'myfunc1'], ['class' => SymfonyTestsListenerForV5::class, 'method' => 'mymethod']],
231+
],
232+
];
233+
}
234+
235+
/**
236+
* @dataProvider providerGetTypeUsesRightTrace
237+
*/
238+
public function testGetTypeUsesRightTrace(string $expectedType, string $message, array $trace): void
239+
{
240+
$deprecation = new Deprecation(
241+
$message,
242+
$trace,
243+
self::getVendorDir().'/myfakevendor/myfakepackage2/MyFakeFile.php'
244+
);
245+
$this->assertEquals($expectedType, $deprecation->getType());
171246
}
172247

173248
/**
@@ -178,4 +253,22 @@ public function debugBacktrace(): array
178253
{
179254
return debug_backtrace();
180255
}
256+
257+
private static function removeDir($dir): void
258+
{
259+
$files = glob($dir.'/*');
260+
foreach ($files as $file) {
261+
if (is_file($file)) {
262+
unlink($file);
263+
} else {
264+
self::removeDir($file);
265+
}
266+
}
267+
rmdir($dir);
268+
}
269+
270+
public static function tearDownAfterClass(): void
271+
{
272+
self::removeDir(self::getVendorDir().'/myfakevendor');
273+
}
181274
}

0 commit comments

Comments
 (0)
0