assertTrue( is_a(XcVmException::class, RuntimeException::class, true), 'XcVmException must extend RuntimeException for backward compat' ); } // ── Container ───────────────────────────────────────────── public function testContainerExceptionExtendsXcVmException(): void { $this->assertTrue(is_a(ContainerException::class, XcVmException::class, true)); } public function testContainerExceptionImplementsPsr11Interface(): void { $this->assertTrue(is_a(ContainerException::class, ContainerExceptionInterface::class, true)); } public function testCircularDependencyExceptionExtendsContainerException(): void { $this->assertTrue(is_a(CircularDependencyException::class, ContainerException::class, true)); } public function testServiceCreationExceptionExtendsContainerException(): void { $this->assertTrue(is_a(ServiceCreationException::class, ContainerException::class, true)); } public function testNotFoundExceptionExtendsContainerException(): void { $this->assertTrue(is_a(NotFoundException::class, ContainerException::class, true)); } public function testNotFoundExceptionImplementsPsr11Interface(): void { $this->assertTrue(is_a(NotFoundException::class, NotFoundExceptionInterface::class, true)); } // ── Module ──────────────────────────────────────────────── public function testModuleExceptionExtendsXcVmException(): void { $this->assertTrue(is_a(ModuleException::class, XcVmException::class, true)); } public function testModuleNotFoundExceptionExtendsModuleException(): void { $this->assertTrue(is_a(ModuleNotFoundException::class, ModuleException::class, true)); } public function testModuleCycleExceptionExtendsModuleException(): void { $this->assertTrue(is_a(ModuleCycleException::class, ModuleException::class, true)); } public function testModuleLoadExceptionExtendsModuleException(): void { $this->assertTrue(is_a(ModuleLoadException::class, ModuleException::class, true)); } public function testModuleManifestExceptionExtendsModuleException(): void { $this->assertTrue(is_a(ModuleManifestException::class, ModuleException::class, true)); } // ── Catchability ────────────────────────────────────────── public function testCircularDependencyIsCatchableAsXcVmException(): void { $caught = false; try { throw new CircularDependencyException('test'); } catch (XcVmException) { $caught = true; } $this->assertTrue($caught, 'CircularDependencyException must be catchable as XcVmException'); } public function testModuleCycleIsCatchableAsModuleException(): void { $caught = false; try { throw new ModuleCycleException('test'); } catch (ModuleException) { $caught = true; } $this->assertTrue($caught); } public function testModuleExceptionIsCatchableAsRuntimeException(): void { $caught = false; try { throw new ModuleException('test'); } catch (RuntimeException) { $caught = true; } $this->assertTrue($caught, 'ModuleException must be catchable as RuntimeException for backward compat'); } }