Closed lukenm closed 5 years ago
@lukenm I looked into that issue and figured out why you only get the topmost exception. The exception chaining is working out fine. The problem is your exception handler.
If you run your script from cli, most likely your xdebug exception handler will kick in for unhandled exceptions. Per default the stacktrace for errors or exceptions is disabled in xdebug.
To properly debug your script try to change your xdebug configurations as follows (don't forget to restart fpm or whatever you use):
xdebug.show_error_trace=1
xdebug.show_exception_trace=1
Then you should get something similar to this:
PHP DomainException: Invalid return value received from the assertion body, only boolean or void can be returned in /vagrant/src/Aspect/AbstractContractAspect.php on line 96
PHP Stack trace:
PHP 1. {main}() /vagrant/demo/demo.php:0
PHP 2. Demo\Account->deposit() /vagrant/demo/demo.php:18
PHP 3. Go\Aop\Framework\DynamicClosureMethodInvocation->__invoke() /vagrant/demo/cache/_proxies/Demo/Account.php:27
PHP 4. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/vendor/goaop/framework/src/Aop/Framework/AbstractMethodInvocation.php:89
PHP 5. Go\Aop\Framework\BeforeInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 6. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/vendor/goaop/framework/src/Aop/Framework/BeforeInterceptor.php:35
PHP 7. Go\Aop\Framework\AroundInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 8. PhpDeal\Aspect\InvariantCheckerAspect->invariantContract() /vagrant/vendor/goaop/framework/src/Aop/Framework/AroundInterceptor.php:34
PHP 9. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/src/Aspect/InvariantCheckerAspect.php:53
PHP 10. Go\Aop\Framework\AroundInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 11. PhpDeal\Aspect\PostconditionCheckerAspect->postConditionContract() /vagrant/vendor/goaop/framework/src/Aop/Framework/AroundInterceptor.php:34
PHP 12. PhpDeal\Aspect\PostconditionCheckerAspect->ensureContracts() /vagrant/src/Aspect/PostconditionCheckerAspect.php:56
PHP PhpDeal\Exception\ContractViolation: Contract $this->balance == $__old->balance+$amount violated for Demo\Account->deposit in /vagrant/demo/Demo/Account.php on line 38
PHP Stack trace:
PHP 1. {main}() /vagrant/demo/demo.php:0
PHP 2. Demo\Account->deposit() /vagrant/demo/demo.php:18
PHP 3. Go\Aop\Framework\DynamicClosureMethodInvocation->__invoke() /vagrant/demo/cache/_proxies/Demo/Account.php:27
PHP 4. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/vendor/goaop/framework/src/Aop/Framework/AbstractMethodInvocation.php:89
PHP 5. Go\Aop\Framework\BeforeInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 6. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/vendor/goaop/framework/src/Aop/Framework/BeforeInterceptor.php:35
PHP 7. Go\Aop\Framework\AroundInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 8. PhpDeal\Aspect\InvariantCheckerAspect->invariantContract() /vagrant/vendor/goaop/framework/src/Aop/Framework/AroundInterceptor.php:34
PHP 9. Go\Aop\Framework\DynamicClosureMethodInvocation->proceed() /vagrant/src/Aspect/InvariantCheckerAspect.php:53
PHP 10. Go\Aop\Framework\AroundInterceptor->invoke() /vagrant/vendor/goaop/framework/src/Aop/Framework/DynamicClosureMethodInvocation.php:43
PHP 11. PhpDeal\Aspect\PostconditionCheckerAspect->postConditionContract() /vagrant/vendor/goaop/framework/src/Aop/Framework/AroundInterceptor.php:34
PHP 12. PhpDeal\Aspect\PostconditionCheckerAspect->ensureContracts() /vagrant/src/Aspect/PostconditionCheckerAspect.php:56
Which is the correct exception chain from top > down. Hope I could help you :)
As for the questions:
DomainException
is catched and wrapped in a ContractViolation
thus the exception chain.\Error
cases are handled - this should probably be added.Hi @lukenm do you need any further information on this? Otherwise I would like to close this issue.
@lukenm ping. Closing this on Wednesday
Closed due to inactivity. If you need any further help. Feel free to open again.
Hi there, would appreciate a discussion regarding this issue, thanks. On master, ref
a1e3bd9
.Expected:
Actual:
I've had some trouble trying to work this one out. I think it has something to do with the exception chaining. I've tried to create a simple test case to isolate the issue outside of the php-deal framework, but haven't been successful - my isolated tests with exception chaining always work as expected, with separate messages for each exception thrown. When running tests with the php-deal framework, the ContractViolation exception is always missing from the cli output.
When I step through the code, the ContractViolation appears to be created correctly, and I can catch it in the outer scope. It seems to be a problem with the way PHP is displaying the exceptions and stack trace.
To recreate the issue, apply the following patch, and run the demo:
I can temporarily get things working as expected by disabling the exception chaining as follows:
Some questions:
ContractViolation
exceptions. Does it make sense to chain the exceptions in this way? To me it would seem better to catch theDomainException
atAspect/AbstractContractAspect.php:89
, and throw aContractViolation
exception without chaining (theDomain Exception
doesn't appear to convey any useful information to the developer).Error
orException
types should be handled differently? It might make sense to have a different exception type in the case the syntax/parsing of the contract failed.\Error $internalError
atAspect/AbstractContractAspect.php:89
and chaining it inAspect/AbstractContractAspect.php:91
will fail due to the type hint inException/ContractViolation.php:29
. I didn't see a test case for that -Aspect/AbstractContractAspect.php:91
isn't included in the code coverage.