From 7f7a91e4ce70cce0a7a5ce4897a225f9b1e36777 Mon Sep 17 00:00:00 2001 From: David Monllao Date: Thu, 21 Nov 2013 13:07:13 +0800 Subject: [PATCH] MDL-41592 behat: Config settings more flexible Adding the option to just set ->behat_wwwroot to allow switching to the behat test site. --- admin/tool/behat/cli/util.php | 26 ++++---- config-dist.php | 10 ++- lib/behat/classes/behat_command.php | 1 + lib/behat/lib.php | 94 +++++++++++++++++++++++++++++ lib/setup.php | 45 ++++++++++---- 5 files changed, 147 insertions(+), 29 deletions(-) diff --git a/admin/tool/behat/cli/util.php b/admin/tool/behat/cli/util.php index 287a53562e4fe..7423dc4315dc1 100644 --- a/admin/tool/behat/cli/util.php +++ b/admin/tool/behat/cli/util.php @@ -93,21 +93,9 @@ // Getting $CFG data. require_once(__DIR__ . '/../../../../config.php'); -// CFG->behat_prefix must be set and with value different than CFG->prefix and phpunit_prefix. -if (empty($CFG->behat_prefix) || - ($CFG->behat_prefix == $CFG->prefix) || - (!empty($CFG->phpunit_prefix) && $CFG->behat_prefix == $CFG->phpunit_prefix)) { - behat_error(BEHAT_EXITCODE_CONFIG, - 'Define $CFG->behat_prefix in config.php with a value different than $CFG->prefix and $CFG->phpunit_prefix'); -} - -// CFG->behat_dataroot must be set and with value different than CFG->dataroot and phpunit_dataroot. -if (empty($CFG->behat_dataroot) || - ($CFG->behat_dataroot == $CFG->dataroot) || - (!empty($CFG->phpunit_dataroot) && $CFG->behat_dataroot == $CFG->phpunit_dataroot)) { - behat_error(BEHAT_EXITCODE_CONFIG, - 'Define $CFG->behat_dataroot in config.php with a value different than $CFG->dataroot and $CFG->phpunit_dataroot'); -} +// Checking the integrity of the provided $CFG->behat_* vars +// to prevent conflicts with production and phpunit environments. +behat_check_config_vars(); // Create behat_dataroot if it doesn't exists. if (!file_exists($CFG->behat_dataroot)) { @@ -137,6 +125,14 @@ testing_initdataroot($CFG->behat_dataroot, 'behat'); } +// When we use the utilities we don't know how the site +// will be accessed, so if neither $CFG->behat_switchcompletely or +// $CFG->behat_wwwroot are set we must think that the site will +// be accessed using the built-in server which is set by default +// to localhost:8000. We need to do this to prevent uses of the production +// wwwroot when the site is being installed / dropped... +$CFG->behat_wwwroot = behat_get_wwwroot(); + // Overrides vars with behat-test ones. $vars = array('wwwroot', 'prefix', 'dataroot'); foreach ($vars as $var) { diff --git a/config-dist.php b/config-dist.php index 4912f73c6c9c5..fdf601908b1c0 100644 --- a/config-dist.php +++ b/config-dist.php @@ -589,10 +589,16 @@ // $CFG->behat_prefix = 'bht_'; // $CFG->behat_dataroot = '/home/example/bht_moodledata'; // -// To set a seperate wwwroot for Behat to use, set it below. -// This is set automatically elsewhere when using PHP's built in webserver. +// To set a seperate wwwroot for Behat to use, use $CFG->behat_wwwroot; this is set automatically +// to http://localhost:8000 as it is the proposed PHP built-in server URL. Instead of that you can, +// for example, use an alias, add a host to /etc/hosts or add a new virtual host having a URL +// poiting to your production site and another one poiting to your test site. Note that you need +// to ensure that this URL is not accessible from the www as the behat test site uses "sugar" +// credentials (admin/admin) and can be easily hackable. +// // Example: // $CFG->behat_wwwroot = 'http://192.168.1.250:8000'; +// $CFG->behat_wwwroot = 'http://localhost/moodlesitetesting'; // // You can override default Moodle configuration for Behat and add your own // params; here you can add more profiles, use different Mink drivers than Selenium... diff --git a/lib/behat/classes/behat_command.php b/lib/behat/classes/behat_command.php index a40a71911a656..20762ae1efe6a 100644 --- a/lib/behat/classes/behat_command.php +++ b/lib/behat/classes/behat_command.php @@ -148,6 +148,7 @@ public static function behat_setup_problem($checkphp = false) { } // Checking behat dataroot existence otherwise echo about admin/tool/behat/cli/init.php. + $CFG->behat_dataroot = realpath($CFG->behat_dataroot); if (empty($CFG->behat_dataroot) || !is_dir($CFG->behat_dataroot) || !is_writable($CFG->behat_dataroot)) { self::output_msg(get_string('runclitool', 'tool_behat', 'php admin/tool/behat/cli/init.php')); return BEHAT_EXITCODE_CONFIG; diff --git a/lib/behat/lib.php b/lib/behat/lib.php index 0d9f2e2a06546..6872e7a847f07 100644 --- a/lib/behat/lib.php +++ b/lib/behat/lib.php @@ -167,3 +167,97 @@ function behat_clean_init_config() { } } + +/** + * Checks that the behat config vars are properly set. + * + * @return void Stops execution with error code if something goes wrong. + */ +function behat_check_config_vars() { + global $CFG; + + // CFG->behat_prefix must be set and with value different than CFG->prefix and phpunit_prefix. + if (empty($CFG->behat_prefix) || + ($CFG->behat_prefix == $CFG->prefix) || + (!empty($CFG->phpunit_prefix) && $CFG->behat_prefix == $CFG->phpunit_prefix)) { + behat_error(BEHAT_EXITCODE_CONFIG, + 'Define $CFG->behat_prefix in config.php with a value different than $CFG->prefix and $CFG->phpunit_prefix'); + } + + // $CFG->behat_wwwroot must be different than CFG->wwwroot if it is set, it may not be set as + // it can take the default value and we should also consider that will have the same value than + // $CFG->wwwroot if $CFG->behat_switchcompletely is set. + if (!empty($CFG->behat_wwwroot) && $CFG->behat_wwwroot == $CFG->wwwroot && empty($CFG->behat_switchcompletely)) { + behat_error(BEHAT_EXITCODE_CONFIG, + 'Define $CFG->behat_wwwroot in config.php with a value different than $CFG->wwwroot'); + } + + // CFG->behat_dataroot must be set and with value different than CFG->dataroot and phpunit_dataroot. + $CFG->dataroot = realpath($CFG->dataroot); + if (!empty($CFG->behat_dataroot)) { + $CFG->behat_dataroot = realpath($CFG->behat_dataroot); + } + if (empty($CFG->behat_dataroot) || + ($CFG->behat_dataroot == $CFG->dataroot) || + (!empty($CFG->phpunit_dataroot) && $CFG->behat_dataroot == $CFG->phpunit_dataroot)) { + behat_error(BEHAT_EXITCODE_CONFIG, + 'Define $CFG->behat_dataroot in config.php with a value different than $CFG->dataroot and $CFG->phpunit_dataroot'); + } + +} + +/** + * Returns a URL based on the priorities between $CFG->behat_* vars. + * + * 1.- Switch completely wins and overwrites behat_wwwroot + * 2.- behat_wwwroot alternatively + * 3.- http://localhost:8000 if there is nothing else + * + * @return string + */ +function behat_get_wwwroot() { + global $CFG; + + if (!empty($CFG->behat_switchcompletely)) { + return $CFG->wwwroot; + } else if (!empty($CFG->behat_wwwroot)) { + return $CFG->behat_wwwroot; + } + + return 'http://localhost:8000'; +} + +/** + * Checks if the URL requested by the user matches the provided argument + * + * @param string $url + * @return bool Returns true if it matches. + */ +function behat_is_requested_url($url) { + + $parsedurl = parse_url($url . '/'); + $parsedurl['port'] = isset($parsedurl['port']) ? $parsedurl['port'] : 80; + $parsedurl['path'] = rtrim($parsedurl['path'], '/'); + + // Removing the port. + $pos = strpos($_SERVER['HTTP_HOST'], ':'); + if ($pos !== false) { + $requestedhost = substr($_SERVER['HTTP_HOST'], 0, $pos); + } else { + $requestedhost = $_SERVER['HTTP_HOST']; + } + + // The path should also match. + if (empty($parsedurl['path'])) { + $matchespath = true; + } else if (strpos($_SERVER['SCRIPT_NAME'], $parsedurl['path']) === 0) { + $matchespath = true; + } + + // The host and the port should match + if ($parsedurl['host'] == $requestedhost && $parsedurl['port'] == $_SERVER['SERVER_PORT'] && !empty($matchespath)) { + return true; + } + + return false; +} diff --git a/lib/setup.php b/lib/setup.php index 55656630fdf2a..7945138dbb92f 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -97,37 +97,58 @@ // * Behat is running (constant set hooking the behat init process before requiring config.php). // * If $CFG->behat_wwwroot has been set and the hostname/port match what the page was requested with. // Test environment is enabled if: -// * User has previously enabled through admin/tool/behat/cli/util.php --enable. +// * User has previously enabled through admin/tool/behat/cli/util.php --enable or admin/tool/behat/cli/init.php // Both are required to switch to test mode if (!defined('BEHAT_SITE_RUNNING') && !empty($CFG->behat_dataroot) && !empty($CFG->behat_prefix) && file_exists($CFG->behat_dataroot)) { - $CFG->behat_dataroot = realpath($CFG->behat_dataroot); + // Only included if behat_* are set, it is not likely to be a production site. + require_once(__DIR__ . '/../lib/behat/lib.php'); + + $defaultbehatwwwroot = behat_get_wwwroot(); if (!empty($CFG->behat_switchcompletely) && php_sapi_name() !== 'cli') { - $behatswitchcompletely = true; - $CFG->behat_wwwroot = $CFG->wwwroot; + // Switch completely uses the production wwwroot as the test site URL. + $behatwwwroot = $defaultbehatwwwroot; } elseif (php_sapi_name() === 'cli-server') { - $behatbuiltinserver = true; - $CFG->behat_wwwroot = 'http://localhost:'.$_SERVER['SERVER_PORT']; + // If we are using the built-in server we use the provided $CFG->behat_wwwroot + // value or the default one if $CFG->behat_wwwroot is not set, only if it matches + // the requested URL. + if (behat_is_requested_url($defaultbehatwwwroot)) { + $behatwwwroot = $defaultbehatwwwroot; + } } elseif (defined('BEHAT_TEST')) { - $behatrunning = true; + // This is when moodle codebase runs through vendor/bin/behat, we "are not supposed" + // to need a wwwroot, but before using the production one we should set something else + // as an alternative. + $behatwwwroot = $defaultbehatwwwroot; } elseif (!empty($CFG->behat_wwwroot) && !empty($_SERVER['HTTP_HOST'])) { - $behaturl = parse_url($CFG->behat_wwwroot.'/'); - $behaturl['port'] = isset($behaturl['port']) ? $behaturl['port'] : 80; - $behataltwww = ($behaturl['host'] == $_SERVER['HTTP_HOST']) && ($behaturl['port'] == $_SERVER['SERVER_PORT']); + // If $CFG->behat_wwwroot was set and matches the requested URL we + // use $CFG->behat_wwwroot as our wwwroot. + if (behat_is_requested_url($CFG->behat_wwwroot)) { + $behatwwwroot = $CFG->behat_wwwroot; + } } - $testenvironmentrequested = !empty($behatswitchcompletely) || !empty($behatbuiltinserver) || !empty($behatrunning) || !empty($behataltwww); + // If we found a proper behatwwwroot then we consider the behat test as requested. + $testenvironmentrequested = !empty($behatwwwroot); // Only switch to test environment if it has been enabled. + $CFG->behat_dataroot = realpath($CFG->behat_dataroot); $testenvironmentenabled = file_exists($CFG->behat_dataroot . '/behat/test_environment_enabled.txt'); if ($testenvironmentenabled && $testenvironmentrequested) { + // Now we know which one will be our behat wwwroot. + $CFG->behat_wwwroot = $behatwwwroot; + + // Checking the integrity of the provided $CFG->behat_* vars and the + // selected wwwroot to prevent conflicts with production and phpunit environments. + behat_check_config_vars(); + // Constant used to inform that the behat test site is being used, // this includes all the processes executed by the behat CLI command like // the site reset, the steps executed by the browser drivers when simulating @@ -138,9 +159,9 @@ define('BEHAT_SITE_RUNNING', true); // Clean extra config.php settings. - require_once(__DIR__ . '/../lib/behat/lib.php'); behat_clean_init_config(); + // Now we can begin switching $CFG->X for $CFG->behat_X. $CFG->wwwroot = $CFG->behat_wwwroot; $CFG->passwordsaltmain = 'moodle'; $CFG->prefix = $CFG->behat_prefix;