source: moodle/trunk/fuentes/admin/tool/generator/classes/testplan_backend.php @ 136

Last change on this file since 136 was 136, checked in by mabarracus, 4 years ago

Ported code to xenial

File size: 11.0 KB
Line 
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Test plan generator.
19 *
20 * @package tool_generator
21 * @copyright 2013 David Monllaó
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * Generates the files required by JMeter.
29 *
30 * @package tool_generator
31 * @copyright 2013 David Monllaó
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 */
34class tool_generator_testplan_backend extends tool_generator_backend {
35
36    /**
37     * @var The URL to the repository of the external project.
38     */
39    protected static $repourl = 'https://github.com/moodlehq/moodle-performance-comparison';
40
41    /**
42     * @var Number of users depending on the selected size.
43     */
44    protected static $users = array(1, 30, 100, 1000, 5000, 10000);
45
46    /**
47     * @var Number of loops depending on the selected size.
48     */
49    protected static $loops = array(5, 5, 5, 6, 6, 7);
50
51    /**
52     * @var Rampup period depending on the selected size.
53     */
54    protected static $rampups = array(1, 6, 40, 100, 500, 800);
55
56    /**
57     * Gets a list of size choices supported by this backend.
58     *
59     * @return array List of size (int) => text description for display
60     */
61    public static function get_size_choices() {
62
63        $options = array();
64        for ($size = self::MIN_SIZE; $size <= self::MAX_SIZE; $size++) {
65            $a = new stdClass();
66            $a->users = self::$users[$size];
67            $a->loops = self::$loops[$size];
68            $a->rampup = self::$rampups[$size];
69            $options[$size] = get_string('testplansize_' . $size, 'tool_generator', $a);
70        }
71        return $options;
72    }
73
74    /**
75     * Gets the list of courses that can be used used to generate a test.
76     *
77     * @return array The list of options as courseid => name
78     */
79    public static function get_course_options() {
80        $courses = get_courses('all', 'c.sortorder ASC', 'c.id, c.shortname, c.fullname');
81        if (!$courses) {
82            print_error('error_nocourses', 'tool_generator');
83        }
84
85        $options = array();
86        unset($courses[1]);
87        foreach ($courses as $course) {
88            $options[$course->id] = $course->fullname . '(' . $course->shortname . ')';
89        }
90        return $options;
91    }
92
93    /**
94     * Getter for moodle-performance-comparison project URL.
95     *
96     * @return string
97     */
98    public static function get_repourl() {
99        return self::$repourl;
100    }
101
102    /**
103     * Creates the test plan file.
104     *
105     * @param int $courseid The target course id
106     * @param int $size The test plan size
107     * @return stored_file
108     */
109    public static function create_testplan_file($courseid, $size) {
110        $jmxcontents = self::generate_test_plan($courseid, $size);
111
112        $fs = get_file_storage();
113        $filerecord = self::get_file_record('testplan', 'jmx');
114        return $fs->create_file_from_string($filerecord, $jmxcontents);
115    }
116
117    /**
118     * Creates the users data file.
119     *
120     * @param int $courseid The target course id
121     * @param bool $updateuserspassword Updates the course users password to $CFG->tool_generator_users_password
122     * @return stored_file
123     */
124    public static function create_users_file($courseid, $updateuserspassword) {
125        $csvcontents = self::generate_users_file($courseid, $updateuserspassword);
126
127        $fs = get_file_storage();
128        $filerecord = self::get_file_record('users', 'csv');
129        return $fs->create_file_from_string($filerecord, $csvcontents);
130    }
131
132    /**
133     * Generates the test plan according to the target course contents.
134     *
135     * @param int $targetcourseid The target course id
136     * @param int $size The test plan size
137     * @return string The test plan as a string
138     */
139    protected static function generate_test_plan($targetcourseid, $size) {
140        global $CFG;
141
142        // Getting the template.
143        $template = file_get_contents(__DIR__ . '/../testplan.template.jmx');
144
145        // Getting the course modules data.
146        $coursedata = self::get_course_test_data($targetcourseid);
147
148        // Host and path to the site.
149        $urlcomponents = parse_url($CFG->wwwroot);
150        if (empty($urlcomponents['path'])) {
151            $urlcomponents['path'] = '';
152        }
153
154        $replacements = array(
155            $CFG->version,
156            self::$users[$size],
157            self::$loops[$size],
158            self::$rampups[$size],
159            $urlcomponents['host'],
160            $urlcomponents['path'],
161            get_string('shortsize_' . $size, 'tool_generator'),
162            $targetcourseid,
163            $coursedata->pageid,
164            $coursedata->forumid,
165            $coursedata->forumdiscussionid,
166            $coursedata->forumreplyid
167        );
168
169        $placeholders = array(
170            '{{MOODLEVERSION_PLACEHOLDER}}',
171            '{{USERS_PLACEHOLDER}}',
172            '{{LOOPS_PLACEHOLDER}}',
173            '{{RAMPUP_PLACEHOLDER}}',
174            '{{HOST_PLACEHOLDER}}',
175            '{{SITEPATH_PLACEHOLDER}}',
176            '{{SIZE_PLACEHOLDER}}',
177            '{{COURSEID_PLACEHOLDER}}',
178            '{{PAGEACTIVITYID_PLACEHOLDER}}',
179            '{{FORUMACTIVITYID_PLACEHOLDER}}',
180            '{{FORUMDISCUSSIONID_PLACEHOLDER}}',
181            '{{FORUMREPLYID_PLACEHOLDER}}'
182        );
183
184        // Fill the template with the target course values.
185        return str_replace($placeholders, $replacements, $template);
186    }
187
188    /**
189     * Generates the user's credentials file with all the course's users
190     *
191     * @param int $targetcourseid
192     * @param bool $updateuserspassword Updates the course users password to $CFG->tool_generator_users_password
193     * @return string The users csv file contents.
194     */
195    protected static function generate_users_file($targetcourseid, $updateuserspassword) {
196        global $CFG;
197
198        $coursecontext = context_course::instance($targetcourseid);
199
200        $users = get_enrolled_users($coursecontext, '', 0, 'u.id, u.username, u.auth', 'u.username ASC');
201        if (!$users) {
202            print_error('coursewithoutusers', 'tool_generator');
203        }
204
205        $lines = array();
206        foreach ($users as $user) {
207
208            // Updating password to the one set in config.php.
209            if ($updateuserspassword) {
210                $userauth = get_auth_plugin($user->auth);
211                if (!$userauth->user_update_password($user, $CFG->tool_generator_users_password)) {
212                    print_error('errorpasswordupdate', 'auth');
213                }
214            }
215
216            // Here we already checked that $CFG->tool_generator_users_password is not null.
217            $lines[] = $user->username . ',' . $CFG->tool_generator_users_password;
218        }
219
220        return implode(PHP_EOL, $lines);
221    }
222
223    /**
224     * Returns a tool_generator file record
225     *
226     * @param string $filearea testplan or users
227     * @param string $filetype The file extension jmx or csv
228     * @return stdClass The file record to use when creating tool_generator files
229     */
230    protected static function get_file_record($filearea, $filetype) {
231
232        $systemcontext = context_system::instance();
233
234        $filerecord = new stdClass();
235        $filerecord->contextid = $systemcontext->id;
236        $filerecord->component = 'tool_generator';
237        $filerecord->filearea = $filearea;
238        $filerecord->itemid = 0;
239        $filerecord->filepath = '/';
240
241        // Random generated number to avoid concurrent execution problems.
242        $filerecord->filename = $filearea . '_' . date('YmdHi', time()) . '_' . rand(1000, 9999) . '.' . $filetype;
243
244        return $filerecord;
245    }
246
247    /**
248     * Gets the data required to fill the test plan template with the database contents.
249     *
250     * @param int $targetcourseid The target course id
251     * @return stdClass The ids required by the test plan
252     */
253    protected static function get_course_test_data($targetcourseid) {
254        global $DB, $USER;
255
256        $data = new stdClass();
257
258        // Getting course contents info as the current user (will be an admin).
259        $course = new stdClass();
260        $course->id = $targetcourseid;
261        $courseinfo = new course_modinfo($course, $USER->id);
262
263        // Getting the first page module instance.
264        if (!$pages = $courseinfo->get_instances_of('page')) {
265            print_error('error_nopageinstances', 'tool_generator');
266        }
267        $data->pageid = reset($pages)->id;
268
269        // Getting the first forum module instance and it's first discussion and reply as well.
270        if (!$forums = $courseinfo->get_instances_of('forum')) {
271            print_error('error_noforuminstances', 'tool_generator');
272        }
273        $forum = reset($forums);
274
275        // Getting the first discussion (and reply).
276        if (!$discussions = forum_get_discussions($forum, 'd.timemodified ASC', false, -1, 1)) {
277            print_error('error_noforumdiscussions', 'tool_generator');
278        }
279        $discussion = reset($discussions);
280
281        $data->forumid = $forum->id;
282        $data->forumdiscussionid = $discussion->discussion;
283        $data->forumreplyid = $discussion->id;
284
285        // According to the current test plan.
286        return $data;
287    }
288
289    /**
290     * Checks if the selected target course is ok.
291     *
292     * @param int|string $course
293     * @param int $size
294     * @return array Errors array or false if everything is ok
295     */
296    public static function has_selected_course_any_problem($course, $size) {
297        global $DB;
298
299        $errors = array();
300
301        if (!is_numeric($course)) {
302            if (!$course = $DB->get_field('course', 'id', array('shortname' => $course))) {
303                $errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
304                return $errors;
305            }
306        }
307
308        $coursecontext = context_course::instance($course, IGNORE_MISSING);
309        if (!$coursecontext) {
310            $errors['courseid'] = get_string('error_nonexistingcourse', 'tool_generator');
311            return $errors;
312        }
313
314        if (!$users = get_enrolled_users($coursecontext, '', 0, 'u.id')) {
315            $errors['courseid'] = get_string('coursewithoutusers', 'tool_generator');
316        }
317
318        // Checks that the selected course has enough users.
319        $coursesizes = tool_generator_course_backend::get_users_per_size();
320        if (count($users) < self::$users[$size]) {
321            $errors['size'] = get_string('notenoughusers', 'tool_generator');
322        }
323
324        if (empty($errors)) {
325            return false;
326        }
327
328        return $errors;
329    }
330}
Note: See TracBrowser for help on using the repository browser.