diff --git a/backup/util/helper/tests/converterhelper_test.php b/backup/util/helper/tests/converterhelper_test.php index d03431588c4..b7d12d13dea 100644 --- a/backup/util/helper/tests/converterhelper_test.php +++ b/backup/util/helper/tests/converterhelper_test.php @@ -42,7 +42,7 @@ class testable_convert_helper extends convert_helper { /** * Defines the test methods */ -class convert_helper_test extends basic_testcase { +class backup_convert_helper_test extends basic_testcase { public function test_choose_conversion_path() { diff --git a/backup/util/helper/tests/decode_test.php b/backup/util/helper/tests/decode_test.php index 75c913085d2..df0ac6bbfc8 100644 --- a/backup/util/helper/tests/decode_test.php +++ b/backup/util/helper/tests/decode_test.php @@ -31,7 +31,7 @@ require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); /** * restore_decode tests (both rule and content) */ -class restore_decode_test extends basic_testcase { +class backup_restore_decode_test extends basic_testcase { /** * test restore_decode_rule class diff --git a/backup/util/loggers/tests/logger_test.php b/backup/util/loggers/tests/logger_test.php index 0907b9e424e..9dab0e29d47 100644 --- a/backup/util/loggers/tests/logger_test.php +++ b/backup/util/loggers/tests/logger_test.php @@ -34,10 +34,11 @@ require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class. require_once($CFG->dirroot . '/backup/util/loggers/database_logger.class.php'); require_once($CFG->dirroot . '/backup/util/loggers/file_logger.class.php'); + /** * logger tests (all) */ -class logger_test extends basic_testcase { +class backup_logger_test extends basic_testcase { /** * test base_logger class diff --git a/backup/util/plan/tests/fixtures/plan_fixtures.php b/backup/util/plan/tests/fixtures/plan_fixtures.php new file mode 100644 index 00000000000..daf1499ee55 --- /dev/null +++ b/backup/util/plan/tests/fixtures/plan_fixtures.php @@ -0,0 +1,130 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +global $CFG; +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); + + +/** + * Instantiable class extending base_plan in order to be able to perform tests + */ +class mock_base_plan extends base_plan { + public function build() { + } +} + +/** + * Instantiable class extending base_step in order to be able to perform tests + */ +class mock_base_step extends base_step { + public function execute() { + } +} + +/** + * Instantiable class extending backup_step in order to be able to perform tests + */ +class mock_backup_step extends backup_step { + public function execute() { + } +} + +/** + * Instantiable class extending backup_task in order to mockup get_taskbasepath() + */ +class mock_backup_task_basepath extends backup_task { + + public function build() { + // Nothing to do + } + + public function define_settings() { + // Nothing to do + } + + public function get_taskbasepath() { + global $CFG; + return $CFG->tempdir . '/test'; + } +} + +/** + * Instantiable class extending backup_structure_step in order to be able to perform tests + */ +class mock_backup_structure_step extends backup_structure_step { + + protected function define_structure() { + + // Create really simple structure (1 nested with 1 attr and 2 fields) + $test = new backup_nested_element('test', + array('id'), + array('field1', 'field2') + ); + $test->set_source_array(array(array('id' => 1, 'field1' => 'value1', 'field2' => 'value2'))); + + return $test; + } +} + +/** + * Instantiable class extending activity_backup_setting to be added to task and perform tests + */ +class mock_fullpath_activity_setting extends activity_backup_setting { + public function process_change($setting, $ctype, $oldv) { + // Nothing to do + } +} + +/** + * Instantiable class extending activity_backup_setting to be added to task and perform tests + */ +class mock_backupid_activity_setting extends activity_backup_setting { + public function process_change($setting, $ctype, $oldv) { + // Nothing to do + } +} + +/** + * Instantiable class extending base_task in order to be able to perform tests + */ +class mock_base_task extends base_task { + public function build() { + } + + public function define_settings() { + } +} + +/** + * Instantiable class extending backup_task in order to be able to perform tests + */ +class mock_backup_task extends backup_task { + public function build() { + } + + public function define_settings() { + } +} diff --git a/backup/util/plan/tests/plan_test.php b/backup/util/plan/tests/plan_test.php index 0683530fd86..b2a7ba3f7f4 100644 --- a/backup/util/plan/tests/plan_test.php +++ b/backup/util/plan/tests/plan_test.php @@ -23,9 +23,7 @@ defined('MOODLE_INTERNAL') || die(); -// Include all the needed stuff -global $CFG; -require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); +require_once(__DIR__.'/fixtures/plan_fixtures.php'); /** @@ -148,11 +146,3 @@ class backup_plan_test extends advanced_testcase { } } - -/** - * Instantiable class extending base_plan in order to be able to perform tests - */ -class mock_base_plan extends base_plan { - public function build() { - } -} diff --git a/backup/util/plan/tests/step_test.php b/backup/util/plan/tests/step_test.php index c3c3678eb12..b5c3aea6eb3 100644 --- a/backup/util/plan/tests/step_test.php +++ b/backup/util/plan/tests/step_test.php @@ -23,65 +23,7 @@ defined('MOODLE_INTERNAL') || die(); -// Include all the needed stuff -global $CFG; -require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/processable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/annotable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/executable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/loggable.class.php'); -require_once($CFG->dirroot . '/backup/backup.class.php'); -require_once($CFG->dirroot . '/backup/util/factories/backup_factory.class.php'); -require_once($CFG->dirroot . '/backup/util/helper/backup_array_iterator.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_dbops.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_controller_dbops.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_structure_dbops.class.php'); -require_once($CFG->dirroot . '/backup/util/helper/backup_helper.class.php'); -require_once($CFG->dirroot . '/backup/util/helper/backup_general_helper.class.php'); -require_once($CFG->dirroot . '/backup/util/checks/backup_check.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/base_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/error_log_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/file_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/database_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/xml/contenttransformer/xml_contenttransformer.class.php'); -require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php'); -require_once($CFG->dirroot . '/backup/util/xml/output/file_xml_output.class.php'); -require_once($CFG->dirroot . '/backup/util/xml/xml_writer.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_atom.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_attribute.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_final_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_nested_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_optigroup.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_processor.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_attribute.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_final_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_nested_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_optigroup.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_optigroup_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_structure_processor.class.php'); -require_once($CFG->dirroot . '/backup/controller/backup_controller.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/base_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/root/root_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/section/section_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/activity/activity_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/moodle2/backup_settingslib.php'); -require_once($CFG->dirroot . '/backup/util/settings/base_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/activity/activity_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_task.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_task.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_execution_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_structure_step.class.php'); -require_once($CFG->dirroot . '/backup/util/output/output_controller.class.php'); -require_once($CFG->dirroot . '/backup/util/ui/backup_ui_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/setting_dependency.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_plan_dbops.class.php'); +require_once(__DIR__.'/fixtures/plan_fixtures.php'); /* @@ -121,8 +63,8 @@ class backup_step_test extends advanced_testcase { */ function test_base_step() { - $bp = new mock_base_plan2('planname'); // We need one plan - $bt = new mock_base_task2('taskname', $bp); // We need one task + $bp = new mock_base_plan('planname'); // We need one plan + $bt = new mock_base_task('taskname', $bp); // We need one task // Instantiate $bs = new mock_base_step('stepname', $bt); $this->assertTrue($bs instanceof base_step); @@ -140,7 +82,7 @@ class backup_step_test extends advanced_testcase { // We need one plan $bp = new backup_plan($bc); // We need one task - $bt = new mock_backup_task2('taskname', $bp); + $bt = new mock_backup_task('taskname', $bp); // Instantiate step $bs = new mock_backup_step('stepname', $bt); $this->assertTrue($bs instanceof backup_step); @@ -222,104 +164,3 @@ class backup_step_test extends advanced_testcase { } } } - -/** - * Instantiable class extending base_step in order to be able to perform tests - */ -class mock_base_step extends base_step { - public function execute() { - } -} - -/** - * Instantiable class extending backup_step in order to be able to perform tests - */ -class mock_backup_step extends backup_step { - public function execute() { - } -} - -/** - * Instantiable class extending backup_task in order to mockup get_taskbasepath() - */ -class mock_backup_task_basepath extends backup_task { - - public function build() { - // Nothing to do - } - - public function define_settings() { - // Nothing to do - } - - public function get_taskbasepath() { - global $CFG; - return $CFG->tempdir . '/test'; - } -} - -/** - * Instantiable class extending backup_structure_step in order to be able to perform tests - */ -class mock_backup_structure_step extends backup_structure_step { - - protected function define_structure() { - - // Create really simple structure (1 nested with 1 attr and 2 fields) - $test = new backup_nested_element('test', - array('id'), - array('field1', 'field2') - ); - $test->set_source_array(array(array('id' => 1, 'field1' => 'value1', 'field2' => 'value2'))); - - return $test; - } -} - -/** - * Instantiable class extending activity_backup_setting to be added to task and perform tests - */ -class mock_fullpath_activity_setting extends activity_backup_setting { - public function process_change($setting, $ctype, $oldv) { - // Nothing to do - } -} - -/** - * Instantiable class extending activity_backup_setting to be added to task and perform tests - */ -class mock_backupid_activity_setting extends activity_backup_setting { - public function process_change($setting, $ctype, $oldv) { - // Nothing to do - } -} - -/** - * Instantiable class extending base_plan in order to be able to perform tests - */ -class mock_base_plan2 extends base_plan { - public function build() { - } -} - -/** - * Instantiable class extending base_task in order to be able to perform tests - */ -class mock_base_task2 extends base_task { - public function build() { - } - - public function define_settings() { - } -} - -/** - * Instantiable class extending backup_task in order to be able to perform tests - */ -class mock_backup_task2 extends backup_task { - public function build() { - } - - public function define_settings() { - } -} diff --git a/backup/util/plan/tests/task_test.php b/backup/util/plan/tests/task_test.php index c89da7057ec..03fbb9ebb13 100644 --- a/backup/util/plan/tests/task_test.php +++ b/backup/util/plan/tests/task_test.php @@ -23,64 +23,7 @@ defined('MOODLE_INTERNAL') || die(); -// Include all the needed stuff -global $CFG; -require_once($CFG->dirroot . '/backup/util/interfaces/checksumable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/executable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/loggable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/processable.class.php'); -require_once($CFG->dirroot . '/backup/util/interfaces/annotable.class.php'); -require_once($CFG->dirroot . '/backup/backup.class.php'); -require_once($CFG->dirroot . '/backup/util/factories/backup_factory.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_dbops.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_controller_dbops.class.php'); -require_once($CFG->dirroot . '/backup/util/helper/backup_helper.class.php'); -require_once($CFG->dirroot . '/backup/util/helper/backup_general_helper.class.php'); -require_once($CFG->dirroot . '/backup/util/checks/backup_check.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/base_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/error_log_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/file_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/database_logger.class.php'); -require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class.php'); -require_once($CFG->dirroot . '/backup/controller/backup_controller.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_task.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_task.class.php'); -require_once($CFG->dirroot . '/backup/util/xml/contenttransformer/xml_contenttransformer.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/base_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/root/root_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/section/section_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/activity/activity_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/moodle2/backup_settingslib.php'); -require_once($CFG->dirroot . '/backup/util/settings/base_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/activity/activity_backup_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_plan.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_task.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_task.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/base_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_execution_step.class.php'); -require_once($CFG->dirroot . '/backup/util/plan/backup_structure_step.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_atom.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_attribute.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_final_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_nested_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_optigroup.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/base_processor.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_attribute.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_final_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_nested_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_optigroup.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_optigroup_element.class.php'); -require_once($CFG->dirroot . '/backup/util/structure/backup_structure_processor.class.php'); -require_once($CFG->dirroot . '/backup/util/output/output_controller.class.php'); -require_once($CFG->dirroot . '/backup/util/ui/backup_ui_setting.class.php'); -require_once($CFG->dirroot . '/backup/util/settings/setting_dependency.class.php'); -require_once($CFG->dirroot . '/backup/util/dbops/backup_plan_dbops.class.php'); +require_once(__DIR__.'/fixtures/plan_fixtures.php'); /** @@ -120,7 +63,7 @@ class backup_task_test extends advanced_testcase { */ function test_base_task() { - $bp = new mock_base_plan3('planname'); // We need one plan + $bp = new mock_base_plan('planname'); // We need one plan // Instantiate $bt = new mock_base_task('taskname', $bp); $this->assertTrue($bt instanceof base_task); @@ -167,7 +110,7 @@ class backup_task_test extends advanced_testcase { } // Add wrong step to task - $bp = new mock_base_plan3('planname'); // We need one plan + $bp = new mock_base_plan('planname'); // We need one plan // Instantiate $bt = new mock_base_task('taskname', $bp); try { @@ -195,34 +138,3 @@ class backup_task_test extends advanced_testcase { } } } - -/** - * Instantiable class extending base_task in order to be able to perform tests - */ -class mock_base_task extends base_task { - public function build() { - } - - public function define_settings() { - } -} - -/** - * Instantiable class extending backup_task in order to be able to perform tests - */ -class mock_backup_task extends backup_task { - public function build() { - } - - public function define_settings() { - } -} - -/** - * Instantiable class extending base_plan in order to be able to perform tests - */ -class mock_base_plan3 extends base_plan { - public function build() { - } -} - diff --git a/backup/util/settings/tests/settings_test.php b/backup/util/settings/tests/settings_test.php index 05ce246b504..28590faf3f3 100644 --- a/backup/util/settings/tests/settings_test.php +++ b/backup/util/settings/tests/settings_test.php @@ -40,7 +40,7 @@ require_once($CFG->dirroot . '/backup/util/ui/backup_ui_setting.class.php'); /** * setting tests (all) */ -class setting_test extends basic_testcase { +class backp_settings_test extends basic_testcase { /** * test base_setting class diff --git a/backup/util/structure/tests/baseatom_test.php b/backup/util/structure/tests/baseatom_test.php new file mode 100644 index 00000000000..d7dbfe713f0 --- /dev/null +++ b/backup/util/structure/tests/baseatom_test.php @@ -0,0 +1,119 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + + +/** + * Unit test case the base_atom class. Note: as it's abstract we are testing + * mock_base_atom instantiable class instead + */ +class backup_base_atom_test extends basic_testcase { + + /** + * Correct base_atom_tests + */ + function test_base_atom() { + $name_with_all_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'; + $value_to_test = 'Some to test'; + + // Create instance with correct names + $instance = new mock_base_atom($name_with_all_chars); + $this->assertInstanceOf('base_atom', $instance); + $this->assertEquals($instance->get_name(), $name_with_all_chars); + $this->assertFalse($instance->is_set()); + $this->assertNull($instance->get_value()); + + // Set value + $instance->set_value($value_to_test); + $this->assertEquals($instance->get_value(), $value_to_test); + $this->assertTrue($instance->is_set()); + + // Clean value + $instance->clean_value(); + $this->assertFalse($instance->is_set()); + $this->assertNull($instance->get_value()); + + // Get to_string() results (with values) + $instance = new mock_base_atom($name_with_all_chars); + $instance->set_value($value_to_test); + $tostring = $instance->to_string(true); + $this->assertTrue(strpos($tostring, $name_with_all_chars) !== false); + $this->assertTrue(strpos($tostring, ' => ') !== false); + $this->assertTrue(strpos($tostring, $value_to_test) !== false); + + // Get to_string() results (without values) + $tostring = $instance->to_string(false); + $this->assertTrue(strpos($tostring, $name_with_all_chars) !== false); + $this->assertFalse(strpos($tostring, ' => ')); + $this->assertFalse(strpos($tostring, $value_to_test)); + } + + /** + * Throwing exception base_atom tests + */ + function test_base_atom_exceptions() { + // empty names + try { + $instance = new mock_base_atom(''); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // whitespace names + try { + $instance = new mock_base_atom('TESTING ATOM'); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // ascii names + try { + $instance = new mock_base_atom('TESTING-ATOM'); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + try { + $instance = new mock_base_atom('TESTING_ATOM_Á'); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // setting already set value + $instance = new mock_base_atom('TEST'); + $instance->set_value('test'); + try { + $instance->set_value('test'); + $this->fail("Expecting base_atom_content_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_content_exception); + } + } +} diff --git a/backup/util/structure/tests/baseattribute_test.php b/backup/util/structure/tests/baseattribute_test.php new file mode 100644 index 00000000000..203ad555a95 --- /dev/null +++ b/backup/util/structure/tests/baseattribute_test.php @@ -0,0 +1,61 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + + +/** + * Unit test case the base_attribute class. Note: No really much to test here as attribute is 100% + * atom extension without new functionality (name/value) + */ +class backup_base_attribute_test extends basic_testcase { + + /** + * Correct base_attribute tests + */ + function test_base_attribute() { + $name_with_all_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'; + $value_to_test = 'Some to test'; + + // Create instance with correct names + $instance = new mock_base_attribute($name_with_all_chars); + $this->assertInstanceOf('base_attribute', $instance); + $this->assertEquals($instance->get_name(), $name_with_all_chars); + $this->assertNull($instance->get_value()); + + // Set value + $instance->set_value($value_to_test); + $this->assertEquals($instance->get_value(), $value_to_test); + + // Get to_string() results (with values) + $instance = new mock_base_attribute($name_with_all_chars); + $instance->set_value($value_to_test); + $tostring = $instance->to_string(true); + $this->assertTrue(strpos($tostring, '@' . $name_with_all_chars) !== false); + $this->assertTrue(strpos($tostring, ' => ') !== false); + $this->assertTrue(strpos($tostring, $value_to_test) !== false); + } +} diff --git a/backup/util/structure/tests/basefinalelement_test.php b/backup/util/structure/tests/basefinalelement_test.php new file mode 100644 index 00000000000..7fc8c69e0af --- /dev/null +++ b/backup/util/structure/tests/basefinalelement_test.php @@ -0,0 +1,163 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + + +/** + * Unit test case the base_final_element class. Note: highly imbricated with base_nested_element class + */ +class backup_base_final_element_test extends basic_testcase { + + /** + * Correct base_final_element tests + */ + function test_base_final_element() { + + // Create instance with name + $instance = new mock_base_final_element('TEST'); + $this->assertInstanceOf('base_final_element', $instance); + $this->assertEquals($instance->get_name(), 'TEST'); + $this->assertNull($instance->get_value()); + $this->assertEquals($instance->get_attributes(), array()); + $this->assertNull($instance->get_parent()); + $this->assertEquals($instance->get_level(), 1); + + // Set value + $instance->set_value('value'); + $this->assertEquals($instance->get_value(), 'value'); + + // Create instance with name and one object attribute + $instance = new mock_base_final_element('TEST', new mock_base_attribute('ATTR1')); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 1); + $this->assertTrue($attrs['ATTR1'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertNull($attrs['ATTR1']->get_value()); + + // Create instance with name and various object attributes + $attr1 = new mock_base_attribute('ATTR1'); + $attr1->set_value('attr1_value'); + $attr2 = new mock_base_attribute('ATTR2'); + $instance = new mock_base_final_element('TEST', array($attr1, $attr2)); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 2); + $this->assertTrue($attrs['ATTR1'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertEquals($attrs['ATTR1']->get_value(), 'attr1_value'); + $this->assertTrue($attrs['ATTR2'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR2']->get_name(), 'ATTR2'); + $this->assertNull($attrs['ATTR2']->get_value()); + + // Create instance with name and one string attribute + $instance = new mock_base_final_element('TEST', 'ATTR1'); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 1); + $this->assertTrue($attrs['ATTR1'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertNull($attrs['ATTR1']->get_value()); + + // Create instance with name and various object attributes + $instance = new mock_base_final_element('TEST', array('ATTR1', 'ATTR2')); + $attrs = $instance->get_attributes(); + $attrs['ATTR1']->set_value('attr1_value'); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 2); + $this->assertTrue($attrs['ATTR1'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertEquals($attrs['ATTR1']->get_value(), 'attr1_value'); + $this->assertTrue($attrs['ATTR2'] instanceof base_attribute); + $this->assertEquals($attrs['ATTR2']->get_name(), 'ATTR2'); + $this->assertNull($attrs['ATTR2']->get_value()); + + // Clean values + $instance = new mock_base_final_element('TEST', array('ATTR1', 'ATTR2')); + $instance->set_value('instance_value'); + $attrs = $instance->get_attributes(); + $attrs['ATTR1']->set_value('attr1_value'); + $this->assertEquals($instance->get_value(), 'instance_value'); + $this->assertEquals($attrs['ATTR1']->get_value(), 'attr1_value'); + $instance->clean_values(); + $this->assertNull($instance->get_value()); + $this->assertNull($attrs['ATTR1']->get_value()); + + // Get to_string() results (with values) + $instance = new mock_base_final_element('TEST', array('ATTR1', 'ATTR2')); + $instance->set_value('final element value'); + $attrs = $instance->get_attributes(); + $attrs['ATTR1']->set_value('attr1 value'); + $tostring = $instance->to_string(true); + $this->assertTrue(strpos($tostring, '#TEST (level: 1)') !== false); + $this->assertTrue(strpos($tostring, ' => ') !== false); + $this->assertTrue(strpos($tostring, 'final element value') !== false); + $this->assertTrue(strpos($tostring, 'attr1 value') !== false); + } + + /** + * Exception base_final_element tests + */ + function test_base_final_element_exceptions() { + + // Create instance with invalid name + try { + $instance = new mock_base_final_element(''); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // Create instance with incorrect (object) attribute + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_final_element('TEST', $obj); + $this->fail("Expecting base_element_attribute_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_attribute_exception); + } + + // Create instance with array containing incorrect (object) attribute + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_final_element('TEST', array($obj)); + $this->fail("Expecting base_element_attribute_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_attribute_exception); + } + + // Create instance with array containing duplicate attributes + try { + $instance = new mock_base_final_element('TEST', array('ATTR1', 'ATTR2', 'ATTR1')); + $this->fail("Expecting base_element_attribute_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_attribute_exception); + } + } +} diff --git a/backup/util/structure/tests/basenestedelement_test.php b/backup/util/structure/tests/basenestedelement_test.php new file mode 100644 index 00000000000..5b2fe9adbbe --- /dev/null +++ b/backup/util/structure/tests/basenestedelement_test.php @@ -0,0 +1,395 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + + +/** + * Unit test case the base_nested_element class. Note: highly imbricated with base_final_element class + */ +class backup_base_nested_element_test extends basic_testcase { + + /** + * Correct creation tests (attributes and final elements) + */ + public function test_creation() { + // Create instance with name, attributes and values and check all them + $instance = new mock_base_nested_element('NAME', array('ATTR1', 'ATTR2'), array('VAL1', 'VAL2', 'VAL3')); + $this->assertInstanceOf('base_nested_element', $instance); + $this->assertEquals($instance->get_name(), 'NAME'); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 2); + $this->assertInstanceOf('base_attribute', $attrs['ATTR1']); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertNull($attrs['ATTR1']->get_value()); + $this->assertEquals($attrs['ATTR2']->get_name(), 'ATTR2'); + $this->assertNull($attrs['ATTR2']->get_value()); + $finals = $instance->get_final_elements(); + $this->assertTrue(is_array($finals)); + $this->assertEquals(count($finals), 3); + $this->assertInstanceOf('base_final_element', $finals['VAL1']); + $this->assertEquals($finals['VAL1']->get_name(), 'VAL1'); + $this->assertNull($finals['VAL1']->get_value()); + $this->assertEquals($finals['VAL1']->get_level(), 2); + $this->assertInstanceOf('base_nested_element', $finals['VAL1']->get_parent()); + $this->assertEquals($finals['VAL2']->get_name(), 'VAL2'); + $this->assertNull($finals['VAL2']->get_value()); + $this->assertEquals($finals['VAL2']->get_level(), 2); + $this->assertInstanceOf('base_nested_element', $finals['VAL1']->get_parent()); + $this->assertEquals($finals['VAL3']->get_name(), 'VAL3'); + $this->assertNull($finals['VAL3']->get_value()); + $this->assertEquals($finals['VAL3']->get_level(), 2); + $this->assertInstanceOf('base_nested_element', $finals['VAL1']->get_parent()); + $this->assertNull($instance->get_parent()); + $this->assertEquals($instance->get_children(), array()); + $this->assertEquals($instance->get_level(), 1); + + // Create instance with name only + $instance = new mock_base_nested_element('NAME'); + $this->assertInstanceOf('base_nested_element', $instance); + $this->assertEquals($instance->get_name(), 'NAME'); + $this->assertEquals($instance->get_attributes(), array()); + $this->assertEquals($instance->get_final_elements(), array()); + $this->assertNull($instance->get_parent()); + $this->assertEquals($instance->get_children(), array()); + $this->assertEquals($instance->get_level(), 1); + + // Add some attributes + $instance->add_attributes(array('ATTR1', 'ATTR2')); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 2); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertNull($attrs['ATTR1']->get_value()); + $this->assertEquals($attrs['ATTR2']->get_name(), 'ATTR2'); + $this->assertNull($attrs['ATTR2']->get_value()); + + // And some more atributes + $instance->add_attributes(array('ATTR3', 'ATTR4')); + $attrs = $instance->get_attributes(); + $this->assertTrue(is_array($attrs)); + $this->assertEquals(count($attrs), 4); + $this->assertEquals($attrs['ATTR1']->get_name(), 'ATTR1'); + $this->assertNull($attrs['ATTR1']->get_value()); + $this->assertEquals($attrs['ATTR2']->get_name(), 'ATTR2'); + $this->assertNull($attrs['ATTR2']->get_value()); + $this->assertEquals($attrs['ATTR3']->get_name(), 'ATTR3'); + $this->assertNull($attrs['ATTR3']->get_value()); + $this->assertEquals($attrs['ATTR4']->get_name(), 'ATTR4'); + $this->assertNull($attrs['ATTR4']->get_value()); + + // Add some final elements + $instance->add_final_elements(array('VAL1', 'VAL2', 'VAL3')); + $finals = $instance->get_final_elements(); + $this->assertTrue(is_array($finals)); + $this->assertEquals(count($finals), 3); + $this->assertEquals($finals['VAL1']->get_name(), 'VAL1'); + $this->assertNull($finals['VAL1']->get_value()); + $this->assertEquals($finals['VAL2']->get_name(), 'VAL2'); + $this->assertNull($finals['VAL2']->get_value()); + $this->assertEquals($finals['VAL3']->get_name(), 'VAL3'); + $this->assertNull($finals['VAL3']->get_value()); + + // Add some more final elements + $instance->add_final_elements('VAL4'); + $finals = $instance->get_final_elements(); + $this->assertTrue(is_array($finals)); + $this->assertEquals(count($finals), 4); + $this->assertEquals($finals['VAL1']->get_name(), 'VAL1'); + $this->assertNull($finals['VAL1']->get_value()); + $this->assertEquals($finals['VAL2']->get_name(), 'VAL2'); + $this->assertNull($finals['VAL2']->get_value()); + $this->assertEquals($finals['VAL3']->get_name(), 'VAL3'); + $this->assertNull($finals['VAL3']->get_value()); + $this->assertEquals($finals['VAL4']->get_name(), 'VAL4'); + $this->assertNull($finals['VAL4']->get_value()); + + // Get to_string() results (with values) + $instance = new mock_base_nested_element('PARENT', array('ATTR1', 'ATTR2'), array('FINAL1', 'FINAL2', 'FINAL3')); + $child1 = new mock_base_nested_element('CHILD1', null, new mock_base_final_element('FINAL4')); + $child2 = new mock_base_nested_element('CHILD2', null, new mock_base_final_element('FINAL5')); + $instance->add_child($child1); + $instance->add_child($child2); + $children = $instance->get_children(); + $final_elements = $children['CHILD1']->get_final_elements(); + $final_elements['FINAL4']->set_value('final4value'); + $final_elements['FINAL4']->add_attributes('ATTR4'); + $grandchild = new mock_base_nested_element('GRANDCHILD', new mock_base_attribute('ATTR5')); + $child2->add_child($grandchild); + $attrs = $grandchild->get_attributes(); + $attrs['ATTR5']->set_value('attr5value'); + $tostring = $instance->to_string(true); + $this->assertTrue(strpos($tostring, 'PARENT (level: 1)') !== false); + $this->assertTrue(strpos($tostring, ' => ') !== false); + $this->assertTrue(strpos($tostring, '#FINAL4 (level: 3) => final4value') !== false); + $this->assertTrue(strpos($tostring, '@ATTR5 => attr5value') !== false); + $this->assertTrue(strpos($tostring, '#FINAL5 (level: 3) => not set') !== false); + + // Clean values + $instance = new mock_base_nested_element('PARENT', array('ATTR1', 'ATTR2'), array('FINAL1', 'FINAL2', 'FINAL3')); + $child1 = new mock_base_nested_element('CHILD1', null, new mock_base_final_element('FINAL4')); + $child2 = new mock_base_nested_element('CHILD2', null, new mock_base_final_element('FINAL4')); + $instance->add_child($child1); + $instance->add_child($child2); + $children = $instance->get_children(); + $final_elements = $children['CHILD1']->get_final_elements(); + $final_elements['FINAL4']->set_value('final4value'); + $final_elements['FINAL4']->add_attributes('ATTR4'); + $grandchild = new mock_base_nested_element('GRANDCHILD', new mock_base_attribute('ATTR4')); + $child2->add_child($grandchild); + $attrs = $grandchild->get_attributes(); + $attrs['ATTR4']->set_value('attr4value'); + $this->assertEquals($final_elements['FINAL4']->get_value(), 'final4value'); + $this->assertEquals($attrs['ATTR4']->get_value(), 'attr4value'); + $instance->clean_values(); + $this->assertNull($final_elements['FINAL4']->get_value()); + $this->assertNull($attrs['ATTR4']->get_value()); + } + + /** + * Incorrect creation tests (attributes and final elements) + */ + function test_wrong_creation() { + + // Create instance with invalid name + try { + $instance = new mock_base_nested_element(''); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // Create instance with incorrect (object) final element + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_nested_element('TEST', null, $obj); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Create instance with array containing incorrect (object) final element + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_nested_element('TEST', null, array($obj)); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Create instance with array containing duplicate final elements + try { + $instance = new mock_base_nested_element('TEST', null, array('VAL1', 'VAL2', 'VAL1')); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to get value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->get_value(); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to set value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->set_value('some_value'); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to clean one value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->clean_value('some_value'); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + } + + /** + * Correct tree tests (children stuff) + */ + function test_tree() { + + // Create parent and child instances, tree-ing them + $parent = new mock_base_nested_element('PARENT'); + $child = new mock_base_nested_element('CHILD'); + $parent->add_child($child); + $this->assertEquals($parent->get_children(), array('CHILD' => $child)); + $this->assertEquals($child->get_parent(), $parent); + $check_children = $parent->get_children(); + $check_child = $check_children['CHILD']; + $check_parent = $check_child->get_parent(); + $this->assertEquals($check_child->get_name(), 'CHILD'); + $this->assertEquals($check_parent->get_name(), 'PARENT'); + $this->assertEquals($check_child->get_level(), 2); + $this->assertEquals($check_parent->get_level(), 1); + $this->assertEquals($check_parent->get_children(), array('CHILD' => $child)); + $this->assertEquals($check_child->get_parent(), $parent); + + // Add parent to grandparent + $grandparent = new mock_base_nested_element('GRANDPARENT'); + $grandparent->add_child($parent); + $this->assertEquals($grandparent->get_children(), array('PARENT' => $parent)); + $this->assertEquals($parent->get_parent(), $grandparent); + $this->assertEquals($parent->get_children(), array('CHILD' => $child)); + $this->assertEquals($child->get_parent(), $parent); + $this->assertEquals($child->get_level(), 3); + $this->assertEquals($parent->get_level(), 2); + $this->assertEquals($grandparent->get_level(), 1); + + // Add grandchild to child + $grandchild = new mock_base_nested_element('GRANDCHILD'); + $child->add_child($grandchild); + $this->assertEquals($child->get_children(), array('GRANDCHILD' => $grandchild)); + $this->assertEquals($grandchild->get_parent(), $child); + $this->assertEquals($grandchild->get_level(), 4); + $this->assertEquals($child->get_level(), 3); + $this->assertEquals($parent->get_level(), 2); + $this->assertEquals($grandparent->get_level(), 1); + + // Add another child to parent + $child2 = new mock_base_nested_element('CHILD2'); + $parent->add_child($child2); + $this->assertEquals($parent->get_children(), array('CHILD' => $child, 'CHILD2' => $child2)); + $this->assertEquals($child2->get_parent(), $parent); + $this->assertEquals($grandchild->get_level(), 4); + $this->assertEquals($child->get_level(), 3); + $this->assertEquals($child2->get_level(), 3); + $this->assertEquals($parent->get_level(), 2); + $this->assertEquals($grandparent->get_level(), 1); + } + + /** + * Incorrect tree tests (children stuff) + */ + function test_wrong_tree() { + + // Add null object child + $parent = new mock_base_nested_element('PARENT'); + $child = null; + try { + $parent->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add non base_element object child + $parent = new mock_base_nested_element('PARENT'); + $child = new stdClass(); + try { + $parent->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add existing element (being parent) + $parent = new mock_base_nested_element('PARENT'); + $child = new mock_base_nested_element('PARENT'); + try { + $parent->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add existing element (being grandparent) + $grandparent = new mock_base_nested_element('GRANDPARENT'); + $parent = new mock_base_nested_element('PARENT'); + $child = new mock_base_nested_element('GRANDPARENT'); + $grandparent->add_child($parent); + try { + $parent->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add existing element (being grandchild) + $grandparent = new mock_base_nested_element('GRANDPARENT'); + $parent = new mock_base_nested_element('PARENT'); + $child = new mock_base_nested_element('GRANDPARENT'); + $parent->add_child($child); + try { + $grandparent->add_child($parent); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add existing element (being cousin) + $grandparent = new mock_base_nested_element('GRANDPARENT'); + $parent1 = new mock_base_nested_element('PARENT1'); + $parent2 = new mock_base_nested_element('PARENT2'); + $child1 = new mock_base_nested_element('CHILD1'); + $child2 = new mock_base_nested_element('CHILD1'); + $grandparent->add_child($parent1); + $parent1->add_child($child1); + $parent2->add_child($child2); + try { + $grandparent->add_child($parent2); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Add element to two parents + $parent1 = new mock_base_nested_element('PARENT1'); + $parent2 = new mock_base_nested_element('PARENT2'); + $child = new mock_base_nested_element('CHILD'); + $parent1->add_child($child); + try { + $parent2->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_parent_exception); + } + + // Add child element already used by own final elements + $nested = new mock_base_nested_element('PARENT1', null, array('FINAL1', 'FINAL2')); + $child = new mock_base_nested_element('FINAL2', null, array('FINAL3', 'FINAL4')); + try { + $nested->add_child($child); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementchildnameconflict'); + $this->assertEquals($e->a, 'FINAL2'); + } + } +} diff --git a/backup/util/structure/tests/baseoptiogroup_test.php b/backup/util/structure/tests/baseoptiogroup_test.php new file mode 100644 index 00000000000..bf229008de3 --- /dev/null +++ b/backup/util/structure/tests/baseoptiogroup_test.php @@ -0,0 +1,137 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + + +/** + * Unit test case the base_optigroup class. Note: highly imbricated with nested/final base elements + */ +class backup_base_optigroup_test extends basic_testcase { + + /** + * Correct creation tests (s) + */ + function test_creation() { + $instance = new mock_base_optigroup('optigroup', null, true); + $this->assertInstanceOf('base_optigroup', $instance); + $this->assertEquals($instance->get_name(), 'optigroup'); + $this->assertNull($instance->get_parent()); + $this->assertEquals($instance->get_children(), array()); + $this->assertEquals($instance->get_level(), 1); + $this->assertTrue($instance->is_multiple()); + + // Get to_string() results (with values) + $child1 = new mock_base_nested_element('child1', null, new mock_base_final_element('four')); + $child2 = new mock_base_nested_element('child2', null, new mock_base_final_element('five')); + $instance->add_child($child1); + $instance->add_child($child2); + $children = $instance->get_children(); + $final_elements = $children['child1']->get_final_elements(); + $final_elements['four']->set_value('final4value'); + $final_elements['four']->add_attributes('attr4'); + $grandchild = new mock_base_nested_element('grandchild', new mock_base_attribute('attr5')); + $child2->add_child($grandchild); + $attrs = $grandchild->get_attributes(); + $attrs['attr5']->set_value('attr5value'); + $tostring = $instance->to_string(true); + $this->assertTrue(strpos($tostring, '!optigroup (level: 1)') !== false); + $this->assertTrue(strpos($tostring, '?child2 (level: 2) =>') !== false); + $this->assertTrue(strpos($tostring, ' => ') !== false); + $this->assertTrue(strpos($tostring, '#four (level: 3) => final4value') !== false); + $this->assertTrue(strpos($tostring, '@attr5 => attr5value') !== false); + $this->assertTrue(strpos($tostring, '#five (level: 3) => not set') !== false); + } + + /** + * Incorrect creation tests (attributes and final elements) + */ + function itest_wrong_creation() { + + // Create instance with invalid name + try { + $instance = new mock_base_nested_element(''); + $this->fail("Expecting base_atom_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_atom_struct_exception); + } + + // Create instance with incorrect (object) final element + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_nested_element('TEST', null, $obj); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Create instance with array containing incorrect (object) final element + try { + $obj = new stdClass; + $obj->name = 'test_attr'; + $instance = new mock_base_nested_element('TEST', null, array($obj)); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Create instance with array containing duplicate final elements + try { + $instance = new mock_base_nested_element('TEST', null, array('VAL1', 'VAL2', 'VAL1')); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to get value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->get_value(); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to set value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->set_value('some_value'); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + + // Try to clean one value of base_nested_element + $instance = new mock_base_nested_element('TEST'); + try { + $instance->clean_value('some_value'); + $this->fail("Expecting base_element_struct_exception exception, none occurred"); + } catch (Exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + } + } +} diff --git a/backup/util/structure/tests/fixtures/structure_fixtures.php b/backup/util/structure/tests/fixtures/structure_fixtures.php new file mode 100644 index 00000000000..4379d873806 --- /dev/null +++ b/backup/util/structure/tests/fixtures/structure_fixtures.php @@ -0,0 +1,137 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +global $CFG; +require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); + +/** + * helper extended base_attribute class that implements some methods for instantiating and testing + */ +class mock_base_attribute extends base_attribute { + // Nothing to do. Just allow instances to be created +} + +/** + * helper extended final_element class that implements some methods for instantiating and testing + */ +class mock_base_final_element extends base_final_element { +/// Implementable API + protected function get_new_attribute($name) { + return new mock_base_attribute($name); + } +} + +/** + * helper extended nested_element class that implements some methods for instantiating and testing + */ +class mock_base_nested_element extends base_nested_element { +/// Implementable API + protected function get_new_attribute($name) { + return new mock_base_attribute($name); + } + + protected function get_new_final_element($name) { + return new mock_base_final_element($name); + } +} + +/** + * helper extended optigroup class that implements some methods for instantiating and testing + */ +class mock_base_optigroup extends base_optigroup { +/// Implementable API + protected function get_new_attribute($name) { + return new mock_base_attribute($name); + } + + protected function get_new_final_element($name) { + return new mock_base_final_element($name); + } + + public function is_multiple() { + return parent::is_multiple(); + } +} + +/** + * helper class that extends backup_final_element in order to skip its value + */ +class mock_skip_final_element extends backup_final_element { + + public function set_value($value) { + $this->clean_value(); + } +} + +/** + * helper class that extends backup_final_element in order to modify its value + */ +class mock_modify_final_element extends backup_final_element { + public function set_value($value) { + parent::set_value('original was ' . $value . ', now changed'); + } +} + +/** + * helper class that extends backup_final_element to delegate any calculation to another class + */ +class mock_final_element_interceptor extends backup_final_element { + public function set_value($value) { + // Get grandparent name + $gpname = $this->get_grandparent()->get_name(); + // Get parent name + $pname = $this->get_parent()->get_name(); + // Get my name + $myname = $this->get_name(); + // Define class and function name + $classname = 'mock_' . $gpname . '_' . $pname . '_interceptor'; + $methodname= 'intercept_' . $pname . '_' . $myname; + // Invoke the interception method + $result = call_user_func(array($classname, $methodname), $value); + // Finally set it + parent::set_value($result); + } +} + +/** + * test interceptor class (its methods are called from interceptor) + */ +abstract class mock_forum_forum_interceptor { + static function intercept_forum_completionposts($element) { + return 'intercepted!'; + } +} + +/** + * Instantiable class extending base_atom in order to be able to perform tests + */ +class mock_base_atom extends base_atom { + // Nothing new in this class, just an instantiable base_atom class + // with the is_set() method public for testing purposes + public function is_set() { + return parent::is_set(); + } +} diff --git a/backup/util/structure/tests/structure_test.php b/backup/util/structure/tests/structure_test.php new file mode 100644 index 00000000000..adfc658a764 --- /dev/null +++ b/backup/util/structure/tests/structure_test.php @@ -0,0 +1,646 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +require_once(__DIR__.'/fixtures/structure_fixtures.php'); + +global $CFG; +require_once($CFG->dirroot . '/backup/util/xml/output/memory_xml_output.class.php'); + + +/** + * Unit test case the all the backup structure classes. Note: Uses database + */ +class backup_structure_test extends advanced_testcase { + + protected $forumid; // To store the inserted forum->id + protected $contextid; // Official contextid for these tests + + + protected function setUp() { + parent::setUp(); + + $this->resetAfterTest(true); + + $this->contextid = 666; // Let's assume this is the context for the forum + $this->fill_records(); // Add common stuff needed by various test methods + } + + private function fill_records() { + global $DB; + + // Create one forum + $forum_data = (object)array('course' => 1, 'name' => 'Test forum', 'intro' => 'Intro forum'); + $this->forumid = $DB->insert_record('forum', $forum_data); + // With two related file + $f1_forum_data = (object)array( + 'contenthash' => 'testf1', 'contextid' => $this->contextid, + 'component'=>'mod_forum', 'filearea' => 'intro', 'filename' => 'tf1', 'itemid' => 0, + 'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0, + 'pathnamehash' => 'testf1' + ); + $DB->insert_record('files', $f1_forum_data); + $f2_forum_data = (object)array( + 'contenthash' => 'tesft2', 'contextid' => $this->contextid, + 'component'=>'mod_forum', 'filearea' => 'intro', 'filename' => 'tf2', 'itemid' => 0, + 'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0, + 'pathnamehash' => 'testf2' + ); + $DB->insert_record('files', $f2_forum_data); + + // Create two discussions + $discussion1 = (object)array('course' => 1, 'forum' => $this->forumid, 'name' => 'd1', 'userid' => 100, 'groupid' => 200); + $d1id = $DB->insert_record('forum_discussions', $discussion1); + $discussion2 = (object)array('course' => 1, 'forum' => $this->forumid, 'name' => 'd2', 'userid' => 101, 'groupid' => 201); + $d2id = $DB->insert_record('forum_discussions', $discussion2); + + // Create four posts + $post1 = (object)array('discussion' => $d1id, 'userid' => 100, 'subject' => 'p1', 'message' => 'm1'); + $p1id = $DB->insert_record('forum_posts', $post1); + $post2 = (object)array('discussion' => $d1id, 'parent' => $p1id, 'userid' => 102, 'subject' => 'p2', 'message' => 'm2'); + $p2id = $DB->insert_record('forum_posts', $post2); + $post3 = (object)array('discussion' => $d1id, 'parent' => $p2id, 'userid' => 103, 'subject' => 'p3', 'message' => 'm3'); + $p3id = $DB->insert_record('forum_posts', $post3); + $post4 = (object)array('discussion' => $d2id, 'userid' => 101, 'subject' => 'p4', 'message' => 'm4'); + $p4id = $DB->insert_record('forum_posts', $post4); + // With two related file + $f1_post1 = (object)array( + 'contenthash' => 'testp1', 'contextid' => $this->contextid, 'component'=>'mod_forum', + 'filearea' => 'post', 'filename' => 'tp1', 'itemid' => $p1id, + 'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0, + 'pathnamehash' => 'testp1' + ); + $DB->insert_record('files', $f1_post1); + $f1_post2 = (object)array( + 'contenthash' => 'testp2', 'contextid' => $this->contextid, 'component'=>'mod_forum', + 'filearea' => 'attachment', 'filename' => 'tp2', 'itemid' => $p2id, + 'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0, + 'pathnamehash' => 'testp2' + ); + $DB->insert_record('files', $f1_post2); + + // Create two ratings + $rating1 = (object)array( + 'contextid' => $this->contextid, 'userid' => 104, 'itemid' => $p1id, 'rating' => 2, + 'scaleid' => -1, 'timecreated' => time(), 'timemodified' => time()); + $r1id = $DB->insert_record('rating', $rating1); + $rating2 = (object)array( + 'contextid' => $this->contextid, 'userid' => 105, 'itemid' => $p1id, 'rating' => 3, + 'scaleid' => -1, 'timecreated' => time(), 'timemodified' => time()); + $r2id = $DB->insert_record('rating', $rating2); + + // Create 1 reads + $read1 = (object)array('userid' => 102, 'forumid' => $this->forumid, 'discussionid' => $d2id, 'postid' => $p4id); + $DB->insert_record('forum_read', $read1); + } + + /** + * Backup structures tests (construction, definition and execution) + */ + function test_backup_structure_construct() { + global $DB; + + $backupid = 'Testing Backup ID'; // Official backupid for these tests + + // Create all the elements that will conform the tree + $forum = new backup_nested_element('forum', + array('id'), + array( + 'type', 'name', 'intro', 'introformat', + 'assessed', 'assesstimestart', 'assesstimefinish', 'scale', + 'maxbytes', 'maxattachments', 'forcesubscribe', 'trackingtype', + 'rsstype', 'rssarticles', 'timemodified', 'warnafter', + 'blockafter', + new backup_final_element('blockperiod'), + new mock_skip_final_element('completiondiscussions'), + new mock_modify_final_element('completionreplies'), + new mock_final_element_interceptor('completionposts')) + ); + $discussions = new backup_nested_element('discussions'); + $discussion = new backup_nested_element('discussion', + array('id'), + array( + 'forum', 'name', 'firstpost', 'userid', + 'groupid', 'assessed', 'timemodified', 'usermodified', + 'timestart', 'timeend') + ); + $posts = new backup_nested_element('posts'); + $post = new backup_nested_element('post', + array('id'), + array( + 'discussion', 'parent', 'userid', 'created', + 'modified', 'mailed', 'subject', 'message', + 'messageformat', 'messagetrust', 'attachment', 'totalscore', + 'mailnow') + ); + $ratings = new backup_nested_element('ratings'); + $rating = new backup_nested_element('rating', + array('id'), + array('userid', 'itemid', 'time', 'post_rating') + ); + $reads = new backup_nested_element('readposts'); + $read = new backup_nested_element('read', + array('id'), + array( + 'userid', 'discussionid', 'postid', + 'firstread', 'lastread') + ); + $inventeds = new backup_nested_element('invented_elements', + array('reason', 'version') + ); + $invented = new backup_nested_element('invented', + null, + array('one', 'two', 'three') + ); + $one = $invented->get_final_element('one'); + $one->add_attributes(array('attr1', 'attr2')); + + // Build the tree + $forum->add_child($discussions); + $discussions->add_child($discussion); + + $discussion->add_child($posts); + $posts->add_child($post); + + $post->add_child($ratings); + $ratings->add_child($rating); + + $forum->add_child($reads); + $reads->add_child($read); + + $forum->add_child($inventeds); + $inventeds->add_child($invented); + + // Let's add 1 optigroup with 4 elements + $alternative1 = new backup_optigroup_element('alternative1', + array('name', 'value'), '../../id', 1); + $alternative2 = new backup_optigroup_element('alternative2', + array('name', 'value'), backup::VAR_PARENTID, 2); + $alternative3 = new backup_optigroup_element('alternative3', + array('name', 'value'), '/forum/discussions/discussion/posts/post/id', 3); + $alternative4 = new backup_optigroup_element('alternative4', + array('forumtype', 'forumname')); // Alternative without conditions + // Create the optigroup, adding one element + $optigroup = new backup_optigroup('alternatives', $alternative1, false); + // Add second opti element + $optigroup->add_child($alternative2); + + // Add optigroup to post element + $post->add_optigroup($optigroup); + // Add third opti element, on purpose after the add_optigroup() line above to check param evaluation works ok + $optigroup->add_child($alternative3); + // Add 4th opti element (the one without conditions, so will be present always) + $optigroup->add_child($alternative4); + + /// Create some new nested elements, both named 'dupetest1', and add them to alternative1 and alternative2 + /// (not problem as far as the optigroup in not unique) + $dupetest1 = new backup_nested_element('dupetest1', null, array('field1', 'field2')); + $dupetest2 = new backup_nested_element('dupetest2', null, array('field1', 'field2')); + $dupetest3 = new backup_nested_element('dupetest3', null, array('field1', 'field2')); + $dupetest4 = new backup_nested_element('dupetest1', null, array('field1', 'field2')); + $dupetest1->add_child($dupetest3); + $dupetest2->add_child($dupetest4); + $alternative1->add_child($dupetest1); + $alternative2->add_child($dupetest2); + + // Define sources + $forum->set_source_table('forum', array('id' => backup::VAR_ACTIVITYID)); + $discussion->set_source_sql('SELECT * + FROM {forum_discussions} + WHERE forum = ?', + array('/forum/id') + ); + $post->set_source_table('forum_posts', array('discussion' => '/forum/discussions/discussion/id')); + $rating->set_source_sql('SELECT * + FROM {rating} + WHERE itemid = ?', + array(backup::VAR_PARENTID) + ); + + $read->set_source_table('forum_read', array('id' => '../../id')); + + $inventeds->set_source_array(array((object)array('reason' => 'I love Moodle', 'version' => '1.0'), + (object)array('reason' => 'I love Moodle', 'version' => '2.0'))); // 2 object array + $invented->set_source_array(array((object)array('one' => 1, 'two' => 2, 'three' => 3), + (object)array('one' => 11, 'two' => 22, 'three' => 33))); // 2 object array + + // Set optigroup_element sources + $alternative1->set_source_array(array((object)array('name' => 'alternative1', 'value' => 1))); // 1 object array + // Skip alternative2 source definition on purpose (will be tested) + // $alternative2->set_source_array(array((object)array('name' => 'alternative2', 'value' => 2))); // 1 object array + $alternative3->set_source_array(array((object)array('name' => 'alternative3', 'value' => 3))); // 1 object array + // Alternative 4 source is the forum type and name, so we'll get that in ALL posts (no conditions) that + // have not another alternative (post4 in our testing data in the only not matching any other alternative) + $alternative4->set_source_sql('SELECT type AS forumtype, name AS forumname + FROM {forum} + WHERE id = ?', + array('/forum/id') + ); + // Set children of optigroup_element source + $dupetest1->set_source_array(array((object)array('field1' => '1', 'field2' => 1))); // 1 object array + $dupetest2->set_source_array(array((object)array('field1' => '2', 'field2' => 2))); // 1 object array + $dupetest3->set_source_array(array((object)array('field1' => '3', 'field2' => 3))); // 1 object array + $dupetest4->set_source_array(array((object)array('field1' => '4', 'field2' => 4))); // 1 object array + + // Define some aliases + $rating->set_source_alias('rating', 'post_rating'); // Map the 'rating' value from DB to 'post_rating' final element + + // Mark to detect files of type 'forum_intro' in forum (and not item id) + $forum->annotate_files('mod_forum', 'intro', null); + + // Mark to detect file of type 'forum_post' and 'forum_attachment' in post (with itemid being post->id) + $post->annotate_files('mod_forum', 'post', 'id'); + $post->annotate_files('mod_forum', 'attachment', 'id'); + + // Mark various elements to be annotated + $discussion->annotate_ids('user1', 'userid'); + $post->annotate_ids('forum_post', 'id'); + $rating->annotate_ids('user2', 'userid'); + $rating->annotate_ids('forum_post', 'itemid'); + + // Create the backup_ids_temp table + backup_controller_dbops::create_backup_ids_temp_table($backupid); + + // Instantiate in memory xml output + $xo = new memory_xml_output(); + + // Instantiate xml_writer and start it + $xw = new xml_writer($xo); + $xw->start(); + + // Instantiate the backup processor + $processor = new backup_structure_processor($xw); + + // Set some variables + $processor->set_var(backup::VAR_ACTIVITYID, $this->forumid); + $processor->set_var(backup::VAR_BACKUPID, $backupid); + $processor->set_var(backup::VAR_CONTEXTID,$this->contextid); + + // Process the backup structure with the backup processor + $forum->process($processor); + + // Stop the xml_writer + $xw->stop(); + + // Check various counters + $this->assertEquals($forum->get_counter(), $DB->count_records('forum')); + $this->assertEquals($discussion->get_counter(), $DB->count_records('forum_discussions')); + $this->assertEquals($rating->get_counter(), $DB->count_records('rating')); + $this->assertEquals($read->get_counter(), $DB->count_records('forum_read')); + $this->assertEquals($inventeds->get_counter(), 2); // Array + + // Perform some validations with the generated XML + $dom = new DomDocument(); + $dom->loadXML($xo->get_allcontents()); + $xpath = new DOMXPath($dom); + // Some more counters + $query = '/forum/discussions/discussion/posts/post'; + $posts = $xpath->query($query); + $this->assertEquals($posts->length, $DB->count_records('forum_posts')); + $query = '/forum/invented_elements/invented'; + $inventeds = $xpath->query($query); + $this->assertEquals($inventeds->length, 2*2); + + // Check ratings information against DB + $ratings = $dom->getElementsByTagName('rating'); + $this->assertEquals($ratings->length, $DB->count_records('rating')); + foreach ($ratings as $rating) { + $ratarr = array(); + $ratarr['id'] = $rating->getAttribute('id'); + foreach ($rating->childNodes as $node) { + if ($node->nodeType != XML_TEXT_NODE) { + $ratarr[$node->nodeName] = $node->nodeValue; + } + } + $this->assertEquals($ratarr['userid'], $DB->get_field('rating', 'userid', array('id' => $ratarr['id']))); + $this->assertEquals($ratarr['itemid'], $DB->get_field('rating', 'itemid', array('id' => $ratarr['id']))); + $this->assertEquals($ratarr['post_rating'], $DB->get_field('rating', 'rating', array('id' => $ratarr['id']))); + } + + // Check forum has "blockeperiod" with value 0 (was declared by object instead of name) + $query = '/forum[blockperiod="0"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check forum is missing "completiondiscussions" (as we are using mock_skip_final_element) + $query = '/forum/completiondiscussions'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + + // Check forum has "completionreplies" with value "original was 0, now changed" (because of mock_modify_final_element) + $query = '/forum[completionreplies="original was 0, now changed"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check forum has "completionposts" with value "intercepted!" (because of mock_final_element_interceptor) + $query = '/forum[completionposts="intercepted!"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check there isn't any alternative2 tag, as far as it hasn't source defined + $query = '//alternative2'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + + // Check there are 4 "field1" elements + $query = '/forum/discussions/discussion/posts/post//field1'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 4); + + // Check first post has one name element with value "alternative1" + $query = '/forum/discussions/discussion/posts/post[@id="1"][name="alternative1"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check there are two "dupetest1" elements + $query = '/forum/discussions/discussion/posts/post//dupetest1'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 2); + + // Check second post has one name element with value "dupetest2" + $query = '/forum/discussions/discussion/posts/post[@id="2"]/dupetest2'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check element "dupetest2" of second post has one field1 element with value "2" + $query = '/forum/discussions/discussion/posts/post[@id="2"]/dupetest2[field1="2"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check forth post has no name element + $query = '/forum/discussions/discussion/posts/post[@id="4"]/name'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + + // Check 1st, 2nd and 3rd posts have no forumtype element + $query = '/forum/discussions/discussion/posts/post[@id="1"]/forumtype'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + $query = '/forum/discussions/discussion/posts/post[@id="2"]/forumtype'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + $query = '/forum/discussions/discussion/posts/post[@id="3"]/forumtype'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 0); + + // Check 4th post has one forumtype element with value "general" + // (because it doesn't matches alternatives 1, 2, 3, then alternative 4, + // the one without conditions is being applied) + $query = '/forum/discussions/discussion/posts/post[@id="4"][forumtype="general"]'; + $result = $xpath->query($query); + $this->assertEquals($result->length, 1); + + // Check annotations information against DB + // Count records in original tables + $c_postsid = $DB->count_records_sql('SELECT COUNT(DISTINCT id) FROM {forum_posts}'); + $c_dissuserid = $DB->count_records_sql('SELECT COUNT(DISTINCT userid) FROM {forum_discussions}'); + $c_ratuserid = $DB->count_records_sql('SELECT COUNT(DISTINCT userid) FROM {rating}'); + // Count records in backup_ids_table + $f_forumpost = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'forum_post')); + $f_user1 = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'user1')); + $f_user2 = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'user2')); + $c_notbackupid = $DB->count_records_select('backup_ids_temp', 'backupid != ?', array($backupid)); + // Peform tests by comparing counts + $this->assertEquals($c_notbackupid, 0); // there isn't any record with incorrect backupid + $this->assertEquals($c_postsid, $f_forumpost); // All posts have been registered + $this->assertEquals($c_dissuserid, $f_user1); // All users coming from discussions have been registered + $this->assertEquals($c_ratuserid, $f_user2); // All users coming from ratings have been registered + + // Check file annotations against DB + $fannotations = $DB->get_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'file')); + $ffiles = $DB->get_records('files', array('contextid' => $this->contextid)); + $this->assertEquals(count($fannotations), count($ffiles)); // Same number of recs in both (all files have been annotated) + foreach ($fannotations as $annotation) { // Check ids annotated + $this->assertTrue($DB->record_exists('files', array('id' => $annotation->itemid))); + } + + // Drop the backup_ids_temp table + backup_controller_dbops::drop_backup_ids_temp_table('testingid'); + } + + /** + * Backup structures wrong tests (trying to do things the wrong way) + */ + function test_backup_structure_wrong() { + + // Instantiate the backup processor + $processor = new backup_structure_processor(new xml_writer(new memory_xml_output())); + $this->assertTrue($processor instanceof base_processor); + + // Set one var twice + $processor->set_var('onenewvariable', 999); + try { + $processor->set_var('onenewvariable', 999); + $this->assertTrue(false, 'backup_processor_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof backup_processor_exception); + $this->assertEquals($e->errorcode, 'processorvariablealreadyset'); + $this->assertEquals($e->a, 'onenewvariable'); + } + + // Get non-existing var + try { + $var = $processor->get_var('nonexistingvar'); + $this->assertTrue(false, 'backup_processor_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof backup_processor_exception); + $this->assertEquals($e->errorcode, 'processorvariablenotfound'); + $this->assertEquals($e->a, 'nonexistingvar'); + } + + // Create nested element and try ro get its parent id (doesn't exisit => exception) + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + try { + $ne->set_source_table('forum', array('id' => backup::VAR_PARENTID)); + $ne->process($processor); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'cannotfindparentidforelement'); + } + + // Try to process one nested/final/attribute elements without processor + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + try { + $ne->process(new stdclass()); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'incorrect_processor'); + } + $fe = new backup_final_element('test'); + try { + $fe->process(new stdclass()); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'incorrect_processor'); + } + $at = new backup_attribute('test'); + try { + $at->process(new stdclass()); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'incorrect_processor'); + } + + // Try to put an incorrect alias + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + try { + $ne->set_source_alias('last', 'nonexisting'); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'incorrectaliasfinalnamenotfound'); + $this->assertEquals($e->a, 'nonexisting'); + } + + // Try various incorrect paths specifying source + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + try { + $ne->set_source_table('forum', array('/test/subtest')); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementincorrectfinalorattribute'); + $this->assertEquals($e->a, 'subtest'); + } + try { + $ne->set_source_table('forum', array('/wrongtest')); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementincorrectgrandparent'); + $this->assertEquals($e->a, 'wrongtest'); + } + try { + $ne->set_source_table('forum', array('../nonexisting')); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementincorrectparent'); + $this->assertEquals($e->a, '..'); + } + + // Try various incorrect file annotations + + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + $ne->annotate_files('test', 'filearea', null); + try { + $ne->annotate_files('test', 'filearea', null); // Try to add annotations twice + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'annotate_files_duplicate_annotation'); + $this->assertEquals($e->a, 'test/filearea/'); + } + + $ne = new backup_nested_element('test', 'one', 'two', 'three'); + try { + $ne->annotate_files('test', 'filearea', 'four'); // Incorrect element + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementincorrectfinalorattribute'); + $this->assertEquals($e->a, 'four'); + } + + // Try to add incorrect element to backup_optigroup + $bog = new backup_optigroup('test'); + try { + $bog->add_child(new backup_nested_element('test2')); + $this->assertTrue(false, 'base_optigroup_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_optigroup_exception); + $this->assertEquals($e->errorcode, 'optigroup_element_incorrect'); + $this->assertEquals($e->a, 'backup_nested_element'); + } + + $bog = new backup_optigroup('test'); + try { + $bog->add_child('test2'); + $this->assertTrue(false, 'base_optigroup_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_optigroup_exception); + $this->assertEquals($e->errorcode, 'optigroup_element_incorrect'); + $this->assertEquals($e->a, 'non object'); + } + + try { + $bog = new backup_optigroup('test', new stdclass()); + $this->assertTrue(false, 'base_optigroup_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_optigroup_exception); + $this->assertEquals($e->errorcode, 'optigroup_elements_incorrect'); + } + + // Try a wrong processor with backup_optigroup + $bog = new backup_optigroup('test'); + try { + $bog->process(new stdclass()); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'incorrect_processor'); + } + + // Try duplicating used elements with backup_optigroup + // Adding top->down + $bog = new backup_optigroup('test', null, true); + $boge1 = new backup_optigroup_element('boge1'); + $boge2 = new backup_optigroup_element('boge2'); + $ne1 = new backup_nested_element('ne1'); + $ne2 = new backup_nested_element('ne1'); + $bog->add_child($boge1); + $bog->add_child($boge2); + $boge1->add_child($ne1); + try { + $boge2->add_child($ne2); + $this->assertTrue(false, 'base_optigroup_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_optigroup_exception); + $this->assertEquals($e->errorcode, 'multiple_optigroup_duplicate_element'); + $this->assertEquals($e->a, 'ne1'); + } + // Adding down->top + $bog = new backup_optigroup('test', null, true); + $boge1 = new backup_optigroup_element('boge1'); + $boge2 = new backup_optigroup_element('boge2'); + $ne1 = new backup_nested_element('ne1'); + $ne2 = new backup_nested_element('ne1'); + $boge1->add_child($ne1); + $boge2->add_child($ne2); + $bog->add_child($boge1); + try { + $bog->add_child($boge2); + $this->assertTrue(false, 'base_element_struct_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof base_element_struct_exception); + $this->assertEquals($e->errorcode, 'baseelementexisting'); + $this->assertEquals($e->a, 'ne1'); + } + } +} diff --git a/backup/util/ui/tests/ui_test.php b/backup/util/ui/tests/ui_test.php new file mode 100644 index 00000000000..27e6d37cbb3 --- /dev/null +++ b/backup/util/ui/tests/ui_test.php @@ -0,0 +1,40 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +global $CFG; +//require_once($CFG->dirroot . '/backup/util/checks/backup_check.class.php'); + +/** + * ui tests (all) + */ +class backup_ui_test extends basic_testcase { + + /** + * test backup_ui class + */ + function test_backup_ui() { + } +} diff --git a/backup/util/xml/tests/writer_test.php b/backup/util/xml/tests/writer_test.php new file mode 100644 index 00000000000..76a5d2ea9f6 --- /dev/null +++ b/backup/util/xml/tests/writer_test.php @@ -0,0 +1,323 @@ +. + +/** + * @package core_backup + * @category phpunit + * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +// Include all the needed stuff +global $CFG; +require_once($CFG->dirroot . '/backup/util/xml/xml_writer.class.php'); +require_once($CFG->dirroot . '/backup/util/xml/output/xml_output.class.php'); +require_once($CFG->dirroot . '/backup/util/xml/output/memory_xml_output.class.php'); +require_once($CFG->dirroot . '/backup/util/xml/contenttransformer/xml_contenttransformer.class.php'); + +/** + * xml_writer tests + */ +class xml_writer_test extends basic_testcase { + + /** + * test xml_writer public methods + */ + function test_xml_writer_public_api() { + global $CFG; + // Instantiate xml_output + $xo = new memory_xml_output(); + $this->assertTrue($xo instanceof xml_output); + + // Instantiate xml_writer with null xml_output + try { + $xw = new mock_xml_writer(null); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'invalid_xml_output'); + } + + // Instantiate xml_writer with wrong xml_output object + try { + $xw = new mock_xml_writer(new stdclass()); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'invalid_xml_output'); + } + + // Instantiate xml_writer with wrong xml_contenttransformer object + try { + $xw = new mock_xml_writer($xo, new stdclass()); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'invalid_xml_contenttransformer'); + } + + // Instantiate xml_writer and start it twice + $xw = new mock_xml_writer($xo); + $xw->start(); + try { + $xw->start(); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_already_started'); + } + + // Instantiate xml_writer and stop it twice + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->stop(); + try { + $xw->stop(); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_already_stopped'); + } + + // Stop writer without starting it + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + try { + $xw->stop(); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_not_started'); + } + + // Start writer after stopping it + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->stop(); + try { + $xw->start(); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_already_stopped'); + } + + // Try to set prologue/schema after start + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + try { + $xw->set_nonamespace_schema('http://moodle.org'); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_already_started'); + } + try { + $xw->set_prologue('sweet prologue'); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_already_started'); + } + + // Instantiate properly with memory_xml_output, start and stop. + // Must get default UTF-8 prologue + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->stop(); + $this->assertEquals($xo->get_allcontents(), $xw->get_default_prologue()); + + // Instantiate, set prologue and schema, put 1 full tag and get results + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->set_prologue('CLEARLY WRONG PROLOGUE'); + $xw->set_nonamespace_schema('http://moodle.org/littleschema'); + $xw->start(); + $xw->full_tag('TEST', 'Hello World!', array('id' => 1)); + $xw->stop(); + $result = $xo->get_allcontents(); + // Perform various checks + $this->assertEquals(strpos($result, 'WRONG'), 8); + $this->assertEquals(strpos($result, 'assertEquals(strpos($result, 'xmlns:xsi='), 39); + $this->assertEquals(strpos($result, 'http://moodle.org/littleschema'), 128); + $this->assertEquals(strpos($result, 'Hello World'), 160); + $this->assertFalse(strpos($result, $xw->get_default_prologue())); + + // Try to close one tag in wrong order + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->begin_tag('first'); + $xw->begin_tag('second'); + try { + $xw->end_tag('first'); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_end_tag_no_match'); + } + + // Try to close one tag before starting any tag + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + try { + $xw->end_tag('first'); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_end_tag_no_match'); + } + + // Full tag without contents (null and empty string) + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); + $xw->full_tag('tagname2', '', array('attrname' => 'attrvalue')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, ''); + + + // Test case-folding is working + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo, null, true); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attrvalue')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, 'textcontent'); + + // Test UTF-8 chars in tag and attribute names, attr values and contents + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('áéíóú', 'ÁÉÍÓÚ', array('àèìòù' => 'ÀÈÌÒÙ')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, '<áéíóú àèìòù="ÀÈÌÒÙ">ÁÉÍÓÚ'); + + // Try non-safe content in attributes + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('tagname', 'textcontent', array('attrname' => 'attr' . chr(27) . '\'"value')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, 'textcontent'); + + // Try non-safe content in text + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('tagname', "text\r\ncontent\rwith" . chr(27), array('attrname' => 'attrvalue')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, 'text' . "\ncontent\n" . 'with'); + + // Try to stop the writer without clossing all the open tags + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->begin_tag('first'); + try { + $xw->stop(); + $this->assertTrue(false, 'xml_writer_exception expected'); + } catch (exception $e) { + $this->assertTrue($e instanceof xml_writer_exception); + $this->assertEquals($e->errorcode, 'xml_writer_open_tags_remaining'); + } + + // Test simple transformer + $xo = new memory_xml_output(); + $xt = new mock_xml_contenttransformer(); + $xw = new mock_xml_writer($xo, $xt); + $xw->set_prologue(''); // empty prologue for easier matching + $xw->start(); + $xw->full_tag('tagname', null, array('attrname' => 'attrvalue')); + $xw->full_tag('tagname2', 'somecontent', array('attrname' => 'attrvalue')); + $xw->stop(); + $result = $xo->get_allcontents(); + $this->assertEquals($result, 'testsomecontent'); + + // Build a complex XML file and test results against stored file in fixtures + $xo = new memory_xml_output(); + $xw = new mock_xml_writer($xo); + $xw->start(); + $xw->begin_tag('toptag', array('name' => 'toptag', 'level' => 1, 'path' => '/toptag')); + $xw->full_tag('secondtag', 'secondvalue', array('name' => 'secondtag', 'level' => 2, 'path' => '/toptag/secondtag', 'value' => 'secondvalue')); + $xw->begin_tag('thirdtag', array('name' => 'thirdtag', 'level' => 2, 'path' => '/toptag/thirdtag')); + $xw->full_tag('onevalue', 'onevalue', array('name' => 'onevalue', 'level' => 3, 'path' => '/toptag/thirdtag/onevalue')); + $xw->full_tag('onevalue', 'anothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'anothervalue')); + $xw->full_tag('onevalue', 'yetanothervalue', array('name' => 'onevalue', 'level' => 3, 'value' => 'yetanothervalue')); + $xw->full_tag('twovalue', 'twovalue', array('name' => 'twovalue', 'level' => 3, 'path' => '/toptag/thirdtag/twovalue')); + $xw->begin_tag('forthtag', array('name' => 'forthtag', 'level' => 3, 'path' => '/toptag/thirdtag/forthtag')); + $xw->full_tag('innervalue', 'innervalue'); + $xw->begin_tag('innertag'); + $xw->begin_tag('superinnertag', array('name' => 'superinnertag', 'level' => 5)); + $xw->full_tag('superinnervalue', 'superinnervalue', array('name' => 'superinnervalue', 'level' => 6)); + $xw->end_tag('superinnertag'); + $xw->end_tag('innertag'); + $xw->end_tag('forthtag'); + $xw->begin_tag('fifthtag', array('level' => 3)); + $xw->begin_tag('sixthtag', array('level' => 4)); + $xw->full_tag('seventh', 'seventh', array('level' => 5)); + $xw->end_tag('sixthtag'); + $xw->end_tag('fifthtag'); + $xw->full_tag('finalvalue', 'finalvalue', array('name' => 'finalvalue', 'level' => 3, 'path' => '/toptag/thirdtag/finalvalue')); + $xw->full_tag('finalvalue'); + $xw->end_tag('thirdtag'); + $xw->end_tag('toptag'); + $xw->stop(); + $result = $xo->get_allcontents(); + $fcontents = file_get_contents($CFG->dirroot . '/backup/util/xml/simpletest/fixtures/test1.xml'); + + // Normalise carriage return characters. + $fcontents = str_replace("\r\n", "\n", $fcontents); + $this->assertEquals(trim($result), trim($fcontents)); + } +} + +/* + * helper extended xml_writer class that makes some methods public for testing + */ +class mock_xml_writer extends xml_writer { + public function get_default_prologue() { + return parent::get_default_prologue(); + } +} + +/* + * helper extended xml_contenttransformer prepending "test" to all the notnull contents + */ +class mock_xml_contenttransformer extends xml_contenttransformer { + public function process($content) { + return is_null($content) ? null : 'test' . $content; + } +} diff --git a/lib/phpunit/readme.md b/lib/phpunit/readme.md index 962b8ce2733..d69e69f85cc 100644 --- a/lib/phpunit/readme.md +++ b/lib/phpunit/readme.md @@ -46,7 +46,6 @@ TODO ---- * add plugin callbacks to data generator * convert remaining tests -* improve performance * hide old SimpleTests and FUnctional DB tests in UI * shell script that prepares everything for the first execution * optionally support for execution of tests and cli/util.php from web UI (to be implemented via shell execution)