mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-01-18 22:12:18 +00:00
9195c88670
Support for this was introduced in PHP 8.0, though not mentioned in any changelog: php/php-src#5777 This simplifies the subprocess handling considerably. However, there is a potential for problems if PHP generates any E_* errors, since these get written to STDOUT as well. To avoid error messages being treated as a command, a hash is attached to each IPC message, seeded with an incrementing counter. This prevents error messages causing command replays or unintended commands. Unfortunately, PHP doesn't support binding pipes other than stdin/stdout/stderr on Windows for the child process, so we have to use stdout for this. In the future, if it becomes possible, a dedicated pipe for the purpose should be introduced. We'd need something like php://fd/<number> to work on Windows.
93 lines
2.9 KiB
PHP
93 lines
2.9 KiB
PHP
<?php
|
|
|
|
/*
|
|
*
|
|
* ____ _ _ __ __ _ __ __ ____
|
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* @author PocketMine Team
|
|
* @link http://www.pocketmine.net/
|
|
*
|
|
*
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace pocketmine\console;
|
|
|
|
use PHPUnit\Framework\TestCase;
|
|
use function mt_rand;
|
|
use function str_repeat;
|
|
|
|
final class ConsoleReaderChildProcessUtilsTest extends TestCase{
|
|
|
|
/**
|
|
* @phpstan-return \Generator<int, array{string}, void, void>
|
|
*/
|
|
public static function commandStringProvider() : \Generator{
|
|
yield ["stop"];
|
|
yield ["pocketmine:status"];
|
|
yield [str_repeat("s", 1000)];
|
|
yield ["time set day"];
|
|
yield ["give \"Steve\" golden_apple"];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider commandStringProvider
|
|
*/
|
|
public function testCreateParseSymmetry(string $input) : void{
|
|
$counterCreate = $counterParse = mt_rand();
|
|
$message = ConsoleReaderChildProcessUtils::createMessage($input, $counterCreate);
|
|
$parsedInput = ConsoleReaderChildProcessUtils::parseMessage($message, $counterParse);
|
|
|
|
self::assertSame($input, $parsedInput);
|
|
}
|
|
|
|
public function testCreateMessage() : void{
|
|
$counter = 0;
|
|
|
|
ConsoleReaderChildProcessUtils::createMessage("", $counter);
|
|
self::assertSame(1, $counter, "createMessage should always bump the counter");
|
|
}
|
|
|
|
/**
|
|
* @phpstan-return \Generator<int, array{string, bool}, void, void>
|
|
*/
|
|
public static function parseMessageProvider() : \Generator{
|
|
$counter = 0;
|
|
yield [ConsoleReaderChildProcessUtils::createMessage("", $counter), true];
|
|
|
|
yield ["", false]; //keepalive message, doesn't bump counter
|
|
|
|
$counter = 1;
|
|
yield [ConsoleReaderChildProcessUtils::createMessage("", $counter), false]; //mismatched counter
|
|
|
|
$counter = 0;
|
|
yield ["a" . ConsoleReaderChildProcessUtils::TOKEN_DELIMITER . "b", false]; //message with delimiter but not a valid IPC message
|
|
}
|
|
|
|
/**
|
|
* @dataProvider parseMessageProvider
|
|
*/
|
|
public static function testParseMessage(string $message, bool $valid) : void{
|
|
$counter = $oldCounter = 0;
|
|
|
|
$input = ConsoleReaderChildProcessUtils::parseMessage($message, $counter);
|
|
if(!$valid){
|
|
self::assertNull($input, "Result should be null on invalid message");
|
|
self::assertSame($oldCounter, $counter, "Counter shouldn't be bumped on invalid message");
|
|
}else{
|
|
self::assertNotNull($input, "This was a valid message, expected a result");
|
|
self::assertSame($oldCounter + 1, $counter, "Counter should be bumped on valid message parse");
|
|
}
|
|
}
|
|
}
|