diff --git a/.github/codecov.yaml b/.github/codecov.yaml new file mode 100644 index 0000000..9457102 --- /dev/null +++ b/.github/codecov.yaml @@ -0,0 +1,24 @@ +coverage: + status: + project: + default: + target: 70% + +component_management: + default_rules: + statuses: + - type: project + target: auto + individual_components: + - component_id: module_exception + name: exception + paths: + - "src/Exception/**" + coverage: + target: 80% + - component_id: module_type + name: type + paths: + - "src/Type/**" + coverage: + target: 80% \ No newline at end of file diff --git a/.github/workflows/Codecov.yml b/.github/workflows/Codecov.yml new file mode 100644 index 0000000..1d2e0f8 --- /dev/null +++ b/.github/workflows/Codecov.yml @@ -0,0 +1,22 @@ +name: Code Coverage + +on: + pull_request: + branches: + - master + - develop + - 'release/v*' + +permissions: read-all + +jobs: + build: + uses: The-FireHub-Project/.github/.github/workflows/Codecov.yml@master + with: + phpVersion: '8.5' + phpExtensions: ${{ vars.PHP_EXTENSIONS }} + tools: "phpunit:13.x" + suites: '["unit"]' + secrets: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index 6a6e86b..a734470 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ /> +[![PHPStan](https://github.com/The-FireHub-Project/Core-Standard/actions/workflows/PHPStan.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Core-Standard/actions/workflows/PHPStan.yml) +[![PHPUnit](https://github.com/The-FireHub-Project/Core-Standard/actions/workflows/PHPUnit.yml/badge.svg?branch=develop)](https://github.com/The-FireHub-Project/Core-Standard/actions/workflows/PHPUnit.yml) +[![Codecov](https://codecov.io/gh/The-FireHub-Project/Core-Standard/branch/develop/graph/badge.svg?token=XW2YEONF51)](https://app.codecov.io/gh/The-FireHub-Project/Core-Standard/tree/develop) +

+ * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=8.2 + * @package Core + */ + +namespace FireHub\Core\Exception; + +use FireHub\Core\Type\ValueObject; +use FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException; + +/** + * ### Error code value object + * @since 1.0.0 + * + * @template TValue of int + * + * @extends \FireHub\Core\Type\ValueObject + */ +final readonly class Code extends ValueObject { + + /** + * ### Constructor + * @since 1.0.0 + * + * @uses \FireHub\Core\Type\ValueObject::guard() As a guard. + * + * @param TValue $value

+ * The error code. + *

+ * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException If the condition is not met. + * @throws \FireHub\Core\Exception\FireHubException If the condition is not met. + * @throws \FireHub\Core\Type\Exception\ValueObjectException If the exception is not a FireHubException. + * + * @return void + */ + public function __construct ( + private int $value + ) { + + $this->guard( + fn() => $value >= 0, + fn() => new InvalidCodeValueException('Value must be positive.') + ); + + } + + /** + * @inheritDoc + * + * @since 1.0.0 + */ + public function value ():int { + + return $this->value; + + } + +} \ No newline at end of file diff --git a/src/Exception/Domain/ValidationException.php b/src/Exception/Domain/ValidationException.php new file mode 100644 index 0000000..b44cb79 --- /dev/null +++ b/src/Exception/Domain/ValidationException.php @@ -0,0 +1,28 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception\Domain; + +use FireHub\Core\Exception\DomainException; + +/** + * ### Domain Validation FireHub Exception + * + * Thrown when input data fails structural or semantic validation rules defined by the system or domain layer. + * + * - Invalid DTO input + * - Missing required fields + * - Type mismatch in value objects + * @since 1.0.0 + */ +abstract class ValidationException extends DomainException {} \ No newline at end of file diff --git a/src/Exception/DomainException.php b/src/Exception/DomainException.php new file mode 100644 index 0000000..3815466 --- /dev/null +++ b/src/Exception/DomainException.php @@ -0,0 +1,60 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception; + +use Throwable; + +/** + * ### Domain FireHub Exception + * + * Represents violations of business rules or domain invariants. + * + * These exceptions indicate that the operation is logically invalid within the domain context, but not a system failure. + * + * - Invalid state transition + * - Rule violation + * - Constraint failure + * @since 1.0.0 + */ +abstract class DomainException extends FireHubException { + + /** + * ### Constructor + * @since 1.0.0 + * + * @uses \FireHub\Core\Exception\Code::value() As a exception code. + * + * @param string $message [optional]

+ * The Exception message to throw. + *

+ * @param null|\FireHub\Core\Exception\Code $code [optional]

+ * The Exception code. + *

+ * @param null|Throwable $previous [optional]

+ * he previous throwable used for the exception chaining. + *

+ * + * @return void + */ + public function __construct (string $message = '', ?Code $code = null, ?Throwable $previous = null) { + + parent::__construct( + $message, + $code?->value() ?? 0, + $previous + ); + + } + +} \ No newline at end of file diff --git a/src/Exception/FireHubException.php b/src/Exception/FireHubException.php new file mode 100644 index 0000000..df79e14 --- /dev/null +++ b/src/Exception/FireHubException.php @@ -0,0 +1,50 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception; + +use Exception, Throwable; + +/** + * ### Base FireHub Exception + * + * Represents a recoverable or expected exceptional condition within the FireHub framework. + * + * All framework-specific exceptions MUST extend this class instead of using \Exception directly. + * @since 1.0.0 + */ +abstract class FireHubException extends Exception { + + /** + * ### Constructor + * @since 1.0.0 + * + * @param string $message [optional]

+ * The Exception message to throw. + *

+ * @param int $code [optional]

+ * The Exception code. + *

+ * @param null|Throwable $previous [optional]

+ * he previous throwable used for the exception chaining. + *

+ * + * @return void + */ + public function __construct (string $message = '', int $code = 0, ?Throwable $previous = null) { + + parent::__construct($message, $code, $previous); + + } + +} \ No newline at end of file diff --git a/src/Exception/Runtime/System/Invariant/InvalidCodeValueException.php b/src/Exception/Runtime/System/Invariant/InvalidCodeValueException.php new file mode 100644 index 0000000..789f552 --- /dev/null +++ b/src/Exception/Runtime/System/Invariant/InvalidCodeValueException.php @@ -0,0 +1,36 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception\Runtime\System\Invariant; + +use FireHub\Core\Exception\Runtime\System\InvariantException; + +/** + * ### Invalid Code Value Exception + * + * Represents a violation of the invariants required by the FireHub Code Value Object. + * + * This exception is thrown when an invalid value is used to construct or maintain a valid exception code within the + * FireHub exception system. + * + * Typical causes include: + * - Negative error codes + * - Zero values when prohibited by the framework + * - Values outside the supported error code range + * - Any state that would result in an invalid Code Value Object + * + * This exception indicates a programming error or framework contract violation rather than a recoverable business or + * validation failure. + * @since 1.0.0 + */ +class InvalidCodeValueException extends InvariantException {} \ No newline at end of file diff --git a/src/Exception/Runtime/System/InvariantException.php b/src/Exception/Runtime/System/InvariantException.php new file mode 100644 index 0000000..326ae7b --- /dev/null +++ b/src/Exception/Runtime/System/InvariantException.php @@ -0,0 +1,28 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception\Runtime\System; + +use FireHub\Core\Exception\Runtime\SystemException; + +/** + * ### Invariant System FireHub Exception + * + * Represents a violation of an internal system or framework invariant within the FireHub ecosystem. + * + * - Invalid format + * - Empty code + * - Illegal state + * @since 1.0.0 + */ +abstract class InvariantException extends SystemException {} \ No newline at end of file diff --git a/src/Exception/Runtime/SystemException.php b/src/Exception/Runtime/SystemException.php new file mode 100644 index 0000000..9d86fb4 --- /dev/null +++ b/src/Exception/Runtime/SystemException.php @@ -0,0 +1,29 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception\Runtime; + +use FireHub\Core\Exception\RuntimeException; + +/** + * ### System Runtime FireHub Exception + * + * Represents infrastructure or environment-level failures that originate from external systems or framework boundaries. + * + * - File system failure + * - Network failure + * - DB connection failure + * - I/O errors + * @since 1.0.0 + */ +abstract class SystemException extends RuntimeException {} \ No newline at end of file diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php new file mode 100644 index 0000000..2098110 --- /dev/null +++ b/src/Exception/RuntimeException.php @@ -0,0 +1,58 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception; + +use Throwable; + +/** + * ### Runtime FireHub Exception + * + * Represents unexpected runtime failures that occur during execution but are not related to business logic or validation. + * + * - Service unavailable + * - Unexpected null state + * - Internal computation failure + * @since 1.0.0 + */ +abstract class RuntimeException extends FireHubException { + + /** + * ### Constructor + * @since 1.0.0 + * + * @uses \FireHub\Core\Exception\Code::value() As a exception code. + * + * @param string $message [optional]

+ * The Exception message to throw. + *

+ * @param null|\FireHub\Core\Exception\Code $code [optional]

+ * The Exception code. + *

+ * @param null|Throwable $previous [optional]

+ * he previous throwable used for the exception chaining. + *

+ * + * @return void + */ + public function __construct (string $message = '', ?Code $code = null, ?Throwable $previous = null) { + + parent::__construct( + $message, + $code?->value() ?? 0, + $previous + ); + + } + +} \ No newline at end of file diff --git a/src/Exception/SecurityException.php b/src/Exception/SecurityException.php new file mode 100644 index 0000000..08e51dc --- /dev/null +++ b/src/Exception/SecurityException.php @@ -0,0 +1,58 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Exception; + +use Throwable; + +/** + * ### Security FireHub Exception + * + * Represents security-related violations such as unauthorized access, permission denial, or integrity violations. + * + * - Unauthorized access + * - Invalid token + * - Forbidden operation + * @since 1.0.0 + */ +abstract class SecurityException extends FireHubException { + + /** + * ### Constructor + * @since 1.0.0 + * + * @uses \FireHub\Core\Exception\Code::value() As a exception code. + * + * @param string $message [optional]

+ * The Exception message to throw. + *

+ * @param null|\FireHub\Core\Exception\Code $code [optional]

+ * The Exception code. + *

+ * @param null|Throwable $previous [optional]

+ * he previous throwable used for the exception chaining. + *

+ * + * @return void + */ + public function __construct (string $message = '', ?Code $code = null, ?Throwable $previous = null) { + + parent::__construct( + $message, + $code?->value() ?? 0, + $previous + ); + + } + +} \ No newline at end of file diff --git a/src/Type/Exception/ValueObjectException.php b/src/Type/Exception/ValueObjectException.php new file mode 100644 index 0000000..a8661f8 --- /dev/null +++ b/src/Type/Exception/ValueObjectException.php @@ -0,0 +1,27 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Core\Type\Exception; + +use FireHub\Core\Exception\Runtime\System\InvariantException; + +/** + * ### Value Object invariant violation + * + * Thrown when a Value Object breaks its defined invariant rules. + * + * This exception indicates a programming contract violation inside the Value Object layer, meaning the object has + * been constructed or mutated with an invalid state that is not allowed under its invariants. + * @since 1.0.0 + */ +class ValueObjectException extends InvariantException {} \ No newline at end of file diff --git a/src/Type/ValueObject.php b/src/Type/ValueObject.php index 34f0ba8..d69f879 100644 --- a/src/Type/ValueObject.php +++ b/src/Type/ValueObject.php @@ -13,6 +13,9 @@ namespace FireHub\Core\Type; +use FireHub\Core\Exception\FireHubException; +use FireHub\Core\Type\Exception\ValueObjectException; + /** * ### Base Value Object * @@ -87,14 +90,29 @@ final public function sameAs (self $other):bool { * @param callable():bool $condition

* The validation condition to evaluate. *

- * @param callable():\Exception $exception

+ * @param callable():\FireHub\Core\Exception\FireHubException $exception

* Exception to be thrown when the condition fails. *

+ * + * @throws \FireHub\Core\Exception\FireHubException If the condition is not met. + * @throws \FireHub\Core\Type\Exception\ValueObjectException If the exception is not a FireHubException. + * * @return void */ final protected function guard (callable $condition, callable $exception):void { - if ($condition() === false) throw $exception(); + if ($condition() === false) { + + $e = $exception(); + + if (!$e instanceof FireHubException) + throw new ValueObjectException( + 'Guard exception must return instance of FireHubException.' + ); + + throw $e; + + } } diff --git a/tests/Stubs/Exception/DummyDomainException.php b/tests/Stubs/Exception/DummyDomainException.php new file mode 100644 index 0000000..7cc8508 --- /dev/null +++ b/tests/Stubs/Exception/DummyDomainException.php @@ -0,0 +1,22 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Tests\Core\Stubs\Exception; + +use FireHub\Core\Exception\DomainException; + +/** + * ### Dummy Domain Exception + * @since 1.0.0 + */ +class DummyDomainException extends DomainException {} \ No newline at end of file diff --git a/tests/Stubs/Exception/DummyException.php b/tests/Stubs/Exception/DummyException.php new file mode 100644 index 0000000..513700e --- /dev/null +++ b/tests/Stubs/Exception/DummyException.php @@ -0,0 +1,22 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Tests\Core\Stubs\Exception; + +use FireHub\Core\Exception\FireHubException; + +/** + * ### Dummy Exception + * @since 1.0.0 + */ +class DummyException extends FireHubException {} \ No newline at end of file diff --git a/tests/Stubs/Exception/DummyNotFireHubException.php b/tests/Stubs/Exception/DummyNotFireHubException.php new file mode 100644 index 0000000..009ee71 --- /dev/null +++ b/tests/Stubs/Exception/DummyNotFireHubException.php @@ -0,0 +1,22 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Tests\Core\Stubs\Exception; + +use Exception; + +/** + * ### Dummy Not FireHub Exception + * @since 1.0.0 + */ +class DummyNotFireHubException extends Exception {} \ No newline at end of file diff --git a/tests/Stubs/Exception/DummyRuntimeException.php b/tests/Stubs/Exception/DummyRuntimeException.php new file mode 100644 index 0000000..98bd3a3 --- /dev/null +++ b/tests/Stubs/Exception/DummyRuntimeException.php @@ -0,0 +1,22 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Tests\Core\Stubs\Exception; + +use FireHub\Core\Exception\RuntimeException; + +/** + * ### Dummy Runtime Exception + * @since 1.0.0 + */ +class DummyRuntimeException extends RuntimeException {} \ No newline at end of file diff --git a/tests/Stubs/Exception/DummySecurityException.php b/tests/Stubs/Exception/DummySecurityException.php new file mode 100644 index 0000000..45e67e1 --- /dev/null +++ b/tests/Stubs/Exception/DummySecurityException.php @@ -0,0 +1,22 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core + */ + +namespace FireHub\Tests\Core\Stubs\Exception; + +use FireHub\Core\Exception\SecurityException; + +/** + * ### Dummy Security Exception + * @since 1.0.0 + */ +class DummySecurityException extends SecurityException {} \ No newline at end of file diff --git a/tests/Stubs/Type/DummyIntVO.php b/tests/Stubs/Type/DummyIntVO.php index 28537cb..b864cc9 100644 --- a/tests/Stubs/Type/DummyIntVO.php +++ b/tests/Stubs/Type/DummyIntVO.php @@ -14,7 +14,7 @@ namespace FireHub\Tests\Core\Stubs\Type; use FireHub\Core\Type\ValueObject; -use InvalidArgumentException; +use FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException; /** * ### Dummy int Value Object @@ -28,6 +28,10 @@ * * @param int $value * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * * @return void */ public function __construct ( @@ -36,7 +40,7 @@ public function __construct ( $this->guard( fn() => $this->value > 0, - fn() => new InvalidArgumentException('Value must be positive.') + fn() => new InvalidCodeValueException('Value must be positive.') ); } diff --git a/tests/Stubs/Type/DummyStringVO.php b/tests/Stubs/Type/DummyStringVO.php index a4e9be0..6664879 100644 --- a/tests/Stubs/Type/DummyStringVO.php +++ b/tests/Stubs/Type/DummyStringVO.php @@ -14,7 +14,7 @@ namespace FireHub\Tests\Core\Stubs\Type; use FireHub\Core\Type\ValueObject; -use InvalidArgumentException; +use FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException; /** * ### Dummy string Value Object @@ -28,6 +28,10 @@ * * @param string $value * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * * @return void */ public function __construct ( @@ -36,7 +40,7 @@ public function __construct ( $this->guard( fn() => $this->value !== '', - fn() => new InvalidArgumentException('Value cannot be empty.') + fn() => new InvalidCodeValueException('Value cannot be empty.') ); } diff --git a/tests/Stubs/Type/DummyVOInvalidGuardException.php b/tests/Stubs/Type/DummyVOInvalidGuardException.php new file mode 100644 index 0000000..3884f7c --- /dev/null +++ b/tests/Stubs/Type/DummyVOInvalidGuardException.php @@ -0,0 +1,59 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=8.2 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Stubs\Type; + +use FireHub\Core\Type\ValueObject; +use FireHub\Tests\Core\Stubs\Exception\DummyNotFireHubException; + +/** + * ### Dummy Value Object with invalid guard exception + * @since 1.0.0 + */ +readonly class DummyVOInvalidGuardException extends ValueObject { + + /** + * ### Constructor + * @since 1.0.0 + * + * @param string $value + * + * @throws \FireHub\Tests\Core\Stubs\Exception\DummyException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + public function __construct ( + private string $value = 'default' + ) { + + $this->guard( + fn() => $this->value !== '', + fn() => new DummyNotFireHubException('Value cannot be empty.') + ); + + } + + /** + * @inheritDoc + * + * @since 1.0.0 + */ + public function value ():string { + + return $this->value; + + } + +} \ No newline at end of file diff --git a/tests/Unit/Exception/CodeTest.php b/tests/Unit/Exception/CodeTest.php new file mode 100644 index 0000000..e01b940 --- /dev/null +++ b/tests/Unit/Exception/CodeTest.php @@ -0,0 +1,72 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Unit\Exception; + +use FireHub\Testing\FireHubTestCase; +use FireHub\Core\Exception\Code; +use FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException; +use PHPUnit\Framework\Attributes\ { + CoversClass, Group, Small, TestWith +}; + +/** + * ### Test Error code value object + * @since 1.0.0 + */ +#[Small] +#[Group('exception')] +#[CoversClass(Code::class)] +final class CodeTest extends FireHubTestCase { + + /** + * @since 1.0.0 + * + * @param int $value + * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + #[TestWith([10])] + #[TestWith([0])] + public function testValue (int $value):void { + + $code = new Code($value); + + self::assertSame($value, $code->value()); + + } + + /** + * @since 1.0.0 + * + * @param int $value + * + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + #[TestWith([-1])] + public function testCreateWithInvalidValue (int $value):void { + + $this->expectException(InvalidCodeValueException::class); + + new Code($value); + + } + +} \ No newline at end of file diff --git a/tests/Unit/Exception/DomainExceptionTest.php b/tests/Unit/Exception/DomainExceptionTest.php new file mode 100644 index 0000000..2b90207 --- /dev/null +++ b/tests/Unit/Exception/DomainExceptionTest.php @@ -0,0 +1,63 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Unit\Exception; + +use FireHub\Testing\FireHubTestCase; +use FireHub\Core\Exception\DomainException; +use FireHub\Core\Exception\Code; +use FireHub\Tests\Core\Stubs\Exception\DummyDomainException; +use PHPUnit\Framework\Attributes\ { + CoversClass, Group, Small, TestWith +}; + +/** + * ### Test Domain FireHub Exception + * @since 1.0.0 + */ +#[Small] +#[Group('exception')] +#[CoversClass(DomainException::class)] +final class DomainExceptionTest extends FireHubTestCase { + + /** + * @since 1.0.0 + * + * @param string $message + * @param int $code + * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + #[TestWith(['error message', 123])] + #[TestWith(['', 0])] + public function testCreate (string $message, int $code):void { + + $previous = new DummyDomainException('previous'); + + $exception = new DummyDomainException( + $message, + new Code($code), + $previous + ); + + $this->assertSame($message, $exception->getMessage()); + $this->assertSame($code, $exception->getCode()); + $this->assertSame($previous, $exception->getPrevious()); + + } + +} \ No newline at end of file diff --git a/tests/Unit/Exception/FireHubExceptionTest.php b/tests/Unit/Exception/FireHubExceptionTest.php new file mode 100644 index 0000000..a0347c1 --- /dev/null +++ b/tests/Unit/Exception/FireHubExceptionTest.php @@ -0,0 +1,74 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Unit\Exception; + +use FireHub\Testing\FireHubTestCase; +use FireHub\Core\Exception\FireHubException; +use FireHub\Tests\Core\Stubs\Exception\DummyException; +use PHPUnit\Framework\Attributes\ { + CoversClass, Group, Small, TestWith +}; + +/** + * ### Test Base FireHub Exception + * @since 1.0.0 + */ +#[Small] +#[Group('exception')] +#[CoversClass(FireHubException::class)] +final class FireHubExceptionTest extends FireHubTestCase { + + /** + * @since 1.0.0 + * + * @param string $message + * @param int $code + * + * @return void + */ + #[TestWith(['error message', 123])] + #[TestWith(['', 0])] + public function testCreate (string $message, int $code):void { + + $previous = new DummyException('previous'); + + $exception = new DummyException( + $message, + $code, + $previous + ); + + $this->assertSame($message, $exception->getMessage()); + $this->assertSame($code, $exception->getCode()); + $this->assertSame($previous, $exception->getPrevious()); + + } + + /** + * @since 1.0.0 + * + * @return void + */ + public function testItSupportsExceptionChaining ():void { + + $root = new DummyException('root', 0); + $mid = new DummyException('mid', 0, $root); + $top = new DummyException('top', 0, $mid); + + $this->assertSame($mid, $top->getPrevious()); + $this->assertSame($root, $top->getPrevious()->getPrevious()); + + } + +} \ No newline at end of file diff --git a/tests/Unit/Exception/RuntimeExceptionTest.php b/tests/Unit/Exception/RuntimeExceptionTest.php new file mode 100644 index 0000000..c4c85d7 --- /dev/null +++ b/tests/Unit/Exception/RuntimeExceptionTest.php @@ -0,0 +1,63 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Unit\Exception; + +use FireHub\Testing\FireHubTestCase; +use FireHub\Core\Exception\RuntimeException; +use FireHub\Core\Exception\Code; +use FireHub\Tests\Core\Stubs\Exception\DummyRuntimeException; +use PHPUnit\Framework\Attributes\ { + CoversClass, Group, Small, TestWith +}; + +/** + * ### Test Runtime FireHub Exception + * @since 1.0.0 + */ +#[Small] +#[Group('exception')] +#[CoversClass(RuntimeException::class)] +final class RuntimeExceptionTest extends FireHubTestCase { + + /** + * @since 1.0.0 + * + * @param string $message + * @param int $code + * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + #[TestWith(['error message', 123])] + #[TestWith(['', 0])] + public function testCreate (string $message, int $code):void { + + $previous = new DummyRuntimeException('previous'); + + $exception = new DummyRuntimeException( + $message, + new Code($code), + $previous + ); + + $this->assertSame($message, $exception->getMessage()); + $this->assertSame($code, $exception->getCode()); + $this->assertSame($previous, $exception->getPrevious()); + + } + +} \ No newline at end of file diff --git a/tests/Unit/Exception/SecurityExceptionTest.php b/tests/Unit/Exception/SecurityExceptionTest.php new file mode 100644 index 0000000..909dcf0 --- /dev/null +++ b/tests/Unit/Exception/SecurityExceptionTest.php @@ -0,0 +1,63 @@ + + * @copyright 2026-present The FireHub Project - All rights reserved + * @license https://opensource.org/license/Apache-2-0 Apache License, Version 2.0 + * + * @php-version >=7.0 + * @package Core\Tests + */ + +namespace FireHub\Tests\Core\Unit\Exception; + +use FireHub\Testing\FireHubTestCase; +use FireHub\Core\Exception\SecurityException; +use FireHub\Core\Exception\Code; +use FireHub\Tests\Core\Stubs\Exception\DummySecurityException; +use PHPUnit\Framework\Attributes\ { + CoversClass, Group, Small, TestWith +}; + +/** + * ### Test Security FireHub Exception + * @since 1.0.0 + */ +#[Small] +#[Group('exception')] +#[CoversClass(SecurityException::class)] +final class SecurityExceptionTest extends FireHubTestCase { + + /** + * @since 1.0.0 + * + * @param string $message + * @param int $code + * + * @throws \FireHub\Core\Exception\Runtime\System\Invariant\InvalidCodeValueException + * @throws \FireHub\Core\Exception\FireHubException + * @throws \FireHub\Core\Type\Exception\ValueObjectException + * + * @return void + */ + #[TestWith(['error message', 123])] + #[TestWith(['', 0])] + public function testCreate (string $message, int $code):void { + + $previous = new DummySecurityException('previous'); + + $exception = new DummySecurityException( + $message, + new Code($code), + $previous + ); + + $this->assertSame($message, $exception->getMessage()); + $this->assertSame($code, $exception->getCode()); + $this->assertSame($previous, $exception->getPrevious()); + + } + +} \ No newline at end of file diff --git a/tests/Unit/Type/ValueObjectTest.php b/tests/Unit/Type/ValueObjectTest.php index a4682a1..ae10af6 100644 --- a/tests/Unit/Type/ValueObjectTest.php +++ b/tests/Unit/Type/ValueObjectTest.php @@ -15,8 +15,9 @@ use FireHub\Testing\FireHubTestCase; use FireHub\Core\Type\ValueObject; +use FireHub\Core\Type\Exception\ValueObjectException; use FireHub\Tests\Core\Stubs\Type\ { - DummyIntVO, DummyStringVO + DummyIntVO, DummyStringVO, DummyVOInvalidGuardException }; use PHPUnit\Framework\Attributes\ { CoversClass, Group, Small, TestWith @@ -47,7 +48,7 @@ public function testEquals (string $a, string $b, bool $expected):void { $a = new DummyStringVO($a); $b = new DummyStringVO($b); - $this::assertEquals($expected, $a->equals($b)); + $this::assertSame($expected, $a->equals($b)); } @@ -67,7 +68,20 @@ public function testSameAs (string $a, string $b, bool $expected):void { $a = new $a; $b = new $b; - $this::assertEquals($expected, $a->sameAs($b)); + $this::assertSame($expected, $a->sameAs($b)); + + } + + /** + * @since 1.0.0 + * + * @return void + */ + public function testCreateWithInvalidValue ():void { + + $this->expectException(ValueObjectException::class); + + new DummyVOInvalidGuardException(''); }