MDL-41592 behat: Config settings more flexible
authorDavid Monllao <davidm@moodle.com>
Thu, 21 Nov 2013 05:07:13 +0000 (13:07 +0800)
committerDavid Monllao <davidm@moodle.com>
Mon, 2 Dec 2013 06:18:10 +0000 (14:18 +0800)
Adding the option to just set ->behat_wwwroot to
allow switching to the behat test site.

admin/tool/behat/cli/util.php
config-dist.php
lib/behat/classes/behat_command.php
lib/behat/lib.php
lib/setup.php

index 287a535..7423dc4 100644 (file)
@@ -93,21 +93,9 @@ ini_set('log_errors', '1');
 // 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 @@ if (!file_exists("$CFG->behat_dataroot/behattestdir.txt")) {
     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) {
index 4912f73..fdf6019 100644 (file)
@@ -589,10 +589,16 @@ $CFG->admin = 'admin';
 // $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...
index a40a719..20762ae 100644 (file)
@@ -148,6 +148,7 @@ class behat_command {
         }
 
         // 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;
index 0d9f2e2..6872e7a 100644 (file)
@@ -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;
+}
index 5565663..7945138 100644 (file)
@@ -97,37 +97,58 @@ if (!isset($CFG->wwwroot) or $CFG->wwwroot === 'http://example.com/moodle') {
 // * 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 @@ if (!defined('BEHAT_SITE_RUNNING') && !empty($CFG->behat_dataroot) &&
         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;