Merge pull request #152 from zhamao-robot/more-windows-support

add phpunit windows support
This commit is contained in:
Jerry Ma
2022-08-22 21:38:21 +08:00
committed by GitHub
10 changed files with 91 additions and 20 deletions

View File

@@ -26,7 +26,7 @@ jobs:
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }}
strategy: strategy:
matrix: matrix:
operating-system: [ "ubuntu-latest", "macos-latest" ] operating-system: [ "ubuntu-latest", "macos-latest", "windows-latest" ]
php-versions: [ "7.4", "8.0", "8.1" ] php-versions: [ "7.4", "8.0", "8.1" ]
steps: steps:
- name: Checkout code - name: Checkout code
@@ -36,7 +36,7 @@ jobs:
uses: "shivammathur/setup-php@v2" uses: "shivammathur/setup-php@v2"
with: with:
php-version: ${{ matrix.php-versions }} php-version: ${{ matrix.php-versions }}
extensions: swoole, posix, json extensions: swoole, posix, json, mbstring
env: env:
SWOOLE_CONFIGURE_OPTS: --enable-openssl SWOOLE_CONFIGURE_OPTS: --enable-openssl
@@ -63,6 +63,9 @@ jobs:
- name: Run Static Analysis - name: Run Static Analysis
run: "composer analyse" run: "composer analyse"
- name: Run PHPUnit
run: "composer test"
cs-check: cs-check:
name: PHP CS Fixer Check name: PHP CS Fixer Check
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@@ -7,38 +7,46 @@ const ZM_TEST_LOG_DEBUG = false;
use OneBot\Driver\Event\Process\WorkerStartEvent; use OneBot\Driver\Event\Process\WorkerStartEvent;
use PHPUnit\TextUI\Command; use PHPUnit\TextUI\Command;
use Swoole\Atomic;
use ZM\Command\Server\ServerStartCommand; use ZM\Command\Server\ServerStartCommand;
use ZM\Event\EventProvider;
use ZM\Framework; use ZM\Framework;
use ZM\Logger\ConsoleLogger; use ZM\Logger\ConsoleLogger;
use ZM\Store\MockAtomic;
$root = dirname(__DIR__); // 引入自动加载
require dirname(__DIR__) . '/vendor/autoload.php';
require $root . '/vendor/autoload.php';
// 声明一个全局的原子计数,用于保存整个进程的退出状态码
global $_swoole_atomic; global $_swoole_atomic;
$_swoole_atomic = new \Swoole\Atomic(); // Windows 没有 Swoole所以就使用了一个假的原子计数器反正 Windows 只有单进程
$_swoole_atomic = class_exists('\\Swoole\\Atomic') ? new Atomic() : new MockAtomic();
ob_logger_register(new ConsoleLogger('error')); // 注册 Logger 等级
ob_logger_register(new ConsoleLogger(ZM_TEST_LOG_DEBUG ? 'debug' : 'error'));
// 使用框架自身的 EventProvider
global $ob_event_provider; global $ob_event_provider;
$ob_event_provider = new \ZM\Event\EventProvider(); $ob_event_provider = new EventProvider();
// 注册一个最低级别的 WorkerStart 事件,用于在框架的事件初始化之后开始运行 PHPUnit
ob_event_provider()->addEventListener(WorkerStartEvent::getName(), function () { ob_event_provider()->addEventListener(WorkerStartEvent::getName(), function () {
try { try {
// 不退出,而是返回 code
$retcode = Command::main(false); $retcode = Command::main(false);
} finally { } finally {
global $_swoole_atomic; global $_swoole_atomic;
$_swoole_atomic->set($retcode ?? 0); $_swoole_atomic->set($retcode ?? 0);
Framework::getInstance()->stop(); Framework::getInstance()->stop($retcode ?? 0);
} }
}, 1); }, 1);
try { try {
$options = ServerStartCommand::exportOptionArray(); $options = ServerStartCommand::exportOptionArray();
$options['driver'] = 'swoole'; $options['driver'] = DIRECTORY_SEPARATOR === '/' ? 'swoole' : 'workerman';
$options['worker-num'] = 1; $options['worker-num'] = 1;
$options['private-mode'] = true; $options['private-mode'] = true;
(new Framework($options))->init()->start(); (new Framework($options))->init()->start();
exit($_swoole_atomic->get()); exit($_swoole_atomic->get());
} catch (Throwable $e) { } catch (Throwable $e) {
echo $e->getMessage() . PHP_EOL; echo $e->getMessage() . PHP_EOL;

3
bin/phpunit-zm.bat Normal file
View File

@@ -0,0 +1,3 @@
@echo off
php %~dp0phpunit-zm %*

View File

@@ -84,7 +84,7 @@ $config['file_server'] = [
$config['mysql'] = [ $config['mysql'] = [
[ [
'pool_name' => '', // 默认只有一个空名称的连接池,如果需要多个连接池,请复制此段配置并修改参数和名称 'pool_name' => '', // 默认只有一个空名称的连接池,如果需要多个连接池,请复制此段配置并修改参数和名称
'host' => '127.0.0.1', // 填写数据库服务器地址后才会创建数据库连接 'host' => '', // 填写数据库服务器地址后才会创建数据库连接
'port' => 3306, 'port' => 3306,
'username' => 'root', 'username' => 'root',
'password' => 'ZhamaoTEST', 'password' => 'ZhamaoTEST',

View File

@@ -130,7 +130,8 @@ class AnnotationHandler
{ {
// 由于3.0有额外的插件模式支持,所以注解就不再提供独立的闭包函数调用支持了 // 由于3.0有额外的插件模式支持,所以注解就不再提供独立的闭包函数调用支持了
// 提取要调用的目标类和方法名称 // 提取要调用的目标类和方法名称
$target_class = new ($v->class)(); $class = $v->class;
$target_class = new $class();
$target_method = $v->method; $target_method = $v->method;
// 先执行规则失败就返回false // 先执行规则失败就返回false
if ($rule_callback !== null && !$rule_callback($v)) { if ($rule_callback !== null && !$rule_callback($v)) {

View File

@@ -97,7 +97,9 @@ class WorkerEventListener
public function onWorkerStop999() public function onWorkerStop999()
{ {
logger()->debug('Worker #' . ProcessManager::getProcessId() . ' stopping'); logger()->debug('Worker #' . ProcessManager::getProcessId() . ' stopping');
ProcessStateManager::removeProcessState(ZM_PROCESS_WORKER, ProcessManager::getProcessId()); if (DIRECTORY_SEPARATOR !== '\\') {
ProcessStateManager::removeProcessState(ZM_PROCESS_WORKER, ProcessManager::getProcessId());
}
} }
/** /**

View File

@@ -109,7 +109,7 @@ class Framework
* 未测试 * 未测试
* @throws ZMKnownException * @throws ZMKnownException
*/ */
public function stop() public function stop(int $retcode = 0)
{ {
switch ($this->driver->getName()) { switch ($this->driver->getName()) {
case 'swoole': case 'swoole':
@@ -120,7 +120,7 @@ class Framework
if (extension_loaded('posix')) { if (extension_loaded('posix')) {
posix_kill(ProcessStateManager::getProcessState(ZM_PROCESS_MASTER)['pid'], SIGTERM); posix_kill(ProcessStateManager::getProcessState(ZM_PROCESS_MASTER)['pid'], SIGTERM);
} else { } else {
Worker::stopAll(); Worker::stopAll($retcode);
} }
break; break;
} }

View File

@@ -9,10 +9,7 @@ use ZM\Store\FileSystem;
class ProcessStateManager class ProcessStateManager
{ {
/** public static array $process_mode = [];
* @var array
*/
public static $process_mode;
/** /**
* @param null|int|string $id_or_name * @param null|int|string $id_or_name

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace ZM\Store;
class MockAtomic
{
private int $num = 0;
public function set(int $num)
{
$this->num = $num;
}
public function get(): int
{
return $this->num;
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Tests\ZM\Middleware;
use PHPUnit\Framework\TestCase;
use ZM\Logger\ConsoleLogger;
use ZM\Middleware\Pipeline;
use ZM\Middleware\TimerMiddleware;
/**
* @internal
*/
class PipelineTest extends TestCase
{
public function setUp(): void
{
ob_logger_register(new ConsoleLogger('debug'));
}
public function tearDown(): void
{
ob_logger_register(new ConsoleLogger('error'));
}
public function testPipeline()
{
$pipe = new Pipeline();
$a = $pipe->send('APP')
->through([TimerMiddleware::class])
->then(function (string $value) {
return $value;
});
$this->assertEquals('APP', $a);
}
}