MDL-41421 tool_generator: Adding a CLI tool to generate the test plan
authorDavid Monllao <davidm@moodle.com>
Thu, 5 Sep 2013 05:38:43 +0000 (13:38 +0800)
committerDavid Monllao <davidm@moodle.com>
Wed, 25 Sep 2013 01:23:37 +0000 (09:23 +0800)
admin/tool/generator/classes/make_testplan_form.php
admin/tool/generator/classes/testplan_backend.php
admin/tool/generator/cli/maketestplan.php [new file with mode: 0644]
admin/tool/generator/lang/en/tool_generator.php
admin/tool/generator/lib.php
admin/tool/generator/maketestplan.php
admin/tool/generator/version.php

index b4c05e0..15552d5 100644 (file)
@@ -64,24 +64,16 @@ class tool_generator_make_testplan_form extends moodleform {
      * @return array An array of errors
      */
     public function validation($data, $files) {
-        global $CFG, $DB;
+        global $CFG;
 
         $errors = array();
         if (empty($CFG->tool_generator_users_password) || is_bool($CFG->tool_generator_users_password)) {
             $errors['updateuserspassword'] = get_string('error_nouserspassword', 'tool_generator');
         }
 
-        // Check the course has users.
         // Better to repeat here the query than to do it afterwards and end up with an exception.
-        $coursecontext = context_course::instance($data['courseid']);
-        if (!$users = get_enrolled_users($coursecontext, '', 0, 'u.id')) {
-            $errors['courseid'] = get_string('coursewithoutusers', 'tool_generator');
-        }
-
-        // Checks that the selected course has enough users.
-        $coursesizes = tool_generator_course_backend::get_users_per_size();
-        if (count($users) < $coursesizes[$data['size']]) {
-            $errors['size'] = get_string('notenoughusers', 'tool_generator');
+        if ($courseerrors = tool_generator_testplan_backend::has_selected_course_any_problem($data['courseid'], $data['size'])) {
+            $errors = array_merge($errors, $courseerrors);
         }
 
         return $errors;
index af1b743..6f70dad 100644 (file)
@@ -33,6 +33,11 @@ defined('MOODLE_INTERNAL') || die();
  */
 class tool_generator_testplan_backend extends tool_generator_backend {
 
+    /**
+     * @var The URL to the repository of the external project.
+     */
+    protected static $repourl = 'https://github.com/moodlehq/moodle-performance-comparison';
+
     /**
      * @var Number of users depending on the selected size.
      */
@@ -85,6 +90,15 @@ class tool_generator_testplan_backend extends tool_generator_backend {
         return $options;
     }
 
+    /**
+     * Getter for moodle-performance-comparison project URL.
+     *
+     * @return string
+     */
+    public static function get_repourl() {
+        return self::$repourl;
+    }
+
     /**
      * Creates the test plan file.
      *
@@ -270,4 +284,45 @@ class tool_generator_testplan_backend extends tool_generator_backend {
         return $data;
     }
 
+    /**
+     * Checks if the selected target course is ok.
+     *
+     * @param int|string $course
+     * @param int $size
+     * @return array Errors array or false if everything is ok
+     */
+    public static function has_selected_course_any_problem($course, $size) {
+        global $DB;
+
+        $errors = array();
+
+        if (!is_numeric($course)) {
+            if (!$course = $DB->get_field('course', 'id', array('shortname' => $course))) {
+                $errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
+                return $errors;
+            }
+        }
+
+        $coursecontext = context_course::instance($course, IGNORE_MISSING);
+        if (!$coursecontext) {
+            $errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
+            return $errors;
+        }
+
+        if (!$users = get_enrolled_users($coursecontext, '', 0, 'u.id')) {
+            $errors['courseid'] = get_string('coursewithoutusers', 'tool_generator');
+        }
+
+        // Checks that the selected course has enough users.
+        $coursesizes = tool_generator_course_backend::get_users_per_size();
+        if (count($users) < $coursesizes[$size]) {
+            $errors['size'] = get_string('notenoughusers', 'tool_generator');
+        }
+
+        if (empty($errors)) {
+            return false;
+        }
+
+        return $errors;
+    }
 }
diff --git a/admin/tool/generator/cli/maketestplan.php b/admin/tool/generator/cli/maketestplan.php
new file mode 100644 (file)
index 0000000..456393d
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * CLI interface for creating a test plan
+ *
+ * @package tool_generator
+ * @copyright 2013 David MonllaĆ³
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('CLI_SCRIPT', true);
+define('NO_OUTPUT_BUFFERING', true);
+
+require(dirname(__FILE__) . '/../../../../config.php');
+require_once($CFG->libdir. '/clilib.php');
+
+// CLI options.
+list($options, $unrecognized) = cli_get_params(
+    array(
+        'help' => false,
+        'shortname' => false,
+        'size' => false,
+        'bypasscheck' => false,
+        'updateuserspassword' => false
+    ),
+    array(
+        'h' => 'help'
+    )
+);
+
+$testplansizes = '* ' . implode(PHP_EOL . '* ', tool_generator_testplan_backend::get_size_choices());
+
+// Display help.
+if (!empty($options['help']) || empty($options['shortname']) || empty($options['size'])) {
+
+    echo get_string('testplanexplanation', 'tool_generator', tool_generator_testplan_backend::get_repourl()) .
+"Options:
+-h, --help              Print out this help
+--shortname             Shortname of the test plan's target course (required)
+--size                  Size of the test plan to create XS, S, M, L, XL, or XXL (required)
+--bypasscheck           Bypasses the developer-mode check (be careful!)
+--updateuserspassword   Updates the target course users password according to \$CFG->tool_generator_users_password
+
+$testplansizes
+
+Consider that, the server resources you will need to run the test plan will be higher as the test plan size is higher.
+
+Example from Moodle root directory:
+\$ sudo -u www-data /usr/bin/php admin/tool/generator/cli/maketestplan.php --shortname=\"testcourse_12\" --size=S
+";
+    // Exit with error unless we're showing this because they asked for it.
+    exit(empty($options['help']) ? 1 : 0);
+}
+
+// Check debugging is set to developer level.
+if (empty($options['bypasscheck']) && !$CFG->debugdeveloper) {
+    cli_error(get_string('error_notdebugging', 'tool_generator'));
+}
+
+// Get options.
+$shortname = $options['shortname'];
+$sizename = $options['size'];
+
+// Check size.
+try {
+    $size = tool_generator_testplan_backend::size_for_name($sizename);
+} catch (coding_exception $e) {
+    cli_error("Error: Invalid size ($sizename). Use --help for help.");
+}
+
+// Check selected course.
+if ($errors = tool_generator_testplan_backend::has_selected_course_any_problem($shortname, $size)) {
+    // Showing the first reported problem.
+    cli_error("Error: " . reset($errors));
+}
+
+// Checking if test users password is set.
+if (empty($CFG->tool_generator_users_password) || is_bool($CFG->tool_generator_users_password)) {
+    cli_error("Error: " . get_string('error_nouserspassword', 'tool_generator'));
+}
+
+// Switch to admin user account.
+session_set_user(get_admin());
+
+// Create files.
+$courseid = $DB->get_field('course', 'id', array('shortname' => $shortname));
+$usersfile = tool_generator_testplan_backend::create_users_file($courseid, !empty($options['updateuserspassword']));
+$testplanfile = tool_generator_testplan_backend::create_testplan_file($courseid, $size);
+
+// One file path per line so other CLI scripts can easily parse the output.
+echo moodle_url::make_pluginfile_url(
+        $testplanfile->get_contextid(),
+        $testplanfile->get_component(),
+        $testplanfile->get_filearea(),
+        $testplanfile->get_itemid(),
+        $testplanfile->get_filepath(),
+        $testplanfile->get_filename()
+    ) .
+    PHP_EOL .
+    moodle_url::make_pluginfile_url(
+        $usersfile->get_contextid(),
+        $usersfile->get_component(),
+        $usersfile->get_filearea(),
+        $usersfile->get_itemid(),
+        $usersfile->get_filepath(),
+        $usersfile->get_filename()
+    ) .
+    PHP_EOL;
index 71d3741..9aab628 100644 (file)
@@ -98,11 +98,10 @@ $string['testplanexplanation'] = 'This tool creates a JMeter test plan file alon
 This test plan is designed to work along with {$a}, which makes easier to run the test plan in a specific Moodle environment, gathers information about the runs and compares the results, so you will need to download it and use it\'s test_runner.sh script or follow the installation and usage instructions.
 
 You need to set a password for the course users in config.php (p.e. $CFG->tool_generator_users_password = \'moodle\';) there
-is no default value for this password to prevent unintended usages of the tool.
+is no default value for this password to prevent unintended usages of the tool. You need to use the update passwords option in case your course users have other passwords or they were generated by tool_generator but without setting a $CFG->tool_generator_users_password value.
 
 It is part of tool_generator so it works well with the courses generated by the courses and the site generators, it can
 also be used with any course that contains, at least:
-
 * Enough enrolled users (depends on the test plan size you select) with the password reset to \'moodle\'
 * A page module instance
 * A forum module instance with at least one discussion and one reply
@@ -112,11 +111,7 @@ can be specially big. The ramp up period has been adjusted according to the numb
 of issues but the load is still huge.
 
 **Do not run the test plan on a live system**. This feature only creates the files to feed JMeter so is not dangerous by
-itself, but you should **NEVER** run this test plan in a production site as:
-
-* It changes the database contents
-* Logins lots of users at the same time so there is risk that your server can not handle the load and dies
-* It can update the course users passwords
+itself, but you should **NEVER** run this test plan in a production site.
 
 ';
 $string['testplansize_0'] = 'XS ({$a->users} users, {$a->loops} loops and {$a->rampup} rampup period)';
index b9b5efb..18e8a09 100644 (file)
@@ -40,8 +40,8 @@ defined('MOODLE_INTERNAL') || die();
  */
 function tool_generator_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) {
 
-    // Only for admins.
-    if (!is_siteadmin()) {
+    // Only for admins or CLI.
+    if (!defined('CLI_SCRIPT') && !is_siteadmin()) {
         die;
     }
 
index 5adef0c..fe2965a 100644 (file)
@@ -34,8 +34,7 @@ echo $OUTPUT->heading(get_string('maketestplan', 'tool_generator'));
 
 // Information message.
 $context = context_system::instance();
-$repourl = 'https://github.com/moodlehq/moodle-performance-comparison';
-$markdownlink = '[' . $repourl . '](' . $repourl . ')';
+$markdownlink = '[' . tool_generator_testplan_backend::get_repourl() . '](' . tool_generator_testplan_backend::get_repourl() . ')';
 echo $OUTPUT->box(format_text(get_string('testplanexplanation', 'tool_generator', $markdownlink),
         FORMAT_MARKDOWN, array('context' => $context)));
 
index 3733d98..fcbb49d 100644 (file)
@@ -24,6 +24,6 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$plugin->version = 2013090200;
-$plugin->requires = 2013090200;
+$plugin->version = 2013090500;
+$plugin->requires = 2013090500;
 $plugin->component = 'tool_generator';