Browse Source

ThrowableController 100% Coverage

2.1.0
Dustin Wilson 1 year ago
parent
commit
43f50f0292
  1. 38
      lib/Catcher/ThrowableController.php
  2. 50
      tests/cases/TestThrowableController.php

38
lib/Catcher/ThrowableController.php

@ -116,10 +116,10 @@ class ThrowableController {
$next = $frames[$key + 1] ?? [];
if (
!empty($frame['file']) &&
!empty($frame['function']) &&
!empty($frame['line']) &&
str_contains($frame['function'], 'call_user_func')
!empty($next['file']) &&
!empty($next['function']) &&
!empty($next['line']) &&
str_contains($next['function'], 'call_user_func')
) {
$file = $next['file'];
$line = $next['line'];
@ -157,11 +157,12 @@ class ThrowableController {
]
];
// Add the error name if it is an Error.
// Add the error code and type if it is an Error.
if ($this->throwable instanceof \Error) {
$error = $this->getErrorType();
if ($error !== null) {
$f['error'] = $error;
$f['code'] = $this->throwable->getCode();
$f['type'] = $error;
}
}
@ -169,20 +170,21 @@ class ThrowableController {
// Go through previous throwables and merge in their frames
if ($prev = $this->getPrevious()) {
$a = $frames;
$b = $prev->getFrames();
$prevThrowable = $prev->getThrowable();
$diff = $a;
for ($i = count($a) - 1, $j = count($b) - 1; $i >= 0 && $j >= 0; $i--, $j--) {
$af = $diff[$i]['file'];
$bf = $b[$j]['file'];
if ($af && $bf && $af === $bf && $diff[$i]['line'] === $b[$j]['line']) {
unset($diff[$i]);
$frames = [ ...$frames, ...$prev->getFrames() ];
$temp = [];
foreach ($frames as $f) {
if (isset($f['file']) && isset($f['line'])) {
foreach ($temp as $t) {
if (isset($t['file']) && isset($t['line']) && $f['file'] === $t['file'] && $f['line'] === $t['line']) {
continue 2;
}
}
}
}
$frames = [ ...$diff, ...$b ];
$temp[] = $f;
}
$frames = $temp;
}
$this->frames = $frames;

50
tests/cases/TestThrowableController.php

@ -88,6 +88,9 @@ class TestThrowableController extends \PHPUnit\Framework\TestCase {
/**
* @covers \MensBeam\Foundation\Catcher\ThrowableController::getFrames
*
* @covers \MensBeam\Foundation\Catcher\ThrowableController::__construct
* @covers \MensBeam\Foundation\Catcher\ThrowableController::getErrorType
* @covers \MensBeam\Foundation\Catcher\ThrowableController::getPrevious
*/
public function testMethod_getFrames(): void {
$f = false;
@ -97,7 +100,7 @@ class TestThrowableController extends \PHPUnit\Framework\TestCase {
$c = new ThrowableController($t);
$f = $c->getFrames();
} finally {
$this->assertEquals('Exception', $f[0]['class']);
$this->assertEquals(\Exception::class, $f[0]['class']);
}
$f = false;
@ -109,5 +112,50 @@ class TestThrowableController extends \PHPUnit\Framework\TestCase {
} finally {
$this->assertEquals(Error::class, $f[0]['class']);
}
$f = false;
try {
throw new \Exception(message: 'Ook!', previous: new Error('Ook!', \E_ERROR));
} catch (\Throwable $t) {
$c = new ThrowableController($t);
$f = $c->getFrames();
} finally {
$this->assertEquals(\Exception::class, $f[0]['class']);
$this->assertEquals(Error::class, $f[count($f) - 2]['class']);
}
$f = false;
try {
call_user_func_array(function () {
throw new \Exception('Ook!');
}, []);
} catch (\Throwable $t) {
$c = new ThrowableController($t);
$f = $c->getFrames();
} finally {
$this->assertEquals(\Exception::class, $f[0]['class']);
$this->assertArrayHasKey('file', $f[2]);
$this->assertMatchesRegularExpression('/TestThrowableController\.php$/', $f[2]['file']);
$this->assertEquals('call_user_func_array', $f[2]['function']);
$this->assertArrayHasKey('line', $f[2]);
$this->assertNotEquals(0, $f[2]['line']);
}
// This is mostly here for code coverage: to delete userland error handling from
// the backtrace
$f = false;
try {
function ook() {}
call_user_func('ook', []);
} catch (\Throwable $t) {
$c = new ThrowableController($t);
$f = $c->getFrames();
} finally {
$this->assertEquals(\TypeError::class, $f[0]['class']);
}
// For code coverage purposes; should use the cached value instead of calculating
// the frames over again.
$f = $c->getFrames();
}
}
Loading…
Cancel
Save