Ignore:
Timestamp:
May 2, 2016, 12:09:23 PM (3 years ago)
Author:
jrpelegrina
Message:

Updated to moodle 3.0.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • moodle/trunk/fuentes/admin/tool/behat/cli/util.php

    r136 r1331  
    1616
    1717/**
    18  * CLI tool with utilities to manage Behat integration in Moodle
     18 * CLI tool with utilities to manage parallel Behat integration in Moodle
    1919 *
    2020 * All CLI utilities uses $CFG->behat_dataroot and $CFG->prefix_dataroot as
     
    3131}
    3232
    33 // Basic functions.
    34 require_once(__DIR__ . '/../../../../lib/clilib.php');
    35 require_once(__DIR__ . '/../../../../lib/behat/lib.php');
    36 
    37 
    38 // CLI options.
    39 list($options, $unrecognized) = cli_get_params(
    40     array(
    41         'help'    => false,
    42         'install' => false,
    43         'drop'    => false,
    44         'enable'  => false,
    45         'disable' => false,
    46         'diag'    => false
    47     ),
    48     array(
    49         'h' => 'help'
    50     )
    51 );
    52 
    53 if ($options['install'] or $options['drop']) {
    54     define('CACHE_DISABLE_ALL', true);
    55 }
    56 
    57 // Checking util.php CLI script usage.
    58 $help = "
    59 Behat utilities to manage the test environment
    60 
    61 Options:
    62 --install  Installs the test environment for acceptance tests
    63 --drop     Drops the database tables and the dataroot contents
    64 --enable   Enables test environment and updates tests list
    65 --disable  Disables test environment
    66 --diag     Get behat test environment status code
    67 
    68 -h, --help     Print out this help
    69 
    70 Example from Moodle root directory:
    71 \$ php admin/tool/behat/cli/util.php --enable
    72 
    73 More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
    74 ";
    75 
    76 if (!empty($options['help'])) {
    77     echo $help;
    78     exit(0);
    79 }
    80 
    81 // Describe this script.
    8233define('BEHAT_UTIL', true);
    8334define('CLI_SCRIPT', true);
    8435define('NO_OUTPUT_BUFFERING', true);
    8536define('IGNORE_COMPONENT_CACHE', true);
    86 
    87 // Only load CFG from config.php, stop ASAP in lib/setup.php.
    8837define('ABORT_AFTER_CONFIG', true);
     38
    8939require_once(__DIR__ . '/../../../../config.php');
    90 
    91 // Remove error handling overrides done in config.php.
    92 $CFG->debug = (E_ALL | E_STRICT);
    93 $CFG->debugdisplay = 1;
    94 error_reporting($CFG->debug);
    95 ini_set('display_errors', '1');
    96 ini_set('log_errors', '1');
    97 
    98 // Finish moodle init.
    99 define('ABORT_AFTER_CONFIG_CANCEL', true);
    100 require("$CFG->dirroot/lib/setup.php");
    101 
    102 raise_memory_limit(MEMORY_HUGE);
    103 
    104 require_once($CFG->libdir.'/adminlib.php');
    105 require_once($CFG->libdir.'/upgradelib.php');
    106 require_once($CFG->libdir.'/clilib.php');
    107 require_once($CFG->libdir.'/installlib.php');
    108 require_once($CFG->libdir.'/testing/classes/test_lock.php');
    109 
    110 if ($unrecognized) {
    111     $unrecognized = implode("\n  ", $unrecognized);
    112     cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
    113 }
    114 
    115 // Behat utilities.
    116 require_once($CFG->libdir . '/behat/classes/util.php');
    117 require_once($CFG->libdir . '/behat/classes/behat_command.php');
    118 
    119 // Run command (only one per time).
     40require_once(__DIR__ . '/../../../../lib/clilib.php');
     41require_once(__DIR__ . '/../../../../lib/behat/lib.php');
     42require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php');
     43require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php');
     44
     45// CLI options.
     46list($options, $unrecognized) = cli_get_params(
     47    array(
     48        'help'        => false,
     49        'install'     => false,
     50        'drop'        => false,
     51        'enable'      => false,
     52        'disable'     => false,
     53        'diag'        => false,
     54        'parallel'    => 0,
     55        'maxruns'     => false,
     56        'updatesteps' => false,
     57        'fromrun'     => 1,
     58        'torun'       => 0,
     59    ),
     60    array(
     61        'h' => 'help',
     62        'j' => 'parallel',
     63        'm' => 'maxruns'
     64    )
     65);
     66
     67// Checking util.php CLI script usage.
     68$help = "
     69Behat utilities to manage the test environment
     70
     71Usage:
     72  php util.php [--install|--drop|--enable|--disable|--diag|--updatesteps|--help] [--parallel=value [--maxruns=value]]
     73
     74Options:
     75--install      Installs the test environment for acceptance tests
     76--drop         Drops the database tables and the dataroot contents
     77--enable       Enables test environment and updates tests list
     78--disable      Disables test environment
     79--diag         Get behat test environment status code
     80--updatesteps  Update feature step file.
     81-j, --parallel Number of parallel behat run operation
     82-m, --maxruns  Max parallel processes to be executed at one time.
     83
     84-h, --help     Print out this help
     85
     86Example from Moodle root directory:
     87\$ php admin/tool/behat/cli/util.php --enable --parallel=4
     88
     89More info in http://docs.moodle.org/dev/Acceptance_testing#Running_tests
     90";
     91
     92if (!empty($options['help'])) {
     93    echo $help;
     94    exit(0);
     95}
     96
     97$cwd = getcwd();
     98
     99// For drop option check if parallel site.
     100if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) {
     101    // Get parallel run info from first run.
     102    $options['parallel'] = behat_config_manager::get_parallel_test_runs($options['fromrun']);
     103}
     104
     105// If not a parallel site then open single run.
     106if (empty($options['parallel'])) {
     107    chdir(__DIR__);
     108    // Check if behat is initialised, if not exit.
     109    passthru("php util_single_run.php --diag", $status);
     110    if ($status) {
     111        exit ($status);
     112    }
     113    $cmd = commands_to_execute($options);
     114    $processes = cli_execute_parallel(array($cmd), __DIR__);
     115    $status = print_sequential_output($processes, false);
     116    chdir($cwd);
     117    exit($status);
     118}
     119
     120// Default torun is maximum parallel runs.
     121if (empty($options['torun'])) {
     122    $options['torun'] = $options['parallel'];
     123}
     124
     125$status = false;
     126$cmds = commands_to_execute($options);
     127
     128// Start executing commands either sequential/parallel for options provided.
     129if ($options['diag'] || $options['enable'] || $options['disable']) {
     130    // Do it sequentially as it's fast and need to be displayed nicely.
     131    foreach (array_chunk($cmds, 1, true) as $cmd) {
     132        $processes = cli_execute_parallel($cmd, __DIR__);
     133        print_sequential_output($processes);
     134    }
     135
     136} else if ($options['drop']) {
     137    $processes = cli_execute_parallel($cmds, __DIR__);
     138    $exitcodes = print_combined_drop_output($processes);
     139    foreach ($exitcodes as $exitcode) {
     140        $status = (bool)$status || (bool)$exitcode;
     141    }
     142
     143} else if ($options['install']) {
     144    // This is intensive compared to behat itself so run them in chunk if option maxruns not set.
     145    if ($options['maxruns']) {
     146        foreach (array_chunk($cmds, $options['maxruns'], true) as $chunk) {
     147            $processes = cli_execute_parallel($chunk, __DIR__);
     148            $exitcodes = print_combined_install_output($processes);
     149            foreach ($exitcodes as $name => $exitcode) {
     150                if ($exitcode != 0) {
     151                    echo "Failed process [[$name]]" . PHP_EOL;
     152                    echo $processes[$name]->getOutput();
     153                    echo PHP_EOL;
     154                    echo $processes[$name]->getErrorOutput();
     155                    echo PHP_EOL . PHP_EOL;
     156                }
     157                $status = (bool)$status || (bool)$exitcode;
     158            }
     159        }
     160    } else {
     161        $processes = cli_execute_parallel($cmds, __DIR__);
     162        $exitcodes = print_combined_install_output($processes);
     163        foreach ($exitcodes as $name => $exitcode) {
     164            if ($exitcode != 0) {
     165                echo "Failed process [[$name]]" . PHP_EOL;
     166                echo $processes[$name]->getOutput();
     167                echo PHP_EOL;
     168                echo $processes[$name]->getErrorOutput();
     169                echo PHP_EOL . PHP_EOL;
     170            }
     171            $status = (bool)$status || (bool)$exitcode;
     172        }
     173    }
     174
     175} else if ($options['updatesteps']) {
     176    // Rewrite config file to ensure we have all the features covered.
     177    if (empty($options['parallel'])) {
     178        behat_config_manager::update_config_file();
     179    } else {
     180        // Update config file, ensuring we have up-to-date behat.yml.
     181        for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
     182            $CFG->behatrunprocess = $i;
     183            behat_config_manager::update_config_file();
     184        }
     185        unset($CFG->behatrunprocess);
     186    }
     187
     188    // Do it sequentially as it's fast and need to be displayed nicely.
     189    foreach (array_chunk($cmds, 1, true) as $cmd) {
     190        $processes = cli_execute_parallel($cmd, __DIR__);
     191        print_sequential_output($processes);
     192    }
     193    exit(0);
     194
     195} else {
     196    // We should never reach here.
     197    echo $help;
     198    exit(1);
     199}
     200
     201// Ensure we have success status to show following information.
     202if ($status) {
     203    echo "Unknown failure $status" . PHP_EOL;
     204    exit((int)$status);
     205}
     206
     207// Show command o/p (only one per time).
    120208if ($options['install']) {
    121     behat_util::install_site();
    122     mtrace("Acceptance tests site installed");
     209    echo "Acceptance tests site installed for sites:".PHP_EOL;
     210
     211    // Display all sites which are installed/drop/diabled.
     212    for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
     213        if (empty($CFG->behat_parallel_run[$i - 1]['behat_wwwroot'])) {
     214            echo $CFG->behat_wwwroot . "/" . BEHAT_PARALLEL_SITE_NAME . $i . PHP_EOL;
     215        } else {
     216            echo $CFG->behat_parallel_run[$i - 1]['behat_wwwroot'] . PHP_EOL;
     217        }
     218
     219    }
    123220} else if ($options['drop']) {
    124     // Ensure no tests are running.
    125     test_lock::acquire('behat');
    126     behat_util::drop_site();
    127     mtrace("Acceptance tests site dropped");
     221    echo "Acceptance tests site dropped for " . $options['parallel'] . " parallel sites" . PHP_EOL;
     222
    128223} else if ($options['enable']) {
    129     behat_util::start_test_mode();
    130     $runtestscommand = behat_command::get_behat_command(true) .
    131         ' --config ' . behat_config_manager::get_behat_cli_config_filepath();
    132     mtrace("Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:\n " . $runtestscommand);
     224    echo "Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:" . PHP_EOL;
     225    echo behat_command::get_behat_command(true, true);
     226    echo PHP_EOL;
     227
    133228} else if ($options['disable']) {
    134     behat_util::stop_test_mode();
    135     mtrace("Acceptance tests environment disabled");
     229    echo "Acceptance tests environment disabled for " . $options['parallel'] . " parallel sites" . PHP_EOL;
     230
    136231} else if ($options['diag']) {
    137     $code = behat_util::get_behat_status();
    138     exit($code);
     232    // Valid option, so nothing to do.
    139233} else {
    140234    echo $help;
    141 }
    142 
     235    chdir($cwd);
     236    exit(1);
     237}
     238
     239chdir($cwd);
    143240exit(0);
     241
     242/**
     243 * Create commands to be executed for parallel run.
     244 *
     245 * @param array $options options provided by user.
     246 * @return array commands to be executed.
     247 */
     248function commands_to_execute($options) {
     249    $removeoptions = array('maxruns', 'fromrun', 'torun');
     250    $cmds = array();
     251    $extraoptions = $options;
     252    $extra = "";
     253
     254    // Remove extra options not in util_single_run.php.
     255    foreach ($removeoptions as $ro) {
     256        $extraoptions[$ro] = null;
     257        unset($extraoptions[$ro]);
     258    }
     259
     260    foreach ($extraoptions as $option => $value) {
     261        if ($options[$option]) {
     262            $extra .= " --$option";
     263            if ($value) {
     264                $extra .= "=$value";
     265            }
     266        }
     267    }
     268
     269    if (empty($options['parallel'])) {
     270        $cmds = "php util_single_run.php " . $extra;
     271    } else {
     272        // Create commands which has to be executed for parallel site.
     273        for ($i = $options['fromrun']; $i <= $options['torun']; $i++) {
     274            $prefix = BEHAT_PARALLEL_SITE_NAME . $i;
     275            $cmds[$prefix] = "php util_single_run.php " . $extra . " --run=" . $i . " 2>&1";
     276        }
     277    }
     278    return $cmds;
     279}
     280
     281/**
     282 * Print drop output merging each run.
     283 *
     284 * @param array $processes list of processes.
     285 * @return array exit codes of each process.
     286 */
     287function print_combined_drop_output($processes) {
     288    $exitcodes = array();
     289    $maxdotsonline = 70;
     290    $remainingprintlen = $maxdotsonline;
     291    $progresscount = 0;
     292    echo "Dropping tables:" . PHP_EOL;
     293
     294    while (count($exitcodes) != count($processes)) {
     295        usleep(10000);
     296        foreach ($processes as $name => $process) {
     297            if ($process->isRunning()) {
     298                $op = $process->getIncrementalOutput();
     299                if (trim($op)) {
     300                    $update = preg_filter('#^\s*([FS\.\-]+)(?:\s+\d+)?\s*$#', '$1', $op);
     301                    $strlentoprint = strlen($update);
     302
     303                    // If not enough dots printed on line then just print.
     304                    if ($strlentoprint < $remainingprintlen) {
     305                        echo $update;
     306                        $remainingprintlen = $remainingprintlen - $strlentoprint;
     307                    } else if ($strlentoprint == $remainingprintlen) {
     308                        $progresscount += $maxdotsonline;
     309                        echo $update . " " . $progresscount . PHP_EOL;
     310                        $remainingprintlen = $maxdotsonline;
     311                    } else {
     312                        while ($part = substr($update, 0, $remainingprintlen) > 0) {
     313                            $progresscount += $maxdotsonline;
     314                            echo $part . " " . $progresscount . PHP_EOL;
     315                            $update = substr($update, $remainingprintlen);
     316                            $remainingprintlen = $maxdotsonline;
     317                        }
     318                    }
     319                }
     320            } else {
     321                // Process exited.
     322                $process->clearOutput();
     323                $exitcodes[$name] = $process->getExitCode();
     324            }
     325        }
     326    }
     327
     328    echo PHP_EOL;
     329    return $exitcodes;
     330}
     331
     332/**
     333 * Print install output merging each run.
     334 *
     335 * @param array $processes list of processes.
     336 * @return array exit codes of each process.
     337 */
     338function print_combined_install_output($processes) {
     339    $exitcodes = array();
     340    $line = array();
     341
     342    // Check what best we can do to accommodate  all parallel run o/p on single line.
     343    // Windows command line has length of 80 chars, so default we will try fit o/p in 80 chars.
     344    if (defined('BEHAT_MAX_CMD_LINE_OUTPUT') && BEHAT_MAX_CMD_LINE_OUTPUT) {
     345        $lengthofprocessline = (int)max(10, BEHAT_MAX_CMD_LINE_OUTPUT / count($processes));
     346    } else {
     347        $lengthofprocessline = (int)max(10, 80 / count($processes));
     348    }
     349
     350    echo "Installing behat site for " . count($processes) . " parallel behat run" . PHP_EOL;
     351
     352    // Show process name in first row.
     353    foreach ($processes as $name => $process) {
     354        // If we don't have enough space to show full run name then show runX.
     355        if ($lengthofprocessline < strlen($name + 2)) {
     356            $name = substr($name, -5);
     357        }
     358        // One extra padding as we are adding | separator for rest of the data.
     359        $line[$name] = str_pad('[' . $name . '] ', $lengthofprocessline + 1);
     360    }
     361    ksort($line);
     362    $tableheader = array_keys($line);
     363    echo implode("", $line) . PHP_EOL;
     364
     365    // Now print o/p from each process.
     366    while (count($exitcodes) != count($processes)) {
     367        usleep(50000);
     368        $poutput = array();
     369        // Create child process.
     370        foreach ($processes as $name => $process) {
     371            if ($process->isRunning()) {
     372                $output = $process->getIncrementalOutput();
     373                if (trim($output)) {
     374                    $poutput[$name] = explode(PHP_EOL, $output);
     375                }
     376            } else {
     377                // Process exited.
     378                $exitcodes[$name] = $process->getExitCode();
     379            }
     380        }
     381        ksort($poutput);
     382
     383        // Get max depth of o/p before displaying.
     384        $maxdepth = 0;
     385        foreach ($poutput as $pout) {
     386            $pdepth = count($pout);
     387            $maxdepth = $pdepth >= $maxdepth ? $pdepth : $maxdepth;
     388        }
     389
     390        // Iterate over each process to get line to print.
     391        for ($i = 0; $i <= $maxdepth; $i++) {
     392            $pline = "";
     393            foreach ($tableheader as $name) {
     394                $po = empty($poutput[$name][$i]) ? "" : substr($poutput[$name][$i], 0, $lengthofprocessline - 1);
     395                $po = str_pad($po, $lengthofprocessline);
     396                $pline .= "|". $po;
     397            }
     398            if (trim(str_replace("|", "", $pline))) {
     399                echo $pline . PHP_EOL;
     400            }
     401        }
     402        unset($poutput);
     403        $poutput = null;
     404
     405    }
     406    echo PHP_EOL;
     407    return $exitcodes;
     408}
     409
     410/**
     411 * Print install output merging showing one run at a time.
     412 * If any process fail then exit.
     413 *
     414 * @param array $processes list of processes.
     415 * @param bool $showprefix show prefix.
     416 * @return bool exitcode.
     417 */
     418function print_sequential_output($processes, $showprefix = true) {
     419    $status = false;
     420    foreach ($processes as $name => $process) {
     421        $shownname = false;
     422        while ($process->isRunning()) {
     423            $op = $process->getIncrementalOutput();
     424            if (trim($op)) {
     425                // Show name of the run once for sequential.
     426                if ($showprefix && !$shownname) {
     427                    echo '[' . $name . '] ';
     428                    $shownname = true;
     429                }
     430                echo $op;
     431            }
     432        }
     433        // If any error then exit.
     434        $exitcode = $process->getExitCode();
     435        if ($exitcode != 0) {
     436            exit($exitcode);
     437        }
     438        $status = $status || (bool)$exitcode;
     439    }
     440    return $status;
     441}
Note: See TracChangeset for help on using the changeset viewer.