mirror of
https://github.com/e107inc/e107.git
synced 2025-08-02 20:57:26 +02:00
Refactored E107Base suite cleanup into "Preparer" classes
Now works with the best of both worlds: * Barebones cleanup in slow Windows environments * Git snapshots in other Git environments
This commit is contained in:
66
lib/preparers/E107Preparer.php
Normal file
66
lib/preparers/E107Preparer.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class E107Preparer implements Preparer
|
||||||
|
{
|
||||||
|
const TEST_HASH = '000000test'; // see e107_config.php
|
||||||
|
|
||||||
|
public function snapshot()
|
||||||
|
{
|
||||||
|
return $this->deleteHashDirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rollback()
|
||||||
|
{
|
||||||
|
return $this->deleteHashDirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function deleteHashDirs()
|
||||||
|
{
|
||||||
|
$system = APP_PATH."/e107_system/".self::TEST_HASH;
|
||||||
|
$this->deleteDir($system);
|
||||||
|
|
||||||
|
$media = APP_PATH."/e107_media/".self::TEST_HASH;
|
||||||
|
$this->deleteDir($media);
|
||||||
|
|
||||||
|
if(is_dir($system))
|
||||||
|
{
|
||||||
|
throw new Exception(get_class() . " couldn't delete ".$system);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteDir($dirPath)
|
||||||
|
{
|
||||||
|
codecept_debug(get_class() . ' is deleting '.escapeshellarg($dirPath).'…');
|
||||||
|
|
||||||
|
if(!is_dir($dirPath))
|
||||||
|
{
|
||||||
|
// echo ($dirPath . "must be a directory");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(substr($dirPath, strlen($dirPath) - 1, 1) != '/')
|
||||||
|
{
|
||||||
|
$dirPath .= '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = glob($dirPath . '*', GLOB_MARK);
|
||||||
|
|
||||||
|
foreach($files as $file)
|
||||||
|
{
|
||||||
|
if(is_dir($file))
|
||||||
|
{
|
||||||
|
$this->deleteDir($file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_dir($dirPath))
|
||||||
|
{
|
||||||
|
rmdir($dirPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
111
lib/preparers/GitPreparer.php
Normal file
111
lib/preparers/GitPreparer.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class GitPreparer implements Preparer
|
||||||
|
{
|
||||||
|
const TEST_IN_PROGRESS = 'TEST-IN-PROGRESS';
|
||||||
|
const TEST_IN_PROGRESS_FILE = APP_PATH."/".self::TEST_IN_PROGRESS;
|
||||||
|
|
||||||
|
public function snapshot()
|
||||||
|
{
|
||||||
|
return $this->setVcsInProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rollback()
|
||||||
|
{
|
||||||
|
return $this->unsetVcsInProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setVcsInProgress()
|
||||||
|
{
|
||||||
|
if ($this->isVcsInProgress())
|
||||||
|
{
|
||||||
|
$this->debug('Git repo shows test in progress. Probably crashed test.');
|
||||||
|
$this->unsetVcsInProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->debug('Setting test locks in Git…');
|
||||||
|
|
||||||
|
touch(self::TEST_IN_PROGRESS_FILE);
|
||||||
|
$this->runCommand('git add -f '.escapeshellarg(self::TEST_IN_PROGRESS_FILE));
|
||||||
|
$this->runCommand('git add -A');
|
||||||
|
|
||||||
|
$commit_command = 'git commit -a --no-gpg-sign ' .
|
||||||
|
"-m '".self::TEST_IN_PROGRESS."! If test crashed, run `git log -1` for instructions' " .
|
||||||
|
"-m 'Running the test again after fixing the crash will clear this commit\nand any related stashes.' " .
|
||||||
|
"-m 'Alternatively, run these commands to restore the repository to its\npre-test state:' ";
|
||||||
|
$unsetVcsInProgress_commands = [
|
||||||
|
'git reset --hard HEAD',
|
||||||
|
'git clean -fdx',
|
||||||
|
'git stash pop',
|
||||||
|
'git reset --mixed HEAD^',
|
||||||
|
'rm -fv '.escapeshellarg(self::TEST_IN_PROGRESS)
|
||||||
|
];
|
||||||
|
foreach($unsetVcsInProgress_commands as $command)
|
||||||
|
{
|
||||||
|
$commit_command .= "-m ".escapeshellarg($command)." ";
|
||||||
|
}
|
||||||
|
$this->runCommand($commit_command);
|
||||||
|
$this->runCommand('git stash push --all -m '.escapeshellarg(self::TEST_IN_PROGRESS));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isVcsInProgress($case = '')
|
||||||
|
{
|
||||||
|
$in_progress = [];
|
||||||
|
|
||||||
|
$in_progress['file'] = file_exists(self::TEST_IN_PROGRESS_FILE);
|
||||||
|
|
||||||
|
$stdout = '';
|
||||||
|
$this->runCommand('git log -1 --pretty=%B', $stdout);
|
||||||
|
$in_progress['commit'] = strpos($stdout, self::TEST_IN_PROGRESS) !== false;
|
||||||
|
|
||||||
|
$stdout = '';
|
||||||
|
$this->runCommand('git stash list', $stdout);
|
||||||
|
$in_progress['stash'] = strpos($stdout, self::TEST_IN_PROGRESS) !== false;
|
||||||
|
|
||||||
|
if(!empty($case)) return $in_progress[$case];
|
||||||
|
return in_array(true, $in_progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function runCommand($command, &$stdout = "", &$stderr = "")
|
||||||
|
{
|
||||||
|
$descriptorspec = [
|
||||||
|
1 => ['pipe', 'w'],
|
||||||
|
2 => ['pipe', 'w'],
|
||||||
|
];
|
||||||
|
$pipes = [];
|
||||||
|
$resource = proc_open($command, $descriptorspec, $pipes, APP_PATH);
|
||||||
|
$stdout .= stream_get_contents($pipes[1]);
|
||||||
|
$stderr .= stream_get_contents($pipes[2]);
|
||||||
|
foreach ($pipes as $pipe)
|
||||||
|
{
|
||||||
|
fclose($pipe);
|
||||||
|
}
|
||||||
|
proc_close($resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function unsetVcsInProgress()
|
||||||
|
{
|
||||||
|
$this->debug('Rolling back Git repo to pre-test state…');
|
||||||
|
$this->runCommand('git reset --hard HEAD');
|
||||||
|
$this->runCommand('git clean -fdx');
|
||||||
|
|
||||||
|
while ($this->isVcsInProgress('commit'))
|
||||||
|
{
|
||||||
|
$this->debug('Going back one commit…');
|
||||||
|
$this->runCommand('git reset --mixed HEAD^');
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($this->isVcsInProgress('stash'))
|
||||||
|
{
|
||||||
|
$this->debug('Popping top of stash…');
|
||||||
|
$this->runCommand('git stash pop');
|
||||||
|
}
|
||||||
|
|
||||||
|
@unlink(self::TEST_IN_PROGRESS_FILE);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function debug($message)
|
||||||
|
{
|
||||||
|
codecept_debug(get_class() . ': ' . $message);
|
||||||
|
}
|
||||||
|
}
|
7
lib/preparers/Preparer.php
Normal file
7
lib/preparers/Preparer.php
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
interface Preparer
|
||||||
|
{
|
||||||
|
public function snapshot();
|
||||||
|
public function rollback();
|
||||||
|
}
|
57
lib/preparers/PreparerFactory.php
Normal file
57
lib/preparers/PreparerFactory.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
spl_autoload_register(function($class_name) {
|
||||||
|
$candidate_path = __DIR__ . "/$class_name.php";
|
||||||
|
if (file_exists($candidate_path))
|
||||||
|
{
|
||||||
|
include_once($candidate_path);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
class PreparerFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return Preparer
|
||||||
|
*/
|
||||||
|
public static function create()
|
||||||
|
{
|
||||||
|
if (self::systemIsSlow())
|
||||||
|
{
|
||||||
|
return self::createFromName('E107Preparer');
|
||||||
|
}
|
||||||
|
elseif (self::systemHasGit() && self::appPathIsGitRepo())
|
||||||
|
{
|
||||||
|
return self::createFromName('GitPreparer');
|
||||||
|
}
|
||||||
|
return self::createFromName('E107Preparer');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $class_name
|
||||||
|
* @return Preparer
|
||||||
|
*/
|
||||||
|
public static function createFromName($class_name)
|
||||||
|
{
|
||||||
|
codecept_debug('Instantiating Preparer: ' . $class_name);
|
||||||
|
return new $class_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function systemIsSlow()
|
||||||
|
{
|
||||||
|
return self::systemIsWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function systemIsWindows()
|
||||||
|
{
|
||||||
|
return strtolower(substr(php_uname('s'), 0, 3)) === 'win';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function systemHasGit()
|
||||||
|
{
|
||||||
|
return stripos(shell_exec('git --version'), 'git version') !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function appPathIsGitRepo()
|
||||||
|
{
|
||||||
|
return file_exists(APP_PATH."/.git");
|
||||||
|
}
|
||||||
|
}
|
@@ -1,75 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Helper;
|
namespace Helper;
|
||||||
|
include_once(codecept_root_dir() . "lib/preparers/PreparerFactory.php");
|
||||||
|
|
||||||
// here you can define custom actions
|
// here you can define custom actions
|
||||||
// all public methods declared in helper class will be available in $I
|
// all public methods declared in helper class will be available in $I
|
||||||
|
|
||||||
|
use Codeception\Lib\ModuleContainer;
|
||||||
|
|
||||||
abstract class E107Base extends Base
|
abstract class E107Base extends Base
|
||||||
{
|
{
|
||||||
const TEST_IN_PROGRESS = 'TEST-IN-PROGRESS';
|
|
||||||
const TEST_IN_PROGRESS_FILE = APP_PATH."/".self::TEST_IN_PROGRESS;
|
|
||||||
const APP_PATH_E107_CONFIG = APP_PATH."/e107_config.php";
|
const APP_PATH_E107_CONFIG = APP_PATH."/e107_config.php";
|
||||||
const TEST_HASH = '000000test'; // see e107_config.php
|
|
||||||
public $e107_mySQLprefix = 'e107_';
|
public $e107_mySQLprefix = 'e107_';
|
||||||
|
protected $preparer = null;
|
||||||
|
|
||||||
|
public function __construct(ModuleContainer $moduleContainer, $config = null)
|
||||||
|
{
|
||||||
|
parent::__construct($moduleContainer, $config);
|
||||||
|
$this->preparer = \PreparerFactory::create();
|
||||||
|
}
|
||||||
|
|
||||||
public function _beforeSuite($settings = array())
|
public function _beforeSuite($settings = array())
|
||||||
{
|
{
|
||||||
$this->backupLocalE107Config();
|
$this->backupLocalE107Config();
|
||||||
$this->deleteHashDirs();
|
$this->preparer->snapshot();
|
||||||
// $this->setVcsInProgress();
|
|
||||||
parent::_beforeSuite($settings);
|
parent::_beforeSuite($settings);
|
||||||
$this->writeLocalE107Config();
|
$this->writeLocalE107Config();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function deleteHashDirs()
|
|
||||||
{
|
|
||||||
$system = APP_PATH."/e107_system/".self::TEST_HASH;
|
|
||||||
$this->deleteDir($system);
|
|
||||||
|
|
||||||
$media = APP_PATH."/e107_media/".self::TEST_HASH;
|
|
||||||
$this->deleteDir($media);
|
|
||||||
|
|
||||||
if(is_dir($system))
|
|
||||||
{
|
|
||||||
echo "Couldn't delete ".$system;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function deleteDir($dirPath)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(!is_dir($dirPath))
|
|
||||||
{
|
|
||||||
// echo ($dirPath . "must be a directory");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(substr($dirPath, strlen($dirPath) - 1, 1) != '/')
|
|
||||||
{
|
|
||||||
$dirPath .= '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
$files = glob($dirPath . '*', GLOB_MARK);
|
|
||||||
|
|
||||||
foreach($files as $file)
|
|
||||||
{
|
|
||||||
if(is_dir($file))
|
|
||||||
{
|
|
||||||
$this->deleteDir($file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unlink($file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_dir($dirPath))
|
|
||||||
{
|
|
||||||
rmdir($dirPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function backupLocalE107Config()
|
protected function backupLocalE107Config()
|
||||||
{
|
{
|
||||||
if(file_exists(self::APP_PATH_E107_CONFIG))
|
if(file_exists(self::APP_PATH_E107_CONFIG))
|
||||||
@@ -78,95 +35,6 @@ abstract class E107Base extends Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function setVcsInProgress()
|
|
||||||
{
|
|
||||||
if ($this->isVcsInProgress())
|
|
||||||
{
|
|
||||||
codecept_debug('Git repo shows test in progress. Probably crashed test.');
|
|
||||||
$this->unsetVcsInProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
codecept_debug('Setting VCS in progress…');
|
|
||||||
|
|
||||||
touch(self::TEST_IN_PROGRESS_FILE);
|
|
||||||
$this->runCommand('git add -f '.escapeshellarg(self::TEST_IN_PROGRESS_FILE));
|
|
||||||
$this->runCommand('git add -A');
|
|
||||||
|
|
||||||
$commit_command = 'git commit -a --no-gpg-sign ' .
|
|
||||||
"-m '".self::TEST_IN_PROGRESS."! If test crashed, run `git log -1` for instructions' " .
|
|
||||||
"-m 'Running the test again after fixing the crash will clear this commit\nand any related stashes.' " .
|
|
||||||
"-m 'Alternatively, run these commands to restore the repository to its\npre-test state:' ";
|
|
||||||
$unsetVcsInProgress_commands = [
|
|
||||||
'git reset --hard HEAD',
|
|
||||||
'git clean -fdx',
|
|
||||||
'git stash pop',
|
|
||||||
'git reset --mixed HEAD^',
|
|
||||||
'rm -fv '.escapeshellarg(self::TEST_IN_PROGRESS)
|
|
||||||
];
|
|
||||||
foreach($unsetVcsInProgress_commands as $command)
|
|
||||||
{
|
|
||||||
$commit_command .= "-m ".escapeshellarg($command)." ";
|
|
||||||
}
|
|
||||||
$this->runCommand($commit_command);
|
|
||||||
$this->runCommand('git stash push --all -m '.escapeshellarg(self::TEST_IN_PROGRESS));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isVcsInProgress($case = '')
|
|
||||||
{
|
|
||||||
$in_progress = [];
|
|
||||||
|
|
||||||
$in_progress['file'] = file_exists(self::TEST_IN_PROGRESS_FILE);
|
|
||||||
|
|
||||||
$stdout = '';
|
|
||||||
$this->runCommand('git log -1 --pretty=%B', $stdout);
|
|
||||||
$in_progress['commit'] = strpos($stdout, self::TEST_IN_PROGRESS) !== false;
|
|
||||||
|
|
||||||
$stdout = '';
|
|
||||||
$this->runCommand('git stash list', $stdout);
|
|
||||||
$in_progress['stash'] = strpos($stdout, self::TEST_IN_PROGRESS) !== false;
|
|
||||||
|
|
||||||
if(!empty($case)) return $in_progress[$case];
|
|
||||||
return in_array(true, $in_progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function runCommand($command, &$stdout = "", &$stderr = "")
|
|
||||||
{
|
|
||||||
$descriptorspec = [
|
|
||||||
1 => ['pipe', 'w'],
|
|
||||||
2 => ['pipe', 'w'],
|
|
||||||
];
|
|
||||||
$pipes = [];
|
|
||||||
$resource = proc_open($command, $descriptorspec, $pipes, APP_PATH);
|
|
||||||
$stdout .= stream_get_contents($pipes[1]);
|
|
||||||
$stderr .= stream_get_contents($pipes[2]);
|
|
||||||
foreach ($pipes as $pipe)
|
|
||||||
{
|
|
||||||
fclose($pipe);
|
|
||||||
}
|
|
||||||
proc_close($resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function unsetVcsInProgress()
|
|
||||||
{
|
|
||||||
codecept_debug('Rolling back VCS to pre-test state…');
|
|
||||||
$this->runCommand('git reset --hard HEAD');
|
|
||||||
$this->runCommand('git clean -fdx');
|
|
||||||
|
|
||||||
while ($this->isVcsInProgress('commit'))
|
|
||||||
{
|
|
||||||
codecept_debug('Going back one commit…');
|
|
||||||
$this->runCommand('git reset --mixed HEAD^');
|
|
||||||
}
|
|
||||||
|
|
||||||
while ($this->isVcsInProgress('stash'))
|
|
||||||
{
|
|
||||||
codecept_debug('Popping top of stash…');
|
|
||||||
$this->runCommand('git stash pop');
|
|
||||||
}
|
|
||||||
|
|
||||||
@unlink(self::TEST_IN_PROGRESS_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function writeLocalE107Config()
|
protected function writeLocalE107Config()
|
||||||
{
|
{
|
||||||
$twig_loader = new \Twig_Loader_Array([
|
$twig_loader = new \Twig_Loader_Array([
|
||||||
@@ -191,9 +59,8 @@ abstract class E107Base extends Base
|
|||||||
{
|
{
|
||||||
parent::_afterSuite();
|
parent::_afterSuite();
|
||||||
$this->revokeLocalE107Config();
|
$this->revokeLocalE107Config();
|
||||||
// $this->unsetVcsInProgress();
|
$this->preparer->rollback();
|
||||||
$this->restoreLocalE107Config();
|
$this->restoreLocalE107Config();
|
||||||
$this->deleteHashDirs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function revokeLocalE107Config()
|
protected function revokeLocalE107Config()
|
||||||
|
Reference in New Issue
Block a user