1
0
mirror of https://github.com/danog/parallel.git synced 2024-12-02 09:37:57 +01:00

Expand context & task exceptions

This commit is contained in:
Aaron Piotrowski 2020-02-11 11:06:30 -06:00
parent 1e8062c702
commit 53a97cbd92
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
14 changed files with 428 additions and 69 deletions

View File

@ -0,0 +1,83 @@
<?php
namespace Amp\Parallel\Sync;
final class ContextPanicError extends PanicError
{
/** @var string */
private $originalMessage;
/** @var int|string */
private $originalCode;
/** @var string[] */
private $originalTrace;
/**
* @param string $className Original exception class name.
* @param string $message Original exception message.
* @param int|string $code Original exception code.
* @param array $trace Backtrace generated by {@see formatFlattenedBacktrace()}.
* @param self|null $previous Instance representing any previous exception thrown in the child process or thread.
*/
public function __construct(string $className, string $message, $code, array $trace, ?self $previous = null)
{
$format = 'Uncaught %s in child process or thread with message "%s" and code "%s"; use %s::getOriginalTrace() '
. 'for the stack trace in the child process or thread';
parent::__construct(
$className,
\sprintf($format, $className, $message, $code, self::class),
formatFlattenedBacktrace($trace),
$previous
);
$this->originalMessage = $message;
$this->originalCode = $code;
$this->originalTrace = $trace;
}
/**
* @return string Original exception class name.
*/
public function getOriginalClassName(): string
{
return $this->getName();
}
/**
* @return string Original exception message.
*/
public function getOriginalMessage(): string
{
return $this->originalMessage;
}
/**
* @return int|string Original exception code.
*/
public function getOriginalCode()
{
return $this->originalCode;
}
/**
* Original exception stack trace.
*
* @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
*/
public function getOriginalTrace(): array
{
return $this->originalTrace;
}
/**
* Original backtrace flattened to a human-readable string.
*
* @return string
*/
public function getOriginalTraceAsString(): string
{
return $this->getPanicTrace();
}
}

View File

@ -39,22 +39,10 @@ final class ExitFailure implements ExitResult
throw $this->createException(); throw $this->createException();
} }
private function createException(): PanicError private function createException(): ContextPanicError
{ {
$previous = $this->previous ? $this->previous->createException() : null; $previous = $this->previous ? $this->previous->createException() : null;
return new PanicError( return new ContextPanicError($this->type, $this->message, $this->code, $this->trace, $previous);
$this->type,
\sprintf(
'Uncaught %s in worker with message "%s" and code "%s"; use %s::getPanicTrace() '
. 'for the stack trace in the context',
$this->type,
$this->message,
$this->code,
PanicError::class
),
\implode("\n", $this->trace),
$previous
);
} }
} }

View File

@ -2,7 +2,11 @@
namespace Amp\Parallel\Sync; namespace Amp\Parallel\Sync;
final class PanicError extends \Error /**
* @deprecated ContextPanicError will be thrown from uncaught exceptions in child processes and threads instead of
* this class.
*/
class PanicError extends \Error
{ {
/** @var string Class name of uncaught exception. */ /** @var string Class name of uncaught exception. */
private $name; private $name;
@ -18,7 +22,7 @@ final class PanicError extends \Error
* @param string $trace The panic stack trace. * @param string $trace The panic stack trace.
* @param \Throwable|null $previous Previous exception. * @param \Throwable|null $previous Previous exception.
*/ */
public function __construct(string $name, string $message = '', string $trace = '', \Throwable $previous = null) public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
{ {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
@ -27,6 +31,8 @@ final class PanicError extends \Error
} }
/** /**
* @deprecated Use ContextPanicError::getOriginalClassName() instead.
*
* Returns the class name of the uncaught exception. * Returns the class name of the uncaught exception.
* *
* @return string * @return string
@ -37,6 +43,8 @@ final class PanicError extends \Error
} }
/** /**
* @deprecated Use ContextPanicError::getOriginalTraceAsString() instead.
*
* Gets the stack trace at the point the panic occurred. * Gets the stack trace at the point the panic occurred.
* *
* @return string * @return string

View File

@ -5,34 +5,47 @@ namespace Amp\Parallel\Sync;
/** /**
* @param \Throwable $exception * @param \Throwable $exception
* *
* @return string[] Serializable array of strings representing the exception backtrace including function arguments. * @return array Serializable exception backtrace, with all function arguments flattened to strings.
*/ */
function flattenThrowableBacktrace(\Throwable $exception): array function flattenThrowableBacktrace(\Throwable $exception): array
{ {
$output = [];
$counter = 0;
$trace = $exception->getTrace(); $trace = $exception->getTrace();
foreach ($trace as $call) { foreach ($trace as &$call) {
unset($call['object']);
$call['args'] = \array_map(__NAMESPACE__ . '\\flattenArgument', $call['args']);
}
return $trace;
}
/**
* @param array $trace Backtrace produced by {@see formatFlattenedBacktrace()}.
*
* @return string
*/
function formatFlattenedBacktrace(array $trace): string
{
$output = [];
foreach ($trace as $index => $call) {
if (isset($call['class'])) { if (isset($call['class'])) {
$name = $call['class'] . $call['type'] . $call['function']; $name = $call['class'] . $call['type'] . $call['function'];
} else { } else {
$name = $call['function']; $name = $call['function'];
} }
$args = \implode(', ', \array_map(__NAMESPACE__ . '\\flattenArgument', $call['args']));
$output[] = \sprintf( $output[] = \sprintf(
'#%d %s(%d): %s(%s)', '#%d %s(%d): %s(%s)',
$counter++, $index,
$call['file'] ?? '[internal function]', $call['file'] ?? '[internal function]',
$call['line'] ?? 0, $call['line'] ?? 0,
$name, $name,
$args \implode(', ', $call['args'])
); );
} }
return $output; return \implode("\n", $output);
} }
/** /**

View File

@ -4,8 +4,8 @@ namespace Amp\Parallel\Worker\Internal;
use Amp\Failure; use Amp\Failure;
use Amp\Parallel\Sync; use Amp\Parallel\Sync;
use Amp\Parallel\Worker\TaskError; use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\TaskException; use Amp\Parallel\Worker\TaskFailureException;
use Amp\Promise; use Amp\Promise;
/** @internal */ /** @internal */
@ -55,23 +55,10 @@ final class TaskFailure extends TaskResult
{ {
$previous = $this->previous ? $this->previous->createException() : null; $previous = $this->previous ? $this->previous->createException() : null;
$format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getWorkerTrace() '
. 'for the stack trace in the worker';
if ($this->parent === self::PARENT_ERROR) { if ($this->parent === self::PARENT_ERROR) {
return new TaskError( return new TaskFailureError($this->type, $this->message, $this->code, $this->trace, $previous);
$this->type,
\sprintf($format, $this->type, $this->message, $this->code, TaskError::class),
\implode("\n", $this->trace),
$previous
);
} }
return new TaskException( return new TaskFailureException($this->type, $this->message, $this->code, $this->trace, $previous);
$this->type,
\sprintf($format, $this->type, $this->message, $this->code, TaskException::class),
\implode("\n", $this->trace),
$previous
);
} }
} }

View File

@ -2,7 +2,10 @@
namespace Amp\Parallel\Worker; namespace Amp\Parallel\Worker;
final class TaskError extends \Error /**
* @deprecated TaskFailureError will be thrown from failed Tasks instead of this class.
*/
class TaskError extends \Error
{ {
/** @var string Class name of error thrown from task. */ /** @var string Class name of error thrown from task. */
private $name; private $name;
@ -16,7 +19,7 @@ final class TaskError extends \Error
* @param string $trace The panic stack trace. * @param string $trace The panic stack trace.
* @param \Throwable|null $previous Previous exception. * @param \Throwable|null $previous Previous exception.
*/ */
public function __construct(string $name, string $message = '', string $trace = '', \Throwable $previous = null) public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
{ {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
@ -25,6 +28,8 @@ final class TaskError extends \Error
} }
/** /**
* @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
*
* Returns the class name of the error thrown from the task. * Returns the class name of the error thrown from the task.
* *
* @return string * @return string
@ -35,6 +40,8 @@ final class TaskError extends \Error
} }
/** /**
* @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
*
* Gets the stack trace at the point the error was thrown in the task. * Gets the stack trace at the point the error was thrown in the task.
* *
* @return string * @return string

View File

@ -2,7 +2,10 @@
namespace Amp\Parallel\Worker; namespace Amp\Parallel\Worker;
final class TaskException extends \Exception /**
* @deprecated TaskFailureException will be thrown from failed Tasks instead of this class.
*/
class TaskException extends \Exception
{ {
/** @var string Class name of exception thrown from task. */ /** @var string Class name of exception thrown from task. */
private $name; private $name;
@ -16,7 +19,7 @@ final class TaskException extends \Exception
* @param string $trace The panic stack trace. * @param string $trace The panic stack trace.
* @param \Throwable|null $previous Previous exception. * @param \Throwable|null $previous Previous exception.
*/ */
public function __construct(string $name, string $message = '', string $trace = '', \Throwable $previous = null) public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
{ {
parent::__construct($message, 0, $previous); parent::__construct($message, 0, $previous);
@ -25,6 +28,8 @@ final class TaskException extends \Exception
} }
/** /**
* @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
*
* Returns the class name of the exception thrown from the task. * Returns the class name of the exception thrown from the task.
* *
* @return string * @return string
@ -35,6 +40,8 @@ final class TaskException extends \Exception
} }
/** /**
* @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
*
* Gets the stack trace at the point the exception was thrown in the task. * Gets the stack trace at the point the exception was thrown in the task.
* *
* @return string * @return string

View File

@ -0,0 +1,86 @@
<?php
namespace Amp\Parallel\Worker;
use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureError extends TaskError implements TaskFailureThrowable
{
/** @var string */
private $originalMessage;
/** @var int|string */
private $originalCode;
/** @var string[] */
private $originalTrace;
/**
* @param string $className Original exception class name.
* @param string $message Original exception message.
* @param int|string $code Original exception code.
* @param array $trace Backtrace generated by
* {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
* @param TaskFailureThrowable|null $previous Instance representing any previous exception thrown in the Task.
*/
public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
{
$format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() '
. 'for the stack trace in the worker';
parent::__construct(
$className,
\sprintf($format, $className, $message, $code, self::class),
formatFlattenedBacktrace($trace),
$previous
);
$this->originalMessage = $message;
$this->originalCode = $code;
$this->originalTrace = $trace;
}
/**
* @return string Original exception class name.
*/
public function getOriginalClassName(): string
{
return $this->getName();
}
/**
* @return string Original exception message.
*/
public function getOriginalMessage(): string
{
return $this->originalMessage;
}
/**
* @return int|string Original exception code.
*/
public function getOriginalCode()
{
return $this->originalCode;
}
/**
* Returns the original exception stack trace.
*
* @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
*/
public function getOriginalTrace(): array
{
return $this->originalTrace;
}
/**
* Original backtrace flattened to a human-readable string.
*
* @return string
*/
public function getOriginalTraceAsString(): string
{
return $this->getWorkerTrace();
}
}

View File

@ -0,0 +1,86 @@
<?php
namespace Amp\Parallel\Worker;
use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureException extends TaskException implements TaskFailureThrowable
{
/** @var string */
private $originalMessage;
/** @var int|string */
private $originalCode;
/** @var string[] */
private $originalTrace;
/**
* @param string $className Original exception class name.
* @param string $message Original exception message.
* @param int|string $code Original exception code.
* @param array $trace Backtrace generated by
* {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
* @param TaskFailureThrowable|null $previous Instance representing any previous exception thrown in the Task.
*/
public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
{
$format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() '
. 'for the stack trace in the worker';
parent::__construct(
$className,
\sprintf($format, $className, $message, $code, self::class),
formatFlattenedBacktrace($trace),
$previous
);
$this->originalMessage = $message;
$this->originalCode = $code;
$this->originalTrace = $trace;
}
/**
* @return string Original exception class name.
*/
public function getOriginalClassName(): string
{
return $this->getName();
}
/**
* @return string Original exception message.
*/
public function getOriginalMessage(): string
{
return $this->originalMessage;
}
/**
* @return int|string Original exception code.
*/
public function getOriginalCode()
{
return $this->originalCode;
}
/**
* Returns the original exception stack trace.
*
* @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
*/
public function getOriginalTrace(): array
{
return $this->originalTrace;
}
/**
* Original backtrace flattened to a human-readable string.
*
* @return string
*/
public function getOriginalTraceAsString(): string
{
return $this->getWorkerTrace();
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace Amp\Parallel\Worker;
/**
* Common interface for exceptions thrown when Task::run() throws an exception when being executed in a worker.
*/
interface TaskFailureThrowable extends \Throwable
{
/**
* @return string Original exception class name.
*/
public function getOriginalClassName(): string;
/**
* @return string Original exception message.
*/
public function getOriginalMessage(): string;
/**
* @return int|string Original exception code.
*/
public function getOriginalCode();
/**
* Returns the original exception stack trace.
*
* @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
*/
public function getOriginalTrace(): array;
/**
* Original backtrace flattened to a human-readable string.
*
* @return string
*/
public function getOriginalTraceAsString(): string;
}

View File

@ -5,7 +5,7 @@ namespace Amp\Parallel\Test\Context;
use Amp\Delayed; use Amp\Delayed;
use Amp\Parallel\Context\Context; use Amp\Parallel\Context\Context;
use Amp\Parallel\Context\ContextException; use Amp\Parallel\Context\ContextException;
use Amp\Parallel\Sync\PanicError; use Amp\Parallel\Sync\ContextPanicError;
use Amp\PHPUnit\AsyncTestCase; use Amp\PHPUnit\AsyncTestCase;
abstract class AbstractContextTest extends AsyncTestCase abstract class AbstractContextTest extends AsyncTestCase
@ -24,7 +24,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testFailingProcess() public function testFailingProcess()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('No string provided'); $this->expectExceptionMessage('No string provided');
$context = $this->createContext(__DIR__ . "/Fixtures/test-process.php"); $context = $this->createContext(__DIR__ . "/Fixtures/test-process.php");
@ -34,7 +34,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testThrowingProcessOnReceive() public function testThrowingProcessOnReceive()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('Test message'); $this->expectExceptionMessage('Test message');
$context = $this->createContext(__DIR__ . "/Fixtures/throwing-process.php"); $context = $this->createContext(__DIR__ . "/Fixtures/throwing-process.php");
@ -44,7 +44,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testThrowingProcessOnSend() public function testThrowingProcessOnSend()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('Test message'); $this->expectExceptionMessage('Test message');
$context = $this->createContext(__DIR__ . "/Fixtures/throwing-process.php"); $context = $this->createContext(__DIR__ . "/Fixtures/throwing-process.php");
@ -55,7 +55,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testInvalidScriptPath() public function testInvalidScriptPath()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage("No script found at '../test-process.php'"); $this->expectExceptionMessage("No script found at '../test-process.php'");
$context = $this->createContext("../test-process.php"); $context = $this->createContext("../test-process.php");
@ -65,7 +65,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testInvalidResult() public function testInvalidResult()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('The given data cannot be sent because it is not serializable'); $this->expectExceptionMessage('The given data cannot be sent because it is not serializable');
$context = $this->createContext(__DIR__ . "/Fixtures/invalid-result-process.php"); $context = $this->createContext(__DIR__ . "/Fixtures/invalid-result-process.php");
@ -75,7 +75,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testNoCallbackReturned() public function testNoCallbackReturned()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('did not return a callable function'); $this->expectExceptionMessage('did not return a callable function');
$context = $this->createContext(__DIR__ . "/Fixtures/no-callback-process.php"); $context = $this->createContext(__DIR__ . "/Fixtures/no-callback-process.php");
@ -85,7 +85,7 @@ abstract class AbstractContextTest extends AsyncTestCase
public function testParseError() public function testParseError()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('contains a parse error'); $this->expectExceptionMessage('contains a parse error');
$context = $this->createContext(__DIR__ . "/Fixtures/parse-error-process.inc"); $context = $this->createContext(__DIR__ . "/Fixtures/parse-error-process.inc");

View File

@ -3,13 +3,13 @@
namespace Amp\Parallel\Test\Worker; namespace Amp\Parallel\Test\Worker;
use Amp\Parallel\Context\StatusError; use Amp\Parallel\Context\StatusError;
use Amp\Parallel\Sync\PanicError; use Amp\Parallel\Sync\ContextPanicError;
use Amp\Parallel\Sync\SerializationException; use Amp\Parallel\Sync\SerializationException;
use Amp\Parallel\Worker\BasicEnvironment; use Amp\Parallel\Worker\BasicEnvironment;
use Amp\Parallel\Worker\Environment; use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task; use Amp\Parallel\Worker\Task;
use Amp\Parallel\Worker\TaskError; use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\TaskException; use Amp\Parallel\Worker\TaskFailureException;
use Amp\Parallel\Worker\WorkerException; use Amp\Parallel\Worker\WorkerException;
use Amp\PHPUnit\AsyncTestCase; use Amp\PHPUnit\AsyncTestCase;
@ -172,8 +172,8 @@ abstract class AbstractWorkerTest extends AsyncTestCase
try { try {
yield $worker->enqueue(new Fixtures\FailingTask(\Exception::class)); yield $worker->enqueue(new Fixtures\FailingTask(\Exception::class));
} catch (TaskException $exception) { } catch (TaskFailureException $exception) {
$this->assertSame(\Exception::class, $exception->getName()); $this->assertSame(\Exception::class, $exception->getOriginalClassName());
} }
yield $worker->shutdown(); yield $worker->shutdown();
@ -185,8 +185,8 @@ abstract class AbstractWorkerTest extends AsyncTestCase
try { try {
yield $worker->enqueue(new Fixtures\FailingTask(\Error::class)); yield $worker->enqueue(new Fixtures\FailingTask(\Error::class));
} catch (TaskError $exception) { } catch (TaskFailureError $exception) {
$this->assertSame(\Error::class, $exception->getName()); $this->assertSame(\Error::class, $exception->getOriginalClassName());
} }
yield $worker->shutdown(); yield $worker->shutdown();
@ -198,11 +198,11 @@ abstract class AbstractWorkerTest extends AsyncTestCase
try { try {
yield $worker->enqueue(new Fixtures\FailingTask(\Error::class, \Exception::class)); yield $worker->enqueue(new Fixtures\FailingTask(\Error::class, \Exception::class));
} catch (TaskError $exception) { } catch (TaskFailureError $exception) {
$this->assertSame(\Error::class, $exception->getName()); $this->assertSame(\Error::class, $exception->getOriginalClassName());
$previous = $exception->getPrevious(); $previous = $exception->getPrevious();
$this->assertInstanceOf(TaskException::class, $previous); $this->assertInstanceOf(TaskFailureException::class, $previous);
$this->assertSame(\Exception::class, $previous->getName()); $this->assertSame(\Exception::class, $previous->getOriginalClassName());
} }
yield $worker->shutdown(); yield $worker->shutdown();
@ -215,8 +215,8 @@ abstract class AbstractWorkerTest extends AsyncTestCase
try { try {
yield $worker->enqueue(new NonAutoloadableTask); yield $worker->enqueue(new NonAutoloadableTask);
$this->fail("Tasks that cannot be autoloaded should throw an exception"); $this->fail("Tasks that cannot be autoloaded should throw an exception");
} catch (TaskError $exception) { } catch (TaskFailureError $exception) {
$this->assertSame("Error", $exception->getName()); $this->assertSame("Error", $exception->getOriginalClassName());
$this->assertGreaterThan(0, \strpos($exception->getMessage(), \sprintf("Classes implementing %s", Task::class))); $this->assertGreaterThan(0, \strpos($exception->getMessage(), \sprintf("Classes implementing %s", Task::class)));
} }
@ -248,7 +248,7 @@ abstract class AbstractWorkerTest extends AsyncTestCase
try { try {
yield $worker->enqueue(new Fixtures\UnserializableResultTask); yield $worker->enqueue(new Fixtures\UnserializableResultTask);
$this->fail("Tasks results that cannot be serialized should throw an exception"); $this->fail("Tasks results that cannot be serialized should throw an exception");
} catch (TaskException $exception) { } catch (TaskFailureException $exception) {
$this->assertSame(0, \strpos($exception->getMessage(), "Uncaught Amp\Parallel\Sync\SerializationException in worker")); $this->assertSame(0, \strpos($exception->getMessage(), "Uncaught Amp\Parallel\Sync\SerializationException in worker"));
} }
@ -296,7 +296,7 @@ abstract class AbstractWorkerTest extends AsyncTestCase
public function testInvalidCustomAutoloader() public function testInvalidCustomAutoloader()
{ {
$this->expectException(PanicError::class); $this->expectException(ContextPanicError::class);
$this->expectExceptionMessage('No file found at bootstrap file path given'); $this->expectExceptionMessage('No file found at bootstrap file path given');
$worker = $this->createWorker(BasicEnvironment::class, __DIR__ . '/Fixtures/not-found.php'); $worker = $this->createWorker(BasicEnvironment::class, __DIR__ . '/Fixtures/not-found.php');

View File

@ -0,0 +1,28 @@
<?php
namespace Amp\Parallel\Test\Worker;
use Amp\Parallel\Worker\TaskFailureError;
use Amp\PHPUnit\AsyncTestCase;
class TaskFailureErrorTest extends AsyncTestCase
{
public function testOriginalMethods(): void
{
$trace = [
[
'function' => 'error_message_trace',
'file' => 'file-name.php',
'line' => 1,
'args' => [],
]
];
$exception = new TaskFailureError('name', 'error_message', 0, $trace);
$this->assertSame('name', $exception->getOriginalClassName());
$this->assertSame('error_message', $exception->getOriginalMessage());
$this->assertSame(0, $exception->getOriginalCode());
$this->assertSame($trace, $exception->getOriginalTrace());
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Amp\Parallel\Test\Worker;
use Amp\Parallel\Worker\TaskFailureException;
use Amp\PHPUnit\AsyncTestCase;
class TaskFailureExceptionTest extends AsyncTestCase
{
public function testOriginalMethods(): void
{
$trace = [
[
'function' => 'error_message_trace',
'file' => 'file-name.php',
'line' => 1,
'args' => [],
]
];
$exception = new TaskFailureException('name', 'error_message', 0, $trace);
$this->assertSame('name', $exception->getOriginalClassName());
$this->assertSame('error_message', $exception->getOriginalMessage());
$this->assertSame(0, $exception->getOriginalCode());
$this->assertSame($trace, $exception->getOriginalTrace());
}
}