Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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   * @package    core_backup
  19   * @category   phpunit
  20   * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
  21   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  
  24  defined('MOODLE_INTERNAL') || die();
  25  
  26  // Include all the needed stuff
  27  global $CFG;
  28  require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php');
  29  
  30  /**
  31   * Backup dbops tests (all).
  32   */
  33  class backup_dbops_testcase extends advanced_testcase {
  34  
  35      protected $moduleid;  // course_modules id used for testing
  36      protected $sectionid; // course_sections id used for testing
  37      protected $courseid;  // course id used for testing
  38      protected $userid;      // user record used for testing
  39  
  40      protected function setUp(): void {
  41          global $DB, $CFG;
  42          parent::setUp();
  43  
  44          $this->resetAfterTest(true);
  45  
  46          $course = $this->getDataGenerator()->create_course();
  47          $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
  48          $coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
  49  
  50          $this->moduleid  = $page->cmid;
  51          $this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
  52          $this->courseid  = $coursemodule->course;
  53          $this->userid = 2; // admin
  54  
  55          $CFG->backup_error_log_logger_level = backup::LOG_NONE;
  56          $CFG->backup_output_indented_logger_level = backup::LOG_NONE;
  57          $CFG->backup_file_logger_level = backup::LOG_NONE;
  58          $CFG->backup_database_logger_level = backup::LOG_NONE;
  59          unset($CFG->backup_file_logger_extra);
  60          $CFG->backup_file_logger_level_extra = backup::LOG_NONE;
  61      }
  62  
  63      /*
  64       * test backup_ops class
  65       */
  66      function test_backup_dbops() {
  67          // Nothing to do here, abstract class + exception, will be tested by the rest
  68      }
  69  
  70      /*
  71       * test backup_controller_dbops class
  72       */
  73      function test_backup_controller_dbops() {
  74          global $DB;
  75  
  76          $dbman = $DB->get_manager(); // Going to use some database_manager services for testing
  77  
  78          // Instantiate non interactive backup_controller
  79          $bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
  80              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
  81          $this->assertTrue($bc instanceof backup_controller);
  82          // Calculate checksum
  83          $checksum = $bc->calculate_checksum();
  84          $this->assertEquals(strlen($checksum), 32); // is one md5
  85  
  86          // save controller
  87          $recid = backup_controller_dbops::save_controller($bc, $checksum);
  88          $this->assertNotEmpty($recid);
  89          // save it again (should cause update to happen)
  90          $recid2 = backup_controller_dbops::save_controller($bc, $checksum);
  91          $this->assertNotEmpty($recid2);
  92          $this->assertEquals($recid, $recid2); // Same record in both save operations
  93  
  94          // Try incorrect checksum
  95          $bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
  96              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
  97          $checksum = $bc->calculate_checksum();
  98          try {
  99              $recid = backup_controller_dbops::save_controller($bc, 'lalala');
 100              $this->assertTrue(false, 'backup_dbops_exception expected');
 101          } catch (exception $e) {
 102              $this->assertTrue($e instanceof backup_dbops_exception);
 103              $this->assertEquals($e->errorcode, 'backup_controller_dbops_saving_checksum_mismatch');
 104          }
 105  
 106          // Try to save non backup_controller object
 107          $bc = new stdclass();
 108          try {
 109              $recid = backup_controller_dbops::save_controller($bc, 'lalala');
 110              $this->assertTrue(false, 'backup_controller_exception expected');
 111          } catch (exception $e) {
 112              $this->assertTrue($e instanceof backup_controller_exception);
 113              $this->assertEquals($e->errorcode, 'backup_controller_expected');
 114          }
 115  
 116          // save and load controller (by backupid). Then compare
 117          $bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
 118              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
 119          $checksum = $bc->calculate_checksum(); // Calculate checksum
 120          $backupid = $bc->get_backupid();
 121          $this->assertEquals(strlen($backupid), 32); // is one md5
 122          $recid = backup_controller_dbops::save_controller($bc, $checksum); // save controller
 123          $newbc = backup_controller_dbops::load_controller($backupid); // load controller
 124          $this->assertTrue($newbc instanceof backup_controller);
 125          $newchecksum = $newbc->calculate_checksum();
 126          $this->assertEquals($newchecksum, $checksum);
 127  
 128          // try to load non-existing controller
 129          try {
 130              $bc = backup_controller_dbops::load_controller('1234567890');
 131              $this->assertTrue(false, 'backup_dbops_exception expected');
 132          } catch (exception $e) {
 133              $this->assertTrue($e instanceof backup_dbops_exception);
 134              $this->assertEquals($e->errorcode, 'backup_controller_dbops_nonexisting');
 135          }
 136  
 137          // backup_ids_temp table tests
 138          // If, for any reason table exists, drop it
 139          if ($dbman->table_exists('backup_ids_temp')) {
 140              $dbman->drop_table(new xmldb_table('backup_ids_temp'));
 141          }
 142          // Check backup_ids_temp table doesn't exist
 143          $this->assertFalse($dbman->table_exists('backup_ids_temp'));
 144          // Create and check it exists
 145          backup_controller_dbops::create_backup_ids_temp_table('testingid');
 146          $this->assertTrue($dbman->table_exists('backup_ids_temp'));
 147          // Drop and check it doesn't exists anymore
 148          backup_controller_dbops::drop_backup_ids_temp_table('testingid');
 149          $this->assertFalse($dbman->table_exists('backup_ids_temp'));
 150  
 151          // Test encoding/decoding of backup_ids_temp,backup_files_temp encode/decode functions.
 152          // We need to handle both objects and data elements.
 153          $object = new stdClass();
 154          $object->item1 = 10;
 155          $object->item2 = 'a String';
 156          $testarray = array($object, 10, null, 'string', array('a' => 'b', 1 => 1));
 157          foreach ($testarray as $item) {
 158              $encoded = backup_controller_dbops::encode_backup_temp_info($item);
 159              $decoded = backup_controller_dbops::decode_backup_temp_info($encoded);
 160              $this->assertEquals($item, $decoded);
 161          }
 162      }
 163  
 164      /**
 165       * Check backup_includes_files
 166       */
 167      function test_backup_controller_dbops_includes_files() {
 168          global $DB;
 169  
 170          $dbman = $DB->get_manager(); // Going to use some database_manager services for testing
 171  
 172          // A MODE_GENERAL controller - this should include files
 173          $bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
 174              backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
 175          $this->assertEquals(backup_controller_dbops::backup_includes_files($bc->get_backupid()), 1);
 176  
 177          // A MODE_IMPORT controller - should not include files
 178          $bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
 179              backup::INTERACTIVE_NO, backup::MODE_IMPORT, $this->userid);
 180          $this->assertEquals(backup_controller_dbops::backup_includes_files($bc->get_backupid()), 0);
 181  
 182          // A MODE_SAMESITE controller - should not include files
 183          $bc = new mock_backup_controller4dbops(backup::TYPE_1COURSE, $this->courseid, backup::FORMAT_MOODLE,
 184              backup::INTERACTIVE_NO, backup::MODE_SAMESITE, $this->userid);
 185          $this->assertEquals(backup_controller_dbops::backup_includes_files($bc->get_backupid()), 0);
 186      }
 187  }
 188  
 189  class mock_backup_controller4dbops extends backup_controller {
 190  
 191      /**
 192       * Change standard behavior so the checksum is also stored and not onlt calculated
 193       */
 194      public function calculate_checksum() {
 195          $this->checksum = parent::calculate_checksum();
 196          return $this->checksum;
 197      }
 198  }