事情的起因是要给一个新的 hyperf2.2 项目集成单元测试
本来很简单,把以前的东西直接放进去就好了,最多增减几个 setup 的 mock 类
但是诡异的事情出现了
执行 compsoer test 出现这个错误
Script co-phounit -prepend test/ootstrap,php -C phpunitxml –colors-almays –testdox handling the test event returmed with eror code 25
当然什么都看不出来,于是加个 -vvv 的参数看看,依旧没什么有用的信息甚至还抛出来了更离奇的异常(这个至今不知道怎么回事)
pentl_fork() has been disabled for security reason in …
于是继续打 var_dump ,我想到开始是要初始化容器的,是不是在构造某个类的时候出了问题,于是在容器的 make 方法中一个个打出来,看是哪个类出了问题,果然发现了异样,有问题的项目打印出来的类名远少于正常执行的对照项目(是的,我有一个可以 run 的项目),并且最后几个类名是 Tracer 相关的,看来问题出在 Tracer 上
然后我发现了和对照项目的差异,对照项目的默认 tracer driver 是 zipkin,而当前默认的是 jaeger
于是换成默认 zipkin,成功啦
可是,为什么呢,于是我一个个类追了进去,终于在 Jaeger\ThriftUdpTransport::doOpen 中找到了原因
private function doOpen(): void
{
$this->socket = @socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$ok = @socket_connect($this->socket, $this->host, $this->port);
if ($ok === false) {
throw new TTransportException('socket_connect failed');
}
}
我发现这里的调用函数被抑制了,这是可以理解的,因为 Jaeger 只是一个监控,不应当影响主业务,但是这里的 @ 导致我无法得到任何信息,去掉 @ 后,再次执行,终于看到了清晰的报错
PHP Fatal error: Uncaught Swoole\Error: API must be called in the coroutine in @swoole-src/library/ext/sockets.php:21
很好,触及了知识盲区,不知道为什么会这样,但是可以解决,在 test/bootstrap.php 做如下修改
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_SOCKETS);
既然你要协程环境,那老子不 hook 你就是了
然后继续报错
Uncaught Swoole\Error: API must be called in the coroutine … gethostbyname
继续修改如下
! defined('SWOOLE_HOOK_FLAGS') && define('SWOOLE_HOOK_FLAGS', SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_SOCKETS ^ SWOOLE_HOOK_BLOCKING_FUNCTION);
摆平,此时默认是 jaeger 也可以正常开启测试
但是讲道理,这种情况最好是在 testing env 中给一个另外的值来处理,大可以不必死磕它