popsu-d7/sites/all/modules/drush/tests/drush_testcase.inc
Bachir Soussi Chiadmi 1bc61b12ad first import
2015-04-08 11:40:19 +02:00

341 lines
9.7 KiB
PHP

<?php
/*
* @file
* Initialize a sandboxed environment. Starts with call unish_init() at bottom.
*/
abstract class Drush_TestCase extends PHPUnit_Framework_TestCase {
// Unix exit codes.
const EXIT_SUCCESS = 0;
const EXIT_ERROR = 1;
/*
* An array of Drupal sites that are setup in the drush-sandbox.
*/
var $sites;
function __construct() {
$this->_output = false;
}
/**
* Assure that each class starts with an empty sandbox directory and
* a clean environment - http://drupal.org/node/1103568.
*/
public static function setUpBeforeClass() {
$sandbox = UNISH_SANDBOX;
if (file_exists($sandbox)) {
unish_file_delete_recursive($sandbox);
}
$ret = mkdir($sandbox, 0777, TRUE);
chdir(UNISH_SANDBOX);
mkdir(getenv('HOME') . '/.drush', 0777, TRUE);
mkdir($sandbox . '/etc/drush', 0777, TRUE);
mkdir($sandbox . '/share/drush/commands', 0777, TRUE);
}
/**
* Runs after each test case. Remove sandbox directory.
*/
public static function tearDownAfterClass() {
if (file_exists(UNISH_SANDBOX)) {
unish_file_delete_recursive(UNISH_SANDBOX);
}
}
public static function is_windows() {
return (strtoupper(substr(PHP_OS, 0, 3)) == "WIN");
}
public static function escapeshellarg($arg) {
// Short-circuit escaping for simple params (keep stuff readable)
if (preg_match('|^[a-zA-Z0-9.:/_-]*$|', $arg)) {
return $arg;
}
elseif (self::is_windows()) {
return self::_escapeshellarg_windows($arg);
}
else {
return escapeshellarg($arg);
}
}
public static function _escapeshellarg_windows($arg) {
// Double up existing backslashes
$arg = preg_replace('/\\\/', '\\\\\\\\', $arg);
// Escape double quotes.
$arg = preg_replace('/"/', '\\"', $arg);
// Escape single quotes.
$arg = preg_replace('/\'/', '\\\'', $arg);
// Add surrounding quotes.
$arg = '"' . $arg . '"';
return $arg;
}
/**
* Actually runs the command. Does not trap the error stream output as this
* need PHP 4.3+.
*
* @param string $command
* The actual command line to run.
* @return integer
* Exit code. Usually self::EXIT_ERROR or self::EXIT_SUCCESS.
*/
function execute($command, $expected_return = self::EXIT_SUCCESS) {
$this->_output = FALSE;
// todo check verbose level from phpunit.
if (TRUE) {
print "\nExecuting: $command \n";
}
exec($command, $this->_output, $return);
$this->assertEquals($expected_return, $return, 'Unexpected exit code: ' . $command);
return $return;
}
/**
* Invoke drush in via execute().
*
* @param command
* A defined drush command such as 'cron', 'status' or any of the available ones such as 'drush pm'.
* @param args
* Command arguments.
* @param $options
* An associative array containing options.
* @param $site_specification
* A site alias or site specification. Include the '@' at start of a site alias.
* @param $cd
* A directory to change into before executing.
* @return integer
* An exit code.
*/
function drush($command, array $args = array(), array $options = array(), $site_specification = NULL, $cd = NULL) {
$cmd[] = $cd ? sprintf('cd %s;', self::escapeshellarg($cd)) : NULL;
$cmd[] = UNISH_DRUSH;
$cmd[] = empty($site_specification) ? NULL : self::escapeshellarg($site_specification);
$cmd[] = $command;
if (in_array('--verbose', $_SERVER['argv'])) $args[] = '--verbose';
if (in_array('--debug', $_SERVER['argv'])) $args[] = '--debug';
foreach ($args as $arg) {
$cmd[] = self::escapeshellarg($arg);
}
$options['nocolor'] = NULL;
foreach ($options as $key => $value) {
if (is_null($value)) {
$cmd[] = "--$key";
}
else {
$cmd[] = "--$key=" . self::escapeshellarg($value);
}
}
$exec = array_filter($cmd, 'strlen'); // Remove NULLs
return $this->execute(implode(' ', $exec));
}
/**
* Accessor for the last output.
* @return string Output as text.
* @access public
*/
function getOutput() {
return implode("\n", $this->_output);
}
/**
* Accessor for the last output.
* @return array Output as array of lines.
* @access public
*/
function getOutputAsList() {
return $this->_output;
}
function setUpDrupal($env = 'dev', $install = FALSE, $version_string = '7.x', $profile = NULL) {
$root = UNISH_SANDBOX . '/web';
$this->sites[$env]['root'] = $root;
$site = "$root/sites/$env";
if (is_null($profile)) {
$profile = substr($version_string, 0, 1) >= 7 ? 'testing' : 'default';
}
// Download Drupal if not already present.
if (!file_exists($root)) {
$options = array(
'destination' => UNISH_SANDBOX,
'drupal-project-rename' => 'web',
'yes' => NULL,
'quiet' => NULL,
);
$this->drush('pm-download', array("drupal-$version_string"), $options);
}
// If specified, install Drupal as a multi-site.
if ($install) {
$options = array(
'root' => $root,
'db-url' => UNISH_DB_URL . '/unish_' . $env,
'sites-subdir' => $env,
'yes' => NULL,
'quiet' => NULL,
);
$this->drush('site-install', array($profile), $options);
// Give us our write perms back.
$ret = chmod($site, 0777);
// Stash the db_url for this site.
$this->sites[$env]['db_url'] = UNISH_DB_URL . '/unish_' . $env;
}
else {
mkdir($site);
touch("$site/settings.php");
}
// Make an alias for the site
$alias_definition = array($env => array('root' => $root, 'uri' => $env));
file_put_contents(UNISH_SANDBOX . '/etc/drush/' . $env . '.alias.drushrc.php', $this->file_aliases($alias_definition));
}
// Copied from D7 - profiles/standard/standard.install
function create_node_types_php() {
$php = "
\$types = array(
array(
'type' => 'page',
'name' => 'Basic page',
'base' => 'node_content',
'description' => 'Use <em>basic pages</em> for your static content, such as an \'About us\' page.',
'custom' => 1,
'modified' => 1,
'locked' => 0,
),
array(
'type' => 'article',
'name' => 'Article',
'base' => 'node_content',
'description' => 'Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.',
'custom' => 1,
'modified' => 1,
'locked' => 0,
),
);
foreach (\$types as \$type) {
\$type = node_type_set_defaults(\$type);
node_type_save(\$type);
node_add_body_field(\$type);
}
";
return $php;
}
/*
* Prepare the contents of an aliases file.
*/
function file_aliases($aliases) {
foreach ($aliases as $name => $alias) {
$records[] = sprintf('$aliases[\'%s\'] = %s;', $name, var_export($alias, TRUE));
}
$contents = "<?php\n\n" . implode("\n\n", $records);
return $contents;
}
/**
* Same code as drush_delete_dir().
* @see drush_delete_dir()
*
* @param string $dir
* @return boolean
*/
function file_delete_recursive($dir) {
if (!file_exists($dir)) {
return TRUE;
}
if (!is_dir($dir)) {
@chmod($dir, 0777); // Make file writeable
return unlink($dir);
}
foreach (scandir($dir) as $item) {
if ($item == '.' || $item == '..') {
continue;
}
if (!self::file_delete_recursive($dir.'/'.$item)) {
return FALSE;
}
}
return rmdir($dir);
}
}
/*
* Initialize our environment at he start of each run (i.e. suite).
*/
function unish_init() {
// We read from globals here because env can be empty and ini did not work in quick test.
define('UNISH_DB_URL', getenv('UNISH_DB_URL') ? getenv('UNISH_DB_URL') : !empty($GLOBALS['UNISH_DB_URL']) ? $GLOBALS['UNISH_DB_URL'] : 'mysql://root:@127.0.0.1');
// UNISH_DRUSH value can come from phpunit.xml or `which drush`.
if (!defined('UNISH_DRUSH')) {
// Let the UNISH_DRUSH environment variable override if set.
$unish_drush = isset($_SERVER['UNISH_DRUSH']) ? $_SERVER['UNISH_DRUSH'] : NULL;
$unish_drush = isset($GLOBALS['UNISH_DRUSH']) ? $GLOBALS['UNISH_DRUSH'] : $unish_drush;
if (empty($unish_drush)) {
$unish_drush = Drush_TestCase::is_windows() ? exec('for %i in (drush) do @echo. %~$PATH:i') : trim(`which drush`);
}
define('UNISH_DRUSH', $unish_drush);
}
define('UNISH_TMP', getenv('UNISH_TMP') ? getenv('UNISH_TMP') : (isset($GLOBALS['UNISH_TMP']) ? $GLOBALS['UNISH_TMP'] : sys_get_temp_dir()));
define('UNISH_SANDBOX', UNISH_TMP . '/drush-sandbox');
$home = UNISH_SANDBOX . '/home';
putenv("HOME=$home");
putenv("HOMEDRIVE=$home");
putenv('ETC_PREFIX=' . UNISH_SANDBOX);
putenv('SHARE_PREFIX=' . UNISH_SANDBOX);
// Cache dir lives outside the sandbox so that we get persistence across classes.
$cache = UNISH_TMP . '/drush_cache';
putenv("CACHE_PREFIX=" . $cache);
// Wipe at beginning of run.
if (file_exists($cache)) {
unish_file_delete_recursive($cache);
}
}
/**
* Same code as drush_delete_dir().
* @see drush_delete_dir()
*
* @param string $dir
* @return boolean
*/
function unish_file_delete_recursive($dir) {
if (!file_exists($dir)) {
return TRUE;
}
if (!is_dir($dir)) {
@chmod($dir, 0777); // Make file writeable
return unlink($dir);
}
foreach (scandir($dir) as $item) {
if ($item == '.' || $item == '..') {
continue;
}
if (!unish_file_delete_recursive($dir.'/'.$item)) {
return FALSE;
}
}
return rmdir($dir);
}
// This code is in global scope.
// TODO: I would rather this code at top of file, but I get Fatal error: Class 'Drush_TestCase' not found
unish_init();