MDL-35413 Assignment: Add unit tests (lots of them).
authorDamyon Wiese <damyon@moodle.com>
Thu, 6 Dec 2012 06:33:43 +0000 (14:33 +0800)
committerDamyon Wiese <damyon@moodle.com>
Fri, 4 Jan 2013 07:51:08 +0000 (15:51 +0800)
mod/assign/locallib.php
mod/assign/tests/generator/lib.php
mod/assign/tests/locallib_test.php [new file with mode: 0644]
mod/assign/tests/upgradelib_test.php [new file with mode: 0644]

index aa1a8d8..09ba8c9 100644 (file)
@@ -154,7 +154,7 @@ class assign {
      *
      * @return bool showintro
      */
-    private function show_intro() {
+    protected function show_intro() {
         if ($this->get_instance()->alwaysshowdescription ||
                 time() > $this->get_instance()->allowsubmissionsfromdate) {
             return true;
@@ -287,7 +287,7 @@ class assign {
      * @param string $subtype - either submission or feedback
      * @return array - The sorted list of plugins
      */
-    private function load_plugins($subtype) {
+    protected function load_plugins($subtype) {
         global $CFG;
         $result = array();
 
@@ -511,7 +511,7 @@ class assign {
      *
      * @return bool
      */
-    private function delete_grades() {
+    protected function delete_grades() {
         global $CFG;
 
         $result = grade_update('mod/assign',
@@ -654,7 +654,7 @@ class assign {
      * @param stdClass $formdata The form data
      * @return bool false if an error occurs
      */
-    private function update_plugin_instance(assign_plugin $plugin, stdClass $formdata) {
+    protected function update_plugin_instance(assign_plugin $plugin, stdClass $formdata) {
         if ($plugin->is_visible()) {
             $enabledname = $plugin->get_subtype() . '_' . $plugin->get_type() . '_enabled';
             if ($formdata->$enabledname) {
@@ -824,7 +824,7 @@ class assign {
      * @param int $userid - The userid we are grading
      * @return void
      */
-    private function add_plugin_grade_elements($grade, MoodleQuickForm $mform, stdClass $data, $userid) {
+    protected function add_plugin_grade_elements($grade, MoodleQuickForm $mform, stdClass $data, $userid) {
         foreach ($this->feedbackplugins as $plugin) {
             if ($plugin->is_enabled() && $plugin->is_visible()) {
                 $mform->addElement('header', 'header_' . $plugin->get_type(), $plugin->get_name());
@@ -845,7 +845,7 @@ class assign {
      *                               This form is modified directly (not returned).
      * @return void
      */
-    private function add_plugin_settings(assign_plugin $plugin, MoodleQuickForm $mform) {
+    protected function add_plugin_settings(assign_plugin $plugin, MoodleQuickForm $mform) {
         global $CFG;
         if ($plugin->is_visible()) {
             $mform->addElement('selectyesno',
@@ -1321,7 +1321,7 @@ class assign {
      *
      * @return array An array of userids
      */
-    private function get_grading_userid_list() {
+    protected function get_grading_userid_list() {
         $filter = get_user_preferences('assign_filter', '');
         $table = new assign_grading_table($this, 0, $filter, 0, false);
 
@@ -1339,7 +1339,7 @@ class assign {
      * @return path of temp file - note this returned file does
      *         not have a .zip extension - it is a temp file.
      */
-    private function pack_files($filesforzipping) {
+    protected function pack_files($filesforzipping) {
         global $CFG;
         // Create path for new zip file.
         $tempzip = tempnam($CFG->tempdir . '/', 'assignment_');
@@ -1379,7 +1379,6 @@ class assign {
         $submissions = $DB->get_records_sql($sql, $params);
 
         if (empty($submissions)) {
-            mtrace('done.');
             return true;
         }
 
@@ -1560,7 +1559,7 @@ class assign {
      * @param moodleform $mform - Used for validation of the submitted data
      * @return string
      */
-    private function view_grant_extension($mform) {
+    protected function view_grant_extension($mform) {
         global $DB, $CFG;
         require_once($CFG->dirroot . '/mod/assign/extensionform.php');
 
@@ -1813,7 +1812,7 @@ class assign {
      *
      * @return string
      */
-    private function view_plugin_page() {
+    protected function view_plugin_page() {
         global $USER;
 
         $o = '';
@@ -1859,7 +1858,7 @@ class assign {
      * @param string $pluginsubtype
      * @return string
      */
-    private function view_plugin_content($pluginsubtype) {
+    protected function view_plugin_content($pluginsubtype) {
         global $USER;
 
         $o = '';
@@ -1986,7 +1985,7 @@ class assign {
      * @param string $message - The description of the result
      * @return string
      */
-    private function view_quickgrading_result($message) {
+    protected function view_quickgrading_result($message) {
         $o = '';
         $o .= $this->get_renderer()->render(new assign_header($this->get_instance(),
                                                       $this->get_context(),
@@ -2004,7 +2003,7 @@ class assign {
      *
      * @return string
      */
-    private function view_footer() {
+    protected function view_footer() {
         return $this->get_renderer()->render_footer();
     }
 
@@ -2013,7 +2012,7 @@ class assign {
      *
      * @return bool
      */
-    private function can_grade() {
+    protected function can_grade() {
         // Permissions check.
         if (!has_capability('mod/assign:grade', $this->context)) {
             return false;
@@ -2027,7 +2026,7 @@ class assign {
      *
      * @return void
      */
-    private function download_submissions() {
+    protected function download_submissions() {
         global $CFG, $DB;
 
         // More efficient to load this here.
@@ -2209,7 +2208,7 @@ class assign {
      * @param int $submissionid The id of the submission we want
      * @return stdClass The submission
      */
-    private function get_submission($submissionid) {
+    protected function get_submission($submissionid) {
         global $DB;
 
         $params = array('assignment'=>$this->get_instance()->id, 'id'=>$submissionid);
@@ -2259,7 +2258,7 @@ class assign {
      * @param int $gradeid The id of the grade
      * @return stdClass The grade record
      */
-    private function get_grade($gradeid) {
+    protected function get_grade($gradeid) {
         global $DB;
 
         $params = array('assignment'=>$this->get_instance()->id, 'id'=>$gradeid);
@@ -2273,7 +2272,7 @@ class assign {
      * @param int $offset
      * @return string
      */
-    private function view_single_grade_page($mform, $offset=0) {
+    protected function view_single_grade_page($mform, $offset=0) {
         global $DB, $CFG;
 
         $o = '';
@@ -2419,7 +2418,7 @@ class assign {
      *
      * @return string
      */
-    private function view_reveal_identities_confirm() {
+    protected function view_reveal_identities_confirm() {
         global $CFG, $USER;
 
         require_capability('mod/assign:revealidentities', $this->get_context());
@@ -2453,7 +2452,7 @@ class assign {
      *
      * @return string
      */
-    private function view_return_links() {
+    protected function view_return_links() {
         $returnaction = optional_param('returnaction', '', PARAM_ALPHA);
         $returnparams = optional_param('returnparams', '', PARAM_TEXT);
 
@@ -2471,7 +2470,7 @@ class assign {
      *
      * @return string
      */
-    private function view_grading_table() {
+    protected function view_grading_table() {
         global $USER, $CFG;
 
         // Include grading options form.
@@ -2610,7 +2609,7 @@ class assign {
      *
      * @return string
      */
-    private function view_grading_page() {
+    protected function view_grading_page() {
         global $CFG;
 
         $o = '';
@@ -2634,7 +2633,7 @@ class assign {
      *
      * @return void
      */
-    private function plagiarism_print_disclosure() {
+    protected function plagiarism_print_disclosure() {
         global $CFG;
         $o = '';
 
@@ -2652,7 +2651,7 @@ class assign {
      *
      * @return string
      */
-    private function view_student_error_message() {
+    protected function view_student_error_message() {
         global $CFG;
 
         $o = '';
@@ -2682,7 +2681,7 @@ class assign {
      *                       edit submission form (e.g. from plugins).
      * @return void
      */
-    private function view_edit_submission_page($mform, $notices) {
+    protected function view_edit_submission_page($mform, $notices) {
         global $CFG;
 
         $o = '';
@@ -2723,7 +2722,7 @@ class assign {
      * @param int $userid
      * @return bool
      */
-    private function is_graded($userid) {
+    protected function is_graded($userid) {
         $grade = $this->get_user_grade($userid, false);
         if ($grade) {
             return ($grade->grade !== null && $grade->grade >= 0);
@@ -2757,7 +2756,7 @@ class assign {
      *
      * @return none
      */
-    private function view_plugin_grading_batch_operation($mform) {
+    protected function view_plugin_grading_batch_operation($mform) {
         require_capability('mod/assign:grade', $this->context);
         $prefix = 'plugingradingbatchoperation_';
 
@@ -2782,7 +2781,7 @@ class assign {
      * @param moodleform $mform Set to a grading batch operations form
      * @return string - the page to view after processing these actions
      */
-    private function process_grading_batch_operation(& $mform) {
+    protected function process_grading_batch_operation(& $mform) {
         global $CFG;
         require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
         require_sesskey();
@@ -2839,7 +2838,7 @@ class assign {
      * @param $mform moodleform - null unless form validation has failed
      * @return string
      */
-    private function check_submit_for_grading($mform) {
+    protected function check_submit_for_grading($mform) {
         global $USER, $CFG;
 
         require_once($CFG->dirroot . '/mod/assign/submissionconfirmform.php');
@@ -3043,7 +3042,7 @@ class assign {
      *
      * @return string
      */
-    private function view_submission_page() {
+    protected function view_submission_page() {
         global $CFG, $DB, $USER, $PAGE;
 
         $instance = $this->get_instance();
@@ -3101,7 +3100,7 @@ class assign {
      * @param stdClass $grade
      * @return array
      */
-    private function convert_grade_for_gradebook(stdClass $grade) {
+    protected function convert_grade_for_gradebook(stdClass $grade) {
         $gradebookgrade = array();
         if ($grade->grade >= 0) {
             $gradebookgrade['rawgrade'] = $grade->grade;
@@ -3126,7 +3125,7 @@ class assign {
      * @param stdClass $submission
      * @return array
      */
-    private function convert_submission_for_gradebook(stdClass $submission) {
+    protected function convert_submission_for_gradebook(stdClass $submission) {
         $gradebookgrade = array();
 
         $gradebookgrade['userid'] = $submission->userid;
@@ -3143,7 +3142,7 @@ class assign {
      * @param mixed $grade stdClass|null
      * @return bool
      */
-    private function gradebook_item_update($submission=null, $grade=null) {
+    protected function gradebook_item_update($submission=null, $grade=null) {
 
         // Do not push grade to gradebook if blind marking is active as
         // the gradebook would reveal the students.
@@ -3186,7 +3185,7 @@ class assign {
      * @param bool $updatetime
      * @return bool
      */
-    private function update_team_submission(stdClass $submission, $userid, $updatetime) {
+    protected function update_team_submission(stdClass $submission, $userid, $updatetime) {
         global $DB;
 
         if ($updatetime) {
@@ -3246,7 +3245,7 @@ class assign {
      * @param bool $teamsubmission
      * @return bool
      */
-    private function update_submission(stdClass $submission, $userid, $updatetime, $teamsubmission) {
+    protected function update_submission(stdClass $submission, $userid, $updatetime, $teamsubmission) {
         global $DB;
 
         if ($teamsubmission) {
@@ -3364,10 +3363,10 @@ class assign {
     /**
      * Returns a list of teachers that should be grading given submission.
      *
-     * @param int $userid
+     * @param int $userid The submission to grade
      * @return array
      */
-    private function get_graders($userid) {
+    protected function get_graders($userid) {
         $potentialgraders = get_enrolled_users($this->context, 'mod/assign:grade');
 
         $graders = array();
@@ -3421,7 +3420,7 @@ class assign {
      * @param string $modulename
      * @param string $assignmentname
      */
-    private static function format_notification_message_text($messagetype,
+    protected static function format_notification_message_text($messagetype,
                                                              $info,
                                                              $course,
                                                              $context,
@@ -3451,7 +3450,7 @@ class assign {
      * @param string $assignmentname
      * @param stdClass $info
      */
-    private static function format_notification_message_html($messagetype,
+    protected static function format_notification_message_html($messagetype,
                                                              $info,
                                                              $course,
                                                              $context,
@@ -3587,7 +3586,7 @@ class assign {
      * @param stdClass $submission
      * @return void
      */
-    private function notify_student_submission_receipt(stdClass $submission) {
+    protected function notify_student_submission_receipt(stdClass $submission) {
         global $DB, $USER;
 
         $adminconfig = $this->get_admin_config();
@@ -3613,7 +3612,7 @@ class assign {
      * @param stdClass $submission
      * @return void
      */
-    private function notify_graders(stdClass $submission) {
+    protected function notify_graders(stdClass $submission) {
         global $DB, $USER;
 
         $instance = $this->get_instance();
@@ -3648,7 +3647,7 @@ class assign {
      *               It can be null.
      * @return bool Return false if the validation fails. This affects which page is displayed next.
      */
-    private function process_submit_for_grading($mform) {
+    protected function process_submit_for_grading($mform) {
         global $USER, $CFG;
 
         // Need submit permission to submit an assignment.
@@ -3731,7 +3730,7 @@ class assign {
      * @param mixed $extensionduedate Either an integer date or null
      * @return boolean
      */
-    private function save_user_extension($userid, $extensionduedate) {
+    protected function save_user_extension($userid, $extensionduedate) {
         global $DB;
 
         $grade = $this->get_user_grade($userid, true);
@@ -3752,7 +3751,7 @@ class assign {
      * @param moodleform $mform The submitted form
      * @return boolean
      */
-    private function process_save_extension(& $mform) {
+    protected function process_save_extension(& $mform) {
         global $DB, $CFG;
 
         // Include extension form.
@@ -3798,7 +3797,7 @@ class assign {
      *
      * @return string The result of the save operation
      */
-    private function process_save_quick_grades() {
+    protected function process_save_quick_grades() {
         global $USER, $DB, $CFG;
 
         // Need grade permission.
@@ -3958,7 +3957,7 @@ class assign {
      *
      * @return void
      */
-    private function process_reveal_identities() {
+    protected function process_reveal_identities() {
         global $DB, $CFG;
 
         require_capability('mod/assign:revealidentities', $this->context);
@@ -4005,7 +4004,7 @@ class assign {
      *
      * @return void
      */
-    private function process_save_grading_options() {
+    protected function process_save_grading_options() {
         global $USER, $CFG;
 
         // Include grading options form.
@@ -4065,7 +4064,7 @@ class assign {
      * @param stdClass $submission
      * @return string
      */
-    private function format_submission_for_log(stdClass $submission) {
+    protected function format_submission_for_log(stdClass $submission) {
         $info = '';
         $info .= get_string('submissionstatus', 'assign') .
                  ': ' .
@@ -4089,7 +4088,7 @@ class assign {
      *                        to the user at the top of the edit submission form.
      * @return bool
      */
-    private function process_save_submission(&$mform, &$notices) {
+    protected function process_save_submission(&$mform, &$notices) {
         global $USER, $CFG;
 
         // Include submission form.
@@ -4221,7 +4220,7 @@ class assign {
      * @param bool $gradingdisabled
      * @return mixed gradingform_instance|null $gradinginstance
      */
-    private function get_grading_instance($userid, $gradingdisabled) {
+    protected function get_grading_instance($userid, $gradingdisabled) {
         global $CFG, $USER;
 
         $grade = $this->get_user_grade($userid, false);
@@ -4416,7 +4415,7 @@ class assign {
      * @param int $userid The current userid (same as $USER->id)
      * @return void
      */
-    private function add_plugin_submission_elements($submission,
+    protected function add_plugin_submission_elements($submission,
                                                     MoodleQuickForm $mform,
                                                     stdClass $data,
                                                     $userid) {
@@ -4522,7 +4521,7 @@ class assign {
      * @param int $userid
      * @return void
      */
-    private function process_revert_to_draft($userid = 0) {
+    protected function process_revert_to_draft($userid = 0) {
         global $DB, $USER;
 
         // Need grade permission.
@@ -4570,7 +4569,7 @@ class assign {
      * @param int $userid
      * @return void
      */
-    private function process_lock($userid = 0) {
+    protected function process_lock($userid = 0) {
         global $USER, $DB;
 
         // Need grade permission.
@@ -4600,7 +4599,7 @@ class assign {
      * @param int $userid
      * @return void
      */
-    private function process_unlock($userid = 0) {
+    protected function process_unlock($userid = 0) {
         global $USER, $DB;
 
         // Need grade permission.
@@ -4631,7 +4630,7 @@ class assign {
      * @param int $userid - the user to apply the grade to
      * @return void
      */
-    private function apply_grade_to_user($formdata, $userid) {
+    protected function apply_grade_to_user($formdata, $userid) {
         global $USER, $CFG, $DB;
 
         $grade = $this->get_user_grade($userid, true);
@@ -4680,7 +4679,7 @@ class assign {
      * @param int $userid
      * @param stdClass $formdata
      */
-    private function process_outcomes($userid, $formdata) {
+    protected function process_outcomes($userid, $formdata) {
         global $CFG, $USER;
 
         if (empty($CFG->enableoutcomes)) {
@@ -4726,7 +4725,7 @@ class assign {
      * @param  moodleform $mform
      * @return bool - was the grade saved
      */
-    private function process_save_grade(&$mform) {
+    protected function process_save_grade(&$mform) {
         global $CFG;
         // Include grade form.
         require_once($CFG->dirroot . '/mod/assign/gradeform.php');
@@ -5230,7 +5229,7 @@ class assign_portfolio_caller extends portfolio_module_caller_base {
      *
      * @return assign_submission_plugin
      */
-    private function get_submission_plugin() {
+    protected function get_submission_plugin() {
         global $CFG;
         if (!$this->plugin || !$this->cmid) {
             return null;
index 9990709..43eb7d0 100644 (file)
@@ -45,81 +45,44 @@ class mod_assign_generator extends phpunit_module_generator {
         if (empty($record->course)) {
             throw new coding_exception('module generator requires $record->course');
         }
-        if (!isset($record->name)) {
-            $record->name = get_string('pluginname', 'data').' '.$i;
-        }
-        if (!isset($record->intro)) {
-            $record->intro = 'Test database '.$i;
-        }
-        if (!isset($record->introformat)) {
-            $record->introformat = FORMAT_MOODLE;
-        }
-        if (!isset($record->alwaysshowdescription)) {
-            $record->alwaysshowdescription = 1;
-        }
-        if (!isset($record->nosubmissions)) {
-            $record->nosubmissions = 0;
-        }
-        if (!isset($record->submissiondrafts)) {
-            $record->submissiondrafts = 1;
-        }
-        if (!isset($record->requiresubmissionstatement)) {
-            $record->requiresubmissionstatement = 0;
-        }
-        if (!isset($record->sendnotifications)) {
-            $record->sendnotifications = 0;
-        }
-        if (!isset($record->sendlatenotifications)) {
-            $record->sendlatenotifications = 0;
-        }
-        if (!isset($record->duedate)) {
-            $record->duedate = 0;
-        }
-        if (!isset($record->allowsubmissionsfromdate)) {
-            $record->allowsubmissionsfromdate = 0;
-        }
-        if (!isset($record->assignsubmission_onlinetext_enabled)) {
-            $record->assignsubmission_onlinetext_enabled = 0;
-        }
-        if (!isset($record->assignsubmission_file_enabled)) {
-            $record->assignsubmission_file_enabled = 0;
-        }
-        if (!isset($record->assignsubmission_comments_enabled)) {
-            $record->assignsubmission_comments_enabled = 0;
-        }
-        if (!isset($record->assignfeedback_comments_enabled)) {
-            $record->assignfeedback_comments_enabled = 0;
-        }
-        if (!isset($record->assignfeedback_file_enabled)) {
-            $record->assignfeedback_file_enabled = 0;
-        }
-        if (!isset($record->assignfeedback_offline_enabled)) {
-            $record->assignfeedback_offline_enabled = 0;
-        }
-        if (!isset($record->grade)) {
-            $record->grade = 100;
-        }
-        if (!isset($record->cutoffdate)) {
-            $record->cutoffdate = 0;
-        }
-        if (!isset($record->teamsubmission)) {
-            $record->teamsubmission = 0;
-        }
-        if (!isset($record->requireallteammemberssubmit)) {
-            $record->requireallteammemberssubmit = 0;
-        }
-        if (!isset($record->teamsubmissiongroupingid)) {
-            $record->teamsubmissiongroupingid = 0;
-        }
-        if (!isset($record->blindmarking)) {
-            $record->blindmarking = 0;
-        }
+
         if (isset($options['idnumber'])) {
             $record->cmidnumber = $options['idnumber'];
         } else {
             $record->cmidnumber = '';
         }
 
+        $defaultsettings = array(
+            'name'                              => get_string('pluginname', 'assign').' '.$i,
+            'intro'                             => 'Test assign ' . $i,
+            'introformat'                       => FORMAT_MOODLE,
+            'alwaysshowdescription'             => 1,
+            'submissiondrafts'                  => 1,
+            'requiresubmissionstatement'        => 0,
+            'sendnotifications'                 => 0,
+            'sendlatenotifications'             => 0,
+            'duedate'                           => 0,
+            'allowsubmissionsfromdate'          => 0,
+            'assignsubmission_onlinetext_enabled' => 0,
+            'assignsubmission_file_enabled'     => 0,
+            'assignsubmission_comments_enabled' => 0,
+            'assignfeedback_comments_enabled'   => 0,
+            'assignfeedback_file_enabled'       => 0,
+            'assignfeedback_offline_enabled'    => 0,
+            'grade'                             => 100,
+            'cutoffdate'                        => 0,
+            'teamsubmission'                    => 0,
+            'requireallteammemberssubmit'       => 0,
+            'teamsubmissiongroupingid'          => 0,
+            'blindmarking'                      => 0,
+        );
+
+        foreach ($defaultsettings as $name => $value) {
+            if (!isset($record->{$name})) {
+                $record->{$name} = $value;
+            }
+        }
+
         $record->coursemodule = $this->precreate_course_module($record->course, $options);
         $id = assign_add_instance($record, null);
         return $this->post_add_instance($id, $record->coursemodule);
diff --git a/mod/assign/tests/locallib_test.php b/mod/assign/tests/locallib_test.php
new file mode 100644 (file)
index 0000000..a9b8ab2
--- /dev/null
@@ -0,0 +1,708 @@
+<?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/>.
+
+/**
+ * Unit tests for (some of) mod/assign/locallib.php.
+ *
+ * @package    mod_assign
+ * @category   phpunit
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
+
+/**
+ * Unit tests for (some of) mod/assign/locallib.php.
+ *
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_locallib_testcase extends advanced_testcase {
+
+    /** @var stdClass $course New course created to hold the assignments */
+    protected $course = null;
+
+    /** @var array $teachers List of 5 default teachers in the course*/
+    protected $teachers = null;
+
+    /** @var array $editingteachers List of 5 default editing teachers in the course*/
+    protected $editingteachers = null;
+
+    /** @var array $students List of 100 default students in the course*/
+    protected $students = null;
+
+    /** @var array $groups List of 10 groups in the course */
+    protected $groups = null;
+
+    /**
+     * Setup function - we will create a course and add an assign instance to it.
+     */
+    protected function setUp() {
+        global $DB, $CFG;
+
+        $this->resetAfterTest(true);
+
+        $this->course = $this->getDataGenerator()->create_course();
+        $this->teachers = array();
+        for ($i = 0; $i < 5; $i++) {
+            array_push($this->teachers, $this->getDataGenerator()->create_user());
+        }
+
+        $this->editingteachers = array();
+        for ($i = 0; $i < 5; $i++) {
+            array_push($this->editingteachers, $this->getDataGenerator()->create_user());
+        }
+
+        $this->students = array();
+        for ($i = 0; $i < 100; $i++) {
+            array_push($this->students, $this->getDataGenerator()->create_user());
+        }
+
+        $this->groups = array();
+        for ($i = 0; $i < 10; $i++) {
+            array_push($this->groups, $this->getDataGenerator()->create_group(array('courseid'=>$this->course->id)));
+        }
+
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        foreach ($this->teachers as $i => $teacher) {
+            $this->getDataGenerator()->enrol_user($teacher->id,
+                                                  $this->course->id,
+                                                  $teacherrole->id);
+            groups_add_member($this->groups[$i % 10], $teacher);
+        }
+
+        $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
+        foreach ($this->editingteachers as $i => $editingteacher) {
+            $this->getDataGenerator()->enrol_user($editingteacher->id,
+                                                  $this->course->id,
+                                                  $editingteacherrole->id);
+            groups_add_member($this->groups[$i % 10], $editingteacher);
+        }
+
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        foreach ($this->students as $i => $student) {
+            $this->getDataGenerator()->enrol_user($student->id,
+                                                  $this->course->id,
+                                                  $studentrole->id);
+            if ($i < 80) {
+                groups_add_member($this->groups[$i % 10], $student);
+            }
+        }
+    }
+
+    private function create_instance($params=array()) {
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params['course'] = $this->course->id;
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        $context = context_module::instance($cm->id);
+        return new testable_assign($context, $cm, $this->course);
+    }
+
+    public function test_return_links() {
+        $this->setUser($this->editingteachers[0]);
+        $returnaction = 'RETURNACTION';
+        $returnparams = array('param'=>1);
+        $assign = $this->create_instance();
+        $assign->register_return_link($returnaction, $returnparams);
+        $this->assertEquals($returnaction, $assign->get_return_action());
+        $this->assertEquals($returnparams, $assign->get_return_params());
+    }
+
+    public function test_get_feedback_plugins() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+        $this->assertEquals(3, count($assign->get_feedback_plugins()));
+    }
+
+    public function test_get_submission_plugins() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+        $this->assertEquals(3, count($assign->get_submission_plugins()));
+    }
+
+    public function test_is_blind_marking() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('blindmarking'=>1));
+        $this->assertEquals(true, $assign->is_blind_marking());
+
+        // Test cannot see student names.
+        $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+        $output = $assign->get_renderer()->render($gradingtable);
+        $this->assertEquals(true, strpos($output, get_string('hiddenuser', 'assign')));
+
+        // Test students cannot reveal identities.
+        $nopermission = false;
+        $this->setUser($this->students[0]);
+        $this->setExpectedException('required_capability_exception');
+        $assign->testable_process_reveal_identities();
+
+        // Test teachers cannot reveal identities.
+        $nopermission = false;
+        $this->setUser($this->teachers[0]);
+        $this->setExpectedException('required_capability_exception');
+        $assign->testable_process_reveal_identities();
+
+        // Test sesskey is required.
+        $nosesskey = true;
+        $this->setUser($this->editingteachers[0]);
+        $this->setExpectedException('moodle_exception');
+        $assign->testable_process_reveal_identities();
+
+        // Test editingteacher can reveal identities if sesskey is ignored.
+        $this->editingteachers[0]->ignoresesskey = true;
+        $this->setUser($this->editingteachers[0]);
+        $assign->testable_process_reveal_identities();
+        $this->assertEquals(false, $assign->is_blind_marking());
+
+        // Test student names are visible.
+        $gradingtable = new assign_grading_table($assign, 1, '', 0, true);
+        $output = $assign->get_renderer()->render($gradingtable);
+        $this->assertEquals(false, strpos($output, get_string('hiddenuser', 'assign')));
+
+        // Set this back to default.
+        $this->editingteachers[0]->ignoresesskey = false;
+    }
+
+    public function test_show_intro() {
+        // Test whether we are showing the intro at the correct times.
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('alwaysshowdescription'=>1));
+
+        $this->assertEquals(true, $assign->testable_show_intro());
+
+        $tomorrow = time() + (24*60*60);
+
+        $assign = $this->create_instance(array('alwaysshowdescription'=>0,
+                                               'allowsubmissionsfromdate'=>$tomorrow));
+        $this->assertEquals(false, $assign->testable_show_intro());
+        $yesterday = time() - (24*60*60);
+        $assign = $this->create_instance(array('alwaysshowdescription'=>0,
+                                               'allowsubmissionsfromdate'=>$yesterday));
+        $this->assertEquals(true, $assign->testable_show_intro());
+    }
+
+    public function test_has_submissions_or_grades() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
+
+        $instance = $assign->get_instance();
+
+        // Should start empty.
+        $this->assertEquals(false, $assign->has_submissions_or_grades());
+
+        // Simulate a submission.
+        $this->setUser($this->students[0]);
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Now test again.
+        $this->assertEquals(true, $assign->has_submissions_or_grades());
+        // Set this back to default.
+        $this->students[0]->ignoresesskey = false;
+    }
+
+    public function test_delete_grades() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        // Now see if the data is in the gradebook.
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id);
+
+        $this->assertNotEquals(0, count($gradinginfo->items));
+
+        $assign->testable_delete_grades();
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id);
+
+        $this->assertEquals(0, count($gradinginfo->items));
+    }
+
+    public function test_delete_instance() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        // Simulate a submission.
+        $this->setUser($this->students[0]);
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Now try and delete.
+        $this->assertEquals(true, $assign->delete_instance());
+    }
+
+    public function test_reset_userdata() {
+        global $DB;
+
+        $now = time();
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1,
+                                               'duedate'=>$now));
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        // Simulate a submission.
+        $this->setUser($this->students[0]);
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        $this->assertEquals(true, $assign->has_submissions_or_grades());
+        // Now try and reset.
+        $data = new stdClass();
+        $data->reset_assign_submissions = 1;
+        $data->reset_gradebook_grades = 1;
+        $data->courseid = $this->course->id;
+        $data->timeshift = 24*60*60;
+        $this->setUser($this->editingteachers[0]);
+        $assign->reset_userdata($data);
+        $this->assertEquals(false, $assign->has_submissions_or_grades());
+
+        // Reload the instance data.
+        $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
+        $this->assertEquals($now + 24*60*60, $instance->duedate);
+    }
+
+    public function test_plugin_settings() {
+        global $DB;
+
+        $now = time();
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_file_enabled'=>1,
+                                               'assignsubmission_file_maxfiles'=>12,
+                                               'assignsubmission_file_maxsizebytes'=>10));
+
+        $plugin = $assign->get_submission_plugin_by_type('file');
+        $this->assertEquals('12', $plugin->get_config('maxfilesubmissions'));
+    }
+
+    public function test_update_calendar() {
+        global $DB;
+
+        $now = time();
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('duedate'=>$now));
+
+        // See if there is an event in the calendar.
+        $params = array('modulename'=>'assign', 'instance'=>$assign->get_instance()->id);
+        $id = $DB->get_field('event', 'id', $params);
+
+        $this->assertEquals(false, empty($id));
+    }
+
+    public function test_update_instance() {
+        global $DB;
+
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
+
+        $now = time();
+        $instance = $assign->get_instance();
+        $instance->duedate = $now;
+        $instance->instance = $instance->id;
+        $instance->assignsubmission_onlinetext_enabled = 1;
+        $instance->assignsubmission_file_enabled = 0;
+        $instance->assignsubmission_comments_enabled = 0;
+        $instance->assignfeedback_comments_enabled = 0;
+        $instance->assignfeedback_file_enabled = 0;
+        $instance->assignfeedback_offline_enabled = 0;
+
+        $assign->update_instance($instance);
+
+        $instance = $DB->get_record('assign', array('id'=>$assign->get_instance()->id));
+        $this->assertEquals($now, $instance->duedate);
+    }
+
+    public function test_list_participants() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('grade'=>100));
+
+        $this->assertEquals(100, count($assign->list_participants(null, true)));
+    }
+
+    public function test_count_teams() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('teamsubmission'=>1));
+
+        $this->assertEquals(11, $assign->count_teams());
+    }
+
+    public function test_count_submissions() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled'=>1));
+
+        // Simulate a submission.
+        $this->setUser($this->students[0]);
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        // Leave this one as DRAFT.
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        // Simulate a submission.
+        $this->setUser($this->students[1]);
+        $submission = $assign->get_user_submission($this->students[1]->id, true);
+        $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+        $assign->testable_update_submission($submission, $this->students[1]->id, true, false);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Simulate a submission.
+        $this->setUser($this->students[2]);
+        $submission = $assign->get_user_submission($this->students[2]->id, true);
+        $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+        $assign->testable_update_submission($submission, $this->students[2]->id, true, false);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Simulate a submission.
+        $this->setUser($this->students[3]);
+        $submission = $assign->get_user_submission($this->students[3]->id, true);
+        $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+        $assign->testable_update_submission($submission, $this->students[3]->id, true, false);
+        $data = new stdClass();
+        $data->onlinetext_editor = array('itemid'=>file_get_unused_draft_itemid(),
+                                         'text'=>'Submission text',
+                                         'format'=>FORMAT_MOODLE);
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $plugin->save($submission, $data);
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[3]->id);
+
+        $this->assertEquals(2, $assign->count_grades());
+        $this->assertEquals(4, $assign->count_submissions());
+        $this->assertEquals(2, $assign->count_submissions_need_grading());
+        $this->assertEquals(3, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED));
+        $this->assertEquals(1, $assign->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_DRAFT));
+    }
+
+    public function test_get_grading_userid_list() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        $users = $assign->testable_get_grading_userid_list();
+        $this->assertEquals(100, count($users));
+    }
+
+    public function test_cron() {
+        // First run cron so there are no messages waiting to be sent (from other tests).
+        cron_setup_user();
+        assign::cron();
+
+        // Now create an assignment and add some feedback.
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[3]->id);
+
+        // Now run cron and see that one message was sent.
+        $this->preventResetByRollback();
+        $sink = $this->redirectMessages();
+        cron_setup_user();
+        $this->expectOutputRegex('/Done processing 1 assignment submissions/');
+        assign::cron();
+
+        $messages = $sink->get_messages();
+        $this->assertEquals(1, count($messages));
+        $this->assertEquals(1, $messages[0]->notification);
+        $this->assertEquals($assign->get_instance()->name, $messages[0]->contexturlname);
+    }
+
+    public function test_is_graded() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        // Simulate adding a grade.
+        $this->setUser($this->teachers[0]);
+        $data = new stdClass();
+        $data->grade = '50.0';
+        $assign->testable_apply_grade_to_user($data, $this->students[0]->id);
+
+        $this->assertEquals(true, $assign->testable_is_graded($this->students[0]->id));
+        $this->assertEquals(false, $assign->testable_is_graded($this->students[1]->id));
+    }
+
+    public function test_can_view_submission() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        $this->setUser($this->students[0]);
+        $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
+        $this->assertEquals(false, $assign->can_view_submission($this->students[1]->id));
+        $this->assertEquals(false, $assign->can_view_submission($this->teachers[0]->id));
+        $this->setUser($this->teachers[0]);
+        $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
+        $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
+        $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
+        $this->setUser($this->editingteachers[0]);
+        $this->assertEquals(true, $assign->can_view_submission($this->students[0]->id));
+        $this->assertEquals(true, $assign->can_view_submission($this->students[1]->id));
+        $this->assertEquals(true, $assign->can_view_submission($this->teachers[0]->id));
+    }
+
+
+    public function test_update_submission() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        $this->setUser($this->students[0]);
+        $now = time();
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
+
+        $this->setUser($this->teachers[0]);
+        // Verify the gradebook update.
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id,
+                                        $this->students[0]->id);
+
+        $this->assertEquals($this->students[0]->id,
+                            $gradinginfo->items[0]->grades[$this->students[0]->id]->usermodified);
+
+        // Now verify group assignments.
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('teamsubmission'=>1));
+
+        $this->setUser($this->students[0]);
+        $now = time();
+        $submission = $assign->get_group_submission($this->students[0]->id, 0, true);
+        $assign->testable_update_submission($submission, $this->students[0]->id, true, true);
+
+        // Check that at least 2 members of the submission group had their submission updated.
+
+        $this->setUser($this->editingteachers[0]);
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id,
+                                        $this->students[0]->id);
+
+        $this->assertEquals($this->students[0]->id,
+                            $gradinginfo->items[0]->grades[$this->students[0]->id]->usermodified);
+
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id,
+                                        $this->students[10]->id);
+
+        $this->assertEquals($this->students[10]->id,
+                            $gradinginfo->items[0]->grades[$this->students[10]->id]->usermodified);
+
+        // Now verify blind marking.
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance(array('blindmarking'=>1));
+
+        $this->setUser($this->students[0]);
+        $now = time();
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
+
+        $this->setUser($this->editingteachers[0]);
+        $gradinginfo = grade_get_grades($this->course->id,
+                                        'mod',
+                                        'assign',
+                                        $assign->get_instance()->id,
+                                        $this->students[0]->id);
+
+        $this->assertEquals(null, $gradinginfo->items[0]->grades[$this->students[0]->id]->datesubmitted);
+    }
+
+    public function test_submissions_open() {
+        $this->setUser($this->editingteachers[0]);
+
+        $now = time();
+        $tomorrow = $now + 24*60*60;
+        $oneweek = $now + 7*24*60*60;
+        $yesterday = $now - 24*60*60;
+
+        $assign = $this->create_instance();
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign = $this->create_instance(array('duedate'=>$tomorrow));
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign = $this->create_instance(array('duedate'=>$yesterday));
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$tomorrow));
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign = $this->create_instance(array('duedate'=>$yesterday, 'cutoffdate'=>$yesterday));
+        $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign->testable_save_user_extension($this->students[0]->id, $tomorrow);
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $assign = $this->create_instance(array('submissiondrafts'=>1));
+        $this->assertEquals(true, $assign->testable_submissions_open($this->students[0]->id));
+
+        $this->setUser($this->students[0]);
+        $now = time();
+        $submission = $assign->get_user_submission($this->students[0]->id, true);
+        $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
+        $assign->testable_update_submission($submission, $this->students[0]->id, true, false);
+        $this->setUser($this->editingteachers[0]);
+        $this->assertEquals(false, $assign->testable_submissions_open($this->students[0]->id));
+    }
+
+    public function test_get_graders() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        $this->assertCount(10, $assign->testable_get_graders($this->students[0]->id));
+
+        $assign = $this->create_instance();
+        // Force create an assignment with SEPARATEGROUPS.
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
+        $params = array('course'=>$this->course->id);
+        $instance = $generator->create_instance($params);
+        $cm = get_coursemodule_from_instance('assign', $instance->id);
+        set_coursemodule_groupmode($cm->id, SEPARATEGROUPS);
+        $cm->groupmode = SEPARATEGROUPS;
+        $context = context_module::instance($cm->id);
+        $assign = new testable_assign($context, $cm, $this->course);
+
+        $this->setUser($this->students[1]);
+        $this->assertCount(2, $assign->testable_get_graders($this->students[0]->id));
+    }
+
+    public function test_get_uniqueid_for_user() {
+        $this->setUser($this->editingteachers[0]);
+        $assign = $this->create_instance();
+
+        foreach ($this->students as $student) {
+            $uniqueid = $assign->get_uniqueid_for_user($student->id);
+            $this->assertEquals($student->id, $assign->get_user_id_for_uniqueid($uniqueid));
+        }
+    }
+
+}
+
+/**
+ * Test subclass that makes all the protected methods we want to test public.
+ */
+class testable_assign extends assign {
+
+    public function testable_process_reveal_identities() {
+        return parent::process_reveal_identities();
+    }
+
+    public function testable_show_intro() {
+        return parent::show_intro();
+    }
+
+    public function testable_delete_grades() {
+        return parent::delete_grades();
+    }
+
+    public function testable_apply_grade_to_user($formdata, $userid) {
+        return parent::apply_grade_to_user($formdata, $userid);
+    }
+
+    public function testable_get_grading_userid_list() {
+        return parent::get_grading_userid_list();
+    }
+
+    public function testable_is_graded($userid) {
+        return parent::is_graded($userid);
+    }
+
+    public function testable_update_submission(stdClass $submission, $userid, $updatetime, $teamsubmission) {
+        return parent::update_submission($submission, $userid, $updatetime, $teamsubmission);
+    }
+
+    public function testable_submissions_open($userid = 0) {
+        return parent::submissions_open($userid);
+    }
+
+    public function testable_save_user_extension($userid, $extensionduedate) {
+        return parent::save_user_extension($userid, $extensionduedate);
+    }
+
+    public function testable_get_graders($userid) {
+        // Changed method from protected to public.
+        return parent::get_graders($userid);
+    }
+}
diff --git a/mod/assign/tests/upgradelib_test.php b/mod/assign/tests/upgradelib_test.php
new file mode 100644 (file)
index 0000000..8454229
--- /dev/null
@@ -0,0 +1,276 @@
+<?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/>.
+
+/**
+ * Unit tests for (some of) mod/assign/upgradelib.php.
+ *
+ * @package    mod_assign
+ * @category   phpunit
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once($CFG->dirroot . '/mod/assign/locallib.php');
+require_once($CFG->dirroot . '/mod/assign/upgradelib.php');
+require_once($CFG->dirroot . '/mod/assignment/lib.php');
+
+/**
+ * Unit tests for (some of) mod/assign/upgradelib.php.
+ *
+ * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_assign_upgradelib_testcase extends advanced_testcase {
+
+    /** @var stdClass $course New course created to hold the assignments */
+    protected $course = null;
+
+    /** @var array $teachers List of 5 default teachers in the course*/
+    protected $teachers = null;
+
+    /** @var array $editingteachers List of 5 default editing teachers in the course*/
+    protected $editingteachers = null;
+
+    /** @var array $students List of 100 default students in the course*/
+    protected $students = null;
+
+    /** @var array $groups List of 10 groups in the course */
+    protected $groups = null;
+
+    /**
+     * Setup function - we will create a course and add users to it.
+     */
+    protected function setUp() {
+        global $DB, $CFG;
+
+        $this->resetAfterTest(true);
+
+        $this->course = $this->getDataGenerator()->create_course();
+        $this->teachers = array();
+        for ($i = 0; $i < 5; $i++) {
+            array_push($this->teachers, $this->getDataGenerator()->create_user());
+        }
+
+        $this->editingteachers = array();
+        for ($i = 0; $i < 5; $i++) {
+            array_push($this->editingteachers, $this->getDataGenerator()->create_user());
+        }
+
+        $this->students = array();
+        for ($i = 0; $i < 100; $i++) {
+            array_push($this->students, $this->getDataGenerator()->create_user());
+        }
+
+        $this->groups = array();
+        for ($i = 0; $i < 10; $i++) {
+            array_push($this->groups, $this->getDataGenerator()->create_group(array('courseid'=>$this->course->id)));
+        }
+
+        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
+        foreach ($this->teachers as $i => $teacher) {
+            $this->getDataGenerator()->enrol_user($teacher->id,
+                                                  $this->course->id,
+                                                  $teacherrole->id);
+            groups_add_member($this->groups[$i % 10], $teacher);
+        }
+
+        $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
+        foreach ($this->editingteachers as $i => $editingteacher) {
+            $this->getDataGenerator()->enrol_user($editingteacher->id,
+                                                  $this->course->id,
+                                                  $editingteacherrole->id);
+            groups_add_member($this->groups[$i % 10], $editingteacher);
+        }
+
+        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
+        foreach ($this->students as $i => $student) {
+            $this->getDataGenerator()->enrol_user($student->id,
+                                                  $this->course->id,
+                                                  $studentrole->id);
+            if ($i < 80) {
+                groups_add_member($this->groups[$i % 10], $student);
+            }
+        }
+    }
+
+    public function test_upgrade_upload_assignment() {
+        global $DB;
+
+        $this->setUser($this->editingteachers[0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
+        $params = array('course'=>$this->course->id,
+                        'assignmenttype'=>'upload');
+        $record = $generator->create_instance($params);
+
+        $assignment = new assignment_base($record->cmid);
+
+        $this->setAdminUser();
+        $log = '';
+        $upgrader = new assign_upgrade_manager();
+
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $record = $DB->get_record('assign', array('course'=>$this->course->id));
+
+        $cm = get_coursemodule_from_instance('assign', $record->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $this->course);
+
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('comments');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('file');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('comments');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('file');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('offline');
+        $this->assertEmpty($plugin->is_enabled());
+
+        $assign->delete_instance();
+        delete_course_module($cm->id);
+        delete_mod_from_section($cm->id, $cm->section);
+    }
+
+    public function test_upgrade_uploadsingle_assignment() {
+        global $DB;
+
+        $this->setUser($this->editingteachers[0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
+        $params = array('course'=>$this->course->id,
+                        'assignmenttype'=>'uploadsingle');
+        $record = $generator->create_instance($params);
+
+        $assignment = new assignment_base($record->cmid);
+
+        $this->setAdminUser();
+        $log = '';
+        $upgrader = new assign_upgrade_manager();
+
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $record = $DB->get_record('assign', array('course'=>$this->course->id));
+
+        $cm = get_coursemodule_from_instance('assign', $record->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $this->course);
+
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('comments');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('file');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('comments');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('file');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('offline');
+        $this->assertEmpty($plugin->is_enabled());
+
+        $assign->delete_instance();
+        delete_course_module($cm->id);
+        delete_mod_from_section($cm->id, $cm->section);
+    }
+
+    public function test_upgrade_onlinetext_assignment() {
+        global $DB;
+
+        $this->setUser($this->editingteachers[0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
+        $params = array('course'=>$this->course->id,
+                        'assignmenttype'=>'online');
+        $record = $generator->create_instance($params);
+
+        $assignment = new assignment_base($record->cmid);
+
+        $this->setAdminUser();
+        $log = '';
+        $upgrader = new assign_upgrade_manager();
+
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $record = $DB->get_record('assign', array('course'=>$this->course->id));
+
+        $cm = get_coursemodule_from_instance('assign', $record->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $this->course);
+
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('comments');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('file');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('comments');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('file');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('offline');
+        $this->assertEmpty($plugin->is_enabled());
+
+        $assign->delete_instance();
+        delete_course_module($cm->id);
+        delete_mod_from_section($cm->id, $cm->section);
+    }
+
+    public function test_upgrade_offline_assignment() {
+        global $DB;
+
+        $this->setUser($this->editingteachers[0]);
+        $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment');
+        $params = array('course'=>$this->course->id,
+                        'assignmenttype'=>'offline');
+        $record = $generator->create_instance($params);
+
+        $assignment = new assignment_base($record->cmid);
+
+        $this->setAdminUser();
+        $log = '';
+        $upgrader = new assign_upgrade_manager();
+
+        $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log));
+        $record = $DB->get_record('assign', array('course'=>$this->course->id));
+
+        $cm = get_coursemodule_from_instance('assign', $record->id);
+        $context = context_module::instance($cm->id);
+
+        $assign = new assign($context, $cm, $this->course);
+
+        $plugin = $assign->get_submission_plugin_by_type('onlinetext');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('comments');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_submission_plugin_by_type('file');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('comments');
+        $this->assertNotEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('file');
+        $this->assertEmpty($plugin->is_enabled());
+        $plugin = $assign->get_feedback_plugin_by_type('offline');
+        $this->assertEmpty($plugin->is_enabled());
+
+        $assign->delete_instance();
+        delete_course_module($cm->id);
+        delete_mod_from_section($cm->id, $cm->section);
+    }
+}