mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-04-20 16:00:20 +00:00
Spoon the TesterPlugin into the main repository
I am eating my own words this once, because having the tester plugin as a separate repository makes no sense - it is just added barriers to writing proper tests with no actual benefit. Since the tester plugin is specifically intended for CI, it doesn't make sense for it to be in its own module.
This commit is contained in:
parent
e6e28b74b5
commit
0cdf4d0c55
7
tests/plugins/TesterPlugin/plugin.yml
Normal file
7
tests/plugins/TesterPlugin/plugin.yml
Normal file
@ -0,0 +1,7 @@
|
||||
name: TesterPlugin
|
||||
main: pmmp\TesterPlugin\Main
|
||||
version: 0.1.0
|
||||
api: [3.0.0]
|
||||
load: POSTWORLD
|
||||
author: pmmp
|
||||
description: Plugin used to run tests on PocketMine-MP
|
@ -0,0 +1,50 @@
|
||||
<?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 pmmp\TesterPlugin;
|
||||
|
||||
use pocketmine\scheduler\Task;
|
||||
|
||||
class CheckTestCompletionTask extends Task{
|
||||
|
||||
/** @var Main */
|
||||
private $plugin;
|
||||
|
||||
public function __construct(Main $plugin){
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
public function onRun(int $currentTick){
|
||||
$test = $this->plugin->getCurrentTest();
|
||||
if($test === null){
|
||||
if(!$this->plugin->startNextTest()){
|
||||
$this->plugin->getScheduler()->cancelTask($this->getHandler()->getTaskId());
|
||||
$this->plugin->onAllTestsCompleted();
|
||||
}
|
||||
}elseif($test->isFinished() or $test->isTimedOut()){
|
||||
$this->plugin->onTestCompleted($test);
|
||||
}else{
|
||||
$test->tick();
|
||||
}
|
||||
}
|
||||
}
|
109
tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/Main.php
Normal file
109
tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/Main.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?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 pmmp\TesterPlugin;
|
||||
|
||||
use pocketmine\event\Listener;
|
||||
use pocketmine\event\server\ServerCommandEvent;
|
||||
use pocketmine\plugin\PluginBase;
|
||||
|
||||
class Main extends PluginBase implements Listener{
|
||||
|
||||
/** @var Test[] */
|
||||
protected $waitingTests = [];
|
||||
/** @var Test|null */
|
||||
protected $currentTest = null;
|
||||
/** @var Test[] */
|
||||
protected $completedTests = [];
|
||||
/** @var int */
|
||||
protected $currentTestNumber = 0;
|
||||
|
||||
public function onEnable(){
|
||||
$this->getServer()->getPluginManager()->registerEvents($this, $this);
|
||||
$this->getScheduler()->scheduleRepeatingTask(new CheckTestCompletionTask($this), 10);
|
||||
|
||||
$this->waitingTests = [
|
||||
new tests\AsyncTaskMemoryLeakTest($this),
|
||||
new tests\AsyncTaskMainLoggerTest($this)
|
||||
];
|
||||
}
|
||||
|
||||
public function onServerCommand(ServerCommandEvent $event){
|
||||
//The CI will send this command as a failsafe to prevent the build from hanging if the tester plugin failed to
|
||||
//run. However, if the plugin loaded successfully we don't want to allow this to stop the server as there may
|
||||
//be asynchronous tests running. Instead we cancel this and stop the server of our own accord once all tests
|
||||
//have completed.
|
||||
if($event->getCommand() === "stop"){
|
||||
$event->setCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Test|null
|
||||
*/
|
||||
public function getCurrentTest(){
|
||||
return $this->currentTest;
|
||||
}
|
||||
|
||||
public function startNextTest() : bool{
|
||||
$this->currentTest = array_shift($this->waitingTests);
|
||||
if($this->currentTest !== null){
|
||||
$this->getLogger()->notice("Running test #" . (++$this->currentTestNumber) . " (" . $this->currentTest->getName() . ")");
|
||||
$this->currentTest->start();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function onTestCompleted(Test $test){
|
||||
$message = "Finished test #" . $this->currentTestNumber . " (" . $test->getName() . "): ";
|
||||
switch($test->getResult()){
|
||||
case Test::RESULT_OK:
|
||||
$message .= "PASS";
|
||||
break;
|
||||
case Test::RESULT_FAILED:
|
||||
$message .= "FAIL";
|
||||
break;
|
||||
case Test::RESULT_ERROR:
|
||||
$message .= "ERROR";
|
||||
break;
|
||||
case Test::RESULT_WAITING:
|
||||
$message .= "TIMEOUT";
|
||||
break;
|
||||
default:
|
||||
$message .= "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
$this->getLogger()->notice($message);
|
||||
|
||||
$this->completedTests[$this->currentTestNumber] = $test;
|
||||
$this->currentTest = null;
|
||||
}
|
||||
|
||||
public function onAllTestsCompleted(){
|
||||
$this->getLogger()->notice("All tests finished, stopping the server");
|
||||
$this->getServer()->shutdown();
|
||||
}
|
||||
}
|
87
tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/Test.php
Normal file
87
tests/plugins/TesterPlugin/src/pmmp/TesterPlugin/Test.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?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 pmmp\TesterPlugin;
|
||||
|
||||
abstract class Test{
|
||||
const RESULT_WAITING = -1;
|
||||
const RESULT_OK = 0;
|
||||
const RESULT_FAILED = 1;
|
||||
const RESULT_ERROR = 2;
|
||||
|
||||
private $plugin;
|
||||
private $result = Test::RESULT_WAITING;
|
||||
private $startTime;
|
||||
private $timeout = 60; //seconds
|
||||
|
||||
public function __construct(Main $plugin){
|
||||
$this->plugin = $plugin;
|
||||
}
|
||||
|
||||
public function getPlugin() : Main{
|
||||
return $this->plugin;
|
||||
}
|
||||
|
||||
final public function start(){
|
||||
$this->startTime = time();
|
||||
try{
|
||||
$this->run();
|
||||
}catch(TestFailedException $e){
|
||||
$this->getPlugin()->getLogger()->error($e->getMessage());
|
||||
$this->setResult(Test::RESULT_FAILED);
|
||||
}catch(\Throwable $e){
|
||||
$this->getPlugin()->getLogger()->logException($e);
|
||||
$this->setResult(Test::RESULT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function tick(){
|
||||
|
||||
}
|
||||
|
||||
abstract public function run();
|
||||
|
||||
public function isFinished() : bool{
|
||||
return $this->result !== Test::RESULT_WAITING;
|
||||
}
|
||||
|
||||
public function isTimedOut() : bool{
|
||||
return !$this->isFinished() and time() - $this->timeout > $this->startTime;
|
||||
}
|
||||
|
||||
protected function setTimeout(int $timeout){
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
public function getResult() : int{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function setResult(int $result){
|
||||
$this->result = $result;
|
||||
}
|
||||
|
||||
abstract public function getName() : string;
|
||||
|
||||
abstract public function getDescription() : string;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?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 pmmp\TesterPlugin;
|
||||
|
||||
class TestFailedException extends \Exception{
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
<?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 pmmp\TesterPlugin\tests;
|
||||
|
||||
use pmmp\TesterPlugin\Test;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\MainLogger;
|
||||
|
||||
class AsyncTaskMainLoggerTest extends Test{
|
||||
|
||||
public function run(){
|
||||
$this->getPlugin()->getServer()->getAsyncPool()->submitTask(new class($this) extends AsyncTask{
|
||||
|
||||
/** @var bool */
|
||||
protected $success = false;
|
||||
|
||||
public function __construct(AsyncTaskMainLoggerTest $testObject){
|
||||
$this->storeLocal($testObject);
|
||||
}
|
||||
|
||||
public function onRun(){
|
||||
ob_start();
|
||||
MainLogger::getLogger()->info("Testing");
|
||||
if(strpos(ob_get_contents(), "Testing") !== false){
|
||||
$this->success = true;
|
||||
}
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
public function onCompletion(Server $server){
|
||||
/** @var AsyncTaskMainLoggerTest $test */
|
||||
$test = $this->fetchLocal();
|
||||
$test->setResult($this->success ? Test::RESULT_OK : Test::RESULT_FAILED);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "MainLogger::getLogger() works in AsyncTasks";
|
||||
}
|
||||
|
||||
public function getDescription() : string{
|
||||
return "Verifies that the MainLogger is accessible by MainLogger::getLogger() in an AsyncTask";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?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 pmmp\TesterPlugin\tests;
|
||||
|
||||
use pmmp\TesterPlugin\Test;
|
||||
use pocketmine\scheduler\AsyncTask;
|
||||
|
||||
class AsyncTaskMemoryLeakTest extends Test{
|
||||
|
||||
public function run(){
|
||||
$this->getPlugin()->getServer()->getAsyncPool()->submitTask(new TestAsyncTask());
|
||||
}
|
||||
|
||||
public function tick(){
|
||||
if(TestAsyncTask::$destroyed === true){
|
||||
$this->setResult(Test::RESULT_OK);
|
||||
}
|
||||
}
|
||||
|
||||
public function getName() : string{
|
||||
return "AsyncTask memory leak after completion";
|
||||
}
|
||||
|
||||
public function getDescription() : string{
|
||||
return "Regression test for AsyncTasks objects not being destroyed after completion";
|
||||
}
|
||||
}
|
||||
|
||||
class TestAsyncTask extends AsyncTask{
|
||||
public static $destroyed = false;
|
||||
|
||||
public function onRun(){
|
||||
usleep(50 * 1000); //1 server tick
|
||||
}
|
||||
|
||||
public function __destruct(){
|
||||
self::$destroyed = true;
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@ fi
|
||||
mkdir "$DATA_DIR"
|
||||
mkdir "$PLUGINS_DIR"
|
||||
mv DevTools.phar "$PLUGINS_DIR"
|
||||
cp -r tests/plugins/PocketMine-TesterPlugin "$PLUGINS_DIR"
|
||||
cp -r tests/plugins/TesterPlugin "$PLUGINS_DIR"
|
||||
echo -e "stop\n" | "$PHP_BINARY" PocketMine-MP.phar --no-wizard --disable-ansi --disable-readline --debug.level=2 --data="$DATA_DIR" --plugins="$PLUGINS_DIR" --anonymous-statistics.enabled=0 --settings.async-workers="$PM_WORKERS" --settings.enable-dev-builds=1
|
||||
|
||||
output=$(grep '\[TesterPlugin\]' "$DATA_DIR/server.log")
|
||||
|
Loading…
x
Reference in New Issue
Block a user