$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('');
}