MDL-74548 backup: Unit tests for course copy refactor
This commit is contained in:
@@ -71,6 +71,19 @@ class controller_test extends \advanced_testcase {
|
||||
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_copy
|
||||
*
|
||||
* @covers \restore_controller::get_copy
|
||||
*/
|
||||
public function test_restore_controller_get_copy() {
|
||||
$copydata = (object)["some" => "copydata"];
|
||||
$rc = new \restore_controller(1729, $this->courseid, backup::INTERACTIVE_NO, backup::MODE_COPY,
|
||||
$this->userid, backup::TARGET_NEW_COURSE, null, backup::RELEASESESSION_NO, $copydata);
|
||||
|
||||
$this->assertEquals($copydata, $rc->get_copy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test instantiating a restore controller for a course copy without providing copy data.
|
||||
*
|
||||
|
||||
@@ -32,8 +32,9 @@ require_once($CFG->libdir . '/completionlib.php');
|
||||
* @copyright 2020 onward The Moodle Users Association <https://moodleassociation.org/>
|
||||
* @author Matt Porritt <mattp@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @coversDefaultClass \copy_helper
|
||||
*/
|
||||
class course_copy_test extends \advanced_testcase {
|
||||
class copy_helper_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -143,8 +144,150 @@ class course_copy_test extends \advanced_testcase {
|
||||
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test process form data with invalid data.
|
||||
*
|
||||
* @covers ::process_formdata
|
||||
*/
|
||||
public function test_process_formdata_missing_fields() {
|
||||
$this->expectException(\moodle_exception::class);
|
||||
\copy_helper::process_formdata(new \stdClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test processing form data.
|
||||
*
|
||||
* @covers ::process_formdata
|
||||
*/
|
||||
public function test_process_formdata() {
|
||||
$validformdata = [
|
||||
'courseid' => 1729,
|
||||
'fullname' => 'Taxicab Numbers',
|
||||
'shortname' => 'Taxi101',
|
||||
'category' => 2,
|
||||
'visible' => 1,
|
||||
'startdate' => 87539319,
|
||||
'enddate' => 6963472309248,
|
||||
'idnumber' => 1730,
|
||||
'userdata' => 1
|
||||
];
|
||||
|
||||
$roles = [
|
||||
'role_one' => 1,
|
||||
'role_two' => 2,
|
||||
'role_three' => 0
|
||||
];
|
||||
|
||||
$expected = (object)array_merge($validformdata, ['keptroles' => []]);
|
||||
$expected->keptroles = [1, 2];
|
||||
$processed = \copy_helper::process_formdata(
|
||||
(object)array_merge(
|
||||
$validformdata,
|
||||
$roles,
|
||||
['extra' => 'stuff', 'remove' => 'this'])
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $processed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test orphaned controller cleanup.
|
||||
*
|
||||
* @covers ::cleanup_orphaned_copy_controllers
|
||||
*/
|
||||
public function test_cleanup_orphaned_copy_controllers() {
|
||||
global $DB;
|
||||
|
||||
// Mock up the form data.
|
||||
$formdata = new \stdClass;
|
||||
$formdata->courseid = $this->course->id;
|
||||
$formdata->fullname = 'foo';
|
||||
$formdata->shortname = 'data1';
|
||||
$formdata->category = 1;
|
||||
$formdata->visible = 1;
|
||||
$formdata->startdate = 1582376400;
|
||||
$formdata->enddate = 0;
|
||||
$formdata->idnumber = 123;
|
||||
$formdata->userdata = 1;
|
||||
$formdata->role_1 = 1;
|
||||
$formdata->role_3 = 3;
|
||||
$formdata->role_5 = 5;
|
||||
|
||||
$copies = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$formdata->shortname = 'data' . $i;
|
||||
$copies[] = \copy_helper::create_copy($formdata);
|
||||
}
|
||||
|
||||
// Delete one of the restore controllers. Simulates a situation where copy creation
|
||||
// interrupted and the restore controller never gets created.
|
||||
$DB->delete_records('backup_controllers', ['backupid' => $copies[0]['restoreid']]);
|
||||
|
||||
// Set a backup/restore controller pair to be in an intermediate state.
|
||||
\backup_controller::load_controller($copies[2]['backupid'])->set_status(backup::STATUS_FINISHED_OK);
|
||||
|
||||
// Set a backup/restore controller pair to completed.
|
||||
\backup_controller::load_controller($copies[3]['backupid'])->set_status(backup::STATUS_FINISHED_OK);
|
||||
\restore_controller::load_controller($copies[3]['restoreid'])->set_status(backup::STATUS_FINISHED_OK);
|
||||
|
||||
// Set a backup/restore controller pair to have a failed backup.
|
||||
\backup_controller::load_controller($copies[4]['backupid'])->set_status(backup::STATUS_FINISHED_ERR);
|
||||
|
||||
// Create some backup/restore controllers that are unrelated to course copies.
|
||||
$bc = new \backup_controller(backup::TYPE_1COURSE, 1, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_ASYNC,
|
||||
2, backup::RELEASESESSION_YES);
|
||||
$rc = new \restore_controller('restore-test-1729', 1, backup::INTERACTIVE_NO, backup::MODE_ASYNC, 1, 2);
|
||||
$rc->save_controller();
|
||||
$unrelatedvanillacontrollers = ['backupid' => $bc->get_backupid(), 'restoreid' => $rc->get_restoreid()];
|
||||
|
||||
$bc = new \backup_controller(backup::TYPE_1COURSE, 1, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_ASYNC,
|
||||
2, backup::RELEASESESSION_YES);
|
||||
$rc = new \restore_controller('restore-test-1729', 1, backup::INTERACTIVE_NO, backup::MODE_ASYNC, 1, 2);
|
||||
$bc->set_status(backup::STATUS_FINISHED_OK);
|
||||
$rc->set_status(backup::STATUS_FINISHED_OK);
|
||||
$unrelatedfinishedcontrollers = ['backupid' => $bc->get_backupid(), 'restoreid' => $rc->get_restoreid()];
|
||||
|
||||
$bc = new \backup_controller(backup::TYPE_1COURSE, 1, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_ASYNC,
|
||||
2, backup::RELEASESESSION_YES);
|
||||
$rc = new \restore_controller('restore-test-1729', 1, backup::INTERACTIVE_NO, backup::MODE_ASYNC, 1, 2);
|
||||
$bc->set_status(backup::STATUS_FINISHED_ERR);
|
||||
$rc->set_status(backup::STATUS_FINISHED_ERR);
|
||||
$unrelatedfailedcontrollers = ['backupid' => $bc->get_backupid(), 'restoreid' => $rc->get_restoreid()];
|
||||
|
||||
// Clean up the backup_controllers table.
|
||||
$records = $DB->get_records('backup_controllers', null, '', 'id, backupid, status, operation, purpose, timecreated');
|
||||
\copy_helper::cleanup_orphaned_copy_controllers($records, 0);
|
||||
|
||||
// Retrieve them again and check.
|
||||
$records = $DB->get_records('backup_controllers', null, '', 'backupid, status');
|
||||
|
||||
// Verify the backup associated with the deleted restore is marked as failed.
|
||||
$this->assertEquals(backup::STATUS_FINISHED_ERR, $records[$copies[0]['backupid']]->status);
|
||||
|
||||
// Verify other controllers remain untouched.
|
||||
$this->assertEquals(backup::STATUS_AWAITING, $records[$copies[1]['backupid']]->status);
|
||||
$this->assertEquals(backup::STATUS_REQUIRE_CONV, $records[$copies[1]['restoreid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $records[$copies[2]['backupid']]->status);
|
||||
$this->assertEquals(backup::STATUS_REQUIRE_CONV, $records[$copies[2]['restoreid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $records[$copies[3]['restoreid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $records[$copies[3]['backupid']]->status);
|
||||
|
||||
// Verify that the restore associated with the failed backup is also marked as failed.
|
||||
$this->assertEquals(backup::STATUS_FINISHED_ERR, $records[$copies[4]['restoreid']]->status);
|
||||
|
||||
// Verify that the unrelated controllers remain unchanged.
|
||||
$this->assertEquals(backup::STATUS_AWAITING, $records[$unrelatedvanillacontrollers['backupid']]->status);
|
||||
$this->assertEquals(backup::STATUS_REQUIRE_CONV, $records[$unrelatedvanillacontrollers['restoreid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $records[$unrelatedfinishedcontrollers['backupid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_OK, $records[$unrelatedfinishedcontrollers['restoreid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_ERR, $records[$unrelatedfailedcontrollers['backupid']]->status);
|
||||
$this->assertEquals(backup::STATUS_FINISHED_ERR, $records[$unrelatedfailedcontrollers['restoreid']]->status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating a course copy.
|
||||
*
|
||||
* @covers ::create_copy
|
||||
*/
|
||||
public function test_create_copy() {
|
||||
|
||||
@@ -197,6 +340,8 @@ class course_copy_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test getting the current copies.
|
||||
*
|
||||
* @covers ::get_copies
|
||||
*/
|
||||
public function test_get_copies() {
|
||||
global $USER;
|
||||
@@ -267,8 +412,69 @@ class course_copy_test extends \advanced_testcase {
|
||||
$this->assertEmpty($copies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting the current copies when they are in an invalid state.
|
||||
*
|
||||
* @covers ::get_copies
|
||||
*/
|
||||
public function test_get_copies_invalid_state() {
|
||||
global $DB, $USER;
|
||||
|
||||
// Mock up the form data.
|
||||
$formdata = new \stdClass;
|
||||
$formdata->courseid = $this->course->id;
|
||||
$formdata->fullname = 'foo';
|
||||
$formdata->shortname = 'bar';
|
||||
$formdata->category = 1;
|
||||
$formdata->visible = 1;
|
||||
$formdata->startdate = 1582376400;
|
||||
$formdata->enddate = 0;
|
||||
$formdata->idnumber = '';
|
||||
$formdata->userdata = 1;
|
||||
$formdata->role_1 = 1;
|
||||
$formdata->role_3 = 3;
|
||||
$formdata->role_5 = 5;
|
||||
|
||||
$formdata2 = clone ($formdata);
|
||||
$formdata2->shortname = 'tree';
|
||||
|
||||
// Create some copies.
|
||||
$copydata = \copy_helper::process_formdata($formdata);
|
||||
$result = \copy_helper::create_copy($copydata);
|
||||
$copydata2 = \copy_helper::process_formdata($formdata2);
|
||||
$result2 = \copy_helper::create_copy($copydata2);
|
||||
|
||||
$copies = \copy_helper::get_copies($USER->id);
|
||||
|
||||
// Verify get_copies gives back both backup controllers.
|
||||
$this->assertEqualsCanonicalizing([$result['backupid'], $result2['backupid']], array_column($copies, 'backupid'));
|
||||
|
||||
// Set one of the backup controllers to failed, this should cause it to not be present.
|
||||
\backup_controller::load_controller($result['backupid'])->set_status(backup::STATUS_FINISHED_ERR);
|
||||
$copies = \copy_helper::get_copies($USER->id);
|
||||
|
||||
// Verify there is only one backup listed, and that it is not the failed one.
|
||||
$this->assertEqualsCanonicalizing([$result2['backupid']], array_column($copies, 'backupid'));
|
||||
|
||||
// Set the controller back to awaiting.
|
||||
\backup_controller::load_controller($result['backupid'])->set_status(backup::STATUS_AWAITING);
|
||||
$copies = \copy_helper::get_copies($USER->id);
|
||||
|
||||
// Verify both backup controllers are back.
|
||||
$this->assertEqualsCanonicalizing([$result['backupid'], $result2['backupid']], array_column($copies, 'backupid'));
|
||||
|
||||
// Delete the restore controller for one of the copies, this should cause it to not be present.
|
||||
$DB->delete_records('backup_controllers', ['backupid' => $result['restoreid']]);
|
||||
$copies = \copy_helper::get_copies($USER->id);
|
||||
|
||||
// Verify there is only one backup listed, and that it is not the failed one.
|
||||
$this->assertEqualsCanonicalizing([$result2['backupid']], array_column($copies, 'backupid'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting the current copies for specific course.
|
||||
*
|
||||
* @covers ::get_copies
|
||||
*/
|
||||
public function test_get_copies_course() {
|
||||
global $USER;
|
||||
@@ -299,6 +505,8 @@ class course_copy_test extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test getting the current copies if course has been deleted.
|
||||
*
|
||||
* @covers ::get_copies
|
||||
*/
|
||||
public function test_get_copies_course_deleted() {
|
||||
global $USER;
|
||||
@@ -329,7 +537,7 @@ class course_copy_test extends \advanced_testcase {
|
||||
$this->assertEmpty($copies);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test course copy.
|
||||
*/
|
||||
public function test_course_copy() {
|
||||
@@ -406,7 +614,7 @@ class course_copy_test extends \advanced_testcase {
|
||||
$this->assertEquals(2, count($discussions));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test course copy, not including any users (or data).
|
||||
*/
|
||||
public function test_course_copy_no_users() {
|
||||
@@ -475,7 +683,7 @@ class course_copy_test extends \advanced_testcase {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test course copy, including students and their data.
|
||||
*/
|
||||
public function test_course_copy_students_data() {
|
||||
@@ -544,7 +752,7 @@ class course_copy_test extends \advanced_testcase {
|
||||
$this->assertEquals($this->courseusers[0], $users[$this->courseusers[0]]->id);
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test course copy, not including any users (or data).
|
||||
*/
|
||||
public function test_course_copy_no_data() {
|
||||
@@ -612,7 +820,7 @@ class course_copy_test extends \advanced_testcase {
|
||||
$this->assertEquals(count($this->courseusers), count($users));
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Test instantiation with incomplete formdata.
|
||||
*/
|
||||
public function test_malformed_instantiation() {
|
||||
Reference in New Issue
Block a user