123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- <?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();
|