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:
parent
1e8062c702
commit
53a97cbd92
83
lib/Sync/ContextPanicError.php
Normal file
83
lib/Sync/ContextPanicError.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
86
lib/Worker/TaskFailureError.php
Normal file
86
lib/Worker/TaskFailureError.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
86
lib/Worker/TaskFailureException.php
Normal file
86
lib/Worker/TaskFailureException.php
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
38
lib/Worker/TaskFailureThrowable.php
Normal file
38
lib/Worker/TaskFailureThrowable.php
Normal 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;
|
||||||
|
}
|
@ -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");
|
||||||
|
@ -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');
|
||||||
|
28
test/Worker/TaskFailureErrorTest.php
Normal file
28
test/Worker/TaskFailureErrorTest.php
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
28
test/Worker/TaskFailureExceptionTest.php
Normal file
28
test/Worker/TaskFailureExceptionTest.php
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user