diff --git a/bin/phpunit-swoole b/bin/phpunit-swoole deleted file mode 100755 index 9a2898b1..00000000 --- a/bin/phpunit-swoole +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env php - SWOOLE_LOG_INFO, - 'trace_flags' => 0, -]); - -/* - * This file is part of PHPUnit. - * - * (c) Sebastian Bergmann - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -if (PHP_VERSION_ID <= 70100) { - fwrite( - STDERR, - sprintf( - 'This version of PHPUnit is supported on PHP 7.1 and above.' . PHP_EOL . - 'You are using PHP %s (%s).' . PHP_EOL, - PHP_VERSION, - PHP_BINARY - ) - ); - - exit(1); -} - -if (!ini_get('date.timezone')) { - ini_set('date.timezone', 'Asia/Shanghai'); -} - -require $root . '/vendor/autoload.php'; - -const ZM_VERSION_ID = ConsoleApplication::VERSION_ID; -const ZM_VERSION = ConsoleApplication::VERSION; - -// 模拟define -const ZM_PROCESS_MASTER = 1; -const ZM_PROCESS_MANAGER = 2; -const ZM_PROCESS_WORKER = 4; -const ZM_PROCESS_USER = 8; -const ZM_PROCESS_TASKWORKER = 16; - -define('FRAMEWORK_ROOT_DIR', $root); -define('WORKING_DIR', $root); -const SOURCE_ROOT_DIR = WORKING_DIR; -define('LOAD_MODE', is_dir(SOURCE_ROOT_DIR . '/src/ZM') ? 0 : 1); -chdir(__DIR__ . '/../'); - -$options = array_map(function ($x) { - return $x->getDefault(); -}, ServerStartCommand::exportDefinition()->getOptions()); -$options['disable-safe-exit'] = true; -$options['worker-num'] = 1; -$options['private-mode'] = true; -$options['log-error'] = true; - -spl_autoload_register(static function ($class) { - $map = [ - TestRunner::class => 'vendor/phpunit/phpunit/src/TextUI/TestRunner.php', - Version::class => 'vendor/phpunit/phpunit/src/Runner/Version.php', - ]; - if (isset($map[$class])) { - $source = file_get_contents(SOURCE_ROOT_DIR . '/' . $map[$class]); - $source = str_replace(['#StandWith', 'Ukraine', 'declare(strict_types=1);'], '', $source); - eval('?>' . $source); - } -}, true, true); - -Console::setLevel(0); -try { - $framework = new Framework($options); -} catch (ConfigException $e) { - echo $e->getMessage(); - exit(1); -} -$start = new OnStart(); -$start->method = function () { - try { - Console::setLevel(ZM_TEST_LOG_DEBUG ? 4 : 0); - $retcode = PHPUnit\TextUI\Command::main(false); - } finally { - Console::setLevel(0); - ZMUtil::stop(($retcode ?? 1) !== 0); - } -}; -EventManager::addEvent(OnStart::class, $start); - -$framework->start(); - -Swoole\Event::wait(); -if (ZMAtomic::get('stop_signal')->get() === 2) { - exit(1); -} diff --git a/bin/phpunit-zm b/bin/phpunit-zm new file mode 100755 index 00000000..f93908b9 --- /dev/null +++ b/bin/phpunit-zm @@ -0,0 +1,46 @@ +#!/usr/bin/env php +addEventListener(WorkerStartEvent::getName(), function () { + try { + $retcode = Command::main(false); + } finally { + global $_swoole_atomic; + $_swoole_atomic->set($retcode ?? 0); + Framework::getInstance()->stop(); + } +}, 1); + +try { + $options = ServerStartCommand::exportOptionArray(); + $options['driver'] = 'swoole'; + $options['worker-num'] = 1; + $options['private-mode'] = true; + (new Framework($options))->init()->start(); + + exit($_swoole_atomic->get()); +} catch (Throwable $e) { + echo $e->getMessage() . PHP_EOL; + exit(1); +} diff --git a/composer.json b/composer.json index e533ab30..672e4496 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ }, "bin": [ "bin/gendoc", - "bin/phpunit-swoole", + "bin/phpunit-zm", "bin/zhamao" ], "config": { diff --git a/src/ZM/Framework.php b/src/ZM/Framework.php index afb97c45..52cf3712 100644 --- a/src/ZM/Framework.php +++ b/src/ZM/Framework.php @@ -18,7 +18,6 @@ use OneBot\Driver\Workerman\Worker; use OneBot\Driver\Workerman\WorkermanDriver; use OneBot\Util\Singleton; use Phar; -use Swoole\Process; use ZM\Command\Server\ServerStartCommand; use ZM\Config\ZMConfig; use ZM\Event\EventProvider; @@ -28,6 +27,7 @@ use ZM\Event\Listener\MasterEventListener; use ZM\Event\Listener\WorkerEventListener; use ZM\Exception\ConfigException; use ZM\Exception\InitException; +use ZM\Exception\ZMKnownException; use ZM\Logger\ConsoleLogger; use ZM\Logger\TablePrinter; use ZM\Process\ProcessStateManager; @@ -107,16 +107,21 @@ class Framework * 停止框架运行 * * 未测试 + * @throws ZMKnownException */ public function stop() { switch ($this->driver->getName()) { case 'swoole': /* @phpstan-ignore-next-line */ - Process::kill($this->driver->getSwooleServer()->master_pid, SIGTERM); + $this->driver->getSwooleServer()->shutdown(); break; case 'workerman': - Worker::stopAll(); + if (extension_loaded('posix')) { + posix_kill(ProcessStateManager::getProcessState(ZM_PROCESS_MASTER)['pid'], SIGTERM); + } else { + Worker::stopAll(); + } break; } } diff --git a/tests/ZM/Utils/ReflectionUtilTest.php b/tests/ZM/Utils/ReflectionUtilTest.php index c7651c86..9f4f567f 100644 --- a/tests/ZM/Utils/ReflectionUtilTest.php +++ b/tests/ZM/Utils/ReflectionUtilTest.php @@ -6,7 +6,11 @@ namespace Tests\ZM\Utils; use Closure; use PHPUnit\Framework\TestCase; +use ReflectionClass; +use ReflectionFunction; use ReflectionFunctionAbstract; +use ReflectionMethod; +use stdClass; use ZM\Utils\ReflectionUtil; /** @@ -26,7 +30,7 @@ class ReflectionUtilTest extends TestCase public function testGetParameterClassName(): void { - $class = new \ReflectionClass(ReflectionUtilTestClass::class); + $class = new ReflectionClass(ReflectionUtilTestClass::class); $method = $class->getMethod('method'); [$string_parameter, $object_parameter] = $method->getParameters(); @@ -51,7 +55,7 @@ class ReflectionUtilTest extends TestCase 'closure' => [Closure::fromCallable([$this, 'testVariableToString']), 'closure'], 'string' => ['string', 'string'], 'array' => [['123', '42', 'hello', 122], 'array["123","42","hello",122]'], - 'object' => [new \stdClass(), 'stdClass'], + 'object' => [new stdClass(), 'stdClass'], 'resource' => [fopen('php://memory', 'rb'), 'resource(stream)'], 'null' => [null, 'null'], 'boolean 1' => [true, 'true'], @@ -76,11 +80,11 @@ class ReflectionUtilTest extends TestCase }; return [ - 'callable' => [[new ReflectionUtilTestClass(), 'method'], new \ReflectionMethod(ReflectionUtilTestClass::class, 'method')], - 'static callable' => [[ReflectionUtilTestClass::class, 'staticMethod'], new \ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], - 'class::method' => [ReflectionUtilTestClass::class . '::staticMethod', new \ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], - 'invokable class' => [new InvokableClass(), new \ReflectionMethod(InvokableClass::class, '__invoke')], - 'closure' => [$closure, new \ReflectionFunction($closure)], + 'callable' => [[new ReflectionUtilTestClass(), 'method'], new ReflectionMethod(ReflectionUtilTestClass::class, 'method')], + 'static callable' => [[ReflectionUtilTestClass::class, 'staticMethod'], new ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], + 'class::method' => [ReflectionUtilTestClass::class . '::staticMethod', new ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], + 'invokable class' => [new InvokableClass(), new ReflectionMethod(InvokableClass::class, '__invoke')], + 'closure' => [$closure, new ReflectionFunction($closure)], ]; } } diff --git a/tests/ZM/Utils/ZMUtilTest.php b/tests/ZM/Utils/ZMUtilTest.php new file mode 100644 index 00000000..8c5bc84d --- /dev/null +++ b/tests/ZM/Utils/ZMUtilTest.php @@ -0,0 +1,13 @@ +assertEquals('zhamao/framework', ZMUtil::getComposerMetadata()['name']); + } +} diff --git a/tests/ZM/API/CQTest.php b/tests_old/ZM/API/CQTest.php similarity index 100% rename from tests/ZM/API/CQTest.php rename to tests_old/ZM/API/CQTest.php diff --git a/tests/ZM/Config/ZMConfigTest.php b/tests_old/ZM/Config/ZMConfigTest.php similarity index 100% rename from tests/ZM/Config/ZMConfigTest.php rename to tests_old/ZM/Config/ZMConfigTest.php diff --git a/tests/ZM/Container/ContainerCallTest.php b/tests_old/ZM/Container/ContainerCallTest.php similarity index 100% rename from tests/ZM/Container/ContainerCallTest.php rename to tests_old/ZM/Container/ContainerCallTest.php diff --git a/tests/ZM/Container/ContainerTest.php b/tests_old/ZM/Container/ContainerTest.php similarity index 100% rename from tests/ZM/Container/ContainerTest.php rename to tests_old/ZM/Container/ContainerTest.php diff --git a/tests/ZM/Container/WorkerContainerTest.php b/tests_old/ZM/Container/WorkerContainerTest.php similarity index 100% rename from tests/ZM/Container/WorkerContainerTest.php rename to tests_old/ZM/Container/WorkerContainerTest.php diff --git a/tests/ZM/Event/EventMapIteratorTest.php b/tests_old/ZM/Event/EventMapIteratorTest.php similarity index 100% rename from tests/ZM/Event/EventMapIteratorTest.php rename to tests_old/ZM/Event/EventMapIteratorTest.php diff --git a/tests/ZM/GlobalFunctionsTest.php b/tests_old/ZM/GlobalFunctionsTest.php similarity index 100% rename from tests/ZM/GlobalFunctionsTest.php rename to tests_old/ZM/GlobalFunctionsTest.php diff --git a/tests/ZM/Store/LightCacheTest.php b/tests_old/ZM/Store/LightCacheTest.php similarity index 100% rename from tests/ZM/Store/LightCacheTest.php rename to tests_old/ZM/Store/LightCacheTest.php diff --git a/tests/ZM/Utils/CommandInfoUtilTest.php b/tests_old/ZM/Utils/CommandInfoUtilTest.php similarity index 100% rename from tests/ZM/Utils/CommandInfoUtilTest.php rename to tests_old/ZM/Utils/CommandInfoUtilTest.php diff --git a/tests/ZM/Utils/DataProviderTest.php b/tests_old/ZM/Utils/DataProviderTest.php similarity index 100% rename from tests/ZM/Utils/DataProviderTest.php rename to tests_old/ZM/Utils/DataProviderTest.php diff --git a/tests/ZM/Utils/HttpUtilTest.php b/tests_old/ZM/Utils/HttpUtilTest.php similarity index 100% rename from tests/ZM/Utils/HttpUtilTest.php rename to tests_old/ZM/Utils/HttpUtilTest.php diff --git a/tests/ZM/Utils/MacroableTest.php b/tests_old/ZM/Utils/MacroableTest.php similarity index 100% rename from tests/ZM/Utils/MacroableTest.php rename to tests_old/ZM/Utils/MacroableTest.php diff --git a/tests/ZM/Utils/MessageUtilTest.php b/tests_old/ZM/Utils/MessageUtilTest.php similarity index 100% rename from tests/ZM/Utils/MessageUtilTest.php rename to tests_old/ZM/Utils/MessageUtilTest.php diff --git a/tests_old/ZM/Utils/ReflectionUtilTest.php b/tests_old/ZM/Utils/ReflectionUtilTest.php new file mode 100644 index 00000000..c7651c86 --- /dev/null +++ b/tests_old/ZM/Utils/ReflectionUtilTest.php @@ -0,0 +1,104 @@ +assertFalse(ReflectionUtil::isNonStaticMethod([ReflectionUtilTestClass::class, 'staticMethod'])); + } + + public function testDetermineNonStaticMethod(): void + { + $this->assertTrue(ReflectionUtil::isNonStaticMethod([ReflectionUtilTestClass::class, 'method'])); + } + + public function testGetParameterClassName(): void + { + $class = new \ReflectionClass(ReflectionUtilTestClass::class); + $method = $class->getMethod('method'); + [$string_parameter, $object_parameter] = $method->getParameters(); + + $this->assertNull(ReflectionUtil::getParameterClassName($string_parameter)); + $this->assertSame(ReflectionUtilTestClass::class, ReflectionUtil::getParameterClassName($object_parameter)); + } + + /** + * @dataProvider provideTestVariableToString + * @param mixed $variable + */ + public function testVariableToString($variable, string $expected): void + { + $this->assertSame($expected, ReflectionUtil::variableToString($variable)); + } + + public function provideTestVariableToString(): array + { + return [ + 'callable' => [[new ReflectionUtilTestClass(), 'method'], ReflectionUtilTestClass::class . '@method'], + 'static callable' => [[ReflectionUtilTestClass::class, 'staticMethod'], ReflectionUtilTestClass::class . '::staticMethod'], + 'closure' => [Closure::fromCallable([$this, 'testVariableToString']), 'closure'], + 'string' => ['string', 'string'], + 'array' => [['123', '42', 'hello', 122], 'array["123","42","hello",122]'], + 'object' => [new \stdClass(), 'stdClass'], + 'resource' => [fopen('php://memory', 'rb'), 'resource(stream)'], + 'null' => [null, 'null'], + 'boolean 1' => [true, 'true'], + 'boolean 2' => [false, 'false'], + 'float' => [123.456, '123.456'], + 'integer' => [123, '123'], + ]; + } + + /** + * @dataProvider provideTestGetCallReflector + * @param mixed $callback + */ + public function testGetCallReflector($callback, ReflectionFunctionAbstract $expected): void + { + $this->assertEquals($expected, ReflectionUtil::getCallReflector($callback)); + } + + public function provideTestGetCallReflector(): array + { + $closure = function () { + }; + + return [ + 'callable' => [[new ReflectionUtilTestClass(), 'method'], new \ReflectionMethod(ReflectionUtilTestClass::class, 'method')], + 'static callable' => [[ReflectionUtilTestClass::class, 'staticMethod'], new \ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], + 'class::method' => [ReflectionUtilTestClass::class . '::staticMethod', new \ReflectionMethod(ReflectionUtilTestClass::class, 'staticMethod')], + 'invokable class' => [new InvokableClass(), new \ReflectionMethod(InvokableClass::class, '__invoke')], + 'closure' => [$closure, new \ReflectionFunction($closure)], + ]; + } +} + +class ReflectionUtilTestClass +{ + public function method(string $string, ReflectionUtilTestClass $class): void + { + } + + public static function staticMethod(string $string, ReflectionUtilTestClass $class): void + { + } +} + +class InvokableClass +{ + public function __invoke(): void + { + } +} diff --git a/tests/ZM/Utils/SingletonTraitTest.php b/tests_old/ZM/Utils/SingletonTraitTest.php similarity index 100% rename from tests/ZM/Utils/SingletonTraitTest.php rename to tests_old/ZM/Utils/SingletonTraitTest.php diff --git a/tests/ZM/Utils/TerminalTest.php b/tests_old/ZM/Utils/TerminalTest.php similarity index 100% rename from tests/ZM/Utils/TerminalTest.php rename to tests_old/ZM/Utils/TerminalTest.php diff --git a/tests_old/bootstrap.php b/tests_old/bootstrap.php new file mode 100644 index 00000000..a075e1e8 --- /dev/null +++ b/tests_old/bootstrap.php @@ -0,0 +1,5 @@ +