Merge branch 'w14_MDL-32149_m23_phpunit2' of git://github.com/skodak/moodle

This commit is contained in:
Eloy Lafuente (stronk7)
2012-04-04 01:32:15 +02:00
151 changed files with 26485 additions and 896 deletions
+1 -1
View File
@@ -29,7 +29,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define('PHPUNIT_CLI_UTIL', true);
define('PHPUNIT_UTIL', true);
require(__DIR__ . '/../../../../lib/phpunit/bootstrap.php');
require_once($CFG->libdir.'/phpunit/lib.php');
@@ -0,0 +1,96 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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');
/*
* controller tests (all)
*/
class backup_controller_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user used if for testing
protected function setUp() {
global $DB, $CFG;
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
// Disable all loggers
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_output_indented_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/*
* test base_setting class
*/
public function test_backup_controller() {
// Instantiate non interactive backup_controller
$bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$this->assertTrue($bc instanceof backup_controller);
$this->assertEquals($bc->get_status(), backup::STATUS_AWAITING);
// Instantiate interactive backup_controller
$bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_YES, backup::MODE_GENERAL, $this->userid);
$this->assertTrue($bc instanceof backup_controller);
$this->assertEquals($bc->get_status(), backup::STATUS_SETTING_UI);
$this->assertEquals(strlen($bc->get_backupid()), 32); // is one md5
// Save and load one backup controller to check everything is in place
$bc = new mock_backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$recid = $bc->save_controller();
$newbc = mock_backup_controller::load_controller($bc->get_backupid());
$this->assertTrue($newbc instanceof backup_controller); // This means checksum and load worked ok
}
}
/*
* helper extended @backup_controller class that makes some methods public for testing
*/
class mock_backup_controller extends backup_controller {
public function save_controller() {
parent::save_controller();
}
}
+475
View File
@@ -0,0 +1,475 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the moodle1 converter
*
* @package core_backup
* @subpackage backup-convert
* @category phpunit
* @copyright 2011 Mark Nielsen <mark@moodlerooms.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/backup/converter/moodle1/lib.php');
class moodle1_converter_testcase extends advanced_testcase {
/** @var string the name of the directory containing the unpacked Moodle 1.9 backup */
protected $tempdir;
protected function setUp() {
global $CFG;
$this->tempdir = convert_helper::generate_id('simpletest');
check_dir_exists("$CFG->tempdir/backup/$this->tempdir/course_files/sub1");
check_dir_exists("$CFG->tempdir/backup/$this->tempdir/moddata/unittest/4/7");
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/moodle.xml",
"$CFG->tempdir/backup/$this->tempdir/moodle.xml"
);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/icon.gif",
"$CFG->tempdir/backup/$this->tempdir/course_files/file1.gif"
);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/icon.gif",
"$CFG->tempdir/backup/$this->tempdir/course_files/sub1/file2.gif"
);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/icon.gif",
"$CFG->tempdir/backup/$this->tempdir/moddata/unittest/4/file1.gif"
);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/icon.gif",
"$CFG->tempdir/backup/$this->tempdir/moddata/unittest/4/icon.gif"
);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/icon.gif",
"$CFG->tempdir/backup/$this->tempdir/moddata/unittest/4/7/icon.gif"
);
}
protected function tearDown() {
global $CFG;
if (empty($CFG->keeptempdirectoriesonbackup)) {
fulldelete("$CFG->tempdir/backup/$this->tempdir");
}
}
public function test_detect_format() {
$detected = moodle1_converter::detect_format($this->tempdir);
$this->assertEquals(backup::FORMAT_MOODLE1, $detected);
}
public function test_convert_factory() {
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$this->assertInstanceOf('moodle1_converter', $converter);
}
public function test_stash_storage_not_created() {
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$this->setExpectedException('moodle1_convert_storage_exception');
$converter->set_stash('tempinfo', 12);
}
public function test_stash_requiring_empty_stash() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->create_stash_storage();
$converter->set_stash('tempinfo', 12);
$this->setExpectedException('moodle1_convert_empty_storage_exception');
try {
$converter->get_stash('anothertempinfo');
} catch (moodle1_convert_empty_storage_exception $e) {
// we must drop the storage here so we are able to re-create it in the next test
$converter->drop_stash_storage();
throw new moodle1_convert_empty_storage_exception('rethrowing');
}
}
public function test_stash_storage() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->create_stash_storage();
// no implicit stashes
$stashes = $converter->get_stash_names();
$this->assertEquals(gettype($stashes), 'array');
$this->assertTrue(empty($stashes));
// test stashes without itemid
$converter->set_stash('tempinfo1', 12);
$converter->set_stash('tempinfo2', array('a' => 2, 'b' => 3));
$stashes = $converter->get_stash_names();
$this->assertEquals('array', gettype($stashes));
$this->assertEquals(2, count($stashes));
$this->assertTrue(in_array('tempinfo1', $stashes));
$this->assertTrue(in_array('tempinfo2', $stashes));
$this->assertEquals(12, $converter->get_stash('tempinfo1'));
$this->assertEquals(array('a' => 2, 'b' => 3), $converter->get_stash('tempinfo2'));
// overwriting a stashed value is allowed
$converter->set_stash('tempinfo1', '13');
$this->assertNotSame(13, $converter->get_stash('tempinfo1'));
$this->assertSame('13', $converter->get_stash('tempinfo1'));
// repeated reading is allowed
$this->assertEquals('13', $converter->get_stash('tempinfo1'));
// storing empty array
$converter->set_stash('empty_array_stash', array());
$restored = $converter->get_stash('empty_array_stash');
//$this->assertEquals(gettype($restored), 'array'); // todo return null now, this needs MDL-27713 to be fixed, then uncomment
$this->assertTrue(empty($restored));
// test stashes with itemid
$converter->set_stash('tempinfo', 'Hello', 1);
$converter->set_stash('tempinfo', 'World', 2);
$this->assertSame('Hello', $converter->get_stash('tempinfo', 1));
$this->assertSame('World', $converter->get_stash('tempinfo', 2));
// test get_stash_itemids()
$ids = $converter->get_stash_itemids('course_fileref');
$this->assertEquals(gettype($ids), 'array');
$this->assertTrue(empty($ids));
$converter->set_stash('course_fileref', null, 34);
$converter->set_stash('course_fileref', null, 52);
$ids = $converter->get_stash_itemids('course_fileref');
$this->assertEquals(2, count($ids));
$this->assertTrue(in_array(34, $ids));
$this->assertTrue(in_array(52, $ids));
$converter->drop_stash_storage();
}
public function test_get_stash_or_default() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->create_stash_storage();
$this->assertTrue(is_null($converter->get_stash_or_default('stashname')));
$this->assertTrue(is_null($converter->get_stash_or_default('stashname', 7)));
$this->assertTrue('default' === $converter->get_stash_or_default('stashname', 0, 'default'));
$this->assertTrue(array('foo', 'bar') === $converter->get_stash_or_default('stashname', 42, array('foo', 'bar')));
//$converter->set_stash('stashname', 0);
//$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
//$converter->set_stash('stashname', '');
//$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
//$converter->set_stash('stashname', array());
//$this->assertFalse(is_null($converter->get_stash_or_default('stashname'))); // todo returns true now, this needs MDL-27713 to be fixed
$converter->set_stash('stashname', 42);
$this->assertTrue(42 === $converter->get_stash_or_default('stashname'));
$this->assertTrue(is_null($converter->get_stash_or_default('stashname', 1)));
$this->assertTrue(42 === $converter->get_stash_or_default('stashname', 0, 61));
$converter->set_stash('stashname', array(42 => (object)array('id' => 42)), 18);
$stashed = $converter->get_stash_or_default('stashname', 18, 1984);
$this->assertEquals(gettype($stashed), 'array');
$this->assertTrue(is_object($stashed[42]));
$this->assertTrue($stashed[42]->id === 42);
$converter->drop_stash_storage();
}
public function test_get_contextid() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
// stash storage must be created in advance
$converter->create_stash_storage();
// ids are generated on the first call
$id1 = $converter->get_contextid(CONTEXT_BLOCK, 10);
$id2 = $converter->get_contextid(CONTEXT_BLOCK, 11);
$id3 = $converter->get_contextid(CONTEXT_MODULE, 10);
$this->assertNotEquals($id1, $id2);
$this->assertNotEquals($id1, $id3);
$this->assertNotEquals($id2, $id3);
// and then re-used if called with the same params
$this->assertEquals($id1, $converter->get_contextid(CONTEXT_BLOCK, 10));
$this->assertEquals($id2, $converter->get_contextid(CONTEXT_BLOCK, 11));
$this->assertEquals($id3, $converter->get_contextid(CONTEXT_MODULE, 10));
// for system and course level, the instance is irrelevant
// as we need only one system and one course
$id1 = $converter->get_contextid(CONTEXT_COURSE);
$id2 = $converter->get_contextid(CONTEXT_COURSE, 10);
$id3 = $converter->get_contextid(CONTEXT_COURSE, 14);
$this->assertEquals($id1, $id2);
$this->assertEquals($id1, $id3);
$id1 = $converter->get_contextid(CONTEXT_SYSTEM);
$id2 = $converter->get_contextid(CONTEXT_SYSTEM, 11);
$id3 = $converter->get_contextid(CONTEXT_SYSTEM, 15);
$this->assertEquals($id1, $id2);
$this->assertEquals($id1, $id3);
$converter->drop_stash_storage();
}
public function test_get_nextid() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$id1 = $converter->get_nextid();
$id2 = $converter->get_nextid();
$id3 = $converter->get_nextid();
$this->assertTrue(0 < $id1);
$this->assertTrue($id1 < $id2);
$this->assertTrue($id2 < $id3);
}
public function test_migrate_file() {
$this->resetAfterTest(true);
// set-up the file manager
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->create_stash_storage();
$contextid = $converter->get_contextid(CONTEXT_MODULE, 32);
$fileman = $converter->get_file_manager($contextid, 'mod_unittest', 'testarea');
// this fileman has not converted anything yet
$fileids = $fileman->get_fileids();
$this->assertEquals(gettype($fileids), 'array');
$this->assertEquals(0, count($fileids));
// try to migrate a non-existing directory
$returned = $fileman->migrate_directory('not/existing/directory');
$this->assertEquals(gettype($returned), 'array');
$this->assertEquals(0, count($returned));
$fileids = $fileman->get_fileids();
$this->assertEquals(gettype($fileids), 'array');
$this->assertEquals(0, count($fileids));
// migrate a single file
$fileman->itemid = 4;
$fileman->migrate_file('moddata/unittest/4/icon.gif');
$this->assertTrue(is_file($converter->get_workdir_path().'/files/4e/4ea114b0558f53e3af8dd9afc0e0810a95c2a724'));
// get the file id
$fileids = $fileman->get_fileids();
$this->assertEquals(gettype($fileids), 'array');
$this->assertEquals(1, count($fileids));
// migrate another single file into another file area
$fileman->filearea = 'anotherarea';
$fileman->itemid = 7;
$fileman->migrate_file('moddata/unittest/4/7/icon.gif', '/', 'renamed.gif');
// get the file records
$filerecordids = $converter->get_stash_itemids('files');
foreach ($filerecordids as $filerecordid) {
$filerecord = $converter->get_stash('files', $filerecordid);
$this->assertEquals('4ea114b0558f53e3af8dd9afc0e0810a95c2a724', $filerecord['contenthash']);
$this->assertEquals($contextid, $filerecord['contextid']);
$this->assertEquals('mod_unittest', $filerecord['component']);
if ($filerecord['filearea'] === 'testarea') {
$this->assertEquals(4, $filerecord['itemid']);
$this->assertEquals('icon.gif', $filerecord['filename']);
}
}
// explicitly clear the list of migrated files
$this->assertTrue(count($fileman->get_fileids()) > 0);
$fileman->reset_fileids();
$this->assertTrue(count($fileman->get_fileids()) == 0);
$converter->drop_stash_storage();
}
public function test_convert_path() {
$path = new convert_path('foo_bar', '/ROOT/THINGS/FOO/BAR');
$this->assertEquals('foo_bar', $path->get_name());
$this->assertEquals('/ROOT/THINGS/FOO/BAR', $path->get_path());
$this->assertEquals('process_foo_bar', $path->get_processing_method());
$this->assertEquals('on_foo_bar_start', $path->get_start_method());
$this->assertEquals('on_foo_bar_end', $path->get_end_method());
}
public function test_convert_path_implicit_recipes() {
$path = new convert_path('foo_bar', '/ROOT/THINGS/FOO/BAR');
$data = array(
'ID' => 76,
'ELOY' => 'stronk7',
'MARTIN' => 'moodler',
'EMPTY' => null,
);
// apply default recipes (converting keys to lowercase)
$data = $path->apply_recipes($data);
$this->assertEquals(4, count($data));
$this->assertEquals(76, $data['id']);
$this->assertEquals('stronk7', $data['eloy']);
$this->assertEquals('moodler', $data['martin']);
$this->assertSame(null, $data['empty']);
}
public function test_convert_path_explicit_recipes() {
$path = new convert_path(
'foo_bar', '/ROOT/THINGS/FOO/BAR',
array(
'newfields' => array(
'david' => 'mudrd8mz',
'petr' => 'skodak',
),
'renamefields' => array(
'empty' => 'nothing',
),
'dropfields' => array(
'id'
),
)
);
$data = array(
'ID' => 76,
'ELOY' => 'stronk7',
'MARTIN' => 'moodler',
'EMPTY' => null,
);
$data = $path->apply_recipes($data);
$this->assertEquals(5, count($data));
$this->assertFalse(array_key_exists('id', $data));
$this->assertEquals('stronk7', $data['eloy']);
$this->assertEquals('moodler', $data['martin']);
$this->assertEquals('mudrd8mz', $data['david']);
$this->assertEquals('skodak', $data['petr']);
$this->assertSame(null, $data['nothing']);
}
public function test_grouped_data_on_nongrouped_convert_path() {
// prepare some grouped data
$data = array(
'ID' => 77,
'NAME' => 'Pale lagers',
'BEERS' => array(
array(
'BEER' => array(
'ID' => 67,
'NAME' => 'Pilsner Urquell',
)
),
array(
'BEER' => array(
'ID' => 34,
'NAME' => 'Heineken',
)
),
)
);
// declare a non-grouped path
$path = new convert_path('beer_style', '/ROOT/BEER_STYLES/BEER_STYLE');
// an attempt to apply recipes throws exception because we do not expect grouped data
$this->setExpectedException('convert_path_exception');
$data = $path->apply_recipes($data);
}
public function test_grouped_convert_path_with_recipes() {
// prepare some grouped data
$data = array(
'ID' => 77,
'NAME' => 'Pale lagers',
'BEERS' => array(
array(
'BEER' => array(
'ID' => 67,
'NAME' => 'Pilsner Urquell',
)
),
array(
'BEER' => array(
'ID' => 34,
'NAME' => 'Heineken',
)
),
)
);
// implict recipes work for grouped data if the path is declared as grouped
$path = new convert_path('beer_style', '/ROOT/BEER_STYLES/BEER_STYLE', array(), true);
$data = $path->apply_recipes($data);
$this->assertEquals('Heineken', $data['beers'][1]['beer']['name']);
// an attempt to provide explicit recipes on grouped elements throws exception
$this->setExpectedException('convert_path_exception');
$path = new convert_path(
'beer_style', '/ROOT/BEER_STYLES/BEER_STYLE',
array(
'renamefields' => array(
'name' => 'beername', // note this is confusing recipe because the 'name' is used for both
// beer-style name ('Pale lagers') and beer name ('Pilsner Urquell')
)
), true);
}
public function test_referenced_course_files() {
$text = 'This is a text containing links to file.php
as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif" /><a href="$@FILEPHP@$$@SLASH@$pics$@SLASH@$news.gif$@FORCEDOWNLOAD@$">download image</a><br />
<br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />';
$files = moodle1_converter::find_referenced_files($text);
$this->assertEquals(gettype($files), 'array');
$this->assertEquals(2, count($files));
$this->assertTrue(in_array('/pics/news.gif', $files));
$this->assertTrue(in_array('/MANUAL.DOC', $files));
$text = moodle1_converter::rewrite_filephp_usage($text, array('/pics/news.gif', '/another/file/notused.txt'), $files);
$this->assertEquals($text, 'This is a text containing links to file.php
as it is parsed from the backup file. <br /><br /><img border="0" width="110" vspace="0" hspace="0" height="92" title="News" alt="News" src="@@PLUGINFILE@@/pics/news.gif" /><a href="@@PLUGINFILE@@/pics/news.gif?forcedownload=1">download image</a><br />
<br /><a href=\'$@FILEPHP@$$@SLASH@$MANUAL.DOC$@FORCEDOWNLOAD@$\'>download manual</a><br />');
}
public function test_question_bank_conversion() {
global $CFG;
$this->resetAfterTest(true);
copy(
"$CFG->dirroot/backup/converter/moodle1/simpletest/files/questions.xml",
"$CFG->tempdir/backup/$this->tempdir/moodle.xml"
);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->convert();
}
public function test_convert_run_convert() {
$this->resetAfterTest(true);
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$converter->convert();
}
public function test_inforef_manager() {
$converter = convert_factory::get_converter('moodle1', $this->tempdir);
$inforef = $converter->get_inforef_manager('unittest');
$inforef->add_ref('file', 45);
$inforef->add_refs('file', array(46, 47));
// todo test the write_refs() via some dummy xml_writer
$this->setExpectedException('coding_exception');
$inforef->add_ref('unknown_referenced_item_name', 76);
}
}
+136
View File
@@ -0,0 +1,136 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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');
/*
* check tests (all)
*/
class backup_check_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user record id
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_output_indented_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
unset($CFG->backup_file_logger_extra);
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/*
* test backup_check class
*/
public function test_backup_check() {
// Check against existing course module/section course or fail
$this->assertTrue(backup_check::check_id(backup::TYPE_1ACTIVITY, $this->moduleid));
$this->assertTrue(backup_check::check_id(backup::TYPE_1SECTION, $this->sectionid));
$this->assertTrue(backup_check::check_id(backup::TYPE_1COURSE, $this->courseid));
$this->assertTrue(backup_check::check_user($this->userid));
// Check against non-existing course module/section/course (0)
try {
backup_check::check_id(backup::TYPE_1ACTIVITY, 0);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_module_not_exists');
}
try {
backup_check::check_id(backup::TYPE_1SECTION, 0);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_section_not_exists');
}
try {
backup_check::check_id(backup::TYPE_1COURSE, 0);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_course_not_exists');
}
// Try wrong type
try {
backup_check::check_id(12345678,0);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_incorrect_type');
}
// Test non-existing user
$userid = 0;
try {
backup_check::check_user($userid);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_user_not_exists');
}
// Security check tests
// Try to pass wrong controller
try {
backup_check::check_security(new stdclass(), true);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_security_requires_backup_controller');
}
// Pass correct controller, check must return true in any case with $apply enabled
// and $bc must continue being mock_backup_controller
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$this->assertTrue(backup_check::check_security($bc, true));
$this->assertTrue($bc instanceof backup_controller);
}
}
+163
View File
@@ -0,0 +1,163 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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');
/*
* dbops tests (all)
*/
class backup_dbops_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user record used for testing
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_output_indented_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
unset($CFG->backup_file_logger_extra);
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/*
* test backup_ops class
*/
function test_backup_dbops() {
// Nothing to do here, abstract class + exception, will be tested by the rest
}
/*
* test backup_controller_dbops class
*/
function test_backup_controller_dbops() {
global $DB;
$dbman = $DB->get_manager(); // Going to use some database_manager services for testing
// Instantiate non interactive backup_controller
$bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$this->assertTrue($bc instanceof backup_controller);
// Calculate checksum
$checksum = $bc->calculate_checksum();
$this->assertEquals(strlen($checksum), 32); // is one md5
// save controller
$recid = backup_controller_dbops::save_controller($bc, $checksum);
$this->assertNotEmpty($recid);
// save it again (should cause update to happen)
$recid2 = backup_controller_dbops::save_controller($bc, $checksum);
$this->assertNotEmpty($recid2);
$this->assertEquals($recid, $recid2); // Same record in both save operations
// Try incorrect checksum
$bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$checksum = $bc->calculate_checksum();
try {
$recid = backup_controller_dbops::save_controller($bc, 'lalala');
$this->assertTrue(false, 'backup_dbops_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_dbops_exception);
$this->assertEquals($e->errorcode, 'backup_controller_dbops_saving_checksum_mismatch');
}
// Try to save non backup_controller object
$bc = new stdclass();
try {
$recid = backup_controller_dbops::save_controller($bc, 'lalala');
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_controller_expected');
}
// save and load controller (by backupid). Then compare
$bc = new mock_backup_controller4dbops(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$checksum = $bc->calculate_checksum(); // Calculate checksum
$backupid = $bc->get_backupid();
$this->assertEquals(strlen($backupid), 32); // is one md5
$recid = backup_controller_dbops::save_controller($bc, $checksum); // save controller
$newbc = backup_controller_dbops::load_controller($backupid); // load controller
$this->assertTrue($newbc instanceof backup_controller);
$newchecksum = $newbc->calculate_checksum();
$this->assertEquals($newchecksum, $checksum);
// try to load non-existing controller
try {
$bc = backup_controller_dbops::load_controller('1234567890');
$this->assertTrue(false, 'backup_dbops_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_dbops_exception);
$this->assertEquals($e->errorcode, 'backup_controller_dbops_nonexisting');
}
// backup_ids_temp table tests
// If, for any reason table exists, drop it
if ($dbman->table_exists('backup_ids_temp')) {
$dbman->drop_temp_table(new xmldb_table('backup_ids_temp'));
}
// Check backup_ids_temp table doesn't exist
$this->assertFalse($dbman->table_exists('backup_ids_temp'));
// Create and check it exists
backup_controller_dbops::create_backup_ids_temp_table('testingid');
$this->assertTrue($dbman->table_exists('backup_ids_temp'));
// Drop and check it doesn't exists anymore
backup_controller_dbops::drop_backup_ids_temp_table('testingid');
$this->assertFalse($dbman->table_exists('backup_ids_temp'));
}
}
class mock_backup_controller4dbops extends backup_controller {
/**
* Change standard behavior so the checksum is also stored and not onlt calculated
*/
public function calculate_checksum() {
$this->checksum = parent::calculate_checksum();
return $this->checksum;
}
}
@@ -0,0 +1,47 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/helper/backup_helper.class.php');
/**
* dbops tests (all)
*/
class backup_destinations_testcase extends basic_testcase {
/**
* test backup_destination class
*/
function test_backup_destination() {
}
/**
* test backup_destination_osfs class
*/
function test_backup_destination_osfs() {
}
}
@@ -0,0 +1,126 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/interfaces/checksumable.class.php');
require_once($CFG->dirroot . '/backup/backup.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/output_indented_logger.class.php');
require_once($CFG->dirroot . '/backup/util/loggers/database_logger.class.php');
require_once($CFG->dirroot . '/backup/util/loggers/file_logger.class.php');
require_once($CFG->dirroot . '/backup/util/factories/backup_factory.class.php');
/**
* backup_factory tests (all)
*/
class backup_factories_testcase extends advanced_testcase {
function setUp() {
global $CFG;
parent::setUp();
$this->resetAfterTest(true);
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_output_indented_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
unset($CFG->backup_file_logger_extra);
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/**
* test get_logger_chain() method
*/
function test_backup_factory() {
global $CFG;
// Default instantiate, all levels = backup::LOG_NONE
// With debugdisplay enabled
$CFG->debugdisplay = true;
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_YES, backup::EXECUTION_INMEDIATE, 'test');
$this->assertTrue($logger1 instanceof error_log_logger); // 1st logger is error_log_logger
$this->assertEquals($logger1->get_level(), backup::LOG_NONE);
$logger2 = $logger1->get_next();
$this->assertTrue($logger2 instanceof output_indented_logger); // 2nd logger is output_indented_logger
$this->assertEquals($logger2->get_level(), backup::LOG_NONE);
$logger3 = $logger2->get_next();
$this->assertTrue($logger3 instanceof file_logger); // 3rd logger is file_logger
$this->assertEquals($logger3->get_level(), backup::LOG_NONE);
$logger4 = $logger3->get_next();
$this->assertTrue($logger4 instanceof database_logger); // 4th logger is database_logger
$this->assertEquals($logger4->get_level(), backup::LOG_NONE);
$logger5 = $logger4->get_next();
$this->assertTrue($logger5 === null);
// With debugdisplay disabled
$CFG->debugdisplay = false;
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_YES, backup::EXECUTION_INMEDIATE, 'test');
$this->assertTrue($logger1 instanceof error_log_logger); // 1st logger is error_log_logger
$this->assertEquals($logger1->get_level(), backup::LOG_NONE);
$logger2 = $logger1->get_next();
$this->assertTrue($logger2 instanceof file_logger); // 2nd logger is file_logger
$this->assertEquals($logger2->get_level(), backup::LOG_NONE);
$logger3 = $logger2->get_next();
$this->assertTrue($logger3 instanceof database_logger); // 3rd logger is database_logger
$this->assertEquals($logger3->get_level(), backup::LOG_NONE);
$logger4 = $logger3->get_next();
$this->assertTrue($logger4 === null);
// Instantiate with debugging enabled and $CFG->backup_error_log_logger_level not set
$CFG->debugdisplay = true;
$CFG->debug = DEBUG_DEVELOPER;
unset($CFG->backup_error_log_logger_level);
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_YES, backup::EXECUTION_INMEDIATE, 'test');
$this->assertTrue($logger1 instanceof error_log_logger); // 1st logger is error_log_logger
$this->assertEquals($logger1->get_level(), backup::LOG_DEBUG); // and must have backup::LOG_DEBUG level
// Set $CFG->backup_error_log_logger_level to backup::LOG_WARNING and test again
$CFG->backup_error_log_logger_level = backup::LOG_WARNING;
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_YES, backup::EXECUTION_INMEDIATE, 'test');
$this->assertTrue($logger1 instanceof error_log_logger); // 1st logger is error_log_logger
$this->assertEquals($logger1->get_level(), backup::LOG_WARNING); // and must have backup::LOG_WARNING level
// Instantiate in non-interactive mode, output_indented_logger must be out
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_NO, backup::EXECUTION_INMEDIATE, 'test');
$logger2 = $logger1->get_next();
$this->assertTrue($logger2 instanceof file_logger); // 2nd logger is file_logger (output_indented_logger skiped)
// Define extra file logger and instantiate, should be 5th and last logger
$CFG->backup_file_logger_extra = '/tmp/test.html';
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
$logger1 = backup_factory::get_logger_chain(backup::INTERACTIVE_YES, backup::EXECUTION_INMEDIATE, 'test');
$logger2 = $logger1->get_next();
$logger3 = $logger2->get_next();
$logger4 = $logger3->get_next();
$logger5 = $logger4->get_next();
$this->assertTrue($logger5 instanceof file_logger); // 5rd logger is file_logger (extra)
$this->assertEquals($logger3->get_level(), backup::LOG_NONE);
$logger6 = $logger5->get_next();
$this->assertTrue($logger6 === null);
}
}
@@ -0,0 +1,145 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/helper/convert_helper.class.php');
/**
* Provides access to the protected methods we need to test
*/
class testable_convert_helper extends convert_helper {
public static function choose_conversion_path($format, array $descriptions) {
return parent::choose_conversion_path($format, $descriptions);
}
}
/**
* Defines the test methods
*/
class backup_convert_helper_testcase extends basic_testcase {
public function test_choose_conversion_path() {
// no converters available
$descriptions = array();
$path = testable_convert_helper::choose_conversion_path(backup::FORMAT_MOODLE1, $descriptions);
$this->assertEquals($path, array());
// missing source and/or targets
$descriptions = array(
// some custom converter
'exporter' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => 'some_custom_format',
'cost' => 10,
),
// another custom converter
'converter' => array(
'from' => 'yet_another_crazy_custom_format',
'to' => backup::FORMAT_MOODLE,
'cost' => 10,
),
);
$path = testable_convert_helper::choose_conversion_path(backup::FORMAT_MOODLE1, $descriptions);
$this->assertEquals($path, array());
$path = testable_convert_helper::choose_conversion_path('some_other_custom_format', $descriptions);
$this->assertEquals($path, array());
// single step conversion
$path = testable_convert_helper::choose_conversion_path('yet_another_crazy_custom_format', $descriptions);
$this->assertEquals($path, array('converter'));
// no conversion needed - this is supposed to be detected by the caller
$path = testable_convert_helper::choose_conversion_path(backup::FORMAT_MOODLE, $descriptions);
$this->assertEquals($path, array());
// two alternatives
$descriptions = array(
// standard moodle 1.9 -> 2.x converter
'moodle1' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => backup::FORMAT_MOODLE,
'cost' => 10,
),
// alternative moodle 1.9 -> 2.x converter
'alternative' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => backup::FORMAT_MOODLE,
'cost' => 8,
)
);
$path = testable_convert_helper::choose_conversion_path(backup::FORMAT_MOODLE1, $descriptions);
$this->assertEquals($path, array('alternative'));
// complex case
$descriptions = array(
// standard moodle 1.9 -> 2.x converter
'moodle1' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => backup::FORMAT_MOODLE,
'cost' => 10,
),
// alternative moodle 1.9 -> 2.x converter
'alternative' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => backup::FORMAT_MOODLE,
'cost' => 8,
),
// custom converter from 1.9 -> custom 'CFv1' format
'cc1' => array(
'from' => backup::FORMAT_MOODLE1,
'to' => 'CFv1',
'cost' => 2,
),
// custom converter from custom 'CFv1' format -> moodle 2.0 format
'cc2' => array(
'from' => 'CFv1',
'to' => backup::FORMAT_MOODLE,
'cost' => 5,
),
// custom converter from CFv1 -> CFv2 format
'cc3' => array(
'from' => 'CFv1',
'to' => 'CFv2',
'cost' => 2,
),
// custom converter from CFv2 -> moodle 2.0 format
'cc4' => array(
'from' => 'CFv2',
'to' => backup::FORMAT_MOODLE,
'cost' => 2,
),
);
// ask the helper to find the most effective way
$path = testable_convert_helper::choose_conversion_path(backup::FORMAT_MOODLE1, $descriptions);
$this->assertEquals($path, array('cc1', 'cc3', 'cc4'));
}
}
+190
View File
@@ -0,0 +1,190 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/restore_includes.php');
/**
* restore_decode tests (both rule and content)
*/
class backup_restore_decode_testcase extends basic_testcase {
/**
* test restore_decode_rule class
*/
function test_restore_decode_rule() {
// Test various incorrect constructors
try {
$dr = new restore_decode_rule('28 HJH', '/index.php', array());
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_incorrect_name');
$this->assertEquals($e->a, '28 HJH');
}
try {
$dr = new restore_decode_rule('HJHJhH', '/index.php', array());
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_incorrect_name');
$this->assertEquals($e->a, 'HJHJhH');
}
try {
$dr = new restore_decode_rule('', '/index.php', array());
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_incorrect_name');
$this->assertEquals($e->a, '');
}
try {
$dr = new restore_decode_rule('TESTRULE', 'index.php', array());
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_incorrect_urltemplate');
$this->assertEquals($e->a, 'index.php');
}
try {
$dr = new restore_decode_rule('TESTRULE', '', array());
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_incorrect_urltemplate');
$this->assertEquals($e->a, '');
}
try {
$dr = new restore_decode_rule('TESTRULE', '/course/view.php?id=$1&c=$2$3', array('test1', 'test2'));
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_mappings_incorrect_count');
$this->assertEquals($e->a->placeholders, 3);
$this->assertEquals($e->a->mappings, 2);
}
try {
$dr = new restore_decode_rule('TESTRULE', '/course/view.php?id=$5&c=$4$1', array('test1', 'test2', 'test3'));
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_nonconsecutive_placeholders');
$this->assertEquals($e->a, '1, 4, 5');
}
try {
$dr = new restore_decode_rule('TESTRULE', '/course/view.php?id=$0&c=$3$2', array('test1', 'test2', 'test3'));
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_nonconsecutive_placeholders');
$this->assertEquals($e->a, '0, 2, 3');
}
try {
$dr = new restore_decode_rule('TESTRULE', '/course/view.php?id=$1&c=$3$3', array('test1', 'test2', 'test3'));
$this->assertTrue(false, 'restore_decode_rule_exception exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof restore_decode_rule_exception);
$this->assertEquals($e->errorcode, 'decode_rule_duplicate_placeholders');
$this->assertEquals($e->a, '1, 3, 3');
}
// Provide some example content and test the regexp is calculated ok
$content = '$@TESTRULE*22*33*44@$';
$linkname = 'TESTRULE';
$urltemplate= '/course/view.php?id=$1&c=$3$2';
$mappings = array('test1', 'test2', 'test3');
$result = '1/course/view.php?id=44&c=8866';
$dr = new mock_restore_decode_rule($linkname, $urltemplate, $mappings);
$this->assertEquals($dr->decode($content), $result);
$content = '$@TESTRULE*22*33*44@$ñ$@TESTRULE*22*33*44@$';
$linkname = 'TESTRULE';
$urltemplate= '/course/view.php?id=$1&c=$3$2';
$mappings = array('test1', 'test2', 'test3');
$result = '1/course/view.php?id=44&c=8866ñ1/course/view.php?id=44&c=8866';
$dr = new mock_restore_decode_rule($linkname, $urltemplate, $mappings);
$this->assertEquals($dr->decode($content), $result);
$content = 'ñ$@TESTRULE*22*0*44@$ñ$@TESTRULE*22*33*44@$ñ';
$linkname = 'TESTRULE';
$urltemplate= '/course/view.php?id=$1&c=$3$2';
$mappings = array('test1', 'test2', 'test3');
$result = 'ñ0/course/view.php?id=22&c=440ñ1/course/view.php?id=44&c=8866ñ';
$dr = new mock_restore_decode_rule($linkname, $urltemplate, $mappings);
$this->assertEquals($dr->decode($content), $result);
}
/**
* test restore_decode_content class
*/
function test_restore_decode_content() {
// TODO: restore_decode_content tests
}
/**
* test restore_decode_processor class
*/
function test_restore_decode_processor() {
// TODO: restore_decode_processor tests
}
}
/**
* Mockup restore_decode_rule for testing purposes
*/
class mock_restore_decode_rule extends restore_decode_rule {
/**
* Originally protected, make it public
*/
public function get_calculated_regexp() {
return parent::get_calculated_regexp();
}
/**
* Simply map each itemid by its double
*/
protected function get_mapping($itemname, $itemid) {
return $itemid * 2;
}
/**
* Simply prefix with '0' non-mapped results and with '1' mapped ones
*/
protected function apply_modifications($toreplace, $mappingsok) {
return ($mappingsok ? '1' : '0') . $toreplace;
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/interfaces/checksumable.class.php');
require_once($CFG->dirroot . '/backup/backup.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');
/*
* backup_helper tests (all)
*/
class backup_helper_testcase extends basic_testcase {
/*
* test backup_helper class
*/
function test_backup_helper() {
}
/*
* test backup_general_helper class
*/
function test_backup_general_helper() {
}
}
@@ -32,6 +32,10 @@ class error_log_logger extends base_logger {
// Protected API starts here
protected function action($message, $level, $options = null) {
if (PHPUNIT_TEST) {
// no logging from PHPUnit, it is admins fault if it does not work!!!
return true;
}
return error_log($message);
}
}
+389
View File
@@ -0,0 +1,389 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/interfaces/checksumable.class.php');
require_once($CFG->dirroot . '/backup/backup.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/output_text_logger.class.php');
require_once($CFG->dirroot . '/backup/util/loggers/output_indented_logger.class.php');
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 backup_logger_testcase extends basic_testcase {
/**
* test base_logger class
*/
function test_base_logger() {
// Test logger with simple action (message * level)
$lo = new mock_base_logger1(backup::LOG_ERROR);
$msg = 13;
$this->assertEquals($lo->process($msg, backup::LOG_ERROR), $msg * backup::LOG_ERROR);
// With lowest level must return true
$lo = new mock_base_logger1(backup::LOG_ERROR);
$msg = 13;
$this->assertTrue($lo->process($msg, backup::LOG_DEBUG));
// Chain 2 loggers, we must get as result the result of the inner one
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
$lo2 = new mock_base_logger2(backup::LOG_ERROR);
$lo1->set_next($lo2);
$msg = 13;
$this->assertEquals($lo1->process($msg, backup::LOG_ERROR), $msg + backup::LOG_ERROR);
// Try circular reference
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
try {
$lo1->set_next($lo1); //self
$this->assertTrue(false, 'base_logger_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_logger_exception);
$this->assertEquals($e->errorcode, 'logger_circular_reference');
$this->assertTrue($e->a instanceof stdclass);
$this->assertEquals($e->a->main, get_class($lo1));
$this->assertEquals($e->a->alreadyinchain, get_class($lo1));
}
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
$lo2 = new mock_base_logger2(backup::LOG_ERROR);
$lo3 = new mock_base_logger3(backup::LOG_ERROR);
$lo1->set_next($lo2);
$lo2->set_next($lo3);
try {
$lo3->set_next($lo1);
$this->assertTrue(false, 'base_logger_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_logger_exception);
$this->assertEquals($e->errorcode, 'logger_circular_reference');
$this->assertTrue($e->a instanceof stdclass);
$this->assertEquals($e->a->main, get_class($lo1));
$this->assertEquals($e->a->alreadyinchain, get_class($lo3));
}
// Test stopper logger
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
$lo2 = new mock_base_logger2(backup::LOG_ERROR);
$lo3 = new mock_base_logger3(backup::LOG_ERROR);
$lo1->set_next($lo2);
$lo2->set_next($lo3);
$this->assertFalse($lo1->process('test', backup::LOG_ERROR));
// Test checksum correct
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
$lo1->is_checksum_correct(get_class($lo1) . '-' . backup::LOG_ERROR);
// Test get_levelstr()
$lo1 = new mock_base_logger1(backup::LOG_ERROR);
$this->assertEquals($lo1->get_levelstr(backup::LOG_NONE), 'undefined');
$this->assertEquals($lo1->get_levelstr(backup::LOG_ERROR), 'error');
$this->assertEquals($lo1->get_levelstr(backup::LOG_WARNING), 'warn');
$this->assertEquals($lo1->get_levelstr(backup::LOG_INFO), 'info');
$this->assertEquals($lo1->get_levelstr(backup::LOG_DEBUG), 'debug');
}
/**
* test error_log_logger class
*/
function test_error_log_logger() {
// Not much really to test, just instantiate and execute, should return true
$lo = new error_log_logger(backup::LOG_ERROR);
$this->assertTrue($lo instanceof error_log_logger);
$message = 'This log exists because you have run Moodle unit tests: Ignore it';
$result = $lo->process($message, backup::LOG_ERROR);
$this->assertTrue($result);
}
/**
* test output_text_logger class
*/
function test_output_text_logger() {
// Instantiate without date nor level output
$lo = new output_text_logger(backup::LOG_ERROR);
$this->assertTrue($lo instanceof output_text_logger);
$message = 'testing output_text_logger';
ob_start(); // Capture output
$result = $lo->process($message, backup::LOG_ERROR);
$contents = ob_get_contents();
ob_end_clean(); // End capture and discard
$this->assertTrue($result);
$this->assertTrue(strpos($contents, $message) !== false);
// Instantiate with date and level output
$lo = new output_text_logger(backup::LOG_ERROR, true, true);
$this->assertTrue($lo instanceof output_text_logger);
$message = 'testing output_text_logger';
ob_start(); // Capture output
$result = $lo->process($message, backup::LOG_ERROR);
$contents = ob_get_contents();
ob_end_clean(); // End capture and discard
$this->assertTrue($result);
$this->assertTrue(strpos($contents,'[') === 0);
$this->assertTrue(strpos($contents,'[error]') !== false);
$this->assertTrue(strpos($contents, $message) !== false);
$this->assertTrue(substr_count($contents , '] ') >= 2);
}
/**
* test output_indented_logger class
*/
function test_output_indented_logger() {
// Instantiate without date nor level output
$options = array('depth' => 2);
$lo = new output_indented_logger(backup::LOG_ERROR);
$this->assertTrue($lo instanceof output_indented_logger);
$message = 'testing output_indented_logger';
ob_start(); // Capture output
$result = $lo->process($message, backup::LOG_ERROR, $options);
$contents = ob_get_contents();
ob_end_clean(); // End capture and discard
$this->assertTrue($result);
if (defined('STDOUT')) {
$check = ' ';
} else {
$check = '&nbsp;&nbsp;';
}
$this->assertTrue(strpos($contents, str_repeat($check, $options['depth']) . $message) !== false);
// Instantiate with date and level output
$options = array('depth' => 3);
$lo = new output_indented_logger(backup::LOG_ERROR, true, true);
$this->assertTrue($lo instanceof output_indented_logger);
$message = 'testing output_indented_logger';
ob_start(); // Capture output
$result = $lo->process($message, backup::LOG_ERROR, $options);
$contents = ob_get_contents();
ob_end_clean(); // End capture and discard
$this->assertTrue($result);
$this->assertTrue(strpos($contents,'[') === 0);
$this->assertTrue(strpos($contents,'[error]') !== false);
$this->assertTrue(strpos($contents, $message) !== false);
$this->assertTrue(substr_count($contents , '] ') >= 2);
if (defined('STDOUT')) {
$check = ' ';
} else {
$check = '&nbsp;&nbsp;';
}
$this->assertTrue(strpos($contents, str_repeat($check, $options['depth']) . $message) !== false);
}
/**
* test database_logger class
*/
function test_database_logger() {
// Instantiate with date and level output (and with specs from the global moodle "log" table so checks will pass
$now = time();
$datecol = 'time';
$levelcol = 'action';
$messagecol = 'info';
$logtable = 'log';
$columns = array('url' => 'http://127.0.0.1');
$loglevel = backup::LOG_ERROR;
$lo = new mock_database_logger(backup::LOG_ERROR, $datecol, $levelcol, $messagecol, $logtable, $columns);
$this->assertTrue($lo instanceof database_logger);
$message = 'testing database_logger';
$result = $lo->process($message, $loglevel);
// Check everything is ready to be inserted to DB
$this->assertEquals($result['table'], $logtable);
$this->assertTrue($result['columns'][$datecol] >= $now);
$this->assertEquals($result['columns'][$levelcol], $loglevel);
$this->assertEquals($result['columns'][$messagecol], $message);
$this->assertEquals($result['columns']['url'], $columns['url']);
}
/**
* test file_logger class
*/
function test_file_logger() {
global $CFG;
$file = $CFG->tempdir . '/test/test_file_logger.txt';
// Remove the test dir and any content
@remove_dir(dirname($file));
// Recreate test dir
if (!check_dir_exists(dirname($file), true, true)) {
throw new moodle_exception('error_creating_temp_dir', 'error', dirname($file));
}
// Instantiate with date and level output, and also use the depth option
$options = array('depth' => 3);
$lo1 = new file_logger(backup::LOG_ERROR, true, true, $file);
$this->assertTrue($lo1 instanceof file_logger);
$message1 = 'testing file_logger';
$result = $lo1->process($message1, backup::LOG_ERROR, $options);
$this->assertTrue($result);
// Another file_logger is going towrite there too without closing
$options = array();
$lo2 = new file_logger(backup::LOG_WARNING, true, true, $file);
$this->assertTrue($lo2 instanceof file_logger);
$message2 = 'testing file_logger2';
$result = $lo2->process($message2, backup::LOG_WARNING, $options);
$this->assertTrue($result);
// Destruct loggers
$lo1 = null;
$lo2 = null;
// Load file results to analyze them
$fcontents = file_get_contents($file);
$acontents = explode(PHP_EOL, $fcontents); // Split by line
$this->assertTrue(strpos($acontents[0], $message1) !== false);
$this->assertTrue(strpos($acontents[0], '[error]') !== false);
$this->assertTrue(strpos($acontents[0], ' ') !== false);
$this->assertTrue(substr_count($acontents[0] , '] ') >= 2);
$this->assertTrue(strpos($acontents[1], $message2) !== false);
$this->assertTrue(strpos($acontents[1], '[warn]') !== false);
$this->assertTrue(strpos($acontents[1], ' ') === false);
$this->assertTrue(substr_count($acontents[1] , '] ') >= 2);
unlink($file); // delete file
// Try one html file
$file = $CFG->tempdir . '/test/test_file_logger.html';
$options = array('depth' => 1);
$lo = new file_logger(backup::LOG_ERROR, true, true, $file);
$this->assertTrue($lo instanceof file_logger);
$this->assertTrue(file_exists($file));
$message = 'testing file_logger';
$result = $lo->process($message, backup::LOG_ERROR, $options);
// Get file contents and inspect them
$fcontents = file_get_contents($file);
$this->assertTrue($result);
$this->assertTrue(strpos($fcontents, $message) !== false);
$this->assertTrue(strpos($fcontents, '[error]') !== false);
$this->assertTrue(strpos($fcontents, '&nbsp;&nbsp;') !== false);
$this->assertTrue(substr_count($fcontents , '] ') >= 2);
unlink($file); // delete file
// Instantiate, write something, force deletion, try to write again
$file = $CFG->tempdir . '/test/test_file_logger.html';
$lo = new mock_file_logger(backup::LOG_ERROR, true, true, $file);
$this->assertTrue(file_exists($file));
$message = 'testing file_logger';
$result = $lo->process($message, backup::LOG_ERROR);
fclose($lo->get_fhandle()); // close file
try {
$result = @$lo->process($message, backup::LOG_ERROR); // Try to write again
$this->assertTrue(false, 'base_logger_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_logger_exception);
$this->assertEquals($e->errorcode, 'error_writing_file');
}
// Instantiate without file
try {
$lo = new file_logger(backup::LOG_WARNING, true, true, '');
$this->assertTrue(false, 'base_logger_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_logger_exception);
$this->assertEquals($e->errorcode, 'missing_fullpath_parameter');
}
// Instantiate in (near) impossible path
$file = $CFG->tempdir . '/test_azby/test_file_logger.txt';
try {
$lo = new file_logger(backup::LOG_WARNING, true, true, $file);
$this->assertTrue(false, 'base_logger_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_logger_exception);
$this->assertEquals($e->errorcode, 'file_not_writable');
$this->assertEquals($e->a, $file);
}
// Instantiate one file logger with level = backup::LOG_NONE
$file = $CFG->tempdir . '/test/test_file_logger.txt';
$lo = new file_logger(backup::LOG_NONE, true, true, $file);
$this->assertTrue($lo instanceof file_logger);
$this->assertFalse(file_exists($file));
// Remove the test dir and any content
@remove_dir(dirname($file));
}
}
/**
* helper extended base_logger class that implements some methods for testing
* Simply return the product of message and level
*/
class mock_base_logger1 extends base_logger {
protected function action($message, $level, $options = null) {
return $message * $level; // Simply return that, for testing
}
public function get_levelstr($level) {
return parent::get_levelstr($level);
}
}
/**
* helper extended base_logger class that implements some methods for testing
* Simply return the sum of message and level
*/
class mock_base_logger2 extends base_logger {
protected function action($message, $level, $options = null) {
return $message + $level; // Simply return that, for testing
}
}
/**
* helper extended base_logger class that implements some methods for testing
* Simply return 8
*/
class mock_base_logger3 extends base_logger {
protected function action($message, $level, $options = null) {
return false; // Simply return false, for testing stopper
}
}
/**
* helper extended database_logger class that implements some methods for testing
* Returns the complete info that normally will be used by insert record calls
*/
class mock_database_logger extends database_logger {
protected function insert_log_record($table, $columns) {
return array('table' => $table, 'columns' => $columns);
}
}
/**
* helper extended file_logger class that implements some methods for testing
* Returns the, usually protected, handle
*/
class mock_file_logger extends file_logger {
function get_fhandle() {
return $this->fhandle;
}
}
+130
View File
@@ -0,0 +1,130 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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() {
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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();
require_once(__DIR__.'/fixtures/plan_fixtures.php');
/**
* plan tests (all)
*/
class backup_plan_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user record used for testing
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
// Disable all loggers
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/**
* test base_plan class
*/
function test_base_plan() {
// Instantiate
$bp = new mock_base_plan('name');
$this->assertTrue($bp instanceof base_plan);
$this->assertEquals($bp->get_name(), 'name');
$this->assertTrue(is_array($bp->get_settings()));
$this->assertEquals(count($bp->get_settings()), 0);
$this->assertTrue(is_array($bp->get_tasks()));
$this->assertEquals(count($bp->get_tasks()), 0);
}
/**
* test backup_plan class
*/
function test_backup_plan() {
// We need one (non interactive) controller for instantiating plan
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
// Instantiate one backup plan
$bp = new backup_plan($bc);
$this->assertTrue($bp instanceof backup_plan);
$this->assertEquals($bp->get_name(), 'backup_plan');
// Calculate checksum and check it
$checksum = $bp->calculate_checksum();
$this->assertTrue($bp->is_checksum_correct($checksum));
}
/**
* wrong base_plan class tests
*/
function test_base_plan_wrong() {
// We need one (non interactive) controller for instantiating plan
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
// Instantiate one backup plan
$bp = new backup_plan($bc);
// Add wrong task
try {
$bp->add_task(new stdclass());
$this->assertTrue(false, 'base_plan_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_plan_exception);
$this->assertEquals($e->errorcode, 'wrong_base_task_specified');
}
}
/**
* wrong backup_plan class tests
*/
function test_backup_plan_wrong() {
// Try to pass one wrong controller
try {
$bp = new backup_plan(new stdclass());
$this->assertTrue(false, 'backup_plan_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_plan_exception);
$this->assertEquals($e->errorcode, 'wrong_backup_controller_specified');
}
try {
$bp = new backup_plan(null);
$this->assertTrue(false, 'backup_plan_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_plan_exception);
$this->assertEquals($e->errorcode, 'wrong_backup_controller_specified');
}
// Try to build one non-existent format plan (when creating the controller)
// We need one (non interactive) controller for instatiating plan
try {
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, 'non_existing_format',
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
$this->assertTrue(false, 'backup_controller_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_controller_exception);
$this->assertEquals($e->errorcode, 'backup_check_unsupported_format');
$this->assertEquals($e->a, 'non_existing_format');
}
}
}
+166
View File
@@ -0,0 +1,166 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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();
require_once(__DIR__.'/fixtures/plan_fixtures.php');
/*
* step tests (all)
*/
class backup_step_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user record used for testing
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
// Disable all loggers
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/**
* test base_step class
*/
function test_base_step() {
$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);
$this->assertEquals($bs->get_name(), 'stepname');
}
/**
* test backup_step class
*/
function test_backup_step() {
// We need one (non interactive) controller for instatiating plan
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
// We need one plan
$bp = new backup_plan($bc);
// We need one task
$bt = new mock_backup_task('taskname', $bp);
// Instantiate step
$bs = new mock_backup_step('stepname', $bt);
$this->assertTrue($bs instanceof backup_step);
$this->assertEquals($bs->get_name(), 'stepname');
}
/**
* test backup_structure_step class
*/
function test_backup_structure_step() {
global $CFG;
$file = $CFG->tempdir . '/test/test_backup_structure_step.txt';
// Remove the test dir and any content
@remove_dir(dirname($file));
// Recreate test dir
if (!check_dir_exists(dirname($file), true, true)) {
throw new moodle_exception('error_creating_temp_dir', 'error', dirname($file));
}
// We need one (non interactive) controller for instatiating plan
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
// We need one plan
$bp = new backup_plan($bc);
// We need one task with mocked basepath
$bt = new mock_backup_task_basepath('taskname');
$bp->add_task($bt);
// Instantiate backup_structure_step (and add it to task)
$bs = new mock_backup_structure_step('steptest', basename($file), $bt);
// Execute backup_structure_step
$bs->execute();
// Test file has been created
$this->assertTrue(file_exists($file));
// Some simple tests with contents
$contents = file_get_contents($file);
$this->assertTrue(strpos($contents, '<?xml version="1.0"') !== false);
$this->assertTrue(strpos($contents, '<test id="1">') !== false);
$this->assertTrue(strpos($contents, '<field1>value1</field1>') !== false);
$this->assertTrue(strpos($contents, '<field2>value2</field2>') !== false);
$this->assertTrue(strpos($contents, '</test>') !== false);
unlink($file); // delete file
// Remove the test dir and any content
@remove_dir(dirname($file));
}
/**
* wrong base_step class tests
*/
function test_base_step_wrong() {
// Try to pass one wrong task
try {
$bt = new mock_base_step('teststep', new stdclass());
$this->assertTrue(false, 'base_step_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_step_exception);
$this->assertEquals($e->errorcode, 'wrong_base_task_specified');
}
}
/**
* wrong backup_step class tests
*/
function test_backup_test_wrong() {
// Try to pass one wrong task
try {
$bt = new mock_backup_step('teststep', new stdclass());
$this->assertTrue(false, 'backup_step_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_step_exception);
$this->assertEquals($e->errorcode, 'wrong_backup_task_specified');
}
}
}
+140
View File
@@ -0,0 +1,140 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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();
require_once(__DIR__.'/fixtures/plan_fixtures.php');
/**
* task tests (all)
*/
class backup_task_testcase extends advanced_testcase {
protected $moduleid; // course_modules id used for testing
protected $sectionid; // course_sections id used for testing
protected $courseid; // course id used for testing
protected $userid; // user record used for testing
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course();
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id), array('section'=>3));
$coursemodule = $DB->get_record('course_modules', array('id'=>$page->cmid));
$this->moduleid = $coursemodule->id;
$this->sectionid = $DB->get_field("course_sections", 'id', array("section"=>$coursemodule->section, "course"=>$course->id));
$this->courseid = $coursemodule->course;
$this->userid = 2; // admin
// Disable all loggers
$CFG->backup_error_log_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level = backup::LOG_NONE;
$CFG->backup_database_logger_level = backup::LOG_NONE;
$CFG->backup_file_logger_level_extra = backup::LOG_NONE;
}
/**
* test base_task class
*/
function test_base_task() {
$bp = new mock_base_plan('planname'); // We need one plan
// Instantiate
$bt = new mock_base_task('taskname', $bp);
$this->assertTrue($bt instanceof base_task);
$this->assertEquals($bt->get_name(), 'taskname');
$this->assertTrue(is_array($bt->get_settings()));
$this->assertEquals(count($bt->get_settings()), 0);
$this->assertTrue(is_array($bt->get_steps()));
$this->assertEquals(count($bt->get_steps()), 0);
}
/**
* test backup_task class
*/
function test_backup_task() {
// We need one (non interactive) controller for instatiating plan
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $this->moduleid, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_GENERAL, $this->userid);
// We need one plan
$bp = new backup_plan($bc);
// Instantiate task
$bt = new mock_backup_task('taskname', $bp);
$this->assertTrue($bt instanceof backup_task);
$this->assertEquals($bt->get_name(), 'taskname');
// Calculate checksum and check it
$checksum = $bt->calculate_checksum();
$this->assertTrue($bt->is_checksum_correct($checksum));
}
/**
* wrong base_task class tests
*/
function test_base_task_wrong() {
// Try to pass one wrong plan
try {
$bt = new mock_base_task('tasktest', new stdclass());
$this->assertTrue(false, 'base_task_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_task_exception);
$this->assertEquals($e->errorcode, 'wrong_base_plan_specified');
}
// Add wrong step to task
$bp = new mock_base_plan('planname'); // We need one plan
// Instantiate
$bt = new mock_base_task('taskname', $bp);
try {
$bt->add_step(new stdclass());
$this->assertTrue(false, 'base_task_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_task_exception);
$this->assertEquals($e->errorcode, 'wrong_base_step_specified');
}
}
/**
* wrong backup_task class tests
*/
function test_backup_task_wrong() {
// Try to pass one wrong plan
try {
$bt = new mock_backup_task('tasktest', new stdclass());
$this->assertTrue(false, 'backup_task_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_task_exception);
$this->assertEquals($e->errorcode, 'wrong_backup_plan_specified');
}
}
}
@@ -0,0 +1,463 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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/interfaces/checksumable.class.php');
require_once($CFG->dirroot . '/backup/backup.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/setting_dependency.class.php');
require_once($CFG->dirroot . '/backup/util/settings/root/root_backup_setting.class.php');
require_once($CFG->dirroot . '/backup/util/settings/activity/activity_backup_setting.class.php');
require_once($CFG->dirroot . '/backup/util/settings/section/section_backup_setting.class.php');
require_once($CFG->dirroot . '/backup/util/settings/course/course_backup_setting.class.php');
require_once($CFG->dirroot . '/backup/util/ui/backup_ui_setting.class.php');
/**
* setting tests (all)
*/
class backp_settings_testcase extends basic_testcase {
/**
* test base_setting class
*/
function test_base_setting() {
// Instantiate base_setting and check everything
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN);
$this->assertTrue($bs instanceof base_setting);
$this->assertEquals($bs->get_name(), 'test');
$this->assertEquals($bs->get_vtype(), base_setting::IS_BOOLEAN);
$this->assertTrue(is_null($bs->get_value()));
$this->assertEquals($bs->get_visibility(), base_setting::VISIBLE);
$this->assertEquals($bs->get_status(), base_setting::NOT_LOCKED);
// Instantiate base_setting with explicit nulls
$bs = new mock_base_setting('test', base_setting::IS_FILENAME, 'filename.txt', null, null);
$this->assertEquals($bs->get_value() , 'filename.txt');
$this->assertEquals($bs->get_visibility(), base_setting::VISIBLE);
$this->assertEquals($bs->get_status(), base_setting::NOT_LOCKED);
// Instantiate base_setting and set value, visibility and status
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN);
$bs->set_value(true);
$this->assertNotEmpty($bs->get_value());
$bs->set_visibility(base_setting::HIDDEN);
$this->assertEquals($bs->get_visibility(), base_setting::HIDDEN);
$bs->set_status(base_setting::LOCKED_BY_HIERARCHY);
$this->assertEquals($bs->get_status(), base_setting::LOCKED_BY_HIERARCHY);
// Instantiate with wrong vtype
try {
$bs = new mock_base_setting('test', 'one_wrong_type');
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_invalid_type');
}
// Instantiate with wrong integer value
try {
$bs = new mock_base_setting('test', base_setting::IS_INTEGER, 99.99);
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_invalid_integer');
}
// Instantiate with wrong filename value
try {
$bs = new mock_base_setting('test', base_setting::IS_FILENAME, '../../filename.txt');
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_invalid_filename');
}
// Instantiate with wrong visibility
try {
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN, null, 'one_wrong_visibility');
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_invalid_visibility');
}
// Instantiate with wrong status
try {
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN, null, null, 'one_wrong_status');
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_invalid_status');
}
// Instantiate base_setting and try to set wrong ui_type
// We need a custom error handler to catch the type hinting error
// that should return incorrect_object_passed
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN);
set_error_handler('backup_setting_error_handler', E_RECOVERABLE_ERROR);
try {
$bs->set_ui('one_wrong_ui_type', 'label', array(), array());
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'incorrect_object_passed');
}
restore_error_handler();
// Instantiate base_setting and try to set wrong ui_label
// We need a custom error handler to catch the type hinting error
// that should return incorrect_object_passed
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN);
set_error_handler('backup_setting_error_handler', E_RECOVERABLE_ERROR);
try {
$bs->set_ui(base_setting::UI_HTML_CHECKBOX, 'one/wrong/label', array(), array());
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'incorrect_object_passed');
}
restore_error_handler();
// Try to change value of locked setting by permission
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN, null, null, base_setting::LOCKED_BY_PERMISSION);
try {
$bs->set_value(true);
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_locked_by_permission');
}
// Try to change value of locked setting by config
$bs = new mock_base_setting('test', base_setting::IS_BOOLEAN, null, null, base_setting::LOCKED_BY_CONFIG);
try {
$bs->set_value(true);
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_locked_by_config');
}
// Try to add same setting twice
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
$bs2 = new mock_base_setting('test2', base_setting::IS_INTEGER, null);
$bs1->add_dependency($bs2, null, array('value'=>0));
try {
$bs1->add_dependency($bs2);
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_already_added');
}
// Try to create one circular reference
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
try {
$bs1->add_dependency($bs1); // self
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_circular_reference');
$this->assertTrue($e->a instanceof stdclass);
$this->assertEquals($e->a->main, 'test1');
$this->assertEquals($e->a->alreadydependent, 'test1');
}
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
$bs2 = new mock_base_setting('test2', base_setting::IS_INTEGER, null);
$bs3 = new mock_base_setting('test3', base_setting::IS_INTEGER, null);
$bs4 = new mock_base_setting('test4', base_setting::IS_INTEGER, null);
$bs1->add_dependency($bs2, null, array('value'=>0));
$bs2->add_dependency($bs3, null, array('value'=>0));
$bs3->add_dependency($bs4, null, array('value'=>0));
try {
$bs4->add_dependency($bs1, null, array('value'=>0));
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_circular_reference');
$this->assertTrue($e->a instanceof stdclass);
$this->assertEquals($e->a->main, 'test1');
$this->assertEquals($e->a->alreadydependent, 'test4');
}
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
$bs2 = new mock_base_setting('test2', base_setting::IS_INTEGER, null);
$bs1->register_dependency(new setting_dependency_disabledif_empty($bs1, $bs2));
try {
// $bs1 is already dependent on $bs2 so this should fail.
$bs2->register_dependency(new setting_dependency_disabledif_empty($bs2, $bs1));
$this->assertTrue(false, 'base_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof base_setting_exception);
$this->assertEquals($e->errorcode, 'setting_circular_reference');
$this->assertTrue($e->a instanceof stdclass);
$this->assertEquals($e->a->main, 'test1');
$this->assertEquals($e->a->alreadydependent, 'test2');
}
// Create 3 settings and observe between them, last one must
// automatically inherit all the settings defined in the main one
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
$bs2 = new mock_base_setting('test2', base_setting::IS_INTEGER, null);
$bs3 = new mock_base_setting('test3', base_setting::IS_INTEGER, null);
$bs1->add_dependency($bs2, setting_dependency::DISABLED_NOT_EMPTY);
$bs2->add_dependency($bs3, setting_dependency::DISABLED_NOT_EMPTY);
// Check values are spreaded ok
$bs1->set_value(123);
$this->assertEquals($bs1->get_value(), 123);
$this->assertEquals($bs2->get_value(), $bs1->get_value());
$this->assertEquals($bs3->get_value(), $bs1->get_value());
// Add one more setting and set value again
$bs4 = new mock_base_setting('test4', base_setting::IS_INTEGER, null);
$bs2->add_dependency($bs4, setting_dependency::DISABLED_NOT_EMPTY);
$bs2->set_value(321);
// The above change should change
$this->assertEquals($bs1->get_value(), 123);
$this->assertEquals($bs2->get_value(), 321);
$this->assertEquals($bs3->get_value(), 321);
$this->assertEquals($bs4->get_value(), 321);
// Check visibility is spreaded ok
$bs1->set_visibility(base_setting::HIDDEN);
$this->assertEquals($bs2->get_visibility(), $bs1->get_visibility());
$this->assertEquals($bs3->get_visibility(), $bs1->get_visibility());
// Check status is spreaded ok
$bs1->set_status(base_setting::LOCKED_BY_HIERARCHY);
$this->assertEquals($bs2->get_status(), $bs1->get_status());
$this->assertEquals($bs3->get_status(), $bs1->get_status());
// Create 3 settings and observe between them, put them in one array,
// force serialize/deserialize to check the observable pattern continues
// working after that
$bs1 = new mock_base_setting('test1', base_setting::IS_INTEGER, null);
$bs2 = new mock_base_setting('test2', base_setting::IS_INTEGER, null);
$bs3 = new mock_base_setting('test3', base_setting::IS_INTEGER, null);
$bs1->add_dependency($bs2, null, array('value'=>0));
$bs2->add_dependency($bs3, null, array('value'=>0));
// Serialize
$arr = array($bs1, $bs2, $bs3);
$ser = base64_encode(serialize($arr));
// Unserialize and copy to new objects
$newarr = unserialize(base64_decode($ser));
$ubs1 = $newarr[0];
$ubs2 = $newarr[1];
$ubs3 = $newarr[2];
// Must continue being base settings
$this->assertTrue($ubs1 instanceof base_setting);
$this->assertTrue($ubs2 instanceof base_setting);
$this->assertTrue($ubs3 instanceof base_setting);
// Set parent setting
$ubs1->set_value(1234);
$ubs1->set_visibility(base_setting::HIDDEN);
$ubs1->set_status(base_setting::LOCKED_BY_HIERARCHY);
// Check changes have been spreaded
$this->assertEquals($ubs2->get_visibility(), $ubs1->get_visibility());
$this->assertEquals($ubs3->get_visibility(), $ubs1->get_visibility());
$this->assertEquals($ubs2->get_status(), $ubs1->get_status());
$this->assertEquals($ubs3->get_status(), $ubs1->get_status());
}
/**
* test backup_setting class
*/
function test_backup_setting() {
// Instantiate backup_setting class and set level
$bs = new mock_backup_setting('test', base_setting::IS_INTEGER, null);
$bs->set_level(1);
$this->assertEquals($bs->get_level(), 1);
// Instantiate backup setting class and try to add one non backup_setting dependency
set_error_handler('backup_setting_error_handler', E_RECOVERABLE_ERROR);
$bs = new mock_backup_setting('test', base_setting::IS_INTEGER, null);
try {
$bs->add_dependency(new stdclass());
$this->assertTrue(false, 'backup_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_setting_exception);
$this->assertEquals($e->errorcode, 'incorrect_object_passed');
}
restore_error_handler();
// Try to assing upper level dependency
$bs1 = new mock_backup_setting('test1', base_setting::IS_INTEGER, null);
$bs1->set_level(1);
$bs2 = new mock_backup_setting('test2', base_setting::IS_INTEGER, null);
$bs2->set_level(2);
try {
$bs2->add_dependency($bs1);
$this->assertTrue(false, 'backup_setting_exception expected');
} catch (exception $e) {
$this->assertTrue($e instanceof backup_setting_exception);
$this->assertEquals($e->errorcode, 'cannot_add_upper_level_dependency');
}
// Check dependencies are working ok
$bs1 = new mock_backup_setting('test1', base_setting::IS_INTEGER, null);
$bs1->set_level(1);
$bs2 = new mock_backup_setting('test2', base_setting::IS_INTEGER, null);
$bs2->set_level(1); // Same level *must* work
$bs1->add_dependency($bs2, setting_dependency::DISABLED_NOT_EMPTY);
$bs1->set_value(123456);
$this->assertEquals($bs2->get_value(), $bs1->get_value());
}
/**
* test activity_backup_setting class
*/
function test_activity_backup_setting() {
$bs = new mock_activity_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::ACTIVITY_LEVEL);
// Check checksum implementation is working
$bs1 = new mock_activity_backup_setting('test', base_setting::IS_INTEGER, null);
$bs1->set_value(123);
$checksum = $bs1->calculate_checksum();
$this->assertNotEmpty($checksum);
$this->assertTrue($bs1->is_checksum_correct($checksum));
}
/**
* test section_backup_setting class
*/
function test_section_backup_setting() {
$bs = new mock_section_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::SECTION_LEVEL);
// Check checksum implementation is working
$bs1 = new mock_section_backup_setting('test', base_setting::IS_INTEGER, null);
$bs1->set_value(123);
$checksum = $bs1->calculate_checksum();
$this->assertNotEmpty($checksum);
$this->assertTrue($bs1->is_checksum_correct($checksum));
}
/**
* test course_backup_setting class
*/
function test_course_backup_setting() {
$bs = new mock_course_backup_setting('test', base_setting::IS_INTEGER, null);
$this->assertEquals($bs->get_level(), backup_setting::COURSE_LEVEL);
// Check checksum implementation is working
$bs1 = new mock_course_backup_setting('test', base_setting::IS_INTEGER, null);
$bs1->set_value(123);
$checksum = $bs1->calculate_checksum();
$this->assertNotEmpty($checksum);
$this->assertTrue($bs1->is_checksum_correct($checksum));
}
}
/**
* helper extended base_setting class that makes some methods public for testing
*/
class mock_base_setting extends base_setting {
public function get_vtype() {
return $this->vtype;
}
public function process_change($setting, $ctype, $oldv) {
// Simply, inherit from the main object
$this->set_value($setting->get_value());
$this->set_visibility($setting->get_visibility());
$this->set_status($setting->get_status());
}
public function get_ui_info() {
// Return an array with all the ui info to be tested
return array($this->ui_type, $this->ui_label, $this->ui_values, $this->ui_options);
}
}
/**
* helper extended backup_setting class that makes some methods public for testing
*/
class mock_backup_setting extends backup_setting {
public function set_level($level) {
$this->level = $level;
}
public function process_change($setting, $ctype, $oldv) {
// Simply, inherit from the main object
$this->set_value($setting->get_value());
$this->set_visibility($setting->get_visibility());
$this->set_status($setting->get_status());
}
}
/**
* helper extended activity_backup_setting class that makes some methods public for testing
*/
class mock_activity_backup_setting extends activity_backup_setting {
public function process_change($setting, $ctype, $oldv) {
// Do nothing
}
}
/**
* helper extended section_backup_setting class that makes some methods public for testing
*/
class mock_section_backup_setting extends section_backup_setting {
public function process_change($setting, $ctype, $oldv) {
// Do nothing
}
}
/**
* helper extended course_backup_setting class that makes some methods public for testing
*/
class mock_course_backup_setting extends course_backup_setting {
public function process_change($setting, $ctype, $oldv) {
// Do nothing
}
}
/**
* This error handler is used to convert errors to excpetions so that simepltest can
* catch them.
*
* This is required in order to catch type hint mismatches that result in a error
* being thrown. It should only ever be used to catch E_RECOVERABLE_ERROR's.
*
* It throws a backup_setting_exception with 'incorrect_object_passed'
*
* @param int $errno E_RECOVERABLE_ERROR
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param array $errcontext
* @return null
*/
function backup_setting_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
if ($errno !== E_RECOVERABLE_ERROR) {
// Currently we only want to deal with type hinting errors
return false;
}
throw new backup_setting_exception('incorrect_object_passed');
}
@@ -0,0 +1,119 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase extends basic_testcase {
/**
* Correct base_atom_tests
*/
function test_base_atom() {
$name_with_all_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_';
$value_to_test = 'Some <value> 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);
}
}
}
@@ -0,0 +1,61 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase extends basic_testcase {
/**
* Correct base_attribute tests
*/
function test_base_attribute() {
$name_with_all_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_';
$value_to_test = 'Some <value> 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);
}
}
@@ -0,0 +1,163 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase 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);
}
}
}
@@ -0,0 +1,395 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase 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');
}
}
}
@@ -0,0 +1,137 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase 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);
}
}
}
@@ -0,0 +1,137 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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();
}
}
@@ -0,0 +1,646 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase 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');
}
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase extends basic_testcase {
/**
* test backup_ui class
*/
function test_backup_ui() {
}
}
+323
View File
@@ -0,0 +1,323 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @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_testcase 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, '<TEST id="1"'), 22);
$this->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, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue"></tagname2>');
// 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, '<TAGNAME ATTRNAME="attrvalue">textcontent</TAGNAME>');
// 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, '<tagname attrname="attr\'&quot;value">textcontent</tagname>');
// 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, '<tagname attrname="attrvalue">text' . "\ncontent\n" . 'with</tagname>');
// 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, '<tagname attrname="attrvalue" /><tagname2 attrname="attrvalue">testsomecontent</tagname2>');
// 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;
}
}
+146
View File
@@ -0,0 +1,146 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for blog
*
* @package core_blog
* @category phpunit
* @copyright 2009 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
global $CFG;
require_once($CFG->dirroot . '/blog/locallib.php');
require_once($CFG->dirroot . '/blog/lib.php');
/**
* Test functions that rely on the DB tables
*/
class bloglib_testcase extends advanced_testcase {
private $courseid; // To store important ids to be used in tests
private $groupid;
private $userid;
private $tagid;
protected function setUp() {
global $DB;
parent::setUp();
$this->resetAfterTest(true);
// Create default course
$course = $this->getDataGenerator()->create_course(array('category'=>1, 'fullname'=>'Anonymous test course', 'shortname'=>'ANON'));
$page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
// Create default group
$group = new stdClass();
$group->courseid = $course->id;
$group->name = 'ANON';
$group->id = $DB->insert_record('groups', $group);
// Create default user
$user = $this->getDataGenerator()->create_user(array('username'=>'testuser', 'firstname'=>'Jimmy', 'lastname'=>'Kinnon'));
// Create default tag
$tag = new stdClass();
$tag->userid = $user->id;
$tag->name = 'testtagname';
$tag->rawname = 'Testtagname';
$tag->tagtype = 'official';
$tag->id = $DB->insert_record('tag', $tag);
// Create default post
$post = new stdClass();
$post->userid = $user->id;
$post->groupid = $group->id;
$post->content = 'test post content text';
$post->id = $DB->insert_record('post', $post);
// Grab important ids
$this->courseid = $course->id;
$this->groupid = $group->id;
$this->userid = $user->id;
$this->tagid = $tag->id;
}
public function test_overrides() {
// Try all the filters at once: Only the entry filter is active
$filters = array('site' => 1, 'course' => $this->courseid, 'module' => 1,
'group' => $this->groupid, 'user' => 1, 'tag' => 1, 'entry' => 1);
$blog_listing = new blog_listing($filters);
$this->assertFalse(array_key_exists('site', $blog_listing->filters));
$this->assertFalse(array_key_exists('course', $blog_listing->filters));
$this->assertFalse(array_key_exists('module', $blog_listing->filters));
$this->assertFalse(array_key_exists('group', $blog_listing->filters));
$this->assertFalse(array_key_exists('user', $blog_listing->filters));
$this->assertFalse(array_key_exists('tag', $blog_listing->filters));
$this->assertTrue(array_key_exists('entry', $blog_listing->filters));
// Again, but without the entry filter: This time, the tag, user and module filters are active
$filters = array('site' => 1, 'course' => $this->courseid, 'module' => 1,
'group' => $this->groupid, 'user' => 1, 'tag' => 1);
$blog_listing = new blog_listing($filters);
$this->assertFalse(array_key_exists('site', $blog_listing->filters));
$this->assertFalse(array_key_exists('course', $blog_listing->filters));
$this->assertFalse(array_key_exists('group', $blog_listing->filters));
$this->assertTrue(array_key_exists('module', $blog_listing->filters));
$this->assertTrue(array_key_exists('user', $blog_listing->filters));
$this->assertTrue(array_key_exists('tag', $blog_listing->filters));
// We should get the same result by removing the 3 inactive filters: site, course and group:
$filters = array('module' => 1, 'user' => 1, 'tag' => 1);
$blog_listing = new blog_listing($filters);
$this->assertFalse(array_key_exists('site', $blog_listing->filters));
$this->assertFalse(array_key_exists('course', $blog_listing->filters));
$this->assertFalse(array_key_exists('group', $blog_listing->filters));
$this->assertTrue(array_key_exists('module', $blog_listing->filters));
$this->assertTrue(array_key_exists('user', $blog_listing->filters));
$this->assertTrue(array_key_exists('tag', $blog_listing->filters));
}
// The following series of 'test_blog..' functions correspond to the blog_get_headers() function within blog/lib.php.
// Some cases are omitted due to the optional_param variables used.
public function test_blog_get_headers_case_1() {
global $CFG, $PAGE, $OUTPUT;
$blog_headers = blog_get_headers();
$this->assertEquals($blog_headers['heading'], get_string('siteblog', 'blog', 'phpunit'));
}
public function test_blog_get_headers_case_6() {
global $CFG, $PAGE, $OUTPUT;
$blog_headers = blog_get_headers($this->courseid, NULL, $this->userid);
$this->assertNotEquals($blog_headers['heading'], '');
}
public function test_blog_get_headers_case_7() {
global $CFG, $PAGE, $OUTPUT;
$blog_headers = blog_get_headers(NULL, 1);
$this->assertNotEquals($blog_headers['heading'], '');
}
public function test_blog_get_headers_case_10() {
global $CFG, $PAGE, $OUTPUT;
$blog_headers = blog_get_headers($this->courseid);
$this->assertNotEquals($blog_headers['heading'], '');
}
}
+6
View File
@@ -490,6 +490,12 @@ $CFG->admin = 'admin';
// $CFG->phpunit_prefix = 'phpu_';
// $CFG->phpunit_dataroot = '/home/example/phpu_moodledata';
// $CFG->phpunit_directorypermissions = 02777; // optional
// $CFG->phpunit_extra_drivers = array(
// 1=>array('dbtype'=>'mysqli', 'dbhost'=>'localhost', 'dbname'=>'moodle', 'dbuser'=>'root', 'dbpass'=>'', 'prefix'=>'phpu2_'),
// 2=>array('dbtype'=>'pgsql', 'dbhost'=>'localhost', 'dbname'=>'moodle', 'dbuser'=>'postgres', 'dbpass'=>'', 'prefix'=>'phpu2_'),
// 3=>array('dbtype'=>'sqlsrv', 'dbhost'=>'127.0.0.1', 'dbname'=>'moodle', 'dbuser'=>'sa', 'dbpass'=>'', 'prefix'=>'phpu2_'),
// 4=>array('dbtype'=>'oci', 'dbhost'=>'127.0.0.1', 'dbname'=>'XE', 'dbuser'=>'sa', 'dbpass'=>'', 'prefix'=>'t_'),
// ); // for database driver testing only, DB is selected via PHPUNIT_TEST_DRIVER=n
//=========================================================================
// ALL DONE! To continue installation, visit your main page with a browser
+99
View File
@@ -0,0 +1,99 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course related unit tests
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
class courselib_testcase extends advanced_testcase {
public function test_reorder_sections() {
global $DB;
$this->resetAfterTest(true);
$this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
$course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
$oldsections = array();
$sections = array();
foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
$oldsections[$section->section] = $section->id;
$sections[$section->id] = $section->section;
}
ksort($oldsections);
$neworder = reorder_sections($sections, 2, 4);
$neworder = array_keys($neworder);
$this->assertEquals($oldsections[0], $neworder[0]);
$this->assertEquals($oldsections[1], $neworder[1]);
$this->assertEquals($oldsections[2], $neworder[4]);
$this->assertEquals($oldsections[3], $neworder[2]);
$this->assertEquals($oldsections[4], $neworder[3]);
$this->assertEquals($oldsections[5], $neworder[5]);
$this->assertEquals($oldsections[6], $neworder[6]);
$neworder = reorder_sections(1, 2, 4);
$this->assertFalse($neworder);
}
public function test_move_section() {
global $DB;
$this->resetAfterTest(true);
$this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
$course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
$oldsections = array();
foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
$oldsections[$section->section] = $section->id;
}
ksort($oldsections);
move_section_to($course, 2, 4);
$sections = array();
foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
$sections[$section->section] = $section->id;
}
ksort($sections);
$this->assertEquals($oldsections[0], $sections[0]);
$this->assertEquals($oldsections[1], $sections[1]);
$this->assertEquals($oldsections[2], $sections[4]);
$this->assertEquals($oldsections[3], $sections[2]);
$this->assertEquals($oldsections[4], $sections[3]);
$this->assertEquals($oldsections[5], $sections[5]);
$this->assertEquals($oldsections[6], $sections[6]);
}
public function test_get_course_display_name_for_list() {
global $CFG;
$this->resetAfterTest(true);
$course = $this->getDataGenerator()->create_course(array('shortname' => 'FROG101', 'fullname' => 'Introduction to pond life'));
$CFG->courselistshortnames = 0;
$this->assertEquals('Introduction to pond life', get_course_display_name_for_list($course));
$CFG->courselistshortnames = 1;
$this->assertEquals('FROG101 Introduction to pond life', get_course_display_name_for_list($course));
}
}
+111
View File
@@ -0,0 +1,111 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit test for the filter_mediaplugin
*
* @package filter_mediaplugin
* @category phpunit
* @copyright 2011 Rossiani Wijaya <rwijaya@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/filter/mediaplugin/filter.php'); // Include the code to test
class filter_mediaplugin_testcase extends advanced_testcase {
function test_filter_mediaplugin_link() {
global $CFG;
$this->resetAfterTest(true);
// we need to enable the plugins somehow
$CFG->filter_mediaplugin_enable_youtube = 1;
$CFG->filter_mediaplugin_enable_vimeo = 1;
$CFG->filter_mediaplugin_enable_mp3 = 1;
$CFG->filter_mediaplugin_enable_flv = 1;
$CFG->filter_mediaplugin_enable_swf = 1;
$CFG->filter_mediaplugin_enable_html5audio = 1;
$CFG->filter_mediaplugin_enable_html5video = 1;
$CFG->filter_mediaplugin_enable_qt = 1;
$CFG->filter_mediaplugin_enable_wmp = 1;
$CFG->filter_mediaplugin_enable_rm = 1;
$filterplugin = new filter_mediaplugin(null, array());
$validtexts = array (
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
'<a href="http://moodle.org/testfile/test.ogg">test ogg</a>',
'<a id="movie player" class="center" href="http://moodle.org/testfile/test.mpg">test mpg</a>',
'<a href="http://moodle.org/testfile/test.ram">test</a>',
'<a href="http://www.youtube.com/watch?v=JghQgA2HMX8" class="href=css">test file</a>',
'<a class="youtube" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
'<a class="_blanktarget" href="http://moodle.org/testfile/test.flv?d=100x100">test flv</a>',
'<a class="hrefcss" href="http://www.youtube.com/watch?v=JghQgA2HMX8">test file</a>',
'<a class="content" href="http://moodle.org/testfile/test.avi">test mp3</a>',
'<a id="audio" href="http://moodle.org/testfile/test.mp3">test mp3</a>',
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
'<a href="http://moodle.org/testfile/test.mp3">test mp3</a>',
'<a href="http://www.youtube.com/watch?v=JghQgA2HMX8?d=200x200">youtube\'s</a>',
'<a
href="http://moodle.org/testfile/test.mp3">
test mp3</a>',
'<a class="content"
href="http://moodle.org/testfile/test.avi">test mp3
</a>',
'<a href="http://www.youtube.com/watch?v=JghQgA2HMX8?d=200x200" >youtube\'s</a>'
);
//test for valid link
foreach ($validtexts as $text) {
$msg = "Testing text: ". $text;
$filter = $filterplugin->filter($text);
$this->assertNotEquals($text, $filter, $msg);
}
$invalidtexts = array(
'<a class="_blanktarget">href="http://moodle.org/testfile/test.mp3"</a>',
'<a>test test</a>',
'<a >test test</a>',
'<a >test test</a>',
'<a >test test</a>',
'<ahref="http://moodle.org/testfile/test.mp3">sample</a>',
'<a href="" test></a>',
'<a href="http://www.moodle.com/path/to?#param=29">test</a>',
'<a href="http://moodle.org/testfile/test.mp3">test mp3',
'<a href="http://moodle.org/testfile/test.mp3"test</a>',
'<a href="http://moodle.org/testfile/">test</a>',
'<href="http://moodle.org/testfile/test.avi">test</a>',
'<abbr href="http://moodle.org/testfile/test.mp3">test mp3</abbr>',
'<ahref="http://moodle.org/testfile/test.mp3">test mp3</a>',
'<aclass="content" href="http://moodle.org/testfile/test.mp3">test mp3</a>'
);
//test for invalid link
foreach ($invalidtexts as $text) {
$msg = "Testing text: ". $text;
$filter = $filterplugin->filter($text);
$this->assertEquals($text, $filter, $msg);
}
}
}
+200
View File
@@ -0,0 +1,200 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit test for the filter_urltolink
*
* @package filter_urltolink
* @category phpunit
* @copyright 2010 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/filter/urltolink/filter.php'); // Include the code to test
class filter_urltolink_testcase extends basic_testcase {
/**
* Helper function that represents the legacy implementation
* of convert_urls_into_links()
*/
protected function old_convert_urls_into_links(&$text) {
/// Make lone URLs into links. eg http://moodle.com/
$text = preg_replace("%([[:space:]]|^|\(|\[)([[:alnum:]]+)://([^[:space:]]*)([[:alnum:]#?/&=])%i",
'$1<a href="$2://$3$4" target="_blank">$2://$3$4</a>', $text);
/// eg www.moodle.com
$text = preg_replace("%([[:space:]]|^|\(|\[)www\.([^[:space:]]*)([[:alnum:]#?/&=])%i",
'$1<a href="http://www.$2$3" target="_blank">www.$2$3</a>', $text);
}
function test_convert_urls_into_links() {
$texts = array (
//just a url
'http://moodle.org - URL' => '<a href="http://moodle.org" class="_blanktarget">http://moodle.org</a> - URL',
'www.moodle.org - URL' => '<a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a> - URL',
//url with params
'URL: http://moodle.org/s/i=1&j=2' => 'URL: <a href="http://moodle.org/s/i=1&j=2" class="_blanktarget">http://moodle.org/s/i=1&j=2</a>',
//url with escaped params
'URL: www.moodle.org/s/i=1&amp;j=2' => 'URL: <a href="http://www.moodle.org/s/i=1&amp;j=2" class="_blanktarget">www.moodle.org/s/i=1&amp;j=2</a>',
//https url with params
'URL: https://moodle.org/s/i=1&j=2' => 'URL: <a href="https://moodle.org/s/i=1&j=2" class="_blanktarget">https://moodle.org/s/i=1&j=2</a>',
//url with port and params
'URL: http://moodle.org:8080/s/i=1' => 'URL: <a href="http://moodle.org:8080/s/i=1" class="_blanktarget">http://moodle.org:8080/s/i=1</a>',
//url in brackets
'(http://moodle.org) - URL' => '(<a href="http://moodle.org" class="_blanktarget">http://moodle.org</a>) - URL',
'(www.moodle.org) - URL' => '(<a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a>) - URL',
//url in square brackets
'[http://moodle.org] - URL' => '[<a href="http://moodle.org" class="_blanktarget">http://moodle.org</a>] - URL',
'[www.moodle.org] - URL' => '[<a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a>] - URL',
//url in brackets with anchor
'[http://moodle.org/main#anchor] - URL' => '[<a href="http://moodle.org/main#anchor" class="_blanktarget">http://moodle.org/main#anchor</a>] - URL',
'[www.moodle.org/main#anchor] - URL' => '[<a href="http://www.moodle.org/main#anchor" class="_blanktarget">www.moodle.org/main#anchor</a>] - URL',
//brackets within the url
'URL: http://cc.org/url_(withpar)_go/?i=2' => 'URL: <a href="http://cc.org/url_(withpar)_go/?i=2" class="_blanktarget">http://cc.org/url_(withpar)_go/?i=2</a>',
'URL: www.cc.org/url_(withpar)_go/?i=2' => 'URL: <a href="http://www.cc.org/url_(withpar)_go/?i=2" class="_blanktarget">www.cc.org/url_(withpar)_go/?i=2</a>',
'URL: http://cc.org/url_(with)_(par)_go/?i=2' => 'URL: <a href="http://cc.org/url_(with)_(par)_go/?i=2" class="_blanktarget">http://cc.org/url_(with)_(par)_go/?i=2</a>',
'URL: www.cc.org/url_(with)_(par)_go/?i=2' => 'URL: <a href="http://www.cc.org/url_(with)_(par)_go/?i=2" class="_blanktarget">www.cc.org/url_(with)_(par)_go/?i=2</a>',
'http://en.wikipedia.org/wiki/Slash_(punctuation)'=>'<a href="http://en.wikipedia.org/wiki/Slash_(punctuation)" class="_blanktarget">http://en.wikipedia.org/wiki/Slash_(punctuation)</a>',
'http://en.wikipedia.org/wiki/%28#Parentheses_.28_.29 - URL' => '<a href="http://en.wikipedia.org/wiki/%28#Parentheses_.28_.29" class="_blanktarget">http://en.wikipedia.org/wiki/%28#Parentheses_.28_.29</a> - URL',
'http://en.wikipedia.org/wiki/(#Parentheses_.28_.29 - URL' => '<a href="http://en.wikipedia.org/wiki/(#Parentheses_.28_.29" class="_blanktarget">http://en.wikipedia.org/wiki/(#Parentheses_.28_.29</a> - URL',
//escaped brackets in url
'http://en.wikipedia.org/wiki/Slash_%28punctuation%29'=>'<a href="http://en.wikipedia.org/wiki/Slash_%28punctuation%29" class="_blanktarget">http://en.wikipedia.org/wiki/Slash_%28punctuation%29</a>',
//anchor tag
'URL: <a href="http://moodle.org">http://moodle.org</a>' => 'URL: <a href="http://moodle.org">http://moodle.org</a>',
'URL: <a href="http://moodle.org">www.moodle.org</a>' => 'URL: <a href="http://moodle.org">www.moodle.org</a>',
'URL: <a href="http://moodle.org"> http://moodle.org</a>' => 'URL: <a href="http://moodle.org"> http://moodle.org</a>',
'URL: <a href="http://moodle.org"> www.moodle.org</a>' => 'URL: <a href="http://moodle.org"> www.moodle.org</a>',
//escaped anchor tag. Commented out as part of MDL-21183
//htmlspecialchars('escaped anchor tag <a href="http://moodle.org">www.moodle.org</a>') => 'escaped anchor tag &lt;a href="http://moodle.org"&gt; www.moodle.org&lt;/a&gt;',
//trailing fullstop
'URL: http://moodle.org/s/i=1&j=2.' => 'URL: <a href="http://moodle.org/s/i=1&j=2" class="_blanktarget">http://moodle.org/s/i=1&j=2</a>.',
'URL: www.moodle.org/s/i=1&amp;j=2.' => 'URL: <a href="http://www.moodle.org/s/i=1&amp;j=2" class="_blanktarget">www.moodle.org/s/i=1&amp;j=2</a>.',
//trailing unmatched bracket
'URL: http://moodle.org)<br />' => 'URL: <a href="http://moodle.org" class="_blanktarget">http://moodle.org</a>)<br />',
//partially escaped html
'URL: <p>text www.moodle.org&lt;/p> text' => 'URL: <p>text <a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a>&lt;/p> text',
//decimal url parameter
'URL: www.moodle.org?u=1.23' => 'URL: <a href="http://www.moodle.org?u=1.23" class="_blanktarget">www.moodle.org?u=1.23</a>',
//escaped space in url
'URL: www.moodle.org?u=test+param&' => 'URL: <a href="http://www.moodle.org?u=test+param&" class="_blanktarget">www.moodle.org?u=test+param&</a>',
//odd characters in url param
'URL: www.moodle.org?param=:)' => 'URL: <a href="http://www.moodle.org?param=:)" class="_blanktarget">www.moodle.org?param=:)</a>',
//multiple urls
'URL: http://moodle.org www.moodle.org'
=> 'URL: <a href="http://moodle.org" class="_blanktarget">http://moodle.org</a> <a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a>',
//containing anchor tags including a class parameter and a url to convert
'URL: <a href="http://moodle.org">http://moodle.org</a> www.moodle.org <a class="customclass" href="http://moodle.org">http://moodle.org</a>'
=> 'URL: <a href="http://moodle.org">http://moodle.org</a> <a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a> <a class="customclass" href="http://moodle.org">http://moodle.org</a>',
//subdomain
'http://subdomain.moodle.org - URL' => '<a href="http://subdomain.moodle.org" class="_blanktarget">http://subdomain.moodle.org</a> - URL',
//multiple subdomains
'http://subdomain.subdomain.moodle.org - URL' => '<a href="http://subdomain.subdomain.moodle.org" class="_blanktarget">http://subdomain.subdomain.moodle.org</a> - URL',
//looks almost like a link but isnt
'This contains http, http:// and www but no actual links.'=>'This contains http, http:// and www but no actual links.',
//no link at all
'This is a story about moodle.coming to a cinema near you.'=>'This is a story about moodle.coming to a cinema near you.',
//URLs containing utf 8 characters
'http://Iñtërnâtiônàlizætiøn.com?ô=nëø'=>'<a href="http://Iñtërnâtiônàlizætiøn.com?ô=nëø" class="_blanktarget">http://Iñtërnâtiônàlizætiøn.com?ô=nëø</a>',
'www.Iñtërnâtiônàlizætiøn.com?ô=nëø'=>'<a href="http://www.Iñtërnâtiônàlizætiøn.com?ô=nëø" class="_blanktarget">www.Iñtërnâtiônàlizætiøn.com?ô=nëø</a>',
//text containing utf 8 characters outside of a url
'Iñtërnâtiônàlizætiøn is important to http://moodle.org'=>'Iñtërnâtiônàlizætiøn is important to <a href="http://moodle.org" class="_blanktarget">http://moodle.org</a>',
//too hard to identify without additional regexs
'moodle.org' => 'moodle.org',
//some text with no link between related html tags
'<b>no link here</b>' => '<b>no link here</b>',
//some text with a link between related html tags
'<b>a link here www.moodle.org</b>' => '<b>a link here <a href="http://www.moodle.org" class="_blanktarget">www.moodle.org</a></b>',
//some text containing a link within unrelated tags
'<br />This is some text. www.moodle.com then some more text<br />' => '<br />This is some text. <a href="http://www.moodle.com" class="_blanktarget">www.moodle.com</a> then some more text<br />',
//check we aren't modifying img tags
'image<img src="http://moodle.org/logo/logo-240x60.gif" />' => 'image<img src="http://moodle.org/logo/logo-240x60.gif" />',
'image<img src="www.moodle.org/logo/logo-240x60.gif" />' => 'image<img src="www.moodle.org/logo/logo-240x60.gif" />',
//and another url within one tag
'<td background="http://moodle.org">&nbsp;</td>' => '<td background="http://moodle.org">&nbsp;</td>',
'<td background="www.moodle.org">&nbsp;</td>' => '<td background="www.moodle.org">&nbsp;</td>',
'<form name="input" action="http://moodle.org/submit.asp" method="get">'=>'<form name="input" action="http://moodle.org/submit.asp" method="get">',
//partially escaped img tag
'partially escaped img tag &lt;img src="http://moodle.org/logo/logo-240x60.gif" />' => 'partially escaped img tag &lt;img src="http://moodle.org/logo/logo-240x60.gif" />',
//fully escaped img tag. Commented out as part of MDL-21183
//htmlspecialchars('fully escaped img tag <img src="http://moodle.org/logo/logo-240x60.gif" />') => 'fully escaped img tag &lt;img src="http://moodle.org/logo/logo-240x60.gif" /&gt;',
//Double http with www
'One more link like http://www.moodle.org to test' => 'One more link like <a href="http://www.moodle.org" class="_blanktarget">http://www.moodle.org</a> to test',
//Encoded URLs in the path
'URL: http://127.0.0.1/one%28parenthesis%29/path?param=value' => 'URL: <a href="http://127.0.0.1/one%28parenthesis%29/path?param=value" class="_blanktarget">http://127.0.0.1/one%28parenthesis%29/path?param=value</a>',
'URL: www.localhost.com/one%28parenthesis%29/path?param=value' => 'URL: <a href="http://www.localhost.com/one%28parenthesis%29/path?param=value" class="_blanktarget">www.localhost.com/one%28parenthesis%29/path?param=value</a>',
//Encoded URLs in the query
'URL: http://127.0.0.1/path/to?param=value_with%28parenthesis%29&param2=1' => 'URL: <a href="http://127.0.0.1/path/to?param=value_with%28parenthesis%29&param2=1" class="_blanktarget">http://127.0.0.1/path/to?param=value_with%28parenthesis%29&param2=1</a>',
'URL: www.localhost.com/path/to?param=value_with%28parenthesis%29&param2=1' => 'URL: <a href="http://www.localhost.com/path/to?param=value_with%28parenthesis%29&param2=1" class="_blanktarget">www.localhost.com/path/to?param=value_with%28parenthesis%29&param2=1</a>',
//URLs in Javascript. Commented out as part of MDL-21183
//'var url="http://moodle.org";'=>'var url="http://moodle.org";',
//'var url = "http://moodle.org";'=>'var url = "http://moodle.org";',
//'var url="www.moodle.org";'=>'var url="www.moodle.org";',
//'var url = "www.moodle.org";'=>'var url = "www.moodle.org";',
//doctype. do we care about this failing?
//'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN http://www.w3.org/TR/html4/strict.dtd">'=>'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN http://www.w3.org/TR/html4/strict.dtd">'
);
$testablefilter = new testable_filter_urltolink();
foreach ($texts as $text => $correctresult) {
$msg = "Testing text: ". str_replace('%', '%%', $text) . ": %s"; // Escape original '%' so sprintf() wont get confused
$testablefilter->convert_urls_into_links($text);
$this->assertEquals($text, $correctresult, $msg);
}
//performance testing
$reps = 1000;
$text = file_get_contents(__DIR__ . '/fixtures/sample.txt');
$time_start = microtime(true);
for($i=0;$i<$reps;$i++) {
$testablefilter->convert_urls_into_links($text);
}
$time_end = microtime(true);
$new_time = $time_end - $time_start;
$time_start = microtime(true);
for($i=0;$i<$reps;$i++) {
$this->old_convert_urls_into_links($text);
}
$time_end = microtime(true);
$old_time = $time_end - $time_start;
$fast_enough = false;
if( $new_time < $old_time ) {
$fast_enough = true;
}
$this->assertEquals($fast_enough, true, 'Timing test: ' . $new_time . 'secs (new) < ' . $old_time . 'secs (old)');
}
}
/**
* Test subclass that makes all the protected methods we want to test public.
*/
class testable_filter_urltolink extends filter_urltolink {
public function __construct() {
}
public function convert_urls_into_links(&$text) {
parent::convert_urls_into_links($text);
}
}
+16
View File
@@ -0,0 +1,16 @@
http://www.lipsum.com
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
Why do we use it?<a href="dummylink.htm">dummy</a>
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
Where does it come from?
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
Where can I get some?
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
<a href="http://en.wikipedia.org/wiki/Lorem_ipsum">Wikipedia</a>
http://www.lorem-ipsum.info/
+138
View File
@@ -0,0 +1,138 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the advanced grading subsystem
*
* @package core
* @subpackage grading
* @category phpunit
* @copyright 2011 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/grade/grading/lib.php'); // Include the code to test
/**
* Makes protected method accessible for testing purposes
*/
class testable_grading_manager extends grading_manager {
}
/**
* Test cases for the grading manager API
*/
class grading_manager_testcase extends advanced_testcase {
public function test_basic_instantiation() {
$manager1 = get_grading_manager();
$fakecontext = (object)array(
'id' => 42,
'contextlevel' => CONTEXT_MODULE,
'instanceid' => 22,
'path' => '/1/3/15/42',
'depth' => 4);
$manager2 = get_grading_manager($fakecontext);
$manager3 = get_grading_manager($fakecontext, 'assignment_upload');
$manager4 = get_grading_manager($fakecontext, 'assignment_upload', 'submission');
}
public function test_set_and_get_grading_area() {
global $DB;
$this->resetAfterTest(true);
//sleep(2); // to make sure the microtime will always return unique values // No sleeping in tests!!! --skodak
$areaname1 = 'area1-' . (string)microtime(true);
$areaname2 = 'area2-' . (string)microtime(true);
$fakecontext = (object)array(
'id' => 42,
'contextlevel' => CONTEXT_MODULE,
'instanceid' => 22,
'path' => '/1/3/15/42',
'depth' => 4);
// non-existing area
$gradingman = get_grading_manager($fakecontext, 'mod_foobar', $areaname1);
$this->assertNull($gradingman->get_active_method());
// creates area implicitly and sets active method
$this->assertTrue($gradingman->set_active_method('rubric'));
$this->assertEquals('rubric', $gradingman->get_active_method());
// repeat setting of already set active method
$this->assertFalse($gradingman->set_active_method('rubric'));
// switch the manager to another area
$gradingman->set_area($areaname2);
$this->assertNull($gradingman->get_active_method());
// switch back and ask again
$gradingman->set_area($areaname1);
$this->assertEquals('rubric', $gradingman->get_active_method());
// attempting to set an invalid method
$this->setExpectedException('moodle_exception');
$gradingman->set_active_method('no_one_should_ever_try_to_implement_a_method_with_this_silly_name');
}
public function test_tokenize() {
$UTFfailuremessage = 'A test using UTF-8 characters has failed. Consider updating PHP and PHP\'s PCRE or INTL extensions (MDL-30494)';
$needle = " šašek, \n\n \r a král; \t";
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEquals(2, count($tokens), $UTFfailuremessage);
$this->assertTrue(in_array('šašek', $tokens), $UTFfailuremessage);
$this->assertTrue(in_array('král', $tokens), $UTFfailuremessage);
$needle = ' " šašek a král " ';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEquals(1, count($tokens));
$this->assertTrue(in_array('šašek a král', $tokens));
$needle = '""';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertTrue(empty($tokens));
$needle = '"0"';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEquals(1, count($tokens));
$this->assertTrue(in_array('0', $tokens));
$needle = '<span>Aha</span>, then who\'s a bad guy here he?';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEquals(8, count($tokens));
$this->assertTrue(in_array('span', $tokens)); // Extracted the tag name
$this->assertTrue(in_array('Aha', $tokens));
$this->assertTrue(in_array('who', $tokens)); // Removed the trailing 's
$this->assertTrue(!in_array('a', $tokens)); //Single letter token was dropped
$this->assertTrue(in_array('he', $tokens)); // Removed the trailing ?
$needle = 'grammar, "english language"';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertTrue(in_array('grammar', $tokens));
$this->assertTrue(in_array('english', $tokens));
$this->assertTrue(in_array('language', $tokens));
$this->assertTrue(!in_array('english language', $tokens)); // Quoting part of the string is not supported
}
}
-48
View File
@@ -1,48 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for grade/report/lib.php.
*
* @author nicolas@moodle.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodlecore
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->dirroot.'/grade/report/lib.php');
/**
* @TODO create a set of mock objects to simulate the database operations. We don't want to connect to any real sql server.
*/
class gradereportlib_test extends UnitTestCaseUsingDatabase {
var $courseid = 1;
var $context = null;
var $report = null;
public static $includecoverage = array('grade/report/lib.php');
function setUp() {
//$this->report = new grade_report($this->courseid, $this->context);
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for grade/edit/tree/lib.php.
*
* @pacakge core_grade
* @category phpunit
* @author Andrew Davis
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot.'/grade/edit/tree/lib.php');
/**
* Tests grade_edit_tree (deals with the data on the categories and items page in the gradebook)
*/
class gradeedittreelib_testcase extends basic_testcase {
var $courseid = 1;
var $context = null;
var $grade_edit_tree = null;
public function test_format_number() {
$numinput = array( 0, 1, 1.01, '1.010', 1.2345);
$numoutput = array(0.0, 1.0, 1.01, 1.01, 1.2345);
for ($i=0; $i<sizeof($numinput); $i++) {
$msg = 'format_number() testing '.$numinput[$i].' %s';
$this->assertEquals(grade_edit_tree::format_number($numinput[$i]),$numoutput[$i],$msg);
}
}
}
+1 -1
View File
@@ -217,7 +217,7 @@ $ACCESSLIB_PRIVATE->capabilities = null; // detailed information about th
*/
function accesslib_clear_all_caches_for_unit_testing() {
global $UNITTEST, $USER;
if (empty($UNITTEST->running) and !PHPUNITTEST) {
if (empty($UNITTEST->running) and !PHPUNIT_TEST) {
throw new coding_exception('You must not call clear_all_caches outside of unit tests.');
}
+131
View File
@@ -0,0 +1,131 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for (some of) ../ajaxlib.php.
*
* @package core
* @category phpunit
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/ajax/ajaxlib.php');
/**
* Unit tests for ../ajaxlib.php functions.
*
* @copyright 2008 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class ajax_testcase extends advanced_testcase {
var $user_agents = array(
'MSIE' => array(
'5.5' => array('Windows 2000' => 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)'),
'6.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'),
'7.0' => array('Windows XP SP2' => 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; YPC 3.0.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)')
),
'Firefox' => array(
'1.0.6' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6'),
'1.5' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; nl; rv:1.8) Gecko/20051107 Firefox/1.5'),
'1.5.0.1' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1'),
'2.0' => array('Windows XP' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1',
'Ubuntu Linux AMD64' => 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.8.1) Gecko/20060601 Firefox/2.0 (Ubuntu-edgy)')
),
'Safari' => array(
'312' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312'),
'2.0' => array('Mac OS X' => 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/412 (KHTML, like Gecko) Safari/412')
),
'Opera' => array(
'8.51' => array('Windows XP' => 'Opera/8.51 (Windows NT 5.1; U; en)'),
'9.0' => array('Windows XP' => 'Opera/9.0 (Windows NT 5.1; U; en)',
'Debian Linux' => 'Opera/9.01 (X11; Linux i686; U; en)')
)
);
/**
* Uses the array of user agents to test ajax_lib::ajaxenabled
*/
function test_ajaxenabled() {
global $CFG, $USER;
$this->resetAfterTest(true);
$CFG->enableajax = 1;
$USER->ajax = 1;
// Should be true
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
$this->assertTrue(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['1.5']['Windows XP'];
$this->assertTrue(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['2.0']['Mac OS X'];
$this->assertTrue(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
$this->assertTrue(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['6.0']['Windows XP SP2'];
$this->assertTrue(ajaxenabled());
// Should be false
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['1.0.6']['Windows XP'];
$this->assertFalse(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['312']['Mac OS X'];
$this->assertFalse(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['8.51']['Windows XP'];
$this->assertFalse(ajaxenabled());
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['5.5']['Windows 2000'];
$this->assertFalse(ajaxenabled());
// Test array of tested browsers
$tested_browsers = array('MSIE' => 6.0, 'Gecko' => 20061111);
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
$this->assertTrue(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['7.0']['Windows XP SP2'];
$this->assertTrue(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['2.0']['Mac OS X'];
$this->assertFalse(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
$this->assertFalse(ajaxenabled($tested_browsers));
$tested_browsers = array('Safari' => 412, 'Opera' => 9.0);
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Firefox']['2.0']['Windows XP'];
$this->assertFalse(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['MSIE']['7.0']['Windows XP SP2'];
$this->assertFalse(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Safari']['2.0']['Mac OS X'];
$this->assertTrue(ajaxenabled($tested_browsers));
$_SERVER['HTTP_USER_AGENT'] = $this->user_agents['Opera']['9.0']['Windows XP'];
$this->assertTrue(ajaxenabled($tested_browsers));
}
}
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/ddl/simpletest/fixtures" VERSION="20120122" COMMENT="This is an invalid xml file used for testing.">
<TABLES>
<TABLE NAME="test_table1" COMMENT="Just a test table">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="incorrect_next_field"/> <!-- invalid because of NEXT value -->
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
<FIELD NAME="name" TYPE="char" LENGTH="30" NOTNULL="false" SEQUENCE="false" DEFAULT="Moodle" PREVIOUS="course" NEXT="secondname"/>
<FIELD NAME="secondname" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false" PREVIOUS="name" NEXT="intro"/>
<FIELD NAME="intro" TYPE="text" LENGTH="medium" NOTNULL="true" SEQUENCE="false" PREVIOUS="secondname" NEXT="avatar"/>
<FIELD NAME="avatar" TYPE="binary" LENGTH="medium" NOTNULL="false" SEQUENCE="false" PREVIOUS="intro" NEXT="grade"/>
<FIELD NAME="grade" TYPE="number" LENGTH="20" DECIMALS="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="avatar"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/ddl/simpletest/fixtures" VERSION="20120122" COMMENT="XMLDB file DLL unit tests">
<TABLES>
<TABLE NAME="test_table1" COMMENT="Just a test table">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="course"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
<FIELD NAME="name" TYPE="char" LENGTH="30" NOTNULL="false" SEQUENCE="false" DEFAULT="Moodle" PREVIOUS="course" NEXT="secondname"/>
<FIELD NAME="secondname" TYPE="char" LENGTH="30" NOTNULL="true" SEQUENCE="false" PREVIOUS="name" NEXT="intro"/>
<FIELD NAME="intro" TYPE="text" LENGTH="medium" NOTNULL="true" SEQUENCE="false" PREVIOUS="secondname" NEXT="avatar"/>
<FIELD NAME="avatar" TYPE="binary" LENGTH="medium" NOTNULL="false" UNSIGNED="false" SEQUENCE="false" PREVIOUS="intro" NEXT="grade"/>
<FIELD NAME="grade" TYPE="number" LENGTH="20" DECIMALS="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="avatar"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
+5 -1
View File
@@ -410,7 +410,11 @@ class mysqli_native_moodle_database extends moodle_database {
$sql = "SHOW INDEXES FROM {$this->prefix}$table";
$this->query_start($sql, null, SQL_QUERY_AUX);
$result = $this->mysqli->query($sql);
$this->query_end($result);
try {
$this->query_end($result);
} catch (dml_read_exception $e) {
return $indexes; // table does not exist - no indexes...
}
if ($result) {
while ($res = $result->fetch_object()) {
if ($res->Key_name === 'PRIMARY') {
File diff suppressed because it is too large Load Diff
+197
View File
@@ -0,0 +1,197 @@
제 1장 총 칙
제 1조 (개요)
이 약관은 전기통신사업법 및 동법 시행령에 의거 ㈜네오플(이하 "회사")이 제공하는 서비스 (이하 "서비스")의 이용조건, 절차, 의무, 책임사항 및 이용에 필요한 기타사항을 규정합니다.
제 2조 (목적)
이 약관은 다음과 같은 내용을 목적으로 합니다.
1. 안정적인 서비스 제공 및 서비스, 시스템의 보호를 목적으로 한다.
2. 이용자의 안정적인 서비스 이용 및 이용자의 데이타 보호를 목적으로 한다.
3. 네트워크 및 서비스 이용자 네트워크의 안정성, 프라이버시, 보안성 유지를 목적으로 한다.
4. 네트워크 및 서비스의 사용 원칙 가이드라인 제시를 목적으로 한다.
제 3조 (약관의 효력과 변경)
1. 회사는 귀하가 본 약관 내용에 동의하는 것을 조건으로 서비스를 제공 합니다.
2. 이 약관은 서비스 내에 게시하여 공시함으로써 효력을 발생합니다.
3. 당사의 서비스 제공 행위 및 귀하의 서비스 사용 행위에는 본 약관이 우선적으로 적용될 것입니다.
4. 회사는 이 약관을 개정할 경우에는 적용일자 및 개정사유를 명시하여 현행약관과 함께 초기화면에 그 적용일자 7일이전부터 적용일자 전일까지 공지합니다.
5. 이용자는 회원등록을 취소(회원탈퇴)할 수 있으며, 계속 사용의 경우는 약관 변경에 대한 동의로 간주됩니다. 변경된 약관은 공지와 동시에 그 효력이 발생됩니다.
제 4조 (약관외 준칙)
1. 서비스 이용에 관하여는 이 약관을 적용하며, 이 약관에 명시되지 아니 한 사항에 대하여는 전기통신 기본법, 전기통신사업법, 정보통신망 이용 촉진 및 정보보호 등에 관한 법률(이하통신망법), 기타 관련법령 및 회사의 공지,이용안내를 적용 합니다.
2. 이 약관의 공지 및 변경사항은 회사의 지정된 홈페이지(http://www.candybar.co.kr)에 게시하는 방법으로 공지합니다.
제 5조 (용어의 정의)
이 약관에서 사용하는 용어의 정의는 다음과 같습니다.
1. 이용자 : 서비스 이용을 신청하고 회사가 이를 승낙하여 회원ID를 발급 받은 자를 말합니다.
2. 가 입 : 회사가 제공하는 양식에 해당 정보를 기입하고, 이 약관에 동의하여 서비스 이용계약을 완료시키는 행위를 말합니다.
3. 회 원 : 회사에 개인 정보를 제공하여 회원 등록을 한 자로서, 회사가 제공하는 서비스를 이용할 수 있는 자를 말합니다.
4. 캔디바 ID : 회원의 서비스 이용을 위하여 회원이 신청하고 회사가 승인하는 문자 및 숫자의 조합을 말합니다.
5. 비밀번호 : 회원ID가 일치하는지를 확인하고 자신의 비밀보호를 위하여 이용자 자신이 선정한 문자와 숫자의 조합을 말합니다.
6. 탈퇴 및 해지 : 회원이 이용계약을 종료 시키는 행위를 말합니다.
제 2장 서비스 이용 계약
제 6조 (이용 계약의 성립)
1. 이용계약은 당사 소정의 가입신청 양식에서 요구하는 사항을 기록하여 가입을 완료 하는것으로 성립함을 원칙으로 합니다.
2. 이용신청은 이용신청자 자신의 실명으로 하여야 합니다. 실명이 아닌경우는 여러가지 불이익을 받을수 도 있습니다.
3. 이용계약은 서비스 이용희망자의 이용약관 동의 후 이용 신청에 대하여 회사가 승낙함으로써 성립합니다.
4. 서비스 이용 희망자가 14세 미만의 미성년자 또는 한정치산자인 경우 부모등 법정대리인의 동의를 받아 이용신청하며 납입책임자는 법정대리인으로 합니다. 또한 금치산자인 경우에는 법정대리인 을 이용자 및 납입책임자로 하여 신청합니다.
제 7조 (이용신청의 승낙)
1. 회사는 제 6조의 규정에 의한 서비스 이용희망자에 대하여 업무수행상 또는 기술상 지장이 없는 경우에는 원칙적으로 접수순서에 따라 이용신청을 승낙합니다.
2. 이용자의 이용신청에 대하여 회사가 이를 승낙한 경우, 회사는 회원 ID와 기타 회사가 필요하다고 인정하는 내용을 이용자에게 통지합니다.
제 8조 (이용신청에 대한 불승낙과 승낙의 보류)
1. 이용자가 신청한 이용 아이디(ID)가 이미 다른 이용자에 의해 쓰여지고 있는 경우 승낙을 하지 아니할 수 있습니다.
2. 회사는 다음 각호에 해당하는 이용신청에 대하여는 승낙을 하지 아니할 수 있습니다.
1) 타인 명의의 신청
2) 허위의 신청이거나 허위사실을 기재한 경우 예) 주민등록 생성기를 이용한 비실명 가입
3) 기타 이용신청고객의 귀책사유로 이용승낙이 곤란한 경우
3. 회사는 전항의 경우에는 이를 이용신청고객에게 가능한 빠른 시일 내에 통지하여야 합니다.
4. 회사는 이용신청고객이 미성년자, 한정치산자인 경우에 법정대리인(부모 등)의 동의없는 이용신청에 대하여 승낙을 보류할 수 있습니다.
5. 회사는 이용신청이 불승낙되거나 승낙을 제한하는 경우에는 이를 이용신청자에게 즉시 통보합니다.
제 9조 (이용 아이디 관리 및 변경)
1. 이용 아이디(ID) 및 비밀번호에 대한 모든 관리책임은 이용자에게 있습니다.
2. 이용 아이디(ID)는 다음에 해당하는 경우에는 이용자와 합의하여 변경할 수 있습니다.
(단, 이용 아이디(ID)를 변경할 경우 기존 이용ID는 소멸됩니다.)
1) 이용 아이디(ID)가 이용자의 전화번호 또는 주민등록번호 등으로 등록되어 사생활 침해가 우려 되는 경우
2) 타인에게 혐오감을 주거나 미풍양속에 어긋나는 경우
3) 기타 회사가 인정하는 합리적인 사유가 있는 경우
3. 회사는 이용 아이디(ID)에 의하여 서비스 이용요금 청구 및 게시판 관리 등 제반 이용자 관리 업무를 수행하며 이용자는 이용 아이디(ID)를 공유, 양도 또는 변경할 수 없습니다. 단, 그 사유가 명백하고 회사가 인정하는 경우에는 그러하지 아니 합니다.
4. 이용자가 신청 또는 변경하여 사용하는 이용 아이디(ID) 및 비밀번호에 의하여 발생하는 서비스 이용상의 과실 또는 제3자에 의한 부정사용등에 대한 모든 책임은 이용자에게 있습니다. 단, 회사의 고의 또는 중대한 과실이 있는 경우에는 그러하지 아니합니다.
5. 기타 아이디의 관리 및 변경 등에 관한 사항은 이 약관과 회사의 공지, 이용안내 에서 정하는 바에 의합니다.
제 3장 계약당사자의 의무 및 책임
제 10조 (회사의 의무)
1. 회사는 이용자로부터 제기되는 의견이나 불만이 정당하다고 인정할 경우에는 즉시 처리하여야 합니다. 즉시 처리가 곤란한 경우에는 그 사유와 처리일정을 서면 또는 전화 등으로 통보합니다.
2. 회사는 서비스 제공과 관련하여 취득한 이용자의 정보를 본인의 동의없이 타인에게 누설 배포할 수 없으며 서비스 관련 업무 이외의 목적으로도 사용할 수 없습니다.
3. 제2항의 경우 관계법령에 의한 규정에 의하여 수사상의 목적으로 관계기관으로부터 요구받은 경우나 정보통신윤리위원회의 요청이 있는 경우 또는 통신망법 24조 1항 '정보통신서비스의 제공에 따른 요금정산을 위하여 필요한 경우'에는 개인정보의 이용 혹은 제 3자에게 제공될수 있으며 그 범위는 회사의 개인정보보호정책을 따릅니다.
4. 회사는 계속적이고 안정적인 서비스 제공을 위하여 설비에 장애가 생기거나 멸실된 경우에는 지체없이 이를 수리 또는 복구하며, 서비스를 다시 이용할 수 있게 된 경우 이 사실을 이용자에게 통지하여야 합니다. 단 천재지변, 비상사태 또는 그밖의 부득이한 경우에는 서비스를 일시 중단하거나 중지할 수 있습니다.
5. 회사는 이용계약의 체결, 계약사항의 변경 및 해지 등 이용자와의 계약에 관련된 절차 및 내용 등에 있어서 이용자에게 편의를 제공하도록 노력합니다.
6. 회사는 이용자가 안전하게 당사서비스를 이용할 수 있도록 이용자의 개인정보(신용정보 포함)보호를 위한 보안시스템을 갖추어야 합니다.
7. 회사는 이용자가 제11조의 이용자의 의무를 위반한 경우 및 고의 또는 중대한 과실로 회사에 손해를 입힌 경우에는 사전 통보 없이 이용계약을 해지하거나 또는 기간을 정하여 서비스의 이용을 중지할 수 있습니다.
제 11 조 (이용자의 의무)
1. 이용자는 이 약관에서 규정하는 사항과 서비스 이용안내 또는 주의사항을 준수하여야 하며,기타 회사의 업무수행에 현저한 지장을 초래하는 행위를 하여서는 아니 됩니다.
2. 이용자는 서비스를 이용함에 있어 문제 발생소지 정보의 책임은 이용자에게 있습니다.
3. 이용자는 서비스를 이용하여 얻은 정보를 가공, 판매하는 행위 등 게재 된 자료를 상업적으로 이용할 수 없으며 이를 위반하여 발생하는 제반 문제에 대한 책임은 이용자에게 있습니다.
4. 이용자는 이용계약에 따라 요금을 지불하여야 하며, 서비스 이용요금의 미납으로 인하여 발생되는 모든 문제에 대한 책임은 이용자에게 있습니다. 단, 회사의 고의 또는 중과실의 경우에는 그러하지 아니 합니다.
5. 이용자는 회원가입시 정보는 정확하게 기입하여야 합니다. 주민등록생성기등을 이용하여 허위로 가입을 하거나 주민등록 생성기를 인터넷에 올리거나 이를 이용해 만든 행위에 관하여서도 주민등록법 개정안에 의거하여 엄중히 법적인 제재를 가할 수 있습니다. 또한 이미 제공된 귀하에 대한 정보가 정확한 정보가 되도록 유지, 갱신하여야 하며, 회원은 자신의 캔디바 ID 및 비밀번호를 제3자에게 이용하게 해서는 안됩니다.
6. 이용자는 당사의 사전 승낙없이 서비스를 이용하여 어떠한 영리행위도 할 수 없습니다.
7. 이용자는 당사 서비스를 이용하여 얻은 정보를 당사의 사전승낙 없이 복사, 복제, 변경, 번역, 출판·방송 기타의 방법으로 사용하거나 이를 타인에게 제공할 수 없습니다.
8. 이용자는 당사 서비스 이용과 관련하여 다음 각 호의 행위를 하여서는 안됩니다.
1) 다른 회원의 캔디바 ID를 부정 사용하는 행위
2) 범죄행위를 목적으로 하거나 기타 범죄행위와 관련된 행위
3) 선량한 풍속, 기타 사회질서를 해하는 행위
4) 타인의 명예를 훼손하거나 모욕하는 행위
5) 타인의 지적재산권 등의 권리를 침해하는 행위
6) 해킹행위 또는 컴퓨터 바이러스의 유포행위
7) 타인의 의사에 반하여 광고성 정보 등 일정한 내용을 지속적으로 전송하는 행위
8) 서비스의 안전적인 운영에 지장을 주거나 줄 우려가 있는 일체의 행위
9) 당사 사이트에 게시된 정보의 변경
10) 기타 전기통신법 제53조와 전기통신사업법 시행령 16조(불온통신), 통신사업법 제53조3항에 위배되는 행위
9. 다른 이용자들에게 피해를 주는 다음 각 호에 해당하는 행위를 하여서는 안됩니다.
1) 회사가 인정하는 서비스의 공식 운영자인 아이디를 사칭하는 내용
2) 선정적이고 음란한 내용
3) 반사회적이고 관계법령에 저촉되는 내용
4) 기타 제3자의 상표권, 저작권에 위배될 가능성이 있는 내용
5) 비어, 속어라고 판단되는 내용
6) 욕설이나 노골적인 성 묘사를 하는 내용
7) 다른 이용자를 희롱하거나, 위협하거나, 특정 이용자에게 지속적으로 고통을 주거나,불편을 주는 행위
8) 서비스 내 또는 웹사이트 상에서 다른 회사 제품의 광고나 판촉활동을 하는 행위
9) 저작권자의 허가 없이 저작권 문제가 발생할 소지가 있는 내용을 서비스 내 또는 웹사이트 상에 배포하는 행위
제 4장 서비스 이용·제한·정지등
제 12조 (서비스의 이용)
1. 캔디바 서비스의 이용은 기본적으로 무료입니다. 단 회사에서 정한 별도의 유효정보 및 유료서비스에 대해서는 그러지 아니하며, 유료서비스 이용에 관한 사항은 회사가 별도로 정한 약관 및 정책에 따릅니다.
2. 유료 서비스 이용의 결제에 관한 사항(충전방법, 사용, 환불 등)은 바(Bar)정책 이용약관에 따릅니다.
3. 아바타 및 게임 아이템 등 유료서비스의 소유권은 회사에 있으며, 웹상의 사용권은 해당 컨텐츠를 구매한 이용자에게 있습니다.
제 13조 (서비스 이용시간 및 중지)
1. 서비스 이용은 회사의 업무상 또는 기술상 특별한 지장이 없는 한 연중 무휴, 1일 24시간을 원칙으로 합니다. 다만, 회사는 서비스의 데이터 베이스별로 이용가능시간을 정할 수 있으며, 이 경우 그 내용은 회사가 정하여 서비스에 게시하거나 별도로 공시하는 바에 따릅니다.
1) 제1항의 규정에도 불구하고 정기점검 등의 필요로 회사가 정한 날 또는 시간은 예외적으로 서비스 이용을 제한할 수 있습니다.
2. 전시,사변,천재지변 또는 이에 준하는 국가비상사태가 발생하거나 발생할 우려가 있는 경우와 전기통신사업법에 의한 기간통신사업자가 전기통신서비스를 중지하는등 기타 부득이한 사유가 있는 경우에는 서비스의 전부 또는 일부를 제한하거나 정지할 수 있습니다.
1) 회사는 제1항의 규정에 의하여 서비스의 전부 또는 일부를 제한하거나 정지한 때에는 지체없이 이용자에게 알려야 합니다.
3. 이용자가 국익 또는 사회적 공익을 저해할 목적이나 범죄적 목적으로 서비스를 이용하고 있다고 판단되는 경우에 회사는 이용자에게 사전 통보 없이 서비스를 중단할 수 있으며 그에 따른 데이터도 복구를 전제로 하지않고 삭제할 수 있습니다.
4. 회사는 이용정지 기간 중에 사유가 해소된 것이 확인된 경우에는 지체없이 서비스를 재개통 또는 이용정지를 해제합니다.
제 14조 (각종 자료의 저장기간)
회사는 필요한 경우 서비스의 일정 부분별로 이용자가 게시한 자료나 이용자의 필요에 의해 저장하고 있는 자료에 대해 일정한 게재기간 또는 저장기간을 정할 수 있으며, 필요에 따라 기간을 변경할 수 있습니다.
제 15조 (게시물의 저작권)
1. 이용자가 서비스 홈페이지에 게시하거나 등록한 자료의 지적재산권은 이용자에게 귀속됩니다. 단, 회사는 서비스 홈페이지의 게재권을 가지며 비상업적 목적으로는 이용자의 게시물을 활용할 수 있습니다.
2. 이용자는 서비스를 이용하여 얻은 정보를 가공, 판매하는 행위 등 게재 된 자료를 상업적으로 이용할 수 없으며 이를 위반하여 발생하는 제반 문제에 대한 책임은 이용자에게 있습니다.
3. 회사는 이용자 게시물의 내용 검열, 검색 및 관리에 따른 일체의 손해배상 책임을 지지아니 합니다.
제 5장 개인정보 보호
제 16조 개인정보보호
회사는 관계법령이 정하는 바에 따라 회원등록정보를 포함한 회원의 개인정보를 보호하기 위하여 노력을 합니다. 회원의 개인정보보호에 관하여 관계법령 및 회사가 정하는 개인정보보호정책에 정한 바에 따릅니다.
제 6장 계약해지 및 이용제한
제 17조 (계약의 해지)
회원이 이용계약을 해지하고자 하는 경우에는 회원 본인이 온라인을 통하여 등록해지신청을 하여야 합니다.
제 18조 (이용제한)
1. 회사는 회원이 다음 각 호의 사유에 해당하는 경우 사전통지 없이 회원의 서비스 이용제한 및 적법한 조치를 취할 수 있으며 이용계약을 해지하거나 또는 기간을 정하여 서비스를 중지할 수 있습니다.
1) 회원 가입신청 또는 변경시 허위 내용을 등록한 경우
2) 타인의 서비스 이용을 방해하거나 그 정보를 도용한 경우
3) 회사의 운영진, 직원 또는 관계자를 사칭하는 경우
4) 회사의 사전승락없이 서비스를 이용하여 영업활동을 하는 경우
5) 회원ID를 타인과 거래하거나 회원ID의 게임상 사이버 자산을 타인과 매매하는 행위를 하는 경우
6) 회사 프로그램상의 버그를 악용하여 정상적이지 아니한 방법으로 게임상 사이버자산을 취득하는 행위를 하는 경우
7) 서비스를 통하여 얻은 정보를 회사의 사전승낙없이 서비스 이용 외이 목적으로 복제하거나 이를 출판 및 방송 등에 사용하거나, 제3자에게 제공하는 경우
8) 회사 또는 제3자의 저작권 등 기타 지적재산권을 침해하는 내용을 전송, 게시, 전자우편 또는 기타의 방법으로 타인에게 유포하는 경우
9) 공공질서 및 미풍약속에 위반되는 음란한 내용의 정보, 문장, 도형, 음향, 동영상을 전송, 게시, 전자우편 또는 기타의 방법으로 타인에게 유포하는 경우
10) 심히 모욕적이거나 개인신상에 대한 내용이어서 타인의 명예나 프라이버시를 침해할 수 있는 내용을 전송, 게시, 전자우편 또는 기타의 방법으로 타인에게 유포하는 경우
11) 서비스에 위해를 가하거나 고의로 방해한 경우
12) 다른 회원을 희롱, 위협하거나 특정 이용자에게 지속적으로 고통, 불편을 주는 행위를 하는 경우
13) 범죄와 관련이 있다고 객관적으로 판단되는 행위를 하는 경우
14) 본 서비스를 이용함에 있어 본 약관 및 기타 회사가 정한 정책 또한 운영 규칙을 위반하는 경우
15) 기타 관련 법령에 위배하는 행위를 하는 경우
제 7장 분쟁조정 및 기타사항
제 19조 (손해배상)
회사는 무료로 제공되는 서비스 이용과 관련하여 회원에게 발생한 어떠한 손해에 관하여도 책임을 지지 않습니다.
제 20조 (면책조항)
1. 회사는 천재지변 또는 이에 준하는 불가항력으로 인하여 서비스를 제공 할 수 없는 경우에는 서비스 제공에 관한 책임이 면제됩니다.
2. 회사는 회원의 귀책사유로 인한 서비스 이용의 장애에 대하여 책임을 지지 않습니다.
3. 회사는 회원이 서비스를 이용하여 기대하는 수익을 상실한 것이나 서비스를 통하여 얻은 자료로 인한 손해에 관하여 책임을 지지 않습니다.
4. 회사는 회원이 서비스에 게재한 정보, 자료, 사실의 신뢰도, 정확성 등 내용에 관하여는 책임을 지지 않습니다.
5. 회사는 서비스 이용과 관련하여 가입자에게 발생한 손해 가운데 가입자의 고의, 과실에 의한 손해에 대하여 책임을 지지 않습니다.
6. 회사는 회원간 또는 회원과 제3자간에 서비스를 매개로 하여 물품거래 혹은 금전적 거래등과 관련하여 어떠한 책임도 부담하지 않습니다.
제 21조(분쟁조정)
회사와 이용고객은 개인정보에 관한 분쟁이 있는 경우 신속하고 효과적인 분쟁해결을 위하여 한국정보보호진흥원내의 개인정보분쟁조정위원회에 그 처리를 의뢰할 수 있습니다.
제 22조(회사의 소유권)
1. 회사의 서비스, 소프트웨어, 이미지, 마크, 로고, 디자인, 서비스명칭, 정보 및 상표 등과 관련된 지적재산권 및 기타 권리는 회사에게 소유권이 있습니다.
2. 이용자는 회사가 명시적으로 승인한 경우를 제외하고는 전항의 소정의 각 재산에 대한 전부 또는 일부의 수정, 대여, 대출, 판매, 배포, 제 작, 양도, 재라이센스, 담보권 설정 행위, 상업적 이용 행위를 할 수 없으며, 제3자로 하여금 이와 같은 행위를 하도록 허락할 수 없습니다.
Binary file not shown.
+127
View File
@@ -0,0 +1,127 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for forms lib.
*
* This file contains all unit test related to forms library.
*
* @package core_form
* @category phpunit
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/form/duration.php');
/**
* Unit tests for MoodleQuickForm_duration
*
* Contains test cases for testing MoodleQuickForm_duration
*
* @package core_form
* @category unittest
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class duration_form_element_testcase extends basic_testcase {
/** @var MoodleQuickForm_duration Keeps reference of MoodleQuickForm_duration object */
private $element;
/**
* Initalize test wide variable, it is called in start of the testcase
*/
function setUp() {
$this->element = new MoodleQuickForm_duration();
}
/**
* Clears the data set in the setUp() method call.
* @see duration_form_element_test::setUp()
*/
function tearDown() {
$this->element = null;
}
/**
* Testcase for testing contructor.
* @expectedException coding_exception
* @retrun void
*/
function test_constructor() {
// Test trying to create with an invalid unit.
$this->element = new MoodleQuickForm_duration('testel', null, array('defaultunit' => 123));
}
/**
* Testcase for testing units (seconds, minutes, hours and days)
*/
function test_get_units() {
$units = $this->element->get_units();
ksort($units);
$this->assertEquals($units, array(1 => get_string('seconds'), 60 => get_string('minutes'),
3600 => get_string('hours'), 86400 => get_string('days')));
}
/**
* Testcase for testing conversion of seconds to the best possible unit
*/
function test_seconds_to_unit() {
$this->assertEquals($this->element->seconds_to_unit(0), array(0, 60)); // Zero minutes, for a nice default unit.
$this->assertEquals($this->element->seconds_to_unit(1), array(1, 1));
$this->assertEquals($this->element->seconds_to_unit(3601), array(3601, 1));
$this->assertEquals($this->element->seconds_to_unit(60), array(1, 60));
$this->assertEquals($this->element->seconds_to_unit(180), array(3, 60));
$this->assertEquals($this->element->seconds_to_unit(3600), array(1, 3600));
$this->assertEquals($this->element->seconds_to_unit(7200), array(2, 3600));
$this->assertEquals($this->element->seconds_to_unit(86400), array(1, 86400));
$this->assertEquals($this->element->seconds_to_unit(90000), array(25, 3600));
$this->element = new MoodleQuickForm_duration('testel', null, array('defaultunit' => 86400));
$this->assertEquals($this->element->seconds_to_unit(0), array(0, 86400)); // Zero minutes, for a nice default unit.
}
/**
* Testcase to check generated timestamp
*/
function test_exportValue() {
$el = new MoodleQuickForm_duration('testel');
$el->_createElements();
$values = array('testel' => array('number' => 10, 'timeunit' => 1));
$this->assertEquals($el->exportValue($values), array('testel' => 10));
$values = array('testel' => array('number' => 3, 'timeunit' => 60));
$this->assertEquals($el->exportValue($values), array('testel' => 180));
$values = array('testel' => array('number' => 1.5, 'timeunit' => 60));
$this->assertEquals($el->exportValue($values), array('testel' => 90));
$values = array('testel' => array('number' => 2, 'timeunit' => 3600));
$this->assertEquals($el->exportValue($values), array('testel' => 7200));
$values = array('testel' => array('number' => 1, 'timeunit' => 86400));
$this->assertEquals($el->exportValue($values), array('testel' => 86400));
$values = array('testel' => array('number' => 0, 'timeunit' => 3600));
$this->assertEquals($el->exportValue($values), array('testel' => 0));
$el = new MoodleQuickForm_duration('testel', null, array('optional' => true));
$el->_createElements();
$values = array('testel' => array('number' => 10, 'timeunit' => 1));
$this->assertEquals($el->exportValue($values), array('testel' => 0));
$values = array('testel' => array('number' => 20, 'timeunit' => 1, 'enabled' => 1));
$this->assertEquals($el->exportValue($values), array('testel' => 20));
}
}
+1 -1
View File
@@ -50,7 +50,7 @@ class calc_formula {
*/
function calc_formula($formula, $params=false) {
$this->_em = new EvalMath();
$this->_em->suppress_errors = !debugging('', DEBUG_DEVELOPER);
$this->_em->suppress_errors = true; // no PHP errors!
if (strpos($formula, '=') !== 0) {
$this->_error = "missing leading '='";
return;
+13 -8
View File
@@ -10767,17 +10767,22 @@ class lang_string {
$this->a = $a;
} else if ($a instanceof lang_string) {
$this->a = $a->out();
} else if (is_object($a)) {
$this->a = new stdClass;
foreach (get_object_vars($a) as $key => $value) {
// Make sure conversion errors don't get displayed (results in '')
$this->a->$key = @(string)$value;
}
} else if (is_array($a)) {
} else if (is_object($a) or is_array($a)) {
$a = (array)$a;
$this->a = array();
foreach ($a as $key => $value) {
// Make sure conversion errors don't get displayed (results in '')
$this->a[$key] = @(string)$value;
if (is_array($value)) {
$this->a[$key] = '';
} else if (is_object($value)) {
if (method_exists($value, '__toString')) {
$this->a[$key] = $value->__toString();
} else {
$this->a[$key] = '';
}
} else {
$this->a[$key] = (string)$value;
}
}
}
}
+45 -18
View File
@@ -22,7 +22,8 @@
* 1 - general error
* 130 - coding error
* 131 - configuration problem
* 132 - drop data, then install new test database
* 132 - install new test database
* 133 - drop old data, then install new test database
*
* @package core
* @category phpunit
@@ -36,13 +37,19 @@ ini_set('display_errors', '1');
ini_set('log_errors', '1');
if (isset($_SERVER['REMOTE_ADDR'])) {
phpunit_bootstrap_error('Unit tests can be executed only from commandline!', 1);
phpunit_bootstrap_error('Unit tests can be executed only from command line!', 1);
}
if (defined('PHPUNITTEST')) {
phpunit_bootstrap_error("PHPUNITTEST constant must not be manually defined anywhere!", 130);
if (defined('PHPUNIT_TEST')) {
phpunit_bootstrap_error("PHPUNIT_TEST constant must not be manually defined anywhere!", 130);
}
/** PHPUnit testing framework active */
define('PHPUNIT_TEST', true);
if (!defined('PHPUNIT_UTIL')) {
/** Identifies utility scripts */
define('PHPUNIT_UTIL', false);
}
define('PHPUNITTEST', true);
if (defined('CLI_SCRIPT')) {
phpunit_bootstrap_error('CLI_SCRIPT must not be manually defined in any PHPUnit test scripts', 130);
@@ -55,10 +62,16 @@ define('NO_OUTPUT_BUFFERING', true);
define('ABORT_AFTER_CONFIG', true);
require(__DIR__ . '/../../config.php');
if (!defined('PHPUNIT_LONGTEST')) {
/** Execute longer version of tests */
define('PHPUNIT_LONGTEST', false);
}
// remove error handling overrides done in config.php
error_reporting(E_ALL);
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', '1');
ini_set('log_errors', '1');
set_time_limit(0); // no time limit in CLI scripts, user may cancel execution
// prepare dataroot
umask(0);
@@ -113,7 +126,10 @@ if (!file_exists("$CFG->phpunit_dataroot/phpunittestdir.txt")) {
// verify db prefix
if (!isset($CFG->phpunit_prefix)) {
phpunit_bootstrap_error('Missing $CFG->phpunit_dataroot in config.php, can not run tests!', 131);
phpunit_bootstrap_error('Missing $CFG->phpunit_prefix in config.php, can not run tests!', 131);
}
if ($CFG->phpunit_prefix === '') {
phpunit_bootstrap_error('$CFG->phpunit_prefix can not be empty, can not run tests!', 131);
}
if (isset($CFG->prefix) and $CFG->prefix === $CFG->phpunit_prefix) {
phpunit_bootstrap_error('$CFG->prefix and $CFG->phpunit_prefix must not be identical, can not run tests!', 131);
@@ -141,12 +157,14 @@ unset($allowed);
unset($productioncfg);
// force the same CFG settings in all sites
$CFG->debug = (E_ALL | E_STRICT | 38911); // can not use DEBUG_DEVELOPER here
$CFG->debug = (E_ALL | E_STRICT); // can not use DEBUG_DEVELOPER yet
$CFG->debugdisplay = 1;
error_reporting($CFG->debug);
ini_set('display_errors', '1');
ini_set('log_errors', '0');
$CFG->passwordsaltmain = 'phpunit'; // makes login via normal UI impossible
$CFG->noemailever = true; // better not mail anybody from tests, override temporarily if necessary
$CFG->cachetext = 0; // disable this very nasty setting
@@ -163,20 +181,27 @@ require("$CFG->dirroot/lib/setup.php");
raise_memory_limit(MEMORY_EXTRA);
if (defined('PHPUNIT_CLI_UTIL')) {
// all other tests are done in the CLI scripts...
if (PHPUNIT_UTIL) {
// we are not going to do testing, this is 'true' in utility scripts that init database usually
return;
}
if (!phpunit_util::is_testing_ready()) {
phpunit_bootstrap_error('Database is not initialised to run unit tests, please use "php admin/tool/phpunit/cli/util.php --install"', 132);
// is database and dataroot ready for testing?
$problem = phpunit_util::testing_ready_problem();
if ($problem) {
switch ($problem) {
case 132:
phpunit_bootstrap_error('Database was not initialised to run unit tests, please use "php admin/tool/phpunit/cli/util.php --install"', $problem);
case 133:
phpunit_bootstrap_error('Database was initialised for different version, please use "php admin/tool/phpunit/cli/util.php --drop; php admin/tool/phpunit/cli/util.php --install"', $problem);
default:
phpunit_bootstrap_error('Unknown problem initialising test database', $problem);
}
}
// refresh data in all tables, clear caches, etc.
phpunit_util::reset_all_data();
// store fresh globals
phpunit_util::init_globals();
// prepare for the first test run - store fresh globals, reset dataroot, etc.
phpunit_util::bootstrap_init();
//=========================================================
@@ -200,7 +225,9 @@ function phpunit_bootstrap_error($text, $errorcode = 1) {
function phpunit_bootstrap_initdataroot($dataroot) {
global $CFG;
file_put_contents("$dataroot/phpunittestdir.txt", 'Contents of this directory are used during tests only, do not delete this file!');
if (!file_exists("$dataroot/phpunittestdir.txt")) {
file_put_contents("$dataroot/phpunittestdir.txt", 'Contents of this directory are used during tests only, do not delete this file!');
}
chmod("$dataroot/phpunittestdir.txt", $CFG->filepermissions);
if (!file_exists("$CFG->phpunit_dataroot/phpunit")) {
mkdir("$CFG->phpunit_dataroot/phpunit", $CFG->directorypermissions);
+470
View File
@@ -0,0 +1,470 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* PHPUnit data generator class
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Data generator for unit tests
*/
class phpunit_data_generator {
protected $usercounter = 0;
protected $categorycount = 0;
protected $coursecount = 0;
protected $blockcount = 0;
protected $modulecount = 0;
protected $scalecount = 0;
/**
* To be called from data reset code only,
* do not use in tests.
* @return void
*/
public function reset() {
$this->usercounter = 0;
$this->categorycount = 0;
$this->coursecount = 0;
$this->blockcount = 0;
$this->modulecount = 0;
$this->scalecount = 0;
}
/**
* Create a test user
* @param array|stdClass $record
* @param array $options
* @return stdClass user record
*/
public function create_user($record=null, array $options=null) {
global $DB, $CFG;
$this->usercounter++;
$i = $this->usercounter;
$record = (array)$record;
if (!isset($record['auth'])) {
$record['auth'] = 'manual';
}
if (!isset($record['firstname'])) {
$record['firstname'] = 'Firstname'.$i;
}
if (!isset($record['lastname'])) {
$record['lastname'] = 'Lastname'.$i;
}
if (!isset($record['idnumber'])) {
$record['idnumber'] = '';
}
if (!isset($record['username'])) {
$record['username'] = 'username'.$i;
}
if (!isset($record['password'])) {
$record['password'] = 'lala';
}
if (!isset($record['email'])) {
$record['email'] = $record['username'].'@example.com';
}
if (!isset($record['confirmed'])) {
$record['confirmed'] = 1;
}
if (!isset($record['mnethostid'])) {
$record['mnethostid'] = $CFG->mnet_localhost_id;
}
if (!isset($record['lang'])) {
$record['lang'] = 'en';
}
if (!isset($record['maildisplay'])) {
$record['maildisplay'] = 1;
}
if (!isset($record['deleted'])) {
$record['deleted'] = 0;
}
$record['timecreated'] = time();
$record['timemodified'] = $record['timecreated'];
$record['lastip'] = '0.0.0.0';
$record['password'] = hash_internal_user_password($record['password']);
if ($record['deleted']) {
$delname = $record['email'].'.'.time();
while ($DB->record_exists('user', array('username'=>$delname))) {
$delname++;
}
$record['idnumber'] = '';
$record['email'] = md5($record['username']);
$record['username'] = $delname;
}
$userid = $DB->insert_record('user', $record);
if (!$record['deleted']) {
context_user::instance($userid);
}
return $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
}
/**
* Create a test course category
* @param array|stdClass $record
* @param array $options
* @return stdClass course category record
*/
function create_category($record=null, array $options=null) {
global $DB, $CFG;
require_once("$CFG->dirroot/course/lib.php");
$this->categorycount++;
$i = $this->categorycount;
$record = (array)$record;
if (!isset($record['name'])) {
$record['name'] = 'Course category '.$i;
}
if (!isset($record['idnumber'])) {
$record['idnumber'] = '';
}
if (!isset($record['description'])) {
$record['description'] = 'Test course category '.$i;
}
if (!isset($record['descriptionformat'])) {
$record['description'] = FORMAT_MOODLE;
}
if (!isset($record['parent'])) {
$record['descriptionformat'] = 0;
}
if ($record['parent'] == 0) {
$parent = new stdClass();
$parent->path = '';
$parent->depth = 0;
} else {
$parent = $DB->get_record('course_categories', array('id'=>$record['parent']), '*', MUST_EXIST);
}
$record['depth'] = $parent->depth+1;
$record['sortorder'] = 0;
$record['timemodified'] = time();
$record['timecreated'] = $record['timemodified'];
$catid = $DB->insert_record('course_categories', $record);
$path = $parent->path . '/' . $catid;
$DB->set_field('course_categories', 'path', $path, array('id'=>$catid));
context_coursecat::instance($catid);
fix_course_sortorder();
return $DB->get_record('course_categories', array('id'=>$catid), '*', MUST_EXIST);
}
/**
* Create a test course
* @param array|stdClass $record
* @param array $options with keys:
* 'createsections'=>bool precreate all sections
* @return stdClass course record
*/
function create_course($record=null, array $options=null) {
global $DB, $CFG;
require_once("$CFG->dirroot/course/lib.php");
$this->coursecount++;
$i = $this->coursecount;
$record = (array)$record;
if (!isset($record['fullname'])) {
$record['fullname'] = 'Test course '.$i;
}
if (!isset($record['shortname'])) {
$record['shortname'] = 'tc_'.$i;
}
if (!isset($record['idnumber'])) {
$record['idnumber'] = '';
}
if (!isset($record['format'])) {
$record['format'] = 'topics';
}
if (!isset($record['newsitems'])) {
$record['newsitems'] = 0;
}
if (!isset($record['numsections'])) {
$record['numsections'] = 5;
}
if (!isset($record['description'])) {
$record['description'] = 'Test course '.$i;
}
if (!isset($record['descriptionformat'])) {
$record['description'] = FORMAT_MOODLE;
}
if (!isset($record['category'])) {
$record['category'] = $DB->get_field_select('course_categories', "MIN(id)", "parent=0");
}
$course = create_course((object)$record);
context_course::instance($course->id);
if (!empty($options['createsections'])) {
for($i=1; $i<$record['numsections']; $i++) {
self::create_course_section(array('course'=>$course->id, 'section'=>$i));
}
}
return $course;
}
/**
* Create course section if does not exist yet
* @param mixed $record
* @param array|null $options
* @return stdClass
* @throws coding_exception
*/
public function create_course_section($record = null, array $options = null) {
global $DB;
$record = (array)$record;
if (empty($record['course'])) {
throw new coding_exception('course must be present in phpunit_util::create_course_section() $record');
}
if (!isset($record['section'])) {
throw new coding_exception('section must be present in phpunit_util::create_course_section() $record');
}
if (!isset($record['name'])) {
$record['name'] = '';
}
if (!isset($record['summary'])) {
$record['summary'] = '';
}
if (!isset($record['summaryformat'])) {
$record['summaryformat'] = FORMAT_MOODLE;
}
if ($section = $DB->get_record('course_sections', array('course'=>$record['course'], 'section'=>$record['section']))) {
return $section;
}
$section = new stdClass();
$section->course = $record['course'];
$section->section = $record['section'];
$section->name = $record['name'];
$section->summary = $record['summary'];
$section->summaryformat = $record['summaryformat'];
$id = $DB->insert_record('course_sections', $section);
return $DB->get_record('course_sections', array('id'=>$id));
}
/**
* Create a test block
* @param string $blockname
* @param array|stdClass $record
* @param array $options
* @return stdClass block instance record
*/
public function create_block($blockname, $record=null, array $options=null) {
global $DB;
$this->blockcount++;
$i = $this->blockcount;
$record = (array)$record;
$record['blockname'] = $blockname;
//TODO: use block callbacks
if (!isset($record['parentcontextid'])) {
$record['parentcontextid'] = context_system::instance()->id;
}
if (!isset($record['showinsubcontexts'])) {
$record['showinsubcontexts'] = 1;
}
if (!isset($record['pagetypepattern'])) {
$record['pagetypepattern'] = '';
}
if (!isset($record['subpagepattern'])) {
$record['subpagepattern'] = '';
}
if (!isset($record['defaultweight'])) {
$record['defaultweight'] = '';
}
$biid = $DB->insert_record('block_instances', $record);
context_block::instance($biid);
return $DB->get_record('block_instances', array('id'=>$biid), '*', MUST_EXIST);
}
/**
* Create a test module
* @param string $modulename
* @param array|stdClass $record
* @param array $options
* @return stdClass activity record
*/
public function create_module($modulename, $record=null, array $options=null) {
global $DB, $CFG;
require_once("$CFG->dirroot/course/lib.php");
$this->modulecount++;
$i = $this->modulecount;
$record = (array)$record;
$options = (array)$options;
if (!isset($record['name'])) {
$record['name'] = get_string('pluginname', $modulename).' '.$i;
}
if (!isset($record['intro'])) {
$record['intro'] = 'Test module '.$i;
}
if (!isset($record['introformat'])) {
$record['introformat'] = FORMAT_MOODLE;
}
if (!isset($options['section'])) {
$options['section'] = 1;
}
//TODO: use module callbacks
if ($modulename === 'page') {
if (!isset($record['content'])) {
$record['content'] = 'Test page content';
}
if (!isset($record['contentformat'])) {
$record['contentformat'] = FORMAT_MOODLE;
}
} else {
error('TODO: only mod_page is supported in data generator for now');
}
$id = $DB->insert_record($modulename, $record);
$cm = new stdClass();
$cm->course = $record['course'];
$cm->module = $DB->get_field('modules', 'id', array('name'=>$modulename));
$cm->section = $options['section'];
$cm->instance = $id;
$cm->id = $DB->insert_record('course_modules', $cm);
$cm->coursemodule = $cm->id;
add_mod_to_section($cm);
context_module::instance($cm->id);
$instance = $DB->get_record($modulename, array('id'=>$id), '*', MUST_EXIST);
$instance->cmid = $cm->id;
return $instance;
}
/**
* Create a test scale
* @param array|stdClass $record
* @param array $options
* @return stdClass block instance record
*/
public function create_scale($record=null, array $options=null) {
global $DB;
$this->scalecount++;
$i = $this->scalecount;
$record = (array)$record;
if (!isset($record['name'])) {
$record['name'] = 'Test scale '.$i;
}
if (!isset($record['scale'])) {
$record['scale'] = 'A,B,C,D,F';
}
if (!isset($record['courseid'])) {
$record['courseid'] = 0;
}
if (!isset($record['userid'])) {
$record['userid'] = 0;
}
if (!isset($record['description'])) {
$record['description'] = 'Test scale description '.$i;
}
if (!isset($record['descriptionformat'])) {
$record['descriptionformat'] = FORMAT_MOODLE;
}
$record['timemodified'] = time();
if (isset($record['id'])) {
$DB->import_record('scale', $record);
$DB->get_manager()->reset_sequence('scale');
$id = $record['id'];
} else {
$id = $DB->insert_record('scale', $record);
}
return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST);
}
}
+503 -98
View File
@@ -48,6 +48,29 @@ class phpunit_util {
*/
protected static $globals = array();
/**
* @var int last value of db writes counter, used for db resetting
*/
protected static $lastdbwrites = null;
/**
* @var phpunit_data_generator
*/
protected static $generator = null;
/**
* Get data generator
* @static
* @return phpunit_data_generator
*/
public static function get_data_generator() {
if (is_null(self::$generator)) {
require_once(__DIR__.'/generatorlib.php');
self::$generator = new phpunit_data_generator();
}
return self::$generator;
}
/**
* Returns contents of all tables right after installation.
* @static
@@ -56,6 +79,11 @@ class phpunit_util {
protected static function get_tabledata() {
global $CFG;
if (!file_exists("$CFG->dataroot/phpunit/tabledata.ser")) {
// not initialised yet
return array();
}
if (!isset(self::$tabledata)) {
$data = file_get_contents("$CFG->dataroot/phpunit/tabledata.ser");
self::$tabledata = unserialize($data);
@@ -69,35 +97,133 @@ class phpunit_util {
}
/**
* Initialise CFG using data from fresh new install.
* Reset all database tables to default values.
* @static
* @param bool $logchanges
* @param null|PHPUnit_Framework_TestCase $caller
* @return bool true if reset done, false if skipped
*/
public static function initialise_cfg() {
global $CFG, $DB;
public static function reset_database($logchanges = false, PHPUnit_Framework_TestCase $caller = null) {
global $DB;
if (!file_exists("$CFG->dataroot/phpunit/tabledata.ser")) {
// most probably PHPUnit CLI installer
if ($logchanges) {
if (self::$lastdbwrites != $DB->perf_get_writes()) {
if ($caller) {
$where = ' in testcase: '.get_class($caller).'->'.$caller->getName(true);
} else {
$where = '';
}
error_log('warning: unexpected database modification, resetting DB state'.$where);
}
}
$tables = $DB->get_tables(false);
if (!$tables or empty($tables['config'])) {
// not installed yet
return;
}
if (!$DB->get_manager()->table_exists('config') or !$DB->count_records('config')) {
@unlink("$CFG->dataroot/phpunit/tabledata.ser");
@unlink("$CFG->dataroot/phpunit/versionshash.txt");
self::$tabledata = null;
return;
$dbreset = false;
if (is_null(self::$lastdbwrites) or self::$lastdbwrites != $DB->perf_get_writes()) {
if ($data = self::get_tabledata()) {
$trans = $DB->start_delegated_transaction(); // faster and safer
$resetseq = array();
foreach ($data as $table=>$records) {
if (empty($records)) {
if ($DB->count_records($table)) {
$DB->delete_records($table, array());
$resetseq[$table] = $table;
}
continue;
}
$firstrecord = reset($records);
if (property_exists($firstrecord, 'id')) {
if ($DB->count_records($table) >= count($records)) {
$currentrecords = $DB->get_records($table, array(), 'id ASC');
$changed = false;
foreach ($records as $id=>$record) {
if (!isset($currentrecords[$id])) {
$changed = true;
break;
}
if ((array)$record != (array)$currentrecords[$id]) {
$changed = true;
break;
}
unset($currentrecords[$id]);
}
if (!$changed) {
if ($currentrecords) {
$remainingfirst = reset($currentrecords);
$lastrecord = end($records);
if ($remainingfirst->id > $lastrecord->id) {
$DB->delete_records_select($table, "id >= ?", array($remainingfirst->id));
$resetseq[$table] = $table;
continue;
}
} else {
continue;
}
}
}
}
$DB->delete_records($table, array());
if (property_exists($firstrecord, 'id')) {
$resetseq[$table] = $table;
}
foreach ($records as $record) {
$DB->import_record($table, $record, false, true);
}
}
// reset all sequences
foreach ($resetseq as $table) {
$DB->get_manager()->reset_sequence($table, true);
}
$trans->allow_commit();
// remove extra tables
foreach ($tables as $tablename) {
if (!isset($data[$tablename])) {
$DB->get_manager()->drop_table(new xmldb_table($tablename));
}
}
$dbreset = true;
}
}
$data = self::get_tabledata();
self::$lastdbwrites = $DB->perf_get_writes();
foreach($data['config'] as $record) {
$name = $record->name;
$value = $record->value;
if (property_exists($CFG, $name)) {
// config.php settings always take precedence
return $dbreset;
}
/**
* Purge dataroot
* @static
* @return void
*/
public static function reset_dataroot() {
global $CFG;
$handle = opendir($CFG->dataroot);
$skip = array('.', '..', 'phpunittestdir.txt', 'phpunit', '.htaccess');
while (false !== ($item = readdir($handle))) {
if (in_array($item, $skip)) {
continue;
}
$CFG->{$name} = $value;
if (is_dir("$CFG->dataroot/$item")) {
remove_dir("$CFG->dataroot/$item", false);
} else {
unlink("$CFG->dataroot/$item");
}
}
closedir($handle);
make_temp_directory('');
make_cache_directory('');
make_cache_directory('htmlpurifier');
}
/**
@@ -105,47 +231,106 @@ class phpunit_util {
*
* Note: this is relatively slow (cca 2 seconds for pg and 7 for mysql) - please use with care!
*
* @param bool $logchanges log changes in global state and database in error log
* @param PHPUnit_Framework_TestCase $caller caller object, used for logging only
* @return void
* @static
*/
public static function reset_all_data() {
global $DB, $CFG;
public static function reset_all_data($logchanges = false, PHPUnit_Framework_TestCase $caller = null) {
global $DB, $CFG, $USER, $SITE, $COURSE, $PAGE, $OUTPUT, $SESSION;
$data = self::get_tabledata();
$dbreset = self::reset_database($logchanges, $caller);
$trans = $DB->start_delegated_transaction(); // faster and safer
foreach ($data as $table=>$records) {
$DB->delete_records($table, array());
$resetseq = null;
foreach ($records as $record) {
if (is_null($resetseq)) {
$resetseq = property_exists($record, 'id');
}
$DB->import_record($table, $record, false, true);
if ($logchanges) {
if ($caller) {
$where = ' in testcase: '.get_class($caller).'->'.$caller->getName(true);
} else {
$where = '';
}
if ($resetseq === true) {
$DB->get_manager()->reset_sequence($table, true);
$oldcfg = self::get_global_backup('CFG');
$oldsite = self::get_global_backup('SITE');
foreach($CFG as $k=>$v) {
if (!property_exists($oldcfg, $k)) {
error_log('warning: unexpected new $CFG->'.$k.' value'.$where);
} else if ($oldcfg->$k !== $CFG->$k) {
error_log('warning: unexpected change of $CFG->'.$k.' value'.$where);
}
unset($oldcfg->$k);
}
if ($oldcfg) {
foreach($oldcfg as $k=>$v) {
error_log('warning: unexpected removal of $CFG->'.$k.$where);
}
}
if ($USER->id != 0) {
error_log('warning: unexpected change of $USER'.$where);
}
if ($COURSE->id != $oldsite->id) {
error_log('warning: unexpected change of $COURSE'.$where);
}
}
$trans->allow_commit();
purge_all_caches();
// restore _SERVER
unset($_SERVER['HTTP_USER_AGENT']);
// restore original config
$CFG = self::get_global_backup('CFG');
$SITE = self::get_global_backup('SITE');
$COURSE = $SITE;
// recreate globals
$OUTPUT = new bootstrap_renderer();
$PAGE = new moodle_page();
$FULLME = null;
$ME = null;
$SCRIPT = null;
$SESSION = new stdClass();
$_SESSION['SESSION'] =& $SESSION;
// set fresh new user
$user = new stdClass();
$user->id = 0;
$user->mnet = 0;
$user->mnethostid = $CFG->mnet_localhost_id;
session_set_user($user);
accesslib_clear_all_caches_for_unit_testing();
// reset all static caches
accesslib_clear_all_caches(true);
get_string_manager()->reset_caches();
//TODO: add more resets here and probably refactor them to new core function
// purge dataroot
self::reset_dataroot();
// restore original config once more in case resetting of caches changes CFG
$CFG = self::get_global_backup('CFG');
// remember db writes
self::$lastdbwrites = $DB->perf_get_writes();
// inform data generator
self::get_data_generator()->reset();
// fix PHP settings
error_reporting($CFG->debug);
}
/**
* Called during bootstrap only!
* @static
*/
public static function init_globals() {
global $CFG;
public static function bootstrap_init() {
global $CFG, $SITE;
// backup the globals
self::$globals['CFG'] = clone($CFG);
self::$globals['SITE'] = clone($SITE);
// refresh data in all tables, clear caches, etc.
phpunit_util::reset_all_data();
}
/**
@@ -178,7 +363,7 @@ class phpunit_util {
if (!file_exists("$CFG->dataroot/phpunittestdir.txt")) {
// this is already tested in bootstrap script,
// but anway presence of this file means the dataroot is for testing
// but anyway presence of this file means the dataroot is for testing
return false;
}
@@ -199,41 +384,41 @@ class phpunit_util {
* Is this site initialised to run unit tests?
*
* @static
* @return bool
* @return int error code, 0 means ok
*/
public static function is_testing_ready() {
public static function testing_ready_problem() {
global $DB, $CFG;
if (!self::is_test_site()) {
return false;
return 131;
}
$tables = $DB->get_tables(true);
if (!$tables) {
return false;
return 132;
}
if (!get_config('core', 'phpunittest')) {
return false;
return 131;
}
if (!file_exists("$CFG->dataroot/phpunit/tabledata.ser")) {
return false;
return 131;
}
if (!file_exists("$CFG->dataroot/phpunit/versionshash.txt")) {
return false;
return 131;
}
$hash = phpunit_util::get_version_hash();
$oldhash = file_get_contents("$CFG->dataroot/phpunit/versionshash.txt");
if ($hash !== $oldhash) {
return false;
return 133;
}
return true;
return 0;
}
/**
@@ -252,18 +437,17 @@ class phpunit_util {
}
// drop dataroot
remove_dir($CFG->dataroot, true);
self::reset_dataroot();
phpunit_bootstrap_initdataroot($CFG->dataroot);
remove_dir("$CFG->dataroot/phpunit", true);
// drop all tables
$trans = $DB->start_delegated_transaction();
$tables = $DB->get_tables(false);
foreach ($tables as $tablename) {
$DB->delete_records($tablename, array());
if (isset($tables['config'])) {
// config always last to prevent problems with interrupted drops!
unset($tables['config']);
$tables['config'] = 'config';
}
$trans->allow_commit();
// now drop them
foreach ($tables as $tablename) {
$table = new xmldb_table($tablename);
$DB->get_manager()->drop_table($table);
@@ -296,8 +480,9 @@ class phpunit_util {
install_cli_database($options, false);
// just in case remove admin password so that normal login is not possible
$DB->set_field('user', 'password', 'not cached', array('username' => 'admin'));
// install timezone info
$timezones = get_records_csv($CFG->libdir.'/timezone.txt', 'timezone');
update_timezone_records($timezones);
// add test db flag
set_config('phpunittest', 'phpunittest');
@@ -306,7 +491,13 @@ class phpunit_util {
$data = array();
$tables = $DB->get_tables();
foreach ($tables as $table) {
$data[$table] = $DB->get_records($table, array());
$columns = $DB->get_columns($table);
if (isset($columns['id'])) {
$data[$table] = $DB->get_records($table, array(), 'id ASC');
} else {
// there should not be many of these
$data[$table] = $DB->get_records($table, array());
}
}
$data = serialize($data);
@unlink("$CFG->dataroot/phpunit/tabledata.ser");
@@ -319,7 +510,7 @@ class phpunit_util {
}
/**
* Culculate unique version hash for all available plugins and core.
* Calculate unique version hash for all available plugins and core.
* @static
* @return string sha1 hash
*/
@@ -372,11 +563,9 @@ class phpunit_util {
global $CFG;
$template = '
<testsuites>
<testsuite name="@component@">
<directory suffix="_test.php">@dir@</directory>
</testsuite>
</testsuites>';
</testsuite>';
$data = file_get_contents("$CFG->dirroot/phpunit.xml.dist");
$suites = '';
@@ -427,6 +616,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @deprecated since 2.3
* @param bool $expected
* @param string $message
* @return void
*/
public function expectException($expected, $message = '') {
// use phpdocs: @expectedException ExceptionClassName
@@ -440,6 +630,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @deprecated since 2.3
* @param bool $expected
* @param string $message
* @return void
*/
public static function expectError($expected = false, $message = '') {
// not available in PHPUnit
@@ -454,6 +645,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @static
* @param mixed $actual
* @param string $messages
* @return void
*/
public static function assertTrue($actual, $messages = '') {
parent::assertTrue((bool)$actual, $messages);
@@ -464,6 +656,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @static
* @param mixed $actual
* @param string $messages
* @return void
*/
public static function assertFalse($actual, $messages = '') {
parent::assertFalse((bool)$actual, $messages);
@@ -475,6 +668,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $expected
* @param mixed $actual
* @param string $message
* @return void
*/
public static function assertEqual($expected, $actual, $message = '') {
parent::assertEquals($expected, $actual, $message);
@@ -486,6 +680,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $expected
* @param mixed $actual
* @param string $message
* @return void
*/
public static function assertNotEqual($expected, $actual, $message = '') {
parent::assertNotEquals($expected, $actual, $message);
@@ -497,6 +692,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $expected
* @param mixed $actual
* @param string $message
* @return void
*/
public static function assertIdentical($expected, $actual, $message = '') {
parent::assertSame($expected, $actual, $message);
@@ -508,6 +704,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $expected
* @param mixed $actual
* @param string $message
* @return void
*/
public static function assertNotIdentical($expected, $actual, $message = '') {
parent::assertNotSame($expected, $actual, $message);
@@ -519,6 +716,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $actual
* @param mixed $expected
* @param string $message
* @return void
*/
public static function assertIsA($actual, $expected, $message = '') {
parent::assertInstanceOf($expected, $actual, $message);
@@ -529,7 +727,7 @@ class UnitTestCase extends PHPUnit_Framework_TestCase {
/**
* The simplest PHPUnit test case customised for Moodle
*
* This test case does not modify database or any globals.
* It is intended for isolated tests that do not modify database or any globals.
*
* @package core
* @category phpunit
@@ -541,17 +739,58 @@ class basic_testcase extends PHPUnit_Framework_TestCase {
/**
* Constructs a test case with the given name.
*
* Note: use setUp() or setUpBeforeClass() in custom test cases.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = NULL, array $data = array(), $dataName = '') {
final public function __construct($name = null, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false);
}
/**
* Runs the bare test sequence and log any changes in global state or database.
* @return void
*/
public function runBare() {
parent::runBare();
phpunit_util::reset_all_data(true, $this);
}
}
/**
* Advanced PHPUnit test case customised for Moodle.
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class advanced_testcase extends PHPUnit_Framework_TestCase {
/** @var bool automatically reset everything? null means log changes */
protected $resetAfterTest;
/**
* Constructs a test case with the given name.
*
* Note: use setUp() or setUpBeforeClass() in custom test cases.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
final public function __construct($name = null, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false);
$this->setInIsolation(false);
}
/**
@@ -559,43 +798,209 @@ class basic_testcase extends PHPUnit_Framework_TestCase {
* @return void
*/
public function runBare() {
global $CFG, $USER, $DB;
$dbwrites = $DB->perf_get_writes();
$this->resetAfterTest = null;
parent::runBare();
$oldcfg = phpunit_util::get_global_backup('CFG');
foreach($CFG as $k=>$v) {
if (!property_exists($oldcfg, $k)) {
unset($CFG->$k);
error_log('warning: unexpected new $CFG->'.$k.' value in testcase: '.get_class($this).'->'.$this->getName(true));
} else if ($oldcfg->$k !== $CFG->$k) {
$CFG->$k = $oldcfg->$k;
error_log('warning: unexpected change of $CFG->'.$k.' value in testcase: '.get_class($this).'->'.$this->getName(true));
}
unset($oldcfg->$k);
}
if ($oldcfg) {
foreach($oldcfg as $k=>$v) {
$CFG->$k = $v;
error_log('warning: unexpected removal of $CFG->'.$k.' in testcase: '.get_class($this).'->'.$this->getName(true));
}
if ($this->resetAfterTest === true) {
self::resetAllData();
} else if ($this->resetAfterTest === false) {
// keep all data untouched for other tests
} else {
// reset but log what changed
phpunit_util::reset_all_data(true, $this);
}
if ($USER->id != 0) {
error_log('warning: unexpected change of $USER in testcase: '.get_class($this).'->'.$this->getName(true));
$USER = new stdClass();
$USER->id = 0;
}
if ($dbwrites != $DB->perf_get_writes()) {
//TODO: find out what was changed exactly
error_log('warning: unexpected database modification, resetting DB state in testcase: '.get_class($this).'->'.$this->getName(true));
phpunit_util::reset_all_data();
}
//TODO: somehow find out if there are changes in dataroot
$this->resetAfterTest = null;
}
}
/**
* Reset everything after current test.
* @param bool $reset true means reset state back, false means keep all data for the next test,
* null means reset state and show warnings if anything changed
* @return void
*/
public function resetAfterTest($reset = true) {
$this->resetAfterTest = $reset;
}
/**
* Cleanup after all tests are executed.
*
* Note: do not forget to call this if overridden...
*
* @static
* @return void
*/
public static function tearDownAfterClass() {
phpunit_util::reset_all_data();
}
/**
* Reset all database tables, restore global state and clear caches and optionally purge dataroot dir.
* @static
* @return void
*/
public static function resetAllData() {
phpunit_util::reset_all_data();
}
/**
* Set current $USER, reset access cache.
* @static
* @param null|int|stdClass $user user record, null means non-logged-in, integer means userid
* @return void
*/
public static function setUser($user = null) {
global $CFG, $DB;
if (is_object($user)) {
$user = clone($user);
} else if (!$user) {
$user = new stdClass();
$user->id = 0;
$user->mnethostid = $CFG->mnet_localhost_id;
} else {
$user = $DB->get_record('user', array('id'=>$user));
}
unset($user->description);
unset($user->access);
session_set_user($user);
}
/**
* Get data generator
* @static
* @return phpunit_data_generator
*/
public static function getDataGenerator() {
return phpunit_util::get_data_generator();
}
/**
* Recursively visit all the files in the source tree. Calls the callback
* function with the pathname of each file found.
*
* @param $path the folder to start searching from.
* @param $callback the method of this class to call with the name of each file found.
* @param $fileregexp a regexp used to filter the search (optional).
* @param $exclude If true, pathnames that match the regexp will be ignored. If false,
* only files that match the regexp will be included. (default false).
* @param array $ignorefolders will not go into any of these folders (optional).
* @return void
*/
public function recurseFolders($path, $callback, $fileregexp = '/.*/', $exclude = false, $ignorefolders = array()) {
$files = scandir($path);
foreach ($files as $file) {
$filepath = $path .'/'. $file;
if (strpos($file, '.') === 0) {
/// Don't check hidden files.
continue;
} else if (is_dir($filepath)) {
if (!in_array($filepath, $ignorefolders)) {
$this->recurseFolders($filepath, $callback, $fileregexp, $exclude, $ignorefolders);
}
} else if ($exclude xor preg_match($fileregexp, $filepath)) {
$this->$callback($filepath);
}
}
}
}
/**
* Special test case for testing of DML drivers and DDL layer.
*
* Note: Use only 'test_table*' when creating new tables.
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class database_driver_testcase extends PHPUnit_Framework_TestCase {
protected static $extradb = null;
/** @var moodle_database */
protected $tdb;
/**
* Constructs a test case with the given name.
*
* @param string $name
* @param array $data
* @param string $dataName
*/
final public function __construct($name = null, array $data = array(), $dataName = '') {
parent::__construct($name, $data, $dataName);
$this->setBackupGlobals(false);
$this->setBackupStaticAttributes(false);
$this->setRunTestInSeparateProcess(false);
}
public static function setUpBeforeClass() {
global $CFG;
if (!defined('PHPUNIT_TEST_DRIVER')) {
// use normal $DB
return;
}
if (!isset($CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER])) {
throw new exception('Can not find driver configuration options with index: '.PHPUNIT_TEST_DRIVER);
}
$dblibrary = empty($CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dblibrary']) ? 'native' : $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dblibrary'];
$dbtype = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dbtype'];
$dbhost = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dbhost'];
$dbname = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dbname'];
$dbuser = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dbuser'];
$dbpass = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dbpass'];
$prefix = $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['prefix'];
$dboptions = empty($CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dboptions']) ? array() : $CFG->phpunit_extra_drivers[PHPUNIT_TEST_DRIVER]['dboptions'];
$classname = "{$dbtype}_{$dblibrary}_moodle_database";
require_once("$CFG->libdir/dml/$classname.php");
$d = new $classname();
if (!$d->driver_installed()) {
throw new exception('Database driver for '.$classname.' is not installed');
}
$d->connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
self::$extradb = $d;
}
protected function setUp() {
global $DB;
if (self::$extradb) {
$this->tdb = self::$extradb;
} else {
$this->tdb = $DB;
}
}
protected function tearDown() {
// delete all test tables
$dbman = $this->tdb->get_manager();
$tables = $this->tdb->get_tables(false);
foreach($tables as $tablename) {
if (strpos($tablename, 'test_table') === 0) {
$table = new xmldb_table($tablename);
$dbman->drop_table($table);
}
}
}
public static function tearDownAfterClass() {
if (self::$extradb) {
self::$extradb->dispose();
self::$extradb = null;
}
phpunit_util::reset_all_data();
}
}
+23 -11
View File
@@ -2,11 +2,18 @@ PHPUnit testing support in Moodle
==================================
Documentation
-------------
* [Moodle Dev wiki](http://docs.moodle.org/dev/PHPUnit)
* [PHPUnit online documentaion](http://www.phpunit.de/manual/current/en/)
* [MDL-32323](http://tracker.moodle.org/browse/MDL-32323), [MDL-32149](http://tracker.moodle.org/browse/MDL-32149), [MDL-31857](http://tracker.moodle.org/browse/MDL-31857)
Installation
------------
1. install PHPUnit PEAR extension - see [PHPUnit docs](http://www.phpunit.de/manual/current/en/installation.html) for more details
2. edit main config.php - add $CFG->phpunit_prefix and $CFG->phpunit_dataroot - see config-dist.php for more details
3. execute `php admin/tool/phpunit/cli/util.php --install` to initialise test database
3. execute `php admin/tool/phpunit/cli/util.php --install` from dirroot to initialise test database and dataroot
4. it is necessary to reinitialise the test database manually after every upgrade or installation of new plugins
@@ -19,15 +26,17 @@ Test execution
* it is possible to create custom configuration files in xml format and use `phpunit -c myconfig.xml`
How to add more tests
---------------------
1. create `tests` directory in any plugin
2. add `*_test.php` files with custom class that extends `basic_testcase`
3. manually add all core unit test locations to `phpunit.xml.dist`
How to add more tests?
----------------------
1. create `tests` directory in your plugin if does not already exist
2. add `*_test.php` files with custom class that extends `basic_testcase` or `advanced_testcase`
3. execute your new test, for example `phpunit core_phpunit_basic_testcase local/mytest/tests/mytest_test.php`
4. optionally build new phpunit.xml by executing `php admin/tool/phpunit/cli/util.php --buildconfig` and run all tests
5. core developers have to add all core unit test locations to `phpunit.xml.dist`
How to convert existing tests
-----------------------------
How to convert existing tests?
------------------------------
1. create new test file in `xxx/tests/yyy_test.php`
2. copy contents of the old test file
3. replace `extends UnitTestCase` with `extends basic_testcase`
@@ -44,6 +53,9 @@ FAQs
TODO
----
* stage 2 - implement advanced_testcase - support for database modifications, object generators, automatic rollback of db, globals and dataroot
* stage 3 - mocking and other advanced features, add support for execution of functional DB tests for different engines together (new options in phpunit.xml)
* other - support for execution of tests and cli/util.php from web UI (to be implemented via shell execution), shell script that prepares everything for the first execution
* add plugin callbacks to data generator
* convert remaining tests
* delete all simpletests
* hide old SimpleTests in UI and delete Functional DB tests
* shell script that prepares everything for the first execution
* optional support for execution of tests and cli/util.php from web UI (to be implemented via shell execution)
+1 -1
View File
@@ -479,7 +479,7 @@ class plugin_manager {
'tool' => array(
'bloglevelupgrade', 'capability', 'customlang', 'dbtransfer', 'generator',
'health', 'innodb', 'langimport', 'multilangupgrade', 'profiling',
'health', 'innodb', 'langimport', 'multilangupgrade', 'phpunit', 'profiling',
'qeupgradehelper', 'replace', 'spamcleaner', 'timezoneimport', 'unittest',
'uploaduser', 'unsuproles', 'xmldb'
),
+7
View File
@@ -1070,6 +1070,13 @@ function session_set_user($user) {
$_SESSION['USER'] = $user;
unset($_SESSION['USER']->description); // conserve memory
sesskey(); // init session key
if (PHPUNIT_TEST) {
// phpunit tests use reversed reference
global $USER;
$USER = $_SESSION['USER'];
$_SESSION['USER'] =& $USER;
}
}
/**
+21 -16
View File
@@ -45,7 +45,7 @@
global $CFG; // this should be done much earlier in config.php before creating new $CFG instance
if (!isset($CFG)) {
if (defined('PHPUNITTEST') and PHPUNITTEST) {
if (defined('PHPUNIT_TEST') and PHPUNIT_TEST) {
echo('There is a missing "global $CFG;" at the beginning of the config.php file.'."\n");
exit(1);
} else {
@@ -134,8 +134,8 @@ if (!defined('NO_OUTPUT_BUFFERING')) {
}
// PHPUnit tests need custom init
if (!defined('PHPUNITTEST')) {
define('PHPUNITTEST', false);
if (!defined('PHPUNIT_TEST')) {
define('PHPUNIT_TEST', false);
}
// Servers should define a default timezone in php.ini, but if they don't then make sure something is defined.
@@ -398,11 +398,13 @@ init_performance_info();
$OUTPUT = new bootstrap_renderer();
// set handler for uncaught exceptions - equivalent to print_error() call
set_exception_handler('default_exception_handler');
set_error_handler('default_error_handler', E_ALL | E_STRICT);
if (!PHPUNIT_TEST or PHPUNIT_UTIL) {
set_exception_handler('default_exception_handler');
set_error_handler('default_error_handler', E_ALL | E_STRICT);
}
// If there are any errors in the standard libraries we want to know!
error_reporting(E_ALL);
error_reporting(E_ALL | E_STRICT);
// Just say no to link prefetching (Moz prefetching, Google Web Accelerator, others)
// http://www.google.com/webmasters/faq.html#prefetchblock
@@ -461,20 +463,21 @@ setup_validate_php_configuration();
// Connect to the database
setup_DB();
// reset DB tables
if (PHPUNIT_TEST and !PHPUNIT_UTIL) {
phpunit_util::reset_database();
}
// Disable errors for now - needed for installation when debug enabled in config.php
if (isset($CFG->debug)) {
$originalconfigdebug = $CFG->debug;
unset($CFG->debug);
} else {
$originalconfigdebug = -1;
$originalconfigdebug = null;
}
// Load up any configuration from the config table
if (PHPUNITTEST) {
phpunit_util::initialise_cfg();
} else {
initialise_cfg();
}
initialise_cfg();
// Verify upgrade is not running unless we are in a script that needs to execute in any case
if (!defined('NO_UPGRADE_CHECK') and isset($CFG->upgraderunning)) {
@@ -495,7 +498,7 @@ if (isset($CFG->debug)) {
$originaldatabasedebug = $CFG->debug;
unset($CFG->debug);
} else {
$originaldatabasedebug = -1;
$originaldatabasedebug = null;
}
// enable circular reference collector in PHP 5.3,
@@ -510,12 +513,12 @@ if (function_exists('register_shutdown_function')) {
}
// Set error reporting back to normal
if ($originaldatabasedebug == -1) {
if ($originaldatabasedebug === null) {
$CFG->debug = DEBUG_MINIMAL;
} else {
$CFG->debug = $originaldatabasedebug;
}
if ($originalconfigdebug !== -1) {
if ($originalconfigdebug !== null) {
$CFG->debug = $originalconfigdebug;
}
unset($originalconfigdebug);
@@ -823,7 +826,9 @@ if (!empty($CFG->customscripts)) {
}
}
if ((CLI_SCRIPT and !defined('WEB_CRON_EMULATED_CLI')) or PHPUNITTEST) {
if (PHPUNIT_TEST) {
// no ip blocking, these are CLI only
} else if (CLI_SCRIPT and !defined('WEB_CRON_EMULATED_CLI')) {
// no ip blocking
} else if (!empty($CFG->allowbeforeblock)) { // allowed list processed before blocked list?
// in this case, ip in allowed list will be performed first
+4
View File
@@ -141,6 +141,10 @@ class moodle_exception extends Exception {
$message = $module . '/' . $errorcode;
}
if (PHPUNIT_TEST and $debuginfo) {
$message = "$message ($debuginfo)";
}
parent::__construct($message, 0);
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
* Unit tests for /lib/externallib.php.
*
* @package webservices
* @copyright 2009 Pwetr Skoda
* @copyright 2009 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-100
View File
@@ -1,100 +0,0 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Unit tests for ../portfoliolib.php.
*
* @author nicolasconnault@gmail.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodlecore
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir . '/portfoliolib.php');
class portfoliolibaddbutton_test extends UnitTestCaseUsingDatabase {
public static $includecoverage = array('lib/portfoliolib.php');
protected $testtables = array(
'lib' => array(
'portfolio_instance', 'portfolio_instance_user'));
public function setUp() {
parent::setUp();
$this->switch_to_test_db(); // Switch to test DB for all the execution
foreach ($this->testtables as $dir => $tables) {
$this->create_test_tables($tables, $dir); // Create tables
}
}
public function tearDown() {
parent::tearDown(); // In charge of droppng all the test tables
}
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*/
/*
* A test of setting and getting formats. What is returned in the getter is a combination of what is explicitly set in
* the button, and what is set in the static method of the export class.
*
* In some cases they conflict, in which case the button wins.
*/
/*
function test_set_formats() {
$button = new portfolio_add_button();
$button->set_callback_options('assignment_portfolio_caller', array('id' => 6), '/mod/assignment/locallib.php');
$formats = array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_IMAGE);
$button->set_formats($formats);
// Expecting $formats + assignment_portfolio_caller::base_supported_formats merged to unique values.
$formats_combined = array_unique(array_merge($formats, assignment_portfolio_caller::base_supported_formats()));
// In this case, neither file or image conflict with leap2a, which is why all three are returned.
$this->assertEqual(count($formats_combined), count($button->get_formats()));
}
*/
}
-50
View File
@@ -1,50 +0,0 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Unit tests for ../portfoliolib.php.
*
* @author nicolasconnault@gmail.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package moodlecore
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->libdir . '/simpletest/portfolio_testclass.php');
// Load tests for various modules
foreach (get_list_of_plugins('mod') as $module) {
$modtest = $CFG->dirroot . '/mod/' . $module . '/simpletest/test_' . $module . '_portfolio_callers.php';
if (file_exists($modtest)) {
require_once($modtest);
}
}
class empty_portfoliolib_test extends UnitTestCase {
// empty, this prevents warning in coverage report
}
+985
View File
@@ -0,0 +1,985 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Full functional accesslib test
*
* @package core
* @category phpunit
* @copyright 2011 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Context caching fixture
*/
class context_inspection extends context_helper {
public static function test_context_cache_size() {
return self::$cache_count;
}
}
/**
* Functional test for accesslib.php
*
* Note: execution may take many minutes especially on slower servers.
*/
class accesslib_testcase extends advanced_testcase {
//TODO: add more tests for the remaining accesslib parts that were not touched by the refactoring in 2.2dev
/**
* Verify comparison of context instances in phpunit asserts
* @return void
*/
public function test_context_comparisons() {
$frontpagecontext1 = context_course::instance(SITEID);
context_helper::reset_caches();
$frontpagecontext2 = context_course::instance(SITEID);
$this->assertEquals($frontpagecontext1, $frontpagecontext2);
$user1 = context_user::instance(1);
$user2 = context_user::instance(2);
$this->assertNotEquals($user1, $user2);
}
/**
* A small functional test of accesslib functions and classes.
* @return void
*/
public function test_everything_in_accesslib() {
global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
$this->resetAfterTest(true);
$generator = $this->getDataGenerator();
// Fill the site with some real data
$testcategories = array();
$testcourses = array();
$testpages = array();
$testblocks = array();
$allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
$systemcontext = context_system::instance();
$frontpagecontext = context_course::instance(SITEID);
// Add block to system context
$bi = $generator->create_block('online_users');
context_block::instance($bi->id);
$testblocks[] = $bi->id;
// Some users
$testusers = array();
for($i=0; $i<20; $i++) {
$user = $generator->create_user();
$testusers[$i] = $user->id;
$usercontext = context_user::instance($user->id);
// Add block to user profile
$bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
$testblocks[] = $bi->id;
}
// Deleted user - should be ignored everywhere, can not have context
$generator->create_user(array('deleted'=>1));
// Add block to frontpage
$bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
$frontpageblockcontext = context_block::instance($bi->id);
$testblocks[] = $bi->id;
// Add a resource to frontpage
$page = $generator->create_module('page', array('course'=>$SITE->id));
$testpages[] = $page->id;
$frontpagepagecontext = context_module::instance($page->cmid);
// Add block to frontpage resource
$bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
$frontpagepageblockcontext = context_block::instance($bi->id);
$testblocks[] = $bi->id;
// Some nested course categories with courses
$manualenrol = enrol_get_plugin('manual');
$parentcat = 0;
for($i=0; $i<5; $i++) {
$cat = $generator->create_category(array('parent'=>$parentcat));
$testcategories[] = $cat->id;
$catcontext = context_coursecat::instance($cat->id);
$parentcat = $cat->id;
if ($i >=4) {
continue;
}
// Add resource to each category
$bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
context_block::instance($bi->id);
// Add a few courses to each category
for($j=0; $j<6; $j++) {
$course = $generator->create_course(array('category'=>$cat->id));
$testcourses[] = $course->id;
$coursecontext = context_course::instance($course->id);
if ($j >= 5) {
continue;
}
// Add manual enrol instance
$manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));
// Add block to each course
$bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
$testblocks[] = $bi->id;
// Add a resource to each course
$page = $generator->create_module('page', array('course'=>$course->id));
$testpages[] = $page->id;
$modcontext = context_module::instance($page->cmid);
// Add block to each module
$bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
$testblocks[] = $bi->id;
}
}
// Make sure all contexts were created properly
$count = 1; //system
$count += $DB->count_records('user', array('deleted'=>0));
$count += $DB->count_records('course_categories');
$count += $DB->count_records('course');
$count += $DB->count_records('course_modules');
$count += $DB->count_records('block_instances');
$this->assertEquals($DB->count_records('context'), $count);
$this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
$this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
// ====== context_helper::get_level_name() ================================
$levels = context_helper::get_all_levels();
foreach ($levels as $level=>$classname) {
$name = context_helper::get_level_name($level);
$this->assertFalse(empty($name));
}
// ======= context::instance_by_id(), context_xxx::instance();
$context = context::instance_by_id($frontpagecontext->id);
$this->assertSame($context->contextlevel, CONTEXT_COURSE);
$this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
try {
context::instance_by_id(-1);
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
$this->assertTrue(context_system::instance() instanceof context_system);
$this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
$this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
$this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
$this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
$this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
$this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
$this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
$this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
try {
context_coursecat::instance(-1);
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
try {
context_course::instance(-1);
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
try {
context_module::instance(-1);
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
try {
context_block::instance(-1);
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
// ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
$testcontexts = array();
$testcontexts[CONTEXT_SYSTEM] = context_system::instance();
$testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
$testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
$testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
$testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
foreach ($testcontexts as $context) {
$name = $context->get_context_name(true, true);
$this->assertFalse(empty($name));
$this->assertTrue($context->get_url() instanceof moodle_url);
$caps = $context->get_capabilities();
$this->assertTrue(is_array($caps));
foreach ($caps as $cap) {
$cap = (array)$cap;
$this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
}
}
unset($testcontexts);
// ===== $context->get_course_context() =========================================
$this->assertFalse($systemcontext->get_course_context(false));
try {
$systemcontext->get_course_context();
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
$context = context_coursecat::instance($testcategories[0]);
$this->assertFalse($context->get_course_context(false));
try {
$context->get_course_context();
$this->fail('exception expected');
} catch (Exception $e) {
$this->assertTrue(true);
}
$this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
$this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
$this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
// ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
$userid = reset($testusers);
$usercontext = context_user::instance($userid);
$this->assertSame($usercontext->get_parent_context(), $systemcontext);
$this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
$this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));
$this->assertSame($systemcontext->get_parent_contexts(), array());
$this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
$this->assertSame($systemcontext->get_parent_context_ids(), array());
$this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
$this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
$this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
$this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
$this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
$this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
$this->assertSame($systemcontext->get_parent_context(), false);
$frontpagecontext = context_course::instance($SITE->id);
$parent = $systemcontext;
foreach ($testcategories as $catid) {
$catcontext = context_coursecat::instance($catid);
$this->assertSame($catcontext->get_parent_context(), $parent);
$parent = $catcontext;
}
$this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
$this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
$this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
// ====== $context->get_child_contexts() ================================
$CFG->debug = 0;
$children = $systemcontext->get_child_contexts();
$CFG->debug = DEBUG_DEVELOPER;
$this->assertEquals(count($children)+1, $DB->count_records('context'));
$context = context_coursecat::instance($testcategories[3]);
$children = $context->get_child_contexts();
$countcats = 0;
$countcourses = 0;
$countblocks = 0;
foreach ($children as $child) {
if ($child->contextlevel == CONTEXT_COURSECAT) {
$countcats++;
}
if ($child->contextlevel == CONTEXT_COURSE) {
$countcourses++;
}
if ($child->contextlevel == CONTEXT_BLOCK) {
$countblocks++;
}
}
$this->assertEquals(count($children), 8);
$this->assertEquals($countcats, 1);
$this->assertEquals($countcourses, 6);
$this->assertEquals($countblocks, 1);
$context = context_course::instance($testcourses[2]);
$children = $context->get_child_contexts();
$this->assertEquals(count($children), 7); // depends on number of default blocks
$context = context_module::instance($testpages[3]);
$children = $context->get_child_contexts();
$this->assertEquals(count($children), 1);
$context = context_block::instance($testblocks[1]);
$children = $context->get_child_contexts();
$this->assertEquals(count($children), 0);
unset($children);
unset($countcats);
unset($countcourses);
unset($countblocks);
// ======= context_helper::reset_caches() ============================
context_helper::reset_caches();
$this->assertEquals(context_inspection::test_context_cache_size(), 0);
context_course::instance($SITE->id);
$this->assertEquals(context_inspection::test_context_cache_size(), 1);
// ======= context preloading ========================================
context_helper::reset_caches();
$sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
FROM {context} c
WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
$records = $DB->get_records_sql($sql);
$firstrecord = reset($records);
$columns = context_helper::get_preload_record_columns('c');
$firstrecord = (array)$firstrecord;
$this->assertSame(array_keys($firstrecord), array_values($columns));
context_helper::reset_caches();
foreach ($records as $record) {
context_helper::preload_from_record($record);
$this->assertEquals($record, new stdClass());
}
$this->assertEquals(context_inspection::test_context_cache_size(), count($records));
unset($records);
unset($columns);
context_helper::reset_caches();
context_helper::preload_course($SITE->id);
$this->assertEquals(7, context_inspection::test_context_cache_size()); // depends on number of default blocks
// ====== assign_capability(), unassign_capability() ====================
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertFalse($rc);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertEquals($rc->permission, CAP_ALLOW);
assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertEquals($rc->permission, CAP_ALLOW);
assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertEquals($rc->permission, CAP_PREVENT);
assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertFalse($rc);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
$rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
$this->assertFalse($rc);
unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
unset($rc);
accesslib_clear_all_caches(false); // must be done after assign_capability()
// ======= role_assign(), role_unassign(), role_unassign_all() ==============
$context = context_course::instance($testcourses[1]);
$this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
role_assign($allroles['teacher'], $testusers[1], $context->id);
role_assign($allroles['teacher'], $testusers[2], $context->id);
role_assign($allroles['manager'], $testusers[1], $context->id);
$this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
role_unassign($allroles['teacher'], $testusers[1], $context->id);
$this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
role_unassign_all(array('contextid'=>$context->id));
$this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
unset($context);
accesslib_clear_all_caches(false); // just in case
// ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
$adminid = get_admin()->id;
$guestid = $CFG->siteguest;
// Enrol some users into some courses
$course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
$course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
$cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
$cm1 = reset($cms);
$blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
$block1 = reset($blocks);
$instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
$instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
for($i=0; $i<9; $i++) {
$manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
}
$manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
$manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
for($i=10; $i<15; $i++) {
$manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
}
$manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
// Add tons of role assignments - the more the better
role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
// Add tons of overrides - the more the better
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
accesslib_clear_all_caches(false); // must be done after assign_capability()
// Extra tests for guests and not-logged-in users because they can not be verified by cross checking
// with get_users_by_capability() where they are ignored
$this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
$this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
$this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
$this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
$this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
$this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
$this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
$this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
$this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
$this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
$this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
$this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
$this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
$this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
$this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
// Test the list of enrolled users
$coursecontext = context_course::instance($course1->id);
$enrolled = get_enrolled_users($coursecontext);
$this->assertEquals(count($enrolled), 10);
for($i=0; $i<10; $i++) {
$this->assertTrue(isset($enrolled[$testusers[$i]]));
}
$enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
$this->assertEquals(count($enrolled), 1);
$this->assertTrue(isset($enrolled[$testusers[9]]));
unset($enrolled);
// role switching
$userid = $testusers[9];
$USER = $DB->get_record('user', array('id'=>$userid));
load_all_capabilities();
$coursecontext = context_course::instance($course1->id);
$this->assertTrue(has_capability('moodle/course:update', $coursecontext));
$this->assertFalse(is_role_switched($course1->id));
role_switch($allroles['student'], $coursecontext);
$this->assertTrue(is_role_switched($course1->id));
$this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
$this->assertFalse(has_capability('moodle/course:update', $coursecontext));
reload_all_capabilities();
$this->assertFalse(has_capability('moodle/course:update', $coursecontext));
role_switch(0, $coursecontext);
$this->assertTrue(has_capability('moodle/course:update', $coursecontext));
$userid = $adminid;
$USER = $DB->get_record('user', array('id'=>$userid));
load_all_capabilities();
$coursecontext = context_course::instance($course1->id);
$blockcontext = context_block::instance($block1->id);
$this->assertTrue(has_capability('moodle/course:update', $blockcontext));
role_switch($allroles['student'], $coursecontext);
$this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
$this->assertFalse(has_capability('moodle/course:update', $blockcontext));
reload_all_capabilities();
$this->assertFalse(has_capability('moodle/course:update', $blockcontext));
load_all_capabilities();
$this->assertTrue(has_capability('moodle/course:update', $blockcontext));
// temp course role for enrol
$DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
$userid = $testusers[5];
$roleid = $allroles['editingteacher'];
$USER = $DB->get_record('user', array('id'=>$userid));
load_all_capabilities();
$coursecontext = context_course::instance($course1->id);
$this->assertFalse(has_capability('moodle/course:update', $coursecontext));
$this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
load_temp_course_role($coursecontext, $roleid);
$this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
$this->assertTrue(has_capability('moodle/course:update', $coursecontext));
remove_temp_course_roles($coursecontext);
$this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
load_temp_course_role($coursecontext, $roleid);
reload_all_capabilities();
$this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
$USER = new stdClass();
$USER->id = 0;
// Now cross check has_capability() with get_users_by_capability(), each using different code paths,
// they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
// at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
$contexts = $DB->get_records('context', array(), 'id');
$contexts = array_values($contexts);
$capabilities = $DB->get_records('capabilities', array(), 'id');
$capabilities = array_values($capabilities);
$roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
$userids = array_values($testusers);
$userids[] = get_admin()->id;
if (!PHPUNIT_LONGTEST) {
$contexts = array_slice($contexts, 0, 10);
$capabilities = array_slice($capabilities, 0, 5);
$userids = array_slice($userids, 0, 5);
}
// Random time!
//srand(666);
foreach($userids as $userid) { // no guest or deleted
// each user gets 0-10 random roles
$rcount = rand(0, 10);
for($j=0; $j<$rcount; $j++) {
$roleid = $roles[rand(0, count($roles)-1)];
$contextid = $contexts[rand(0, count($contexts)-1)]->id;
role_assign($roleid, $userid, $contextid);
}
}
$permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
$maxoverrides = count($contexts)*10;
for($j=0; $j<$maxoverrides; $j++) {
$roleid = $roles[rand(0, count($roles)-1)];
$contextid = $contexts[rand(0, count($contexts)-1)]->id;
$permission = $permissions[rand(0,count($permissions)-1)];
$capname = $capabilities[rand(0, count($capabilities)-1)]->name;
assign_capability($capname, $permission, $roleid, $contextid, true);
}
unset($permissions);
unset($roles);
accesslib_clear_all_caches(false); // must be done after assign_capability()
// Test time - let's set up some real user, just in case the logic for USER affects the others...
$USER = $DB->get_record('user', array('id'=>$testusers[3]));
load_all_capabilities();
$userids[] = $CFG->siteguest;
$userids[] = 0; // not-logged-in user
$userids[] = -1; // non-existent user
foreach ($contexts as $crecord) {
$context = context::instance_by_id($crecord->id);
if ($coursecontext = $context->get_course_context(false)) {
$enrolled = get_enrolled_users($context);
} else {
$enrolled = array();
}
foreach ($capabilities as $cap) {
$allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
if ($enrolled) {
$enrolledwithcap = get_enrolled_users($context, $cap->name);
} else {
$enrolledwithcap = array();
}
foreach ($userids as $userid) {
if ($userid == 0 or isguestuser($userid)) {
if ($userid == 0) {
$CFG->forcelogin = true;
$this->assertFalse(has_capability($cap->name, $context, $userid));
unset($CFG->forcelogin);
}
if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
$this->assertFalse(has_capability($cap->name, $context, $userid));
}
$this->assertFalse(isset($allowed[$userid]));
} else {
if (is_siteadmin($userid)) {
$this->assertTrue(has_capability($cap->name, $context, $userid, true));
}
$hascap = has_capability($cap->name, $context, $userid, false);
$this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
if (isset($enrolled[$userid])) {
$this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
}
}
}
}
}
// Back to nobody
$USER = new stdClass();
$USER->id = 0;
unset($contexts);
unset($userids);
unset($capabilities);
// Now let's do all the remaining tests that break our carefully prepared fake site
// ======= $context->mark_dirty() =======================================
$DB->delete_records('cache_flags', array());
accesslib_clear_all_caches(false);
$systemcontext->mark_dirty();
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
$this->assertTrue(isset($dirty[$systemcontext->path]));
$this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
// ======= $context->reload_if_dirty(); =================================
$DB->delete_records('cache_flags', array());
accesslib_clear_all_caches(false);
load_all_capabilities();
$context = context_course::instance($testcourses[2]);
$page = $DB->get_record('page', array('course'=>$testcourses[2]));
$pagecontext = context_module::instance($page->id);
$context->mark_dirty();
$this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
$USER->access['test'] = true;
$context->reload_if_dirty();
$this->assertFalse(isset($USER->access['test']));
$context->mark_dirty();
$this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
$USER->access['test'] = true;
$pagecontext->reload_if_dirty();
$this->assertFalse(isset($USER->access['test']));
// ======= context_helper::build_all_paths() ============================
$oldcontexts = $DB->get_records('context', array(), 'id');
$DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
$DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
context_helper::build_all_paths();
$newcontexts = $DB->get_records('context', array(), 'id');
$this->assertEquals($oldcontexts, $newcontexts);
unset($oldcontexts);
unset($newcontexts);
// ======= $context->reset_paths() ======================================
$context = context_course::instance($testcourses[2]);
$children = $context->get_child_contexts();
$context->reset_paths(false);
$this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
$this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
foreach ($children as $child) {
$this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
$this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
}
$this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
$this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>NULL)));
$context = context_course::instance($testcourses[2]);
$context->reset_paths(true);
$context = context_course::instance($testcourses[2]);
$this->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
$this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
$this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
$this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));
// ====== $context->update_moved(); ======================================
accesslib_clear_all_caches(false);
$DB->delete_records('cache_flags', array());
$course = $DB->get_record('course', array('id'=>$testcourses[0]));
$context = context_course::instance($course->id);
$oldpath = $context->path;
$miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
$categorycontext = context_coursecat::instance($miscid);
$course->category = $miscid;
$DB->update_record('course', $course);
$context->update_moved($categorycontext);
$context = context_course::instance($course->id);
$this->assertEquals($context->get_parent_context(), $categorycontext);
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
$this->assertTrue(isset($dirty[$oldpath]));
$this->assertTrue(isset($dirty[$context->path]));
// ====== $context->delete_content() =====================================
context_helper::reset_caches();
$context = context_module::instance($testpages[3]);
$this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
$this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
$context->delete_content();
$this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
$this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
// ====== $context->delete() =============================
context_helper::reset_caches();
$context = context_module::instance($testpages[4]);
$this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
$this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
$bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
$bicontext = context_block::instance($bi->id);
$DB->delete_records('cache_flags', array());
$context->delete(); // should delete also linked blocks
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
$this->assertTrue(isset($dirty[$context->path]));
$this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
$this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
$this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
context_module::instance($testpages[4]);
// ====== context_helper::delete_instance() =============================
context_helper::reset_caches();
$lastcourse = array_pop($testcourses);
$this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
$coursecontext = context_course::instance($lastcourse);
$this->assertEquals(context_inspection::test_context_cache_size(), 1);
$this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
$DB->delete_records('cache_flags', array());
context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
$this->assertTrue(isset($dirty[$coursecontext->path]));
$this->assertEquals(context_inspection::test_context_cache_size(), 0);
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
context_course::instance($lastcourse);
// ======= context_helper::create_instances() ==========================
$prevcount = $DB->count_records('context');
$DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
context_helper::create_instances(null, true);
$this->assertSame($DB->count_records('context'), $prevcount);
$this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
$this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
$DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
$DB->delete_records('block_instances', array());
$prevcount = $DB->count_records('context');
$DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
context_helper::create_instances(null, true);
$this->assertSame($DB->count_records('context'), $prevcount);
$this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
$this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
// ======= context_helper::cleanup_instances() ==========================
$lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
$DB->delete_records('course', array('id'=>$lastcourse));
$lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
$DB->delete_records('course_categories', array('id'=>$lastcategory));
$lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
$DB->delete_records('user', array('id'=>$lastuser));
$DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
$DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
context_helper::cleanup_instances();
$count = 1; //system
$count += $DB->count_records('user', array('deleted'=>0));
$count += $DB->count_records('course_categories');
$count += $DB->count_records('course');
$count += $DB->count_records('course_modules');
$count += $DB->count_records('block_instances');
$this->assertEquals($DB->count_records('context'), $count);
// ======= context cache size restrictions ==============================
$testusers= array();
for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
$user = $generator->create_user();
$testusers[$i] = $user->id;
}
context_helper::create_instances(null, true);
context_helper::reset_caches();
for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
context_user::instance($testusers[$i]);
if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
$this->assertEquals(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
} else if ($i == CONTEXT_CACHE_MAX_SIZE) {
// once the limit is reached roughly 1/3 of records should be removed from cache
$this->assertEquals(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
}
}
// We keep the first 100 cached
$prevsize = context_inspection::test_context_cache_size();
for ($i=0; $i<100; $i++) {
context_user::instance($testusers[$i]);
$this->assertEquals(context_inspection::test_context_cache_size(), $prevsize);
}
context_user::instance($testusers[102]);
$this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
unset($testusers);
// =================================================================
// ======= basic test of legacy functions ==========================
// =================================================================
// note: watch out, the fake site might be pretty borked already
$this->assertSame(get_system_context(), context_system::instance());
foreach ($DB->get_records('context') as $contextid=>$record) {
$context = context::instance_by_id($contextid);
$this->assertSame(get_context_instance_by_id($contextid), $context);
$this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
$this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
if ($context->id == SYSCONTEXTID) {
$this->assertSame(get_parent_contextid($context), false);
} else {
$this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
}
}
$CFG->debug = 0;
$children = get_child_contexts($systemcontext);
$CFG->debug = DEBUG_DEVELOPER;
$this->assertEquals(count($children), $DB->count_records('context')-1);
unset($children);
$DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
create_contexts();
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));
$DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
build_context_path();
$this->assertFalse($DB->record_exists('context', array('depth'=>0)));
$lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
$DB->delete_records('course', array('id'=>$lastcourse));
$lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
$DB->delete_records('course_categories', array('id'=>$lastcategory));
$lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
$DB->delete_records('user', array('id'=>$lastuser));
$DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
$DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
cleanup_contexts();
$count = 1; //system
$count += $DB->count_records('user', array('deleted'=>0));
$count += $DB->count_records('course_categories');
$count += $DB->count_records('course');
$count += $DB->count_records('course_modules');
$count += $DB->count_records('block_instances');
$this->assertEquals($DB->count_records('context'), $count);
context_helper::reset_caches();
preload_course_contexts($SITE->id);
$this->assertEquals(context_inspection::test_context_cache_size(), 1);
context_helper::reset_caches();
list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
$sql = "SELECT c.id $select FROM {course_categories} c $join";
$records = $DB->get_records_sql($sql);
foreach ($records as $record) {
context_instance_preload($record);
$record = (array)$record;
$this->assertEquals(1, count($record)); // only id left
}
$this->assertEquals(count($records), context_inspection::test_context_cache_size());
accesslib_clear_all_caches(true);
$DB->delete_records('cache_flags', array());
mark_context_dirty($systemcontext->path);
$dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
$this->assertTrue(isset($dirty[$systemcontext->path]));
accesslib_clear_all_caches(false);
$DB->delete_records('cache_flags', array());
$course = $DB->get_record('course', array('id'=>$testcourses[2]));
$context = get_context_instance(CONTEXT_COURSE, $course->id);
$oldpath = $context->path;
$miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
$categorycontext = context_coursecat::instance($miscid);
$course->category = $miscid;
$DB->update_record('course', $course);
context_moved($context, $categorycontext);
$context = get_context_instance(CONTEXT_COURSE, $course->id);
$this->assertEquals($context->get_parent_context(), $categorycontext);
$this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
delete_context(CONTEXT_COURSE, $testcourses[2]);
$this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
$name = get_contextlevel_name(CONTEXT_COURSE);
$this->assertFalse(empty($name));
$context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
$name = print_context_name($context);
$this->assertFalse(empty($name));
$url = get_context_url($coursecontext);
$this->assertFalse($url instanceof modole_url);
$page = $DB->get_record('page', array('id'=>$testpages[7]));
$context = get_context_instance(CONTEXT_MODULE, $page->id);
$coursecontext = get_course_context($context);
$this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
$this->assertEquals(get_courseid_from_context($context), $page->course);
$caps = fetch_context_capabilities($systemcontext);
$this->assertTrue(is_array($caps));
unset($caps);
}
}
+386
View File
@@ -0,0 +1,386 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for the block_manager class in ../blocklib.php.
*
* @package core
* @category phpunit
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/pagelib.php');
require_once($CFG->libdir . '/blocklib.php');
require_once($CFG->dirroot . '/blocks/moodleblock.class.php');
/** Test-specific subclass to make some protected things public. */
class testable_block_manager extends block_manager {
public function mark_loaded() {
$this->birecordsbyregion = array();
}
public function get_loaded_blocks() {
return $this->birecordsbyregion;
}
}
class block_ablocktype extends block_base {
public function init() {
}
}
/**
* Test functions that don't need to touch the database.
*/
class moodle_block_manager_testcase extends basic_testcase {
protected $testpage;
protected $blockmanager;
protected function setUp() {
parent::setUp();
$this->testpage = new moodle_page();
$this->testpage->set_context(get_context_instance(CONTEXT_SYSTEM));
$this->blockmanager = new testable_block_manager($this->testpage);
}
protected function tearDown() {
$this->testpage = null;
$this->blockmanager = null;
parent::tearDown();
}
public function test_no_regions_initially() {
// Exercise SUT & Validate
$this->assertEquals(array(), $this->blockmanager->get_regions());
}
public function test_add_region() {
// Exercise SUT.
$this->blockmanager->add_region('a-region-name');
// Validate
$this->assertEquals(array('a-region-name'), $this->blockmanager->get_regions());
}
public function test_add_regions() {
// Set up fixture.
$regions = array('a-region', 'another-region');
// Exercise SUT.
$this->blockmanager->add_regions($regions);
// Validate
$this->assertEquals($regions, $this->blockmanager->get_regions(), '', 0, 10, true);
}
public function test_add_region_twice() {
// Exercise SUT.
$this->blockmanager->add_region('a-region-name');
$this->blockmanager->add_region('another-region');
// Validate
$this->assertEquals(array('a-region-name', 'another-region'), $this->blockmanager->get_regions(), '', 0, 10, true);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_cannot_add_region_after_loaded() {
// Set up fixture.
$this->blockmanager->mark_loaded();
// Exercise SUT.
$this->blockmanager->add_region('too-late');
}
public function test_set_default_region() {
// Set up fixture.
$this->blockmanager->add_region('a-region-name');
// Exercise SUT.
$this->blockmanager->set_default_region('a-region-name');
// Validate
$this->assertEquals('a-region-name', $this->blockmanager->get_default_region());
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_cannot_set_unknown_region_as_default() {
// Exercise SUT.
$this->blockmanager->set_default_region('a-region-name');
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_cannot_change_default_region_after_loaded() {
// Set up fixture.
$this->blockmanager->mark_loaded();
// Exercise SUT.
$this->blockmanager->set_default_region('too-late');
}
public function test_matching_page_type_patterns() {
$this->assertEquals(array('site-index', 'site-index-*', 'site-*', '*'),
matching_page_type_patterns('site-index'), '', 0, 10, true);
$this->assertEquals(array('mod-quiz-report-overview', 'mod-quiz-report-overview-*', 'mod-quiz-report-*', 'mod-quiz-*', 'mod-*', '*'),
matching_page_type_patterns('mod-quiz-report-overview'), '', 0, 10, true);
$this->assertEquals(array('mod-forum-view', 'mod-*-view', 'mod-forum-view-*', 'mod-forum-*', 'mod-*', '*'),
matching_page_type_patterns('mod-forum-view'), '', 0, 10, true);
$this->assertEquals(array('mod-forum-index', 'mod-*-index', 'mod-forum-index-*', 'mod-forum-*', 'mod-*', '*'),
matching_page_type_patterns('mod-forum-index'), '', 0, 10, true);
}
}
/**
* Test methods that load and save data from block_instances and block_positions.
*/
class moodle_block_manager_test_saving_loading_testcase extends advanced_testcase {
protected $isediting = null;
protected function purge_blocks() {
global $DB;
$bis = $DB->get_records('block_instances');
foreach($bis as $instance) {
blocks_delete_instance($instance);
}
$this->resetAfterTest(true);
}
protected function get_a_page_and_block_manager($regions, $context, $pagetype, $subpage = '') {
$page = new moodle_page;
$page->set_context($context);
$page->set_pagetype($pagetype);
$page->set_subpage($subpage);
$blockmanager = new testable_block_manager($page);
$blockmanager->add_regions($regions);
$blockmanager->set_default_region($regions[0]);
return array($page, $blockmanager);
}
protected function get_a_known_block_type() {
global $DB;
$block = new stdClass;
$block->name = 'ablocktype';
$DB->insert_record('block', $block);
return $block->name;
}
protected function assertContainsBlocksOfType($typearray, $blockarray) {
if (!$this->assertEquals(count($typearray), count($blockarray), "Blocks array contains the wrong number of elements %s.")) {
return;
}
$types = array_values($typearray);
$i = 0;
foreach ($blockarray as $block) {
$blocktype = $types[$i];
$this->assertEquals($blocktype, $block->name(), "Block types do not match at postition $i %s.");
$i++;
}
}
public function test_empty_initially() {
$this->purge_blocks();
// Set up fixture.
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array('a-region'),
get_context_instance(CONTEXT_SYSTEM), 'page-type');
// Exercise SUT.
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_loaded_blocks();
$this->assertEquals(array('a-region' => array()), $blocks);
}
public function test_adding_and_retrieving_one_block() {
$this->purge_blocks();
// Set up fixture.
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
$context = get_context_instance(CONTEXT_SYSTEM);
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$context, 'page-type');
// Exercise SUT.
$blockmanager->add_block($blockname, $regionname, 0, false);
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array($blockname), $blocks);
}
public function test_adding_and_retrieving_two_blocks() {
$this->purge_blocks();
// Set up fixture.
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
$context = get_context_instance(CONTEXT_SYSTEM);
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$context, 'page-type');
// Exercise SUT.
$blockmanager->add_block($blockname, $regionname, 0, false);
$blockmanager->add_block($blockname, $regionname, 1, false);
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array($blockname, $blockname), $blocks);
}
public function test_block_not_included_in_different_context() {
global $DB;
$this->purge_blocks();
// Set up fixture.
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$cat = new stdClass();
$cat->name = 'testcategory';
$cat->parent = 0;
$cat->depth = 1;
$cat->sortorder = 100;
$cat->timemodified = time();
$catid = $DB->insert_record('course_categories', $cat);
$DB->set_field('course_categories', 'path', '/' . $catid, array('id' => $catid));
$fakecontext = context_coursecat::instance($catid);
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $fakecontext, 'page-type');
list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
$addbm->add_block($blockname, $regionname, 0, false);
// Exercise SUT.
$viewbm->load_blocks();
// Validate.
$blocks = $viewbm->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array(), $blocks);
}
public function test_block_included_in_sub_context() {
$this->purge_blocks();
// Set up fixture.
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$childcontext = context_coursecat::instance(1);
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $childcontext, 'page-type');
$addbm->add_block($blockname, $regionname, 0, true);
// Exercise SUT.
$viewbm->load_blocks();
// Validate.
$blocks = $viewbm->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array($blockname), $blocks);
}
public function test_block_not_included_on_different_page_type() {
$this->purge_blocks();
// Set up fixture.
$syscontext = get_context_instance(CONTEXT_SYSTEM);
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
list($addpage, $addbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'page-type');
list($viewpage, $viewbm) = $this->get_a_page_and_block_manager(array($regionname), $syscontext, 'other-page-type');
$addbm->add_block($blockname, $regionname, 0, true);
// Exercise SUT.
$viewbm->load_blocks();
// Validate.
$blocks = $viewbm->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array(), $blocks);
}
public function test_block_not_included_on_different_sub_page() {
$this->purge_blocks();
// Set up fixture.
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
$syscontext = get_context_instance(CONTEXT_SYSTEM);
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$syscontext, 'page-type', 'sub-page');
$blockmanager->add_block($blockname, $regionname, 0, true, $page->pagetype, 'other-sub-page');
// Exercise SUT.
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array(), $blocks);
}
public function test_block_included_with_explicit_sub_page() {
$this->purge_blocks();
// Set up fixture.
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
$syscontext = get_context_instance(CONTEXT_SYSTEM);
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$syscontext, 'page-type', 'sub-page');
$blockmanager->add_block($blockname, $regionname, 0, true, $page->pagetype, $page->subpage);
// Exercise SUT.
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array($blockname), $blocks);
}
public function test_block_included_with_page_type_pattern() {
$this->purge_blocks();
// Set up fixture.
$regionname = 'a-region';
$blockname = $this->get_a_known_block_type();
$syscontext = get_context_instance(CONTEXT_SYSTEM);
list($page, $blockmanager) = $this->get_a_page_and_block_manager(array($regionname),
$syscontext, 'page-type', 'sub-page');
$blockmanager->add_block($blockname, $regionname, 0, true, 'page-*', $page->subpage);
// Exercise SUT.
$blockmanager->load_blocks();
// Validate.
$blocks = $blockmanager->get_blocks_for_region($regionname);
$this->assertContainsBlocksOfType(array($blockname), $blocks);
}
}
+56
View File
@@ -0,0 +1,56 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Code quality unit tests that are fast enough to run each time.
*
* @package core
* @category phpunit
* @copyright &copy; 2006 The Open University
* @author T.J.Hunt@open.ac.uk
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
defined('MOODLE_INTERNAL') || die();
class code_testcase extends advanced_testcase {
protected $badstrings;
protected $extensions_to_ignore = array('exe', 'gif', 'ico', 'jpg', 'png', 'ttf', 'log');
protected $ignore_folders = array();
public function test_dnc() {
global $CFG;
$regexp = '/\.(' . implode('|', $this->extensions_to_ignore) . ')$/';
$this->badstrings = array();
$this->badstrings['DONOT' . 'COMMIT'] = 'DONOT' . 'COMMIT'; // If we put the literal string here, it fails the test!
$this->badstrings['trailing whitespace'] = "[\t ][\r\n]";
foreach ($this->badstrings as $description => $ignored) {
$this->allok[$description] = true;
}
$this->recurseFolders($CFG->dirroot, 'search_file_for_dnc', $regexp, true);
$this->assertTrue(true); // executed only if no file failed the test
}
protected function search_file_for_dnc($filepath) {
$content = file_get_contents($filepath);
foreach ($this->badstrings as $description => $badstring) {
if (stripos($content, $badstring) !== false) {
$this->fail("File $filepath contains $description.");
}
}
}
}
+182
View File
@@ -0,0 +1,182 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for /lib/componentlib.class.php.
*
* @package core
* @category phpunit
* @copyright 2011 Tomasz Muras
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir.'/componentlib.class.php');
class componentlib_testcase extends advanced_testcase {
public function test_component_installer() {
global $CFG;
$ci = new component_installer('http://download.moodle.org', 'unittest', 'downloadtests.zip');
$this->assertTrue($ci->check_requisites());
$destpath = $CFG->dataroot.'/downloadtests';
//carefully remove component files to enforce fresh installation
@unlink($destpath.'/'.'downloadtests.md5');
@unlink($destpath.'/'.'test.html');
@unlink($destpath.'/'.'test.jpg');
@rmdir($destpath);
$this->assertEquals(COMPONENT_NEEDUPDATE, $ci->need_upgrade());
$status = $ci->install();
$this->assertEquals(COMPONENT_INSTALLED, $status);
$this->assertEquals('9e94f74b3efb1ff6cf075dc6b2abf15c', $ci->get_component_md5());
//it's already installed, so Moodle should detect it's up to date
$this->assertEquals(COMPONENT_UPTODATE, $ci->need_upgrade());
$status = $ci->install();
$this->assertEquals(COMPONENT_UPTODATE, $status);
//check if correct files were downloaded
$this->assertEquals('2af180e813dc3f446a9bb7b6af87ce24', md5_file($destpath.'/'.'test.jpg'));
$this->assertEquals('47250a973d1b88d9445f94db4ef2c97a', md5_file($destpath.'/'.'test.html'));
}
/**
* Test the public API of the {@link lang_installer} class
*/
public function test_lang_installer() {
// test the manipulation with the download queue
$installer = new testable_lang_installer();
$this->assertFalse($installer->protected_is_queued());
$installer->protected_add_to_queue('cs');
$installer->protected_add_to_queue(array('cs', 'sk'));
$this->assertTrue($installer->protected_is_queued());
$this->assertTrue($installer->protected_is_queued('cs'));
$this->assertTrue($installer->protected_is_queued('sk'));
$this->assertFalse($installer->protected_is_queued('de_kids'));
$installer->set_queue('de_kids');
$this->assertFalse($installer->protected_is_queued('cs'));
$this->assertFalse($installer->protected_is_queued('sk'));
$this->assertFalse($installer->protected_is_queued('de'));
$this->assertFalse($installer->protected_is_queued('de_du'));
$this->assertTrue($installer->protected_is_queued('de_kids'));
$installer->set_queue(array('cs', 'de_kids'));
$this->assertTrue($installer->protected_is_queued('cs'));
$this->assertFalse($installer->protected_is_queued('sk'));
$this->assertFalse($installer->protected_is_queued('de'));
$this->assertFalse($installer->protected_is_queued('de_du'));
$this->assertTrue($installer->protected_is_queued('de_kids'));
$installer->set_queue(array());
$this->assertFalse($installer->protected_is_queued());
unset($installer);
// install a set of lang packs
$installer = new testable_lang_installer(array('cs', 'de_kids', 'xx'));
$result = $installer->run();
$this->assertEquals($result['cs'], lang_installer::RESULT_UPTODATE);
$this->assertEquals($result['de_kids'], lang_installer::RESULT_INSTALLED);
$this->assertEquals($result['xx'], lang_installer::RESULT_DOWNLOADERROR);
// the following two were automatically added to the queue
$this->assertEquals($result['de_du'], lang_installer::RESULT_INSTALLED);
$this->assertEquals($result['de'], lang_installer::RESULT_UPTODATE);
// exception throwing
$installer = new testable_lang_installer(array('yy'));
try {
$installer->run();
$this->fail('lang_installer_exception exception expected');
} catch (Exception $e) {
$this->assertEquals('lang_installer_exception', get_class($e));
}
}
}
/**
* Testable lang_installer subclass that does not actually install anything
* and provides access to the protected methods of the parent class
*
* @copyright 2011 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class testable_lang_installer extends lang_installer {
/**
* @see parent::is_queued()
*/
public function protected_is_queued($langcode = '') {
return $this->is_queued($langcode);
}
/**
* @see parent::add_to_queue()
*/
public function protected_add_to_queue($langcodes) {
return $this->add_to_queue($langcodes);
}
/**
* Simulate lang pack installation via component_installer
*
* Language packages 'de_du' and 'de_kids' reported as installed
* Language packages 'cs' and 'de' reported as up-to-date
* Language package 'xx' returns download error
* All other language packages will throw an unknown exception
*
* @see parent::install_language_pack()
*/
protected function install_language_pack($langcode) {
switch ($langcode) {
case 'de_du':
case 'de_kids':
return self::RESULT_INSTALLED;
case 'cs':
case 'de':
return self::RESULT_UPTODATE;
case 'xx':
return self::RESULT_DOWNLOADERROR;
default:
throw new lang_installer_exception('testing-unknown-exception', $langcode);
}
}
/**
* Simulate detection of parent languge
*
* @see parent::get_parent_language()
*/
protected function get_parent_language($langcode) {
switch ($langcode) {
case 'de_kids':
return 'de_du';
case 'de_du':
return 'de';
default:
return '';
}
}
}
+366
View File
@@ -0,0 +1,366 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for conditional activities
*
* @package core
* @category phpunit
* @copyright &copy; 2008 The Open University
* @author Sam Marshall
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/lib/conditionlib.php');
class conditionlib_testcase extends advanced_testcase {
protected function setUp() {
global $CFG;
parent::setUp();
$this->resetAfterTest(true);
$CFG->enableavailability = 1;
$CFG->enablecompletion = 1;
}
function test_constructor() {
global $DB,$CFG;
$cm=new stdClass;
// Test records
$id=$DB->insert_record('course_modules',(object)array(
'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,'course'=>64));
// no ID
try {
$test=new condition_info($cm);
$this->fail();
} catch(coding_exception $e) {
}
// no other data
$cm->id=$id;
$test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
$this->assertEquals(
(object)array('id'=>$id,'showavailability'=>1,
'availablefrom'=>17,'availableuntil'=>398,'course'=>64,
'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
$test->get_full_course_module());
// just the course_modules stuff; check it doesn't request that from db
$cm->showavailability=0;
$cm->availablefrom=2;
$cm->availableuntil=74;
$cm->course=38;
$test=new condition_info($cm,CONDITION_MISSING_EXTRATABLE);
$this->assertEquals(
(object)array('id'=>$id,'showavailability'=>0,
'availablefrom'=>2,'availableuntil'=>74,'course'=>38,
'conditionsgrade'=>array(), 'conditionscompletion'=>array()),
$test->get_full_course_module());
// Now let's add some actual grade/completion conditions
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'sourcecmid'=>42,
'requiredcompletion'=>2
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'sourcecmid'=>666,
'requiredcompletion'=>1
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$id,
'gradeitemid'=>37,
'grademin'=>5.5
));
$cm=(object)array('id'=>$id);
$test=new condition_info($cm,CONDITION_MISSING_EVERYTHING);
$fullcm=$test->get_full_course_module();
$this->assertEquals(array(42=>2,666=>1),$fullcm->conditionscompletion);
$this->assertEquals(array(37=>(object)array('min'=>5.5,'max'=>null,'name'=>'!missing')),
$fullcm->conditionsgrade);
}
private function make_course() {
global $DB;
$categoryid=$DB->insert_record('course_categories',(object)array('name'=>'conditionlibtest'));
return $DB->insert_record('course',(object)array(
'fullname'=>'Condition test','shortname'=>'CT1',
'category'=>$categoryid,'enablecompletion'=>1));
}
private function make_course_module($courseid,$params=array()) {
global $DB;
static $moduleid=0;
if(!$moduleid) {
$moduleid=$DB->get_field('modules','id',array('name'=>'resource'));
}
$rid=$DB->insert_record('resource',(object)array('course'=>$courseid,
'name'=>'xxx','alltext'=>'','popup'=>''));
$settings=(object)array(
'course'=>$courseid,'module'=>$moduleid,'instance'=>$rid);
foreach($params as $name=>$value) {
$settings->{$name}=$value;
}
return $DB->insert_record('course_modules',$settings);
}
private function make_section($courseid,$cmids,$sectionnum=0) {
global $DB;
$DB->insert_record('course_sections',(object)array(
'course'=>$courseid,'sequence'=>implode(',',$cmids),'section'=>$sectionnum));
}
function test_modinfo() {
global $DB;
// Let's make a course
$courseid=$this->make_course();
// Now let's make a couple modules on that course
$cmid1=$this->make_course_module($courseid,array(
'showavailability'=>1,'availablefrom'=>17,'availableuntil'=>398,
'completion'=>COMPLETION_TRACKING_MANUAL));
$cmid2=$this->make_course_module($courseid,array(
'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
$this->make_section($courseid,array($cmid1,$cmid2));
// Add a fake grade item
$gradeitemid=$DB->insert_record('grade_items',(object)array(
'courseid'=>$courseid,'itemname'=>'frog'));
// One of the modules has grade and completion conditions, other doesn't
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$cmid2,
'sourcecmid'=>$cmid1,
'requiredcompletion'=>1
));
$DB->insert_record('course_modules_availability',(object)array(
'coursemoduleid'=>$cmid2,
'gradeitemid'=>$gradeitemid,
'grademin'=>5.5
));
// Okay sweet, now get modinfo
$course = $DB->get_record('course',array('id'=>$courseid));
$modinfo=get_fast_modinfo($course);
// Test basic data
$this->assertEquals(1,$modinfo->cms[$cmid1]->showavailability);
$this->assertEquals(17,$modinfo->cms[$cmid1]->availablefrom);
$this->assertEquals(398,$modinfo->cms[$cmid1]->availableuntil);
$this->assertEquals(0,$modinfo->cms[$cmid2]->showavailability);
$this->assertEquals(0,$modinfo->cms[$cmid2]->availablefrom);
$this->assertEquals(0,$modinfo->cms[$cmid2]->availableuntil);
// Test condition arrays
$this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionscompletion);
$this->assertEquals(array(),$modinfo->cms[$cmid1]->conditionsgrade);
$this->assertEquals(array($cmid1=>1),
$modinfo->cms[$cmid2]->conditionscompletion);
$this->assertEquals(array($gradeitemid=>(object)array('min'=>5.5,'max'=>null,'name'=>'frog')),
$modinfo->cms[$cmid2]->conditionsgrade);
}
function test_add_and_remove() {
global $DB;
// Make course and module
$courseid=$this->make_course();
$cmid=$this->make_course_module($courseid,array(
'showavailability'=>0,'availablefrom'=>0,'availableuntil'=>0));
$this->make_section($courseid,array($cmid));
// Check it has no conditions
$test1=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test1->get_full_course_module();
$this->assertEquals(array(),$cm->conditionscompletion);
$this->assertEquals(array(),$cm->conditionsgrade);
// Add conditions of each type
$test1->add_completion_condition(13,3);
$this->assertEquals(array(13=>3),$cm->conditionscompletion);
$test1->add_grade_condition(666,0.4,null,true);
$this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
$cm->conditionsgrade);
// Check they were really added in db
$test2=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test2->get_full_course_module();
$this->assertEquals(array(13=>3),$cm->conditionscompletion);
$this->assertEquals(array(666=>(object)array('min'=>0.4,'max'=>null,'name'=>'!missing')),
$cm->conditionsgrade);
// Wipe conditions
$test2->wipe_conditions();
$this->assertEquals(array(),$cm->conditionscompletion);
$this->assertEquals(array(),$cm->conditionsgrade);
// Check they were really wiped
$test3=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$cm=$test3->get_full_course_module();
$this->assertEquals(array(),$cm->conditionscompletion);
$this->assertEquals(array(),$cm->conditionsgrade);
}
function test_is_available() {
global $DB,$USER;
$courseid=$this->make_course();
// No conditions
$cmid=$this->make_course_module($courseid);
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertTrue($ci->is_available($text,false,0));
$this->assertEquals('',$text);
// Time (from)
$time=time()+100;
$cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertFalse($ci->is_available($text));
$this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$text);
$time=time()-100;
$cmid=$this->make_course_module($courseid,array('availablefrom'=>$time));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertTrue($ci->is_available($text));
$this->assertEquals('',$text);
$this->assertRegExp('/'.preg_quote(userdate($time,get_string('strftimedate','langconfig'))).'/',$ci->get_full_information());
// Time (until)
$cmid=$this->make_course_module($courseid,array('availableuntil'=>time()-100));
$ci=new condition_info((object)array('id'=>$cmid),
CONDITION_MISSING_EVERYTHING);
$this->assertFalse($ci->is_available($text));
$this->assertEquals('',$text);
// Completion
$oldid=$cmid;
$cmid=$this->make_course_module($courseid);
$this->make_section($courseid,array($oldid,$cmid));
$oldcm=$DB->get_record('course_modules',array('id'=>$oldid));
$oldcm->completion=COMPLETION_TRACKING_MANUAL;
$DB->update_record('course_modules',$oldcm);
// Need to reset modinfo after changing the options
rebuild_course_cache($courseid);
$reset = 'reset';
get_fast_modinfo($reset);
$ci=new condition_info((object)array('id'=>$cmid),CONDITION_MISSING_EVERYTHING);
$ci->add_completion_condition($oldid,COMPLETION_COMPLETE);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text,false));
$this->assertEquals(get_string('requires_completion_1','condition','xxx'),$text);
completion_info::wipe_session_cache();
$completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
$completion->update_state($oldcm,COMPLETION_COMPLETE);
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
$this->assertFalse($ci->is_available($text,false,$USER->id+1));
completion_info::wipe_session_cache();
condition_info::wipe_session_cache();
$completion=new completion_info($DB->get_record('course',array('id'=>$courseid)));
$completion->update_state($oldcm,COMPLETION_INCOMPLETE);
$this->assertFalse($ci->is_available($text));
$ci->wipe_conditions();
$ci->add_completion_condition($oldid,COMPLETION_INCOMPLETE);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
$this->assertTrue($ci->is_available($text,false,$USER->id+1));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text,true));
// Grade
$ci->wipe_conditions();
// Add a fake grade item
$gradeitemid=$DB->insert_record('grade_items',(object)array(
'courseid'=>$courseid,'itemname'=>'frog'));
// Add a condition on a value existing...
$ci->add_grade_condition($gradeitemid,null,null,true);
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_any','condition','frog'),$text);
// Fake it existing
$DB->insert_record('grade_grades',(object)array(
'itemid'=>$gradeitemid,'userid'=>$USER->id,'finalgrade'=>3.78));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text,true));
// Now require that user gets more than 3.78001
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3.78001,null,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_min','condition','frog'),$text);
// ...just on 3.78...
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3.78,null,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...less than 3.78
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,null,3.78,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_max','condition','frog'),$text);
// ...less than 3.78001
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,null,3.78001,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that includes it
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,3,4,true);
condition_info::wipe_session_cache();
$this->assertTrue($ci->is_available($text));
// ...in a range that doesn't include it
$ci->wipe_conditions();
$ci->add_grade_condition($gradeitemid,4,5,true);
condition_info::wipe_session_cache();
$this->assertFalse($ci->is_available($text));
$this->assertEquals(get_string('requires_grade_range','condition','frog'),$text);
}
}
+721
View File
@@ -0,0 +1,721 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the unittests for the css optimiser in csslib.php
*
* @package core_css
* @category phpunit
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/csslib.php');
/**
* CSS optimiser test class
*
* @package core_css
* @category css
* @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_optimiser_testcase extends advanced_testcase {
/**
* Sets up the test class
*/
protected function setUp() {
global $CFG;
parent::setUp();
// We need to disable these if they are enabled to that we can predict
// the output.
$CFG->cssoptimiserstats = false;
$CFG->cssoptimiserpretty = false;
$this->resetAfterTest(true);
}
/**
* Test the process method
*/
public function test_process() {
$optimiser = new css_optimiser;
$this->check_background($optimiser);
$this->check_borders($optimiser);
$this->check_colors($optimiser);
$this->check_margins($optimiser);
$this->check_padding($optimiser);
$this->check_widths($optimiser);
$this->try_broken_css_found_in_moodle($optimiser);
$this->try_invalid_css_handling($optimiser);
$this->try_bulk_processing($optimiser);
$this->try_break_things($optimiser);
}
/**
* Background colour tests
* @param css_optimiser $optimiser
*/
protected function check_background(css_optimiser $optimiser) {
$cssin = '.test {background-color: #123456;}';
$cssout = '.test{background:#123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background-image: url(\'test.png\');}';
$cssout = '.test{background-image:url(\'test.png\');}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background: #123456 url(\'test.png\') no-repeat top left;}';
$cssout = '.test{background:#123456 url(\'test.png\') no-repeat top left;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background: url(\'test.png\') no-repeat top left;}.test{background-position: bottom right}.test {background-color:#123456;}';
$cssout = '.test{background:#123456 url(\'test.png\') no-repeat bottom right;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background: url( \'test.png\' )}.test{background: bottom right}.test {background:#123456;}';
$cssout = '.test{background-image:url(\'test.png\');background-position:bottom right;background-color:#123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background-color: #123456;background-repeat: repeat-x; background-position: 100% 0%;}';
$cssout = '.test{background-color:#123456;background-repeat:repeat-x;background-position:100% 0%;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.tree_item.branch {background-image: url([[pix:t/expanded]]);background-position: 0 10%;background-repeat: no-repeat;}
.tree_item.branch.navigation_node {background-image:none;padding-left:0;}';
$cssout = '.tree_item.branch{background:url([[pix:t/expanded]]) no-repeat 0 10%;} .tree_item.branch.navigation_node{background-image:none;padding-left:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.block_tree .tree_item.emptybranch {background-image: url([[pix:t/collapsed_empty]]);background-position: 0% 5%;background-repeat: no-repeat;}
.block_tree .collapsed .tree_item.branch {background-image: url([[pix:t/collapsed]]);}';
$cssout = '.block_tree .tree_item.emptybranch{background:url([[pix:t/collapsed_empty]]) no-repeat 0% 5%;} .block_tree .collapsed .tree_item.branch{background-image:url([[pix:t/collapsed]]);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '#nextLink{background:url(data:image/gif;base64,AAAA);}';
$cssout = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
$cssout = '#nextLink{background-image:url(data:image/gif;base64,AAAA);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {background: #123456 url(data:image/gif;base64,AAAA) no-repeat top left;}';
$cssout = '.test{background:#123456 url(data:image/gif;base64,AAAA) no-repeat top left;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Border tests
* @param css_optimiser $optimiser
*/
protected function check_borders(css_optimiser $optimiser) {
$cssin = '.test {border: 1px solid #654321} .test {border-bottom-color: #123456}';
$cssout = '.test{border:1px solid;border-color:#654321 #654321 #123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {border:1px solid red;}';
$cssout = '.one{border:1px solid #FF0000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {border:1px solid;} .one {border:2px dotted #DDD;}';
$cssout = '.one{border:2px dotted #DDDDDD;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {border:2px dotted #DDD;}.one {border:1px solid;} ';
$cssout = '.one{border:1px solid #DDDDDD;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one, .two {border:1px solid red;}';
$cssout = ".one, .two{border:1px solid #FF0000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one, .two {border:0px;}';
$cssout = ".one, .two{border-width:0;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one, .two {border-top: 5px solid white;}';
$cssout = ".one, .two{border-top:5px solid #FFFFFF;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {border:1px solid red;} .two {border:1px solid red;}';
$cssout = ".one, .two{border:1px solid #FF0000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {border:1px solid red;width:20px;} .two {border:1px solid red;height:20px;}';
$cssout = ".one{width:20px;border:1px solid #FF0000;} .two{height:20px;border:1px solid #FF0000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border: 1px solid #123456;} .test {border-color: #654321}';
$cssout = '.test{border:1px solid #654321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border-width: 1px; border-style: solid; border-color: #123456;}';
$cssout = '.test{border:1px solid #123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border:1px solid #123456;border-top:2px dotted #654321;}';
$cssout = '.test{border:1px solid #123456;border-top:2px dotted #654321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border:1px solid #123456;border-left:2px dotted #654321;}';
$cssout = '.test{border:1px solid #123456;border-left:2px dotted #654321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border-left:2px dotted #654321;border:1px solid #123456;}';
$cssout = '.test{border:1px solid #123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border:1px solid;border-top-color:#123456;}';
$cssout = '.test{border:1px solid;border-top-color:#123456;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;}';
$cssout = '.test{border:1px solid;border-top-color:#111;border-bottom-color:#222;border-left-color:#333;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;border-right-color:#444;}';
$cssout = '.test{border:1px solid;border-color:#111 #444 #222 #333;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.generaltable .cell {border-color:#EEEEEE;} .generaltable .cell {border-width: 1px;border-style: solid;}';
$cssout = '.generaltable .cell{border:1px solid #EEEEEE;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '#page-admin-roles-override .rolecap {border:none;border-bottom:1px solid #CECECE;}';
$cssout = '#page-admin-roles-override .rolecap{border-top:0;border-right:0;border-bottom:1px solid #CECECE;border-left:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Test colour styles
* @param css_optimiser $optimiser
*/
protected function check_colors(css_optimiser $optimiser) {
$css = '.css{}';
$this->assertEquals($css, $optimiser->process($css));
$css = '.css{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = '#some{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div.css{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div#some{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div[type=blah]{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div.css[type=blah]{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div#some[type=blah]{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = '#some.css[type=blah]{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$css = '#some .css[type=blah]{color:#123456;}';
$this->assertEquals($css, $optimiser->process($css));
$cssin = '.one {color:red;} .two {color:#F00;}';
$cssout = ".one, .two{color:#F00;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:#123;color:#321;}';
$cssout = '.one{color:#321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:#123; color : #321 ;}';
$cssout = '.one{color:#321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:#123;} .one {color:#321;}';
$cssout = '.one{color:#321;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:#123 !important;color:#321;}';
$cssout = '.one{color:#123 !important;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:#123 !important;} .one {color:#321;}';
$cssout = '.one{color:#123 !important;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:rgb(255, 128, 1)}';
$cssout = '.one{color:rgb(255, 128, 1);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:rgba(255, 128, 1, 0.5)}';
$cssout = '.one{color:rgba(255, 128, 1, 0.5);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:hsl(120, 65%, 75%)}';
$cssout = '.one{color:hsl(120, 65%, 75%);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:hsla(120,65%,75%,0.5)}';
$cssout = '.one{color:hsla(120,65%,75%,0.5);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Try some invalid colours to make sure we don't mangle them.
$css = 'div#some{color:#1;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div#some{color:#12;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div#some{color:#1234;}';
$this->assertEquals($css, $optimiser->process($css));
$css = 'div#some{color:#12345;}';
$this->assertEquals($css, $optimiser->process($css));
}
protected function check_widths(css_optimiser $optimiser) {
$cssin = '.css {width:0}';
$cssout = '.css{width:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.css {width:0px}';
$cssout = '.css{width:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.css {width:0em}';
$cssout = '.css{width:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.css {width:0pt}';
$cssout = '.css{width:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.css {width:0mm}';
$cssout = '.css{width:0;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.css {width:100px}';
$cssout = '.css{width:100px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Test margin styles
* @param css_optimiser $optimiser
*/
protected function check_margins(css_optimiser $optimiser) {
$cssin = '.one {margin: 1px 2px 3px 4px}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin-top:1px; margin-left:4px; margin-right:2px; margin-bottom: 3px;}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin-top:1px; margin-left:4px;}';
$cssout = '.one{margin-top:1px;margin-left:4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin:1px; margin-left:4px;}';
$cssout = '.one{margin:1px 1px 1px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin:1px; margin-bottom:4px;}';
$cssout = '.one{margin:1px 1px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}';
$cssout = '.one, .two, .one .two{margin:0;} .one.two{margin:0 7px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Test padding styles
*
* @param css_optimiser $optimiser
*/
protected function check_padding(css_optimiser $optimiser) {
$cssin = '.one {margin: 1px 2px 3px 4px}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin-top:1px; margin-left:4px; margin-right:2px; margin-bottom: 3px;}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin-top:1px; margin-left:4px;}';
$cssout = '.one{margin-top:1px;margin-left:4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin:1px; margin-left:4px;}';
$cssout = '.one{margin:1px 1px 1px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin:1px; margin-bottom:4px;}';
$cssout = '.one{margin:1px 1px 4px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {margin:0 !important;}';
$cssout = '.one{margin:0 !important;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {padding:0 !important;}';
$cssout = '.one{padding:0 !important;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}';
$cssout = '.one, .two, .one .two{margin:0;} .one.two{margin:0 7px;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Test some totally invalid CSS optimisation
*
* @param css_optimiser $optimiser
*/
protected function try_invalid_css_handling(css_optimiser $optimiser) {
$cssin = array(
'.one{}',
'.one {:}',
'.one {;}',
'.one {;;;;;}',
'.one {:;}',
'.one {:;:;:;:::;;;}',
'.one {!important}',
'.one {:!important}',
'.one {:!important;}',
'.one {;!important}'
);
$cssout = '.one{}';
foreach ($cssin as $css) {
$this->assertEquals($cssout, $optimiser->process($css));
}
$cssin = array(
'.one{background-color:red;}',
'.one {background-color:red;} .one {background-color:}',
'.one {background-color:red;} .one {background-color;}',
'.one {background-color:red;} .one {background-color}',
'.one {background-color:red;} .one {background-color:;}',
'.one {background-color:red;} .one {:blue;}',
'.one {background-color:red;} .one {:#00F}',
);
$cssout = '.one{background:#F00;}';
foreach ($cssin as $css) {
$this->assertEquals($cssout, $optimiser->process($css));
}
$cssin = '..one {background-color:color:red}';
$cssout = '..one{background-color:color:red;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '#.one {background-color:color:red}';
$cssout = '#.one{background-color:color:red;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '##one {background-color:color:red}';
$cssout = '##one{background-color:color:red;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {background-color:color:red}';
$cssout = '.one{background-color:color:red;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {background-color:red;color;border-color:blue}';
$cssout = '.one{background:#F00;border-color:#00F;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '{background-color:#123456;color:red;}{color:green;}';
$cssout = "{color:#008000;background:#123456;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
$cssin = '.one {color:red;} {color:green;} .one {background-color:blue;}';
$cssout = ".one{color:#F00;background:#00F;} {color:#008000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* Try to break some things
* @param css_optimiser $optimiser
*/
protected function try_break_things(css_optimiser $optimiser) {
// Wildcard test
$cssin = '* {color: black;}';
$cssout = '*{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Wildcard test
$cssin = '.one * {color: black;}';
$cssout = '.one *{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Wildcard test
$cssin = '* .one * {color: black;}';
$cssout = '* .one *{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Wildcard test
$cssin = '*,* {color: black;}';
$cssout = '*{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Wildcard test
$cssin = '*, * .one {color: black;}';
$cssout = "*,\n* .one{color:#000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
// Wildcard test
$cssin = '*, *.one {color: black;}';
$cssout = "*,\n*.one{color:#000;}";
$this->assertEquals($cssout, $optimiser->process($cssin));
// Psedo test
$cssin = '.one:before {color: black;}';
$cssout = '.one:before{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Psedo test
$cssin = '.one:after {color: black;}';
$cssout = '.one:after{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Psedo test
$cssin = '.one:onclick {color: black;}';
$cssout = '.one:onclick{color:#000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Test complex CSS rules that don't really exist but mimic other CSS rules
$cssin = '.one {master-of-destruction: explode(\' \', "What madness");}';
$cssout = '.one{master-of-destruction:explode(\' \', "What madness");}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Test some complex IE css... I couldn't even think of a more complext solution
// than the CSS they came up with.
$cssin = 'a { opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50); }';
$cssout = 'a{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
/**
* A bulk processing test
* @param css_optimiser $optimiser
*/
protected function try_bulk_processing(css_optimiser $optimiser) {
global $CFG;
$cssin = <<<CSS
.test .one {
margin:5px;
border:0;
}
.test .one {
margin: 10px;
color: red;
}
.test.one {
margin: 15px;
}
#test .one {margin: 20px;}
#test #one {margin: 25px;}.test #one {margin: 30px;}
.test .one { background-color: #123; }
.test.one{border:1px solid blue}.test.one{border-color:green;}
@media print {
#test .one {margin: 35px;}
}
@media print {
#test .one {margin: 40px;color: #123456;}
#test #one {margin: 45px;}
}
@media print,screen {
#test .one {color: #654321;}
}
#test .one,
#new.style {color:#000;}
CSS;
$cssout = <<<CSS
.test .one{color:#F00;margin:10px;border-width:0;background:#123;}
.test.one{margin:15px;border:1px solid #008000;}
#test .one{color:#000;margin:20px;}
#test #one{margin:25px;}
.test #one{margin:30px;}
#new.style{color:#000;}
@media print {
#test .one{color:#123456;margin:40px;}
#test #one{margin:45px;}
}
@media print,screen {
#test .one{color:#654321;}
}
CSS;
$CFG->cssoptimiserpretty = 1;
$this->assertEquals($optimiser->process($cssin), $cssout);
}
/**
* Test CSS colour matching
*/
public function test_css_is_colour() {
// First lets test hex colours
$this->assertTrue(css_is_colour('#123456'));
$this->assertTrue(css_is_colour('#123'));
$this->assertTrue(css_is_colour('#ABCDEF'));
$this->assertTrue(css_is_colour('#ABC'));
$this->assertTrue(css_is_colour('#abcdef'));
$this->assertTrue(css_is_colour('#abc'));
$this->assertTrue(css_is_colour('#aBcDeF'));
$this->assertTrue(css_is_colour('#aBc'));
$this->assertTrue(css_is_colour('#1a2Bc3'));
$this->assertTrue(css_is_colour('#1Ac'));
// Note the following two colour's arn't really colours but browsers process
// them still.
$this->assertTrue(css_is_colour('#A'));
$this->assertTrue(css_is_colour('#12'));
// Having four or five characters however are not valid colours and
// browsers don't parse them. They need to fail so that broken CSS
// stays broken after optimisation.
$this->assertFalse(css_is_colour('#1234'));
$this->assertFalse(css_is_colour('#12345'));
$this->assertFalse(css_is_colour('#BCDEFG'));
$this->assertFalse(css_is_colour('#'));
$this->assertFalse(css_is_colour('#0000000'));
$this->assertFalse(css_is_colour('#132-245'));
$this->assertFalse(css_is_colour('#13 23 43'));
$this->assertFalse(css_is_colour('123456'));
// Next lets test real browser mapped colours
$this->assertTrue(css_is_colour('black'));
$this->assertTrue(css_is_colour('blue'));
$this->assertTrue(css_is_colour('BLACK'));
$this->assertTrue(css_is_colour('Black'));
$this->assertTrue(css_is_colour('bLACK'));
$this->assertTrue(css_is_colour('mediumaquamarine'));
$this->assertTrue(css_is_colour('mediumAquamarine'));
$this->assertFalse(css_is_colour('monkey'));
$this->assertFalse(css_is_colour(''));
$this->assertFalse(css_is_colour('not a colour'));
// Next lets test rgb(a) colours
$this->assertTrue(css_is_colour('rgb(255,255,255)'));
$this->assertTrue(css_is_colour('rgb(0, 0, 0)'));
$this->assertTrue(css_is_colour('RGB (255, 255 , 255)'));
$this->assertTrue(css_is_colour('rgba(0,0,0,0)'));
$this->assertTrue(css_is_colour('RGBA(255,255,255,1)'));
$this->assertTrue(css_is_colour('rgbA(255,255,255,0.5)'));
$this->assertFalse(css_is_colour('rgb(-255,-255,-255)'));
$this->assertFalse(css_is_colour('rgb(256,-256,256)'));
// Now lets test HSL colours
$this->assertTrue(css_is_colour('hsl(0,0%,100%)'));
$this->assertTrue(css_is_colour('hsl(180, 0%, 10%)'));
$this->assertTrue(css_is_colour('hsl (360, 100% , 95%)'));
// Finally test the special values
$this->assertTrue(css_is_colour('inherit'));
}
/**
* Test the css_is_width function
*/
public function test_css_is_width() {
$this->assertTrue(css_is_width('0'));
$this->assertTrue(css_is_width('0px'));
$this->assertTrue(css_is_width('0em'));
$this->assertTrue(css_is_width('199px'));
$this->assertTrue(css_is_width('199em'));
$this->assertTrue(css_is_width('199%'));
$this->assertTrue(css_is_width('-1'));
$this->assertTrue(css_is_width('-1px'));
$this->assertTrue(css_is_width('auto'));
$this->assertTrue(css_is_width('inherit'));
$this->assertFalse(css_is_width('-'));
$this->assertFalse(css_is_width('bananas'));
$this->assertFalse(css_is_width(''));
$this->assertFalse(css_is_width('top'));
}
/**
* This function tests some of the broken crazy CSS we have in Moodle.
* For each of these things the value needs to be corrected if we can be 100%
* certain what is going wrong, Or it needs to be left as is.
*
* @param css_optimiser $optimiser
*/
public function try_broken_css_found_in_moodle(css_optimiser $optimiser) {
// Notice how things are out of order here but that they get corrected
$cssin = '.test {background:url([[pix:theme|pageheaderbgred]]) top center no-repeat}';
$cssout = '.test{background:url([[pix:theme|pageheaderbgred]]) no-repeat top center;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Cursor hand isn't valid
$cssin = '.test {cursor: hand;}';
$cssout = '.test{cursor:hand;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Zoom property isn't valid
$cssin = '.test {zoom: 1;}';
$cssout = '.test{zoom:1;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Left isn't a valid position property
$cssin = '.test {position: left;}';
$cssout = '.test{position:left;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// The dark red color isn't a valid HTML color but has a standardised
// translation of #8B0000
$cssin = '.test {color: darkred;}';
$cssout = '.test{color:#8B0000;}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// You can't use argb colours as border colors
$cssin = '.test {border-bottom: 1px solid rgba(0,0,0,0.25);}';
$cssout = '.test{border-bottom:1px solid rgba(0,0,0,0.25);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
// Opacity with annoying IE equivilants....
$cssin = '.test {opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50);}';
$cssout = '.test{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
$this->assertEquals($cssout, $optimiser->process($cssin));
}
}
+233
View File
@@ -0,0 +1,233 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests events subsystems
*
* @package core
* @subpackage event
* @copyright 2007 onwards Martin Dougiamas (http://dougiamas.com)
* @author Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
// test handler function
function sample_function_handler($eventdata) {
static $called = 0;
static $ignorefail = false;
if ($eventdata == 'status') {
return $called;
} else if ($eventdata == 'reset') {
$called = 0;
$ignorefail = false;
return;
} else if ($eventdata == 'fail') {
if ($ignorefail) {
$called++;
return true;
} else {
return false;
}
} else if ($eventdata == 'ignorefail') {
$ignorefail = true;
return;
} else if ($eventdata == 'ok') {
$called++;
return true;
}
print_error('invalideventdata', '', '', $eventdata);
}
// test handler class with static method
class sample_handler_class {
static function static_method($eventdata) {
static $called = 0;
static $ignorefail = false;
if ($eventdata == 'status') {
return $called;
} else if ($eventdata == 'reset') {
$called = 0;
$ignorefail = false;
return;
} else if ($eventdata == 'fail') {
if ($ignorefail) {
$called++;
return true;
} else {
return false;
}
} else if ($eventdata == 'ignorefail') {
$ignorefail = true;
return;
} else if ($eventdata == 'ok') {
$called++;
return true;
}
print_error('invalideventdata', '', '', $eventdata);
}
}
class eventslib_testcase extends advanced_testcase {
/**
* Create temporary entries in the database for these tests.
* These tests have to work no matter the data currently in the database
* (meaning they should run on a brand new site). This means several items of
* data have to be artificially inseminated (:-) in the DB.
* @return void
*/
protected function setUp() {
parent::setUp();
// Set global category settings to -1 (not force)
sample_function_handler('reset');
sample_handler_class::static_method('reset');
events_update_definition('unittest');
$this->resetAfterTest(true);
}
/**
* Delete temporary entries from the database
* @return void
*/
protected function tearDown() {
events_uninstall('unittest');
parent::tearDown();
}
/**
* Tests the installation of event handlers from file
* @return void
*/
public function test_events_update_definition__install() {
global $CFG, $DB;
$dbcount = $DB->count_records('events_handlers', array('component'=>'unittest'));
$handlers = array();
require(__DIR__.'/fixtures/events.php');
$filecount = count($handlers);
$this->assertEquals($dbcount, $filecount, 'Equal number of handlers in file and db: %s');
}
/**
* Tests the uninstallation of event handlers from file
* @return void
*/
public function test_events_update_definition__uninstall() {
global $DB;
events_uninstall('unittest');
$this->assertEquals(0, $DB->count_records('events_handlers', array('component'=>'unittest')), 'All handlers should be uninstalled: %s');
}
/**
* Tests the update of event handlers from file
* @return void
*/
public function test_events_update_definition__update() {
global $DB;
// first modify directly existing handler
$handler = $DB->get_record('events_handlers', array('component'=>'unittest', 'eventname'=>'test_instant'));
$original = $handler->handlerfunction;
// change handler in db
$DB->set_field('events_handlers', 'handlerfunction', serialize('some_other_function_handler'), array('id'=>$handler->id));
// update the definition, it should revert the handler back
events_update_definition('unittest');
$handler = $DB->get_record('events_handlers', array('component'=>'unittest', 'eventname'=>'test_instant'));
$this->assertEquals($handler->handlerfunction, $original, 'update should sync db with file definition: %s');
}
/**
* tests events_trigger_is_registered funtion()
* @return void
*/
public function test_events_is_registered() {
$this->assertTrue(events_is_registered('test_instant', 'unittest'));
}
/**
* tests events_trigger funtion()
* @return void
*/
public function test_events_trigger__instant() {
$this->assertEquals(0, events_trigger('test_instant', 'ok'));
$this->assertEquals(0, events_trigger('test_instant', 'ok'));
$this->assertEquals(2, sample_function_handler('status'));
}
/**
* tests events_trigger funtion()
* @return void
*/
public function test_events_trigger__cron() {
$this->assertEquals(0, events_trigger('test_cron', 'ok'));
$this->assertEquals(0, sample_handler_class::static_method('status'));
events_cron('test_cron');
$this->assertEquals(1, sample_handler_class::static_method('status'));
}
/**
* tests events_pending_count()
* @return void
*/
public function test_events_pending_count() {
events_trigger('test_cron', 'ok');
events_trigger('test_cron', 'ok');
events_cron('test_cron');
$this->assertEquals(0, events_pending_count('test_cron'), 'all messages should be already dequeued: %s');
}
/**
* tests events_trigger funtion() when instant handler fails
* @return void
*/
public function test_events_trigger__failed_instant() {
$this->assertEquals(1, events_trigger('test_instant', 'fail'), 'fail first event: %s');
$this->assertEquals(1, events_trigger('test_instant', 'ok'), 'this one should fail too: %s');
$this->assertEquals(0, events_cron('test_instant'), 'all events should stay in queue: %s');
$this->assertEquals(2, events_pending_count('test_instant'), 'two events should in queue: %s');
$this->assertEquals(0, sample_function_handler('status'), 'verify no event dispatched yet: %s');
sample_function_handler('ignorefail'); //ignore "fail" eventdata from now on
$this->assertEquals(1, events_trigger('test_instant', 'ok'), 'this one should go to queue directly: %s');
$this->assertEquals(3, events_pending_count('test_instant'), 'three events should in queue: %s');
$this->assertEquals(0, sample_function_handler('status'), 'verify previous event was not dispatched: %s');
$this->assertEquals(3, events_cron('test_instant'), 'all events should be dispatched: %s');
$this->assertEquals(3, sample_function_handler('status'), 'verify three events were dispatched: %s');
$this->assertEquals(0, events_pending_count('test_instant'), 'no events should in queue: %s');
$this->assertEquals(0, events_trigger('test_instant', 'ok'), 'this event should be dispatched immediately: %s');
$this->assertEquals(4, sample_function_handler('status'), 'verify event was dispatched: %s');
$this->assertEquals(0, events_pending_count('test_instant'), 'no events should in queue: %s');
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for /lib/externallib.php.
*
* @package core
* @subpackage phpunit
* @copyright 2009 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/externallib.php');
class externallib_testcase extends basic_testcase {
public function test_validate_params() {
$params = array('text'=>'aaa', 'someid'=>'6',);
$description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value'),
'text' => new external_value(PARAM_ALPHA, 'Some text value')));
$result = external_api::validate_parameters($description, $params);
$this->assertEquals(count($result), 2);
reset($result);
$this->assertTrue(key($result) === 'someid');
$this->assertTrue($result['someid'] === 6);
$this->assertTrue($result['text'] === 'aaa');
$params = array('someids'=>array('1', 2, 'a'=>'3'), 'scalar'=>666);
$description = new external_function_parameters(array('someids' => new external_multiple_structure(new external_value(PARAM_INT, 'Some ID')),
'scalar' => new external_value(PARAM_ALPHANUM, 'Some text value')));
$result = external_api::validate_parameters($description, $params);
$this->assertEquals(count($result), 2);
reset($result);
$this->assertTrue(key($result) === 'someids');
$this->assertTrue($result['someids'] == array(0=>1, 1=>2, 2=>3));
$this->assertTrue($result['scalar'] === '666');
$params = array('text'=>'aaa');
$description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value', false),
'text' => new external_value(PARAM_ALPHA, 'Some text value')));
$result = external_api::validate_parameters($description, $params);
$this->assertEquals(count($result), 2);
reset($result);
$this->assertTrue(key($result) === 'someid');
$this->assertTrue($result['someid'] === null);
$this->assertTrue($result['text'] === 'aaa');
$params = array('text'=>'aaa');
$description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value', false, 6),
'text' => new external_value(PARAM_ALPHA, 'Some text value')));
$result = external_api::validate_parameters($description, $params);
$this->assertEquals(count($result), 2);
reset($result);
$this->assertTrue(key($result) === 'someid');
$this->assertTrue($result['someid'] === 6);
$this->assertTrue($result['text'] === 'aaa');
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for /lib/filelib.php.
*
* @package core_files
* @category phpunit
* @copyright 2009 Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/filelib.php');
class filelib_testcase extends basic_testcase {
public function test_format_postdata_for_curlcall() {
//POST params with just simple types
$postdatatoconvert =array( 'userid' => 1, 'roleid' => 22, 'name' => 'john');
$expectedresult = "userid=1&roleid=22&name=john";
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEquals($postdata, $expectedresult);
//POST params with a string containing & character
$postdatatoconvert =array( 'name' => 'john&emilie', 'roleid' => 22);
$expectedresult = "name=john%26emilie&roleid=22"; //urlencode: '%26' => '&'
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEquals($postdata, $expectedresult);
//POST params with an empty value
$postdatatoconvert =array( 'name' => null, 'roleid' => 22);
$expectedresult = "name=&roleid=22";
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEquals($postdata, $expectedresult);
//POST params with complex types
$postdatatoconvert =array( 'users' => array(
array(
'id' => 2,
'customfields' => array(
array
(
'type' => 'Color',
'value' => 'violet'
)
)
)
)
);
$expectedresult = "users[0][id]=2&users[0][customfields][0][type]=Color&users[0][customfields][0][value]=violet";
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEquals($postdata, $expectedresult);
//POST params with other complex types
$postdatatoconvert = array ('members' =>
array(
array('groupid' => 1, 'userid' => 1)
, array('groupid' => 1, 'userid' => 2)
)
);
$expectedresult = "members[0][groupid]=1&members[0][userid]=1&members[1][groupid]=1&members[1][userid]=2";
$postdata = format_postdata_for_curlcall($postdatatoconvert);
$this->assertEquals($postdata, $expectedresult);
}
public function test_download_file_content() {
$testhtml = "http://download.moodle.org/unittest/test.html";
$contents = download_file_content($testhtml);
$this->assertEquals('47250a973d1b88d9445f94db4ef2c97a', md5($contents));
}
}
+767
View File
@@ -0,0 +1,767 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for the parts of ../filterlib.php that involve loading the configuration
* from, and saving the configuration to, the database.
*
* @package core_filter
* @category phpunit
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/filterlib.php');
/**
* Test functions that affect filter_active table with contextid = $syscontextid.
*/
class filter_active_global_testcase extends advanced_testcase {
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_active', array());
$this->resetAfterTest(false);
}
private function assert_only_one_filter_globally($filter, $state) {
global $DB;
$recs = $DB->get_records('filter_active');
$this->assertEquals(1, count($recs), 'More than one record returned %s.');
$rec = reset($recs);
unset($rec->id);
$expectedrec = new stdClass();
$expectedrec->filter = $filter;
$expectedrec->contextid = context_system::instance()->id;
$expectedrec->active = $state;
$expectedrec->sortorder = 1;
$this->assertEquals($expectedrec, $rec);
}
private function assert_global_sort_order($filters) {
global $DB;
$sortedfilters = $DB->get_records_menu('filter_active',
array('contextid' => context_system::instance()->id), 'sortorder', 'sortorder,filter');
$testarray = array();
$index = 1;
foreach($filters as $filter) {
$testarray[$index++] = $filter;
}
$this->assertEquals($testarray, $sortedfilters);
}
public function test_set_filter_globally_on() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/name', TEXTFILTER_ON, 1);
// Validate.
$this->assert_only_one_filter_globally('filter/name', TEXTFILTER_ON);
}
public function test_set_filter_globally_off() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/name', TEXTFILTER_OFF, 1);
// Validate.
$this->assert_only_one_filter_globally('filter/name', TEXTFILTER_OFF);
}
public function test_set_filter_globally_disabled() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/name', TEXTFILTER_DISABLED, 1);
// Validate.
$this->assert_only_one_filter_globally('filter/name', TEXTFILTER_DISABLED);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_global_config_exception_on_invalid_state() {
filter_set_global_state('filter/name', 0, 1);
}
public function test_set_no_sortorder_clash() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/one', TEXTFILTER_DISABLED, 1);
filter_set_global_state('filter/two', TEXTFILTER_DISABLED, 1);
// Validate - should have pushed other filters down.
$this->assert_global_sort_order(array('filter/two', 'filter/one'));
}
public function test_auto_sort_order_disabled() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/one', TEXTFILTER_DISABLED);
filter_set_global_state('filter/two', TEXTFILTER_DISABLED);
// Validate.
$this->assert_global_sort_order(array('filter/one', 'filter/two'));
}
public function test_auto_sort_order_enabled() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/one', TEXTFILTER_ON);
filter_set_global_state('filter/two', TEXTFILTER_OFF);
// Validate.
$this->assert_global_sort_order(array('filter/one', 'filter/two'));
}
public function test_auto_sort_order_mixed() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/0', TEXTFILTER_DISABLED);
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_DISABLED);
filter_set_global_state('filter/3', TEXTFILTER_OFF);
// Validate.
$this->assert_global_sort_order(array('filter/1', 'filter/3', 'filter/0', 'filter/2'));
}
public function test_update_existing_dont_duplicate() {
// Setup fixture.
// Exercise SUT.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_global_state('filter/name', TEXTFILTER_OFF);
// Validate.
$this->assert_only_one_filter_globally('filter/name', TEXTFILTER_OFF);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_sort_order_not_too_low() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
// Exercise SUT.
filter_set_global_state('filter/2', TEXTFILTER_ON, 0);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_sort_order_not_too_high() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
// Exercise SUT.
filter_set_global_state('filter/2', TEXTFILTER_ON, 3);
}
public function test_update_reorder_down() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_ON);
filter_set_global_state('filter/3', TEXTFILTER_ON);
// Exercise SUT.
filter_set_global_state('filter/2', TEXTFILTER_ON, 1);
// Validate.
$this->assert_global_sort_order(array('filter/2', 'filter/1', 'filter/3'));
}
public function test_update_reorder_up() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_ON);
filter_set_global_state('filter/3', TEXTFILTER_ON);
filter_set_global_state('filter/4', TEXTFILTER_ON);
// Exercise SUT.
filter_set_global_state('filter/2', TEXTFILTER_ON, 3);
// Validate.
$this->assert_global_sort_order(array('filter/1', 'filter/3', 'filter/2', 'filter/4'));
}
public function test_auto_sort_order_change_to_enabled() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_DISABLED);
filter_set_global_state('filter/3', TEXTFILTER_DISABLED);
// Exercise SUT.
filter_set_global_state('filter/3', TEXTFILTER_ON);
// Validate.
$this->assert_global_sort_order(array('filter/1', 'filter/3', 'filter/2'));
}
public function test_auto_sort_order_change_to_disabled() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_ON);
filter_set_global_state('filter/3', TEXTFILTER_DISABLED);
// Exercise SUT.
filter_set_global_state('filter/1', TEXTFILTER_DISABLED);
// Validate.
$this->assert_global_sort_order(array('filter/2', 'filter/1', 'filter/3'));
}
public function test_filter_get_global_states() {
// Setup fixture.
filter_set_global_state('filter/1', TEXTFILTER_ON);
filter_set_global_state('filter/2', TEXTFILTER_OFF);
filter_set_global_state('filter/3', TEXTFILTER_DISABLED);
// Exercise SUT.
$filters = filter_get_global_states();
// Validate.
$this->assertEquals(array(
'filter/1' => (object) array('filter' => 'filter/1', 'active' => TEXTFILTER_ON, 'sortorder' => 1),
'filter/2' => (object) array('filter' => 'filter/2', 'active' => TEXTFILTER_OFF, 'sortorder' => 2),
'filter/3' => (object) array('filter' => 'filter/3', 'active' => TEXTFILTER_DISABLED, 'sortorder' => 3)
), $filters);
}
}
/**
* Test functions that affect filter_active table with contextid = $syscontextid.
*/
class filter_active_local_testcase extends advanced_testcase {
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_active', array());
$this->resetAfterTest(false);
}
private function assert_only_one_local_setting($filter, $contextid, $state) {
global $DB;
$recs = $DB->get_records('filter_active');
$this->assertEquals(1, count($recs), 'More than one record returned %s.');
$rec = reset($recs);
unset($rec->id);
unset($rec->sortorder);
$expectedrec = new stdClass();
$expectedrec->filter = $filter;
$expectedrec->contextid = $contextid;
$expectedrec->active = $state;
$this->assertEquals($expectedrec, $rec);
}
private function assert_no_local_setting() {
global $DB;
$this->assertEquals(0, $DB->count_records('filter_active'));
}
public function test_local_on() {
// Exercise SUT.
filter_set_local_state('filter/name', 123, TEXTFILTER_ON);
// Validate.
$this->assert_only_one_local_setting('filter/name', 123, TEXTFILTER_ON);
}
public function test_local_off() {
// Exercise SUT.
filter_set_local_state('filter/name', 123, TEXTFILTER_OFF);
// Validate.
$this->assert_only_one_local_setting('filter/name', 123, TEXTFILTER_OFF);
}
public function test_local_inherit() {
// Exercise SUT.
filter_set_local_state('filter/name', 123, TEXTFILTER_INHERIT);
// Validate.
$this->assert_no_local_setting();
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_local_invalid_state_throws_exception() {
// Exercise SUT.
filter_set_local_state('filter/name', 123, -9999);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_throws_exception_when_setting_global() {
// Exercise SUT.
filter_set_local_state('filter/name', get_context_instance(CONTEXT_SYSTEM)->id, TEXTFILTER_INHERIT);
}
public function test_local_inherit_deletes_existing() {
// Setup fixture.
filter_set_local_state('filter/name', 123, TEXTFILTER_INHERIT);
// Exercise SUT.
filter_set_local_state('filter/name', 123, TEXTFILTER_INHERIT);
// Validate.
$this->assert_no_local_setting();
}
}
/**
* Test functions that use just the filter_config table.
*/
class filter_config_testcase extends advanced_testcase {
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_config', array());
$this->resetAfterTest(false);
}
private function assert_only_one_config($filter, $context, $name, $value) {
global $DB;
$recs = $DB->get_records('filter_config');
$this->assertEquals(1, count($recs), 'More than one record returned %s.');
$rec = reset($recs);
unset($rec->id);
$expectedrec = new stdClass();
$expectedrec->filter = $filter;
$expectedrec->contextid = $context;
$expectedrec->name = $name;
$expectedrec->value = $value;
$this->assertEquals($expectedrec, $rec);
}
public function test_set_new_config() {
// Exercise SUT.
filter_set_local_config('filter/name', 123, 'settingname', 'An arbitrary value');
// Validate.
$this->assert_only_one_config('filter/name', 123, 'settingname', 'An arbitrary value');
}
public function test_update_existing_config() {
// Setup fixture.
filter_set_local_config('filter/name', 123, 'settingname', 'An arbitrary value');
// Exercise SUT.
filter_set_local_config('filter/name', 123, 'settingname', 'A changed value');
// Validate.
$this->assert_only_one_config('filter/name', 123, 'settingname', 'A changed value');
}
public function test_filter_get_local_config() {
// Setup fixture.
filter_set_local_config('filter/name', 123, 'setting1', 'An arbitrary value');
filter_set_local_config('filter/name', 123, 'setting2', 'Another arbitrary value');
filter_set_local_config('filter/name', 122, 'settingname', 'Value from another context');
filter_set_local_config('filter/other', 123, 'settingname', 'Someone else\'s value');
// Exercise SUT.
$config = filter_get_local_config('filter/name', 123);
// Validate.
$this->assertEquals(array('setting1' => 'An arbitrary value', 'setting2' => 'Another arbitrary value'), $config);
}
}
class filter_get_active_available_in_context_testcase extends advanced_testcase {
private static $syscontext;
private static $childcontext;
private static $childcontext2;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
$course = self::getDataGenerator()->create_course(array('category'=>1));
self::$childcontext = context_coursecat::instance(1);
self::$childcontext2 = context_course::instance($course->id);
self::$syscontext = context_system::instance();
}
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_active', array());
$DB->delete_records('filter_config', array());
$this->resetAfterTest(false);
}
private function assert_filter_list($expectedfilters, $filters) {
$this->assertEquals($expectedfilters, array_keys($filters), '', 0, 10, true);
}
public function test_globally_on_is_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
// Exercise SUT.
$filters = filter_get_active_in_context(self::$syscontext);
// Validate.
$this->assert_filter_list(array('filter/name'), $filters);
// Check no config returned correctly.
$this->assertEquals(array(), $filters['filter/name']);
}
public function test_globally_off_not_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_OFF);
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext2);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_globally_off_overridden() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_OFF);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_ON);
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext2);
// Validate.
$this->assert_filter_list(array('filter/name'), $filters);
}
public function test_globally_on_overridden() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext2);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_globally_disabled_not_overridden() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_DISABLED);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_ON);
// Exercise SUT.
$filters = filter_get_active_in_context(self::$syscontext);
// Validate.
$this->assert_filter_list(array(), $filters);
}
public function test_single_config_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_config('filter/name', self::$childcontext->id, 'settingname', 'A value');
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value'), $filters['filter/name']);
}
public function test_multi_config_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_config('filter/name', self::$childcontext->id, 'settingname', 'A value');
filter_set_local_config('filter/name', self::$childcontext->id, 'anothersettingname', 'Another value');
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value', 'anothersettingname' => 'Another value'), $filters['filter/name']);
}
public function test_config_from_other_context_not_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_config('filter/name', self::$childcontext->id, 'settingname', 'A value');
filter_set_local_config('filter/name', self::$childcontext2->id, 'anothersettingname', 'Another value');
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext2);
// Validate.
$this->assertEquals(array('anothersettingname' => 'Another value'), $filters['filter/name']);
}
public function test_config_from_other_filter_not_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_config('filter/name', self::$childcontext->id, 'settingname', 'A value');
filter_set_local_config('filter/other', self::$childcontext->id, 'anothersettingname', 'Another value');
// Exercise SUT.
$filters = filter_get_active_in_context(self::$childcontext);
// Validate.
$this->assertEquals(array('settingname' => 'A value'), $filters['filter/name']);
}
protected function assert_one_available_filter($filter, $localstate, $inheritedstate, $filters) {
$this->assertEquals(1, count($filters), 'More than one record returned %s.');
$rec = $filters[$filter];
unset($rec->id);
$expectedrec = new stdClass();
$expectedrec->filter = $filter;
$expectedrec->localstate = $localstate;
$expectedrec->inheritedstate = $inheritedstate;
$this->assertEquals($expectedrec, $rec);
}
public function test_available_in_context_localoverride() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
$filters = filter_get_available_in_context(self::$childcontext);
// Validate.
$this->assert_one_available_filter('filter/name', TEXTFILTER_OFF, TEXTFILTER_ON, $filters);
}
public function test_available_in_context_nolocaloverride() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_OFF);
// Exercise SUT.
$filters = filter_get_available_in_context(self::$childcontext2);
// Validate.
$this->assert_one_available_filter('filter/name', TEXTFILTER_INHERIT, TEXTFILTER_OFF, $filters);
}
public function test_available_in_context_disabled_not_returned() {
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_DISABLED);
filter_set_local_state('filter/name', self::$childcontext->id, TEXTFILTER_ON);
// Exercise SUT.
$filters = filter_get_available_in_context(self::$childcontext);
// Validate.
$this->assertEquals(array(), $filters);
}
/**
* @expectedException coding_exception
* @return void
*/
public function test_available_in_context_exception_with_syscontext() {
// Exercise SUT.
filter_get_available_in_context(self::$syscontext);
}
}
class filter_preload_activities_testcase extends advanced_testcase {
private static $syscontext;
private static $catcontext;
private static $coursecontext;
private static $course;
private static $activity1context;
private static $activity2context;
public static function setUpBeforeClass() {
parent::setUpBeforeClass();
self::$syscontext = context_system::instance();
self::$catcontext = context_coursecat::instance(1);
self::$course = self::getDataGenerator()->create_course(array('category'=>1));
self::$coursecontext = context_course::instance(self::$course->id);
$page1 = self::getDataGenerator()->create_module('page', array('course'=>self::$course->id));
self::$activity1context = context_module::instance($page1->cmid);
$page2 = self::getDataGenerator()->create_module('page', array('course'=>self::$course->id));
self::$activity2context = context_module::instance($page2->cmid);
}
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_active', array());
$DB->delete_records('filter_config', array());
$this->resetAfterTest(false);
}
private function assert_matches($modinfo) {
global $FILTERLIB_PRIVATE, $DB;
// Use preload cache...
$FILTERLIB_PRIVATE = new stdClass();
filter_preload_activities($modinfo);
// Get data and check no queries are made
$before = $DB->perf_get_reads();
$plfilters1 = filter_get_active_in_context(self::$activity1context);
$plfilters2 = filter_get_active_in_context(self::$activity2context);
$after = $DB->perf_get_reads();
$this->assertEquals($before, $after);
// Repeat without cache and check it makes queries now
$FILTERLIB_PRIVATE = new stdClass;
$before = $DB->perf_get_reads();
$filters1 = filter_get_active_in_context(self::$activity1context);
$filters2 = filter_get_active_in_context(self::$activity2context);
$after = $DB->perf_get_reads();
$this->assertTrue($after > $before);
// Check they match
$this->assertEquals($plfilters1, $filters1);
$this->assertEquals($plfilters2, $filters2);
}
public function test_preload() {
// Get course and modinfo
$modinfo = new course_modinfo(self::$course, 2);
// Note: All the tests in this function check that the result from the
// preloaded cache is the same as the result from calling the standard
// function without preloading.
// Initially, check with no filters enabled
$this->assert_matches($modinfo);
// Enable filter globally, check
filter_set_global_state('filter/name', TEXTFILTER_ON);
$this->assert_matches($modinfo);
// Disable for activity 2
filter_set_local_state('filter/name', self::$activity2context->id, TEXTFILTER_OFF);
$this->assert_matches($modinfo);
// Disable at category
filter_set_local_state('filter/name', self::$catcontext->id, TEXTFILTER_OFF);
$this->assert_matches($modinfo);
// Enable for activity 1
filter_set_local_state('filter/name', self::$activity1context->id, TEXTFILTER_ON);
$this->assert_matches($modinfo);
// Disable globally
filter_set_global_state('filter/name', TEXTFILTER_DISABLED);
$this->assert_matches($modinfo);
// Add another 2 filters
filter_set_global_state('filter/frog', TEXTFILTER_ON);
filter_set_global_state('filter/zombie', TEXTFILTER_ON);
$this->assert_matches($modinfo);
// Disable random one of these in each context
filter_set_local_state('filter/zombie', self::$activity1context->id, TEXTFILTER_OFF);
filter_set_local_state('filter/frog', self::$activity2context->id, TEXTFILTER_OFF);
$this->assert_matches($modinfo);
// Now do some filter options
filter_set_local_config('filter/name', self::$activity1context->id, 'a', 'x');
filter_set_local_config('filter/zombie', self::$activity1context->id, 'a', 'y');
filter_set_local_config('filter/frog', self::$activity1context->id, 'a', 'z');
// These last two don't do anything as they are not at final level but I
// thought it would be good to have that verified in test
filter_set_local_config('filter/frog', self::$coursecontext->id, 'q', 'x');
filter_set_local_config('filter/frog', self::$catcontext->id, 'q', 'z');
$this->assert_matches($modinfo);
}
}
class filter_delete_config_testcase extends advanced_testcase {
protected function setUp() {
global $DB;
parent::setUp();
$DB->delete_records('filter_active', array());
$DB->delete_records('filter_config', array());
$this->resetAfterTest(false);
}
public function test_filter_delete_all_for_filter() {
global $DB;
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_global_state('filter/other', TEXTFILTER_ON);
filter_set_local_config('filter/name', context_system::instance()->id, 'settingname', 'A value');
filter_set_local_config('filter/other', context_system::instance()->id, 'settingname', 'Other value');
set_config('configname', 'A config value', 'filter_name');
set_config('configname', 'Other config value', 'filter_other');
// Exercise SUT.
filter_delete_all_for_filter('filter/name');
// Validate.
$this->assertEquals(1, $DB->count_records('filter_active'));
$this->assertTrue($DB->record_exists('filter_active', array('filter' => 'filter/other')));
$this->assertEquals(1, $DB->count_records('filter_config'));
$this->assertTrue($DB->record_exists('filter_config', array('filter' => 'filter/other')));
$expectedconfig = new stdClass;
$expectedconfig->configname = 'Other config value';
$this->assertEquals($expectedconfig, get_config('filter_other'));
$this->assertEquals(get_config('filter_name'), new stdClass());
}
public function test_filter_delete_all_for_context() {
global $DB;
// Setup fixture.
filter_set_global_state('filter/name', TEXTFILTER_ON);
filter_set_local_state('filter/name', 123, TEXTFILTER_OFF);
filter_set_local_config('filter/name', 123, 'settingname', 'A value');
filter_set_local_config('filter/other', 123, 'settingname', 'Other value');
filter_set_local_config('filter/other', 122, 'settingname', 'Other value');
// Exercise SUT.
filter_delete_all_for_context(123);
// Validate.
$this->assertEquals(1, $DB->count_records('filter_active'));
$this->assertTrue($DB->record_exists('filter_active', array('contextid' => context_system::instance()->id)));
$this->assertEquals(1, $DB->count_records('filter_config'));
$this->assertTrue($DB->record_exists('filter_config', array('filter' => 'filter/other')));
}
}
class filter_filter_set_applies_to_strings extends advanced_testcase {
protected $origcfgstringfilters;
protected $origcfgfilterall;
protected function setUp() {
global $DB, $CFG;
parent::setUp();
$DB->delete_records('filter_active', array());
$DB->delete_records('filter_config', array());
$this->resetAfterTest(false);
// Store original $CFG;
$this->origcfgstringfilters = $CFG->stringfilters;
$this->origcfgfilterall = $CFG->filterall;
}
protected function tearDown() {
global $CFG;
$CFG->stringfilters = $this->origcfgstringfilters;
$CFG->filterall = $this->origcfgfilterall;
parent::tearDown();
}
public function test_set() {
global $CFG;
// Setup fixture.
$CFG->filterall = 0;
$CFG->stringfilters = '';
// Exercise SUT.
filter_set_applies_to_strings('filter/name', true);
// Validate.
$this->assertEquals('filter/name', $CFG->stringfilters);
$this->assertEquals(1, $CFG->filterall);
}
public function test_unset_to_empty() {
global $CFG;
// Setup fixture.
$CFG->filterall = 1;
$CFG->stringfilters = 'filter/name';
// Exercise SUT.
filter_set_applies_to_strings('filter/name', false);
// Validate.
$this->assertEquals('', $CFG->stringfilters);
$this->assertEquals('', $CFG->filterall);
}
public function test_unset_multi() {
global $CFG;
// Setup fixture.
$CFG->filterall = 1;
$CFG->stringfilters = 'filter/name,filter/other';
// Exercise SUT.
filter_set_applies_to_strings('filter/name', false);
// Validate.
$this->assertEquals('filter/other', $CFG->stringfilters);
$this->assertEquals(1, $CFG->filterall);
}
}
+42
View File
@@ -0,0 +1,42 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Test event handler definition used only from unit tests.
*
* @package core
* @subpackage event
* @copyright 2007 onwards Martin Dougiamas (http://dougiamas.com)
* @author Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$handlers = array (
'test_instant' => array (
'handlerfile' => '/lib/tests/eventslib_test.php',
'handlerfunction' => 'sample_function_handler',
'schedule' => 'instant',
'internal' => 1,
),
'test_cron' => array (
'handlerfile' => '/lib/tests/eventslib_test.php',
'handlerfunction' => array('sample_handler_class', 'static_method'),
'schedule' => 'cron',
'internal' => 1,
)
);
+220
View File
@@ -0,0 +1,220 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for /lib/formslib.php.
*
* @package core_form
* @category phpunit
* @copyright 2011 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->libdir . '/form/radio.php');
require_once($CFG->libdir . '/form/select.php');
require_once($CFG->libdir . '/form/text.php');
class formslib_testcase extends basic_testcase {
public function test_require_rule() {
global $CFG;
$strictformsrequired = null;
if (isset($CFG->strictformsrequired)) {
$strictformsrequired = $CFG->strictformsrequired;
}
$rule = new MoodleQuickForm_Rule_Required();
// First run the tests with strictformsrequired off
$CFG->strictformsrequired = false;
// Passes
$this->assertTrue($rule->validate('Something'));
$this->assertTrue($rule->validate("Something\nmore"));
$this->assertTrue($rule->validate("\nmore"));
$this->assertTrue($rule->validate(" more "));
$this->assertTrue($rule->validate("0"));
$this->assertTrue($rule->validate(0));
$this->assertTrue($rule->validate(true));
$this->assertTrue($rule->validate(' '));
$this->assertTrue($rule->validate(' '));
$this->assertTrue($rule->validate("\t"));
$this->assertTrue($rule->validate("\n"));
$this->assertTrue($rule->validate("\r"));
$this->assertTrue($rule->validate("\r\n"));
$this->assertTrue($rule->validate(" \t \n \r "));
$this->assertTrue($rule->validate('<p></p>'));
$this->assertTrue($rule->validate('<p> </p>'));
$this->assertTrue($rule->validate('<p>x</p>'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile" />'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"/>'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"></img>'));
$this->assertTrue($rule->validate('<hr />'));
$this->assertTrue($rule->validate('<hr/>'));
$this->assertTrue($rule->validate('<hr>'));
$this->assertTrue($rule->validate('<hr></hr>'));
$this->assertTrue($rule->validate('<br />'));
$this->assertTrue($rule->validate('<br/>'));
$this->assertTrue($rule->validate('<br>'));
$this->assertTrue($rule->validate('&nbsp;'));
// Fails
$this->assertFalse($rule->validate(''));
$this->assertFalse($rule->validate(false));
$this->assertFalse($rule->validate(null));
// Now run the same tests with it on to make sure things work as expected
$CFG->strictformsrequired = true;
// Passes
$this->assertTrue($rule->validate('Something'));
$this->assertTrue($rule->validate("Something\nmore"));
$this->assertTrue($rule->validate("\nmore"));
$this->assertTrue($rule->validate(" more "));
$this->assertTrue($rule->validate("0"));
$this->assertTrue($rule->validate(0));
$this->assertTrue($rule->validate(true));
$this->assertTrue($rule->validate('<p>x</p>'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile" />'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"/>'));
$this->assertTrue($rule->validate('<img src="smile.jpg" alt="smile"></img>'));
$this->assertTrue($rule->validate('<hr />'));
$this->assertTrue($rule->validate('<hr/>'));
$this->assertTrue($rule->validate('<hr>'));
$this->assertTrue($rule->validate('<hr></hr>'));
// Fails
$this->assertFalse($rule->validate(' '));
$this->assertFalse($rule->validate(' '));
$this->assertFalse($rule->validate("\t"));
$this->assertFalse($rule->validate("\n"));
$this->assertFalse($rule->validate("\r"));
$this->assertFalse($rule->validate("\r\n"));
$this->assertFalse($rule->validate(" \t \n \r "));
$this->assertFalse($rule->validate('<p></p>'));
$this->assertFalse($rule->validate('<p> </p>'));
$this->assertFalse($rule->validate('<br />'));
$this->assertFalse($rule->validate('<br/>'));
$this->assertFalse($rule->validate('<br>'));
$this->assertFalse($rule->validate('&nbsp;'));
$this->assertFalse($rule->validate(''));
$this->assertFalse($rule->validate(false));
$this->assertFalse($rule->validate(null));
if (isset($strictformsrequired)) {
$CFG->strictformsrequired = $strictformsrequired;
}
}
public function test_generate_id_select() {
$el = new MoodleQuickForm_select('choose_one', 'Choose one',
array(1 => 'One', '2' => 'Two'));
$el->_generateId();
$this->assertEquals('id_choose_one', $el->getAttribute('id'));
}
public function test_generate_id_like_repeat() {
$el = new MoodleQuickForm_text('text[7]', 'Type something');
$el->_generateId();
$this->assertEquals('id_text_7', $el->getAttribute('id'));
}
public function test_can_manually_set_id() {
$el = new MoodleQuickForm_text('elementname', 'Type something',
array('id' => 'customelementid'));
$el->_generateId();
$this->assertEquals('customelementid', $el->getAttribute('id'));
}
public function test_generate_id_radio() {
$el = new MoodleQuickForm_radio('radio', 'Label', 'Choice label', 'choice_value');
$el->_generateId();
$this->assertEquals('id_radio_choice_value', $el->getAttribute('id'));
}
public function test_radio_can_manually_set_id() {
$el = new MoodleQuickForm_radio('radio2', 'Label', 'Choice label', 'choice_value',
array('id' => 'customelementid2'));
$el->_generateId();
$this->assertEquals('customelementid2', $el->getAttribute('id'));
}
public function test_generate_id_radio_like_repeat() {
$el = new MoodleQuickForm_radio('repeatradio[2]', 'Label', 'Choice label', 'val');
$el->_generateId();
$this->assertEquals('id_repeatradio_2_val', $el->getAttribute('id'));
}
public function test_rendering() {
$form = new formslib_test_form();
ob_start();
$form->display();
$html = ob_get_clean();
$this->assertTag(array('tag'=>'select', 'id'=>'id_choose_one',
'attributes'=>array('name'=>'choose_one')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_text_0',
'attributes'=>array('type'=>'text', 'name'=>'text[0]')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_text_1',
'attributes'=>array('type'=>'text', 'name'=>'text[1]')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_radio_choice_value',
'attributes'=>array('type'=>'radio', 'name'=>'radio', 'value'=>'choice_value')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'customelementid2',
'attributes'=>array('type'=>'radio', 'name'=>'radio2')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_repeatradio_0_2',
'attributes'=>array('type'=>'radio', 'name'=>'repeatradio[0]', 'value'=>'2')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_repeatradio_2_1',
'attributes'=>array('type'=>'radio', 'name'=>'repeatradio[2]', 'value'=>'1')), $html);
$this->assertTag(array('tag'=>'input', 'id'=>'id_repeatradio_2_2',
'attributes'=>array('type'=>'radio', 'name'=>'repeatradio[2]', 'value'=>'2')), $html);
}
}
/**
* Test form to be used by {@link formslib_test::test_rendering()}.
*/
class formslib_test_form extends moodleform {
public function definition() {
$this->_form->addElement('select', 'choose_one', 'Choose one',
array(1 => 'One', '2' => 'Two'));
$repeatels = array(
$this->_form->createElement('text', 'text', 'Type something')
);
$this->repeat_elements($repeatels, 2, array(), 'numtexts', 'addtexts');
$this->_form->addElement('radio', 'radio', 'Label', 'Choice label', 'choice_value');
$this->_form->addElement('radio', 'radio2', 'Label', 'Choice label', 'choice_value',
array('id' => 'customelementid2'));
$repeatels = array(
$this->_form->createElement('radio', 'repeatradio', 'Choose {no}', 'One', 1),
$this->_form->createElement('radio', 'repeatradio', 'Choose {no}', 'Two', 2),
);
$this->repeat_elements($repeatels, 3, array(), 'numradios', 'addradios');
}
}
+146
View File
@@ -0,0 +1,146 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests our html2text hacks
*
* Note: includes original tests from testweblib.php
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
class html2text_testcase extends basic_testcase {
/**
* ALT as image replacements
*/
public function test_images() {
$this->assertEquals('[edit]', html_to_text('<img src="edit.png" alt="edit" />'));
$text = 'xx<img src="gif.gif" alt="some gif" />xx';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, 'xx[some gif]xx');
}
/**
* No magic quotes messing
*/
public function test_no_strip_slashes() {
$this->assertEquals('[\edit]', html_to_text('<img src="edit.png" alt="\edit" />'));
$text = '\\magic\\quotes\\are\\\\horrible';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, $text);
}
/**
* Textlib integration
*/
public function test_textlib() {
$text = '<strong>Žluťoučký koníček</strong>';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, 'ŽLUŤOUČKÝ KONÍČEK');
}
/**
* Protect 0
*/
public function test_zero() {
$text = '0';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, $text);
$this->assertSame('0', html_to_text('0'));
}
// ======= Standard html2text conversion features =======
/**
* Various invalid HTML typed by users that ignore html strict
**/
public function test_invalid_html() {
$text = 'Gin & Tonic';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, $text);
$text = 'Gin > Tonic';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, $text);
$text = 'Gin < Tonic';
$result = html_to_text($text, null, false, false);
$this->assertSame($result, $text);
}
/**
* Basic text formatting.
*/
public function test_simple() {
$this->assertEquals("_Hello_ WORLD!", html_to_text('<p><i>Hello</i> <b>world</b>!</p>'));
$this->assertEquals("All the WORLDS a stage.\n\n-- William Shakespeare", html_to_text('<p>All the <strong>worlds</strong> a stage.</p><p>-- William Shakespeare</p>'));
$this->assertEquals("HELLO WORLD!\n\n", html_to_text('<h1>Hello world!</h1>'));
$this->assertEquals("Hello\nworld!", html_to_text('Hello<br />world!'));
}
/**
* Test line wrapping
*/
public function test_text_nowrap() {
$long = "Here is a long string, more than 75 characters long, since by default html_to_text wraps text at 75 chars.";
$wrapped = "Here is a long string, more than 75 characters long, since by default\nhtml_to_text wraps text at 75 chars.";
$this->assertEquals($long, html_to_text($long, 0));
$this->assertEquals($wrapped, html_to_text($long));
}
/**
* Whitespace removal
*/
public function test_trailing_whitespace() {
$this->assertEquals('With trailing whitespace and some more text', html_to_text("With trailing whitespace \nand some more text", 0));
}
/**
* PRE parsing
*/
public function test_html_to_text_pre_parsing_problem() {
$strorig = 'Consider the following function:<br /><pre><span style="color: rgb(153, 51, 102);">void FillMeUp(char* in_string) {'.
'<br /> int i = 0;<br /> while (in_string[i] != \'\0\') {<br /> in_string[i] = \'X\';<br /> i++;<br /> }<br />'.
'}</span></pre>What would happen if a non-terminated string were input to this function?<br /><br />';
$strconv = 'Consider the following function:
void FillMeUp(char* in_string) {
int i = 0;
while (in_string[i] != \'\0\') {
in_string[i] = \'X\';
i++;
}
}
What would happen if a non-terminated string were input to this function?
';
$this->assertSame($strconv, html_to_text($strorig));
}
}
+92
View File
@@ -0,0 +1,92 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the html_writer class.
*
* @package core
* @category phpunit
* @copyright 2010 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/outputcomponents.php');
/**
* Unit tests for the html_writer class.
*
* @copyright 2010 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class html_writer_testcase extends basic_testcase {
public function test_start_tag() {
$this->assertEquals('<div>', html_writer::start_tag('div'));
}
public function test_start_tag_with_attr() {
$this->assertEquals('<div class="frog">',
html_writer::start_tag('div', array('class' => 'frog')));
}
public function test_start_tag_with_attrs() {
$this->assertEquals('<div class="frog" id="mydiv">',
html_writer::start_tag('div', array('class' => 'frog', 'id' => 'mydiv')));
}
public function test_end_tag() {
$this->assertEquals('</div>', html_writer::end_tag('div'));
}
public function test_empty_tag() {
$this->assertEquals('<br />', html_writer::empty_tag('br'));
}
public function test_empty_tag_with_attrs() {
$this->assertEquals('<input type="submit" value="frog" />',
html_writer::empty_tag('input', array('type' => 'submit', 'value' => 'frog')));
}
public function test_nonempty_tag_with_content() {
$this->assertEquals('<div>Hello world!</div>',
html_writer::nonempty_tag('div', 'Hello world!'));
}
public function test_nonempty_tag_empty() {
$this->assertEquals('',
html_writer::nonempty_tag('div', ''));
}
public function test_nonempty_tag_null() {
$this->assertEquals('',
html_writer::nonempty_tag('div', null));
}
public function test_nonempty_tag_zero() {
$this->assertEquals('<div class="score">0</div>',
html_writer::nonempty_tag('div', 0, array('class' => 'score')));
}
public function test_nonempty_tag_zero_string() {
$this->assertEquals('<div class="score">0</div>',
html_writer::nonempty_tag('div', '0', array('class' => 'score')));
}
}
+218
View File
@@ -0,0 +1,218 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests of mathslib wrapper and underlying EvalMath library.
*
* @package core
* @category phpunit
* @copyright 2007 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/mathslib.php');
class mathsslib_testcase extends basic_testcase {
/**
* Tests the basic formula evaluation
*/
public function test__basic() {
$formula = new calc_formula('=1+2');
$res = $formula->evaluate();
$this->assertEquals($res, 3, '3+1 is: %s');
}
/**
* Tests the formula params
*/
public function test__params() {
$formula = new calc_formula('=a+b+c', array('a'=>10, 'b'=>20, 'c'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 60, '10+20+30 is: %s');
}
/**
* Tests the changed params
*/
public function test__changing_params() {
$formula = new calc_formula('=a+b+c', array('a'=>10, 'b'=>20, 'c'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 60, '10+20+30 is: %s');
$formula->set_params(array('a'=>1, 'b'=>2, 'c'=>3));
$res = $formula->evaluate();
$this->assertEquals($res, 6, 'changed params 1+2+3 is: %s');
}
/**
* Tests the spreadsheet emulation function in formula
*/
public function test__calc_function() {
$formula = new calc_formula('=sum(a, b, c)', array('a'=>10, 'b'=>20, 'c'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 60, 'sum(a, b, c) is: %s');
}
public function test_other_functions() {
$formula = new calc_formula('=average(1,2,3)');
$this->assertEquals($formula->evaluate(), 2);
$formula = new calc_formula('=mod(10,3)');
$this->assertEquals($formula->evaluate(), 1);
$formula = new calc_formula('=power(2,3)');
$this->assertEquals($formula->evaluate(), 8);
}
/**
* Tests the min and max functions
*/
public function test__minmax_function() {
$formula = new calc_formula('=min(a, b, c)', array('a'=>10, 'b'=>20, 'c'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 10, 'minimum is: %s');
$formula = new calc_formula('=max(a, b, c)', array('a'=>10, 'b'=>20, 'c'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 30, 'maximum is: %s');
}
/**
* Tests special chars
*/
public function test__specialchars() {
$formula = new calc_formula('=gi1 + gi2 + gi11', array('gi1'=>10, 'gi2'=>20, 'gi11'=>30));
$res = $formula->evaluate();
$this->assertEquals($res, 60, 'sum is: %s');
}
/**
* Tests some slightly more complex expressions
*/
public function test__more_complex_expressions() {
$formula = new calc_formula('=pi() + a', array('a'=>10));
$res = $formula->evaluate();
$this->assertEquals($res, pi()+10);
$formula = new calc_formula('=pi()^a', array('a'=>10));
$res = $formula->evaluate();
$this->assertEquals($res, pow(pi(), 10));
$formula = new calc_formula('=-8*(5/2)^2*(1-sqrt(4))-8');
$res = $formula->evaluate();
$this->assertEquals($res, -8*pow((5/2), 2)*(1-sqrt(4))-8);
}
/**
* Tests some slightly more complex expressions
*/
public function test__error_handling() {
$formula = new calc_formula('=pi( + a', array('a'=>10));
$res = $formula->evaluate();
$this->assertEquals($res, false);
$this->assertEquals($formula->get_error(),
get_string('unexpectedoperator', 'mathslib', '+'));
$formula = new calc_formula('=pi(');
$res = $formula->evaluate();
$this->assertEquals($res, false);
$this->assertEquals($formula->get_error(),
get_string('expectingaclosingbracket', 'mathslib'));
$formula = new calc_formula('=pi()^');
$res = $formula->evaluate();
$this->assertEquals($res, false);
$this->assertEquals($formula->get_error(),
get_string('operatorlacksoperand', 'mathslib', '^'));
}
public function test_rounding_function() {
$formula = new calc_formula('=round(2.5)');
$this->assertEquals($formula->evaluate(), 3);
$formula = new calc_formula('=round(1.5)');
$this->assertEquals($formula->evaluate(), 2);
$formula = new calc_formula('=round(-1.49)');
$this->assertEquals($formula->evaluate(), -1);
$formula = new calc_formula('=round(-2.49)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=round(-1.5)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=round(-2.5)');
$this->assertEquals($formula->evaluate(), -3);
$formula = new calc_formula('=ceil(2.5)');
$this->assertEquals($formula->evaluate(), 3);
$formula = new calc_formula('=ceil(1.5)');
$this->assertEquals($formula->evaluate(), 2);
$formula = new calc_formula('=ceil(-1.49)');
$this->assertEquals($formula->evaluate(), -1);
$formula = new calc_formula('=ceil(-2.49)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=ceil(-1.5)');
$this->assertEquals($formula->evaluate(), -1);
$formula = new calc_formula('=ceil(-2.5)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=floor(2.5)');
$this->assertEquals($formula->evaluate(), 2);
$formula = new calc_formula('=floor(1.5)');
$this->assertEquals($formula->evaluate(), 1);
$formula = new calc_formula('=floor(-1.49)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=floor(-2.49)');
$this->assertEquals($formula->evaluate(), -3);
$formula = new calc_formula('=floor(-1.5)');
$this->assertEquals($formula->evaluate(), -2);
$formula = new calc_formula('=floor(-2.5)');
$this->assertEquals($formula->evaluate(), -3);
}
public function test_scientific_notation() {
$formula = new calc_formula('=10e10');
$this->assertEquals($formula->evaluate(), 1e11, '', 1e11*1e-15);
$formula = new calc_formula('=10e-10');
$this->assertEquals($formula->evaluate(), 1e-9, '', 1e11*1e-15);
$formula = new calc_formula('=10e+10');
$this->assertEquals($formula->evaluate(), 1e11, '', 1e11*1e-15);
$formula = new calc_formula('=10e10*5');
$this->assertEquals($formula->evaluate(), 5e11, '', 1e11*1e-15);
$formula = new calc_formula('=10e10^2');
$this->assertEquals($formula->evaluate(), 1e22, '', 1e22*1e-15);
}
}
File diff suppressed because it is too large Load Diff
+538
View File
@@ -0,0 +1,538 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for lib/navigationlib.php
*
* @package core
* @category phpunit
* @copyright 2009 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later (5)
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/navigationlib.php');
class navigation_node_testcase extends basic_testcase {
protected $tree;
protected $fakeproperties = array(
'text' => 'text',
'shorttext' => 'A very silly extra long short text string, more than 25 characters',
'key' => 'key',
'type' => 'navigation_node::TYPE_COURSE',
'action' => 'http://www.moodle.org/');
protected $activeurl = null;
protected $inactivenode = null;
/**
* @var navigation_node
*/
public $node;
protected function setUp() {
global $CFG, $PAGE, $SITE;
parent::setUp();
$PAGE->set_url('/');
$PAGE->set_course($SITE);
$this->activeurl = $PAGE->url;
navigation_node::override_active_url($this->activeurl);
$this->inactiveurl = new moodle_url('http://www.moodle.com/');
$this->fakeproperties['action'] = $this->inactiveurl;
$this->node = new navigation_node('Test Node');
$this->node->type = navigation_node::TYPE_SYSTEM;
$demo1 = $this->node->add('demo1', $this->inactiveurl, navigation_node::TYPE_COURSE, null, 'demo1', new pix_icon('i/course', ''));
$demo2 = $this->node->add('demo2', $this->inactiveurl, navigation_node::TYPE_COURSE, null, 'demo2', new pix_icon('i/course', ''));
$demo3 = $this->node->add('demo3', $this->inactiveurl, navigation_node::TYPE_CATEGORY, null, 'demo3',new pix_icon('i/course', ''));
$demo4 = $demo3->add('demo4', $this->inactiveurl,navigation_node::TYPE_COURSE, null, 'demo4', new pix_icon('i/course', ''));
$demo5 = $demo3->add('demo5', $this->activeurl, navigation_node::TYPE_COURSE, null, 'demo5',new pix_icon('i/course', ''));
$demo5->add('activity1', null, navigation_node::TYPE_ACTIVITY, null, 'activity1')->make_active();
$hiddendemo1 = $this->node->add('hiddendemo1', $this->inactiveurl, navigation_node::TYPE_CATEGORY, null, 'hiddendemo1', new pix_icon('i/course', ''));
$hiddendemo1->hidden = true;
$hiddendemo1->add('hiddendemo2', $this->inactiveurl, navigation_node::TYPE_COURSE, null, 'hiddendemo2', new pix_icon('i/course', ''))->helpbutton = 'Here is a help button';;
$hiddendemo1->add('hiddendemo3', $this->inactiveurl, navigation_node::TYPE_COURSE,null, 'hiddendemo3', new pix_icon('i/course', ''))->display = false;
}
public function test___construct() {
global $CFG;
$node = new navigation_node($this->fakeproperties);
$this->assertEquals($node->text, $this->fakeproperties['text']);
$this->assertEquals($node->title, $this->fakeproperties['text']);
$this->assertTrue(strpos($this->fakeproperties['shorttext'], substr($node->shorttext,0, -3))===0);
$this->assertEquals($node->key, $this->fakeproperties['key']);
$this->assertEquals($node->type, $this->fakeproperties['type']);
$this->assertEquals($node->action, $this->fakeproperties['action']);
}
public function test_add() {
global $CFG;
// Add a node with all args set
$node1 = $this->node->add('test_add_1','http://www.moodle.org/',navigation_node::TYPE_COURSE,'testadd1','key',new pix_icon('i/course', ''));
// Add a node with the minimum args required
$node2 = $this->node->add('test_add_2',null, navigation_node::TYPE_CUSTOM,'testadd2');
$node3 = $this->node->add(str_repeat('moodle ', 15),str_repeat('moodle', 15));
$this->assertInstanceOf('navigation_node', $node1);
$this->assertInstanceOf('navigation_node', $node2);
$this->assertInstanceOf('navigation_node', $node3);
$ref = $this->node->get('key');
$this->assertSame($node1, $ref);
$ref = $this->node->get($node2->key);
$this->assertSame($node2, $ref);
$ref = $this->node->get($node2->key, $node2->type);
$this->assertSame($node2, $ref);
$ref = $this->node->get($node3->key, $node3->type);
$this->assertSame($node3, $ref);
}
public function test_add_before() {
global $CFG;
// Create 3 nodes
$node1 = navigation_node::create('test_add_1', null, navigation_node::TYPE_CUSTOM,
'test 1', 'testadd1');
$node2 = navigation_node::create('test_add_2', null, navigation_node::TYPE_CUSTOM,
'test 2', 'testadd2');
$node3 = navigation_node::create('test_add_3', null, navigation_node::TYPE_CUSTOM,
'test 3', 'testadd3');
// Add node 2, then node 1 before 2, then node 3 at end
$this->node->add_node($node2);
$this->node->add_node($node1, 'testadd2');
$this->node->add_node($node3);
// Check the last 3 nodes are in 1, 2, 3 order and have those indexes
foreach($this->node->children as $child) {
$keys[] = $child->key;
}
$this->assertEquals('testadd1', $keys[count($keys)-3]);
$this->assertEquals('testadd2', $keys[count($keys)-2]);
$this->assertEquals('testadd3', $keys[count($keys)-1]);
}
public function test_add_class() {
$node = $this->node->get('demo1');
$this->assertInstanceOf('navigation_node', $node);
if ($node !== false) {
$node->add_class('myclass');
$classes = $node->classes;
$this->assertTrue(in_array('myclass', $classes));
}
}
public function test_check_if_active() {
// First test the string urls
// demo1 -> action is http://www.moodle.org/, thus should be true
$demo5 = $this->node->find('demo5', navigation_node::TYPE_COURSE);
if ($this->assertInstanceOf('navigation_node', $demo5)) {
$this->assertTrue($demo5->check_if_active());
}
// demo2 -> action is http://www.moodle.com/, thus should be false
$demo2 = $this->node->get('demo2');
if ($this->assertInstanceOf('navigation_node', $demo2)) {
$this->assertFalse($demo2->check_if_active());
}
}
public function test_contains_active_node() {
// demo5, and activity1 were set to active during setup
// Should be true as it contains all nodes
$this->assertTrue($this->node->contains_active_node());
// Should be true as demo5 is a child of demo3
$this->assertTrue($this->node->get('demo3')->contains_active_node());
// Obviously duff
$this->assertFalse($this->node->get('demo1')->contains_active_node());
// Should be true as demo5 contains activity1
$this->assertTrue($this->node->get('demo3')->get('demo5')->contains_active_node());
// Should be true activity1 is the active node
$this->assertTrue($this->node->get('demo3')->get('demo5')->get('activity1')->contains_active_node());
// Obviously duff
$this->assertFalse($this->node->get('demo3')->get('demo4')->contains_active_node());
}
public function test_find_active_node() {
$activenode1 = $this->node->find_active_node();
$activenode2 = $this->node->get('demo1')->find_active_node();
if ($this->assertInstanceOf('navigation_node', $activenode1)) {
$ref = $this->node->get('demo3')->get('demo5')->get('activity1');
$this->assertSame($activenode1, $ref);
}
$this->assertNotInstanceOf('navigation_node', $activenode2);
}
public function test_find() {
$node1 = $this->node->find('demo1', navigation_node::TYPE_COURSE);
$node2 = $this->node->find('demo5', navigation_node::TYPE_COURSE);
$node3 = $this->node->find('demo5', navigation_node::TYPE_CATEGORY);
$node4 = $this->node->find('demo0', navigation_node::TYPE_COURSE);
$this->assertInstanceOf('navigation_node', $node1);
$this->assertInstanceOf('navigation_node', $node2);
$this->assertNotInstanceOf('navigation_node', $node3);
$this->assertNotInstanceOf('navigation_node', $node4);
}
public function test_find_expandable() {
$expandable = array();
$this->node->find_expandable($expandable);
//TODO: find out what is wrong here - it was returning 4 before the conversion
//$this->assertEquals(count($expandable), 4);
$this->assertEquals(count($expandable), 0);
if (count($expandable) === 4) {
$name = $expandable[0]['key'];
$name .= $expandable[1]['key'];
$name .= $expandable[2]['key'];
$name .= $expandable[3]['key'];
$this->assertEquals($name, 'demo1demo2demo4hiddendemo2');
}
}
public function test_get() {
$node1 = $this->node->get('demo1'); // Exists
$node2 = $this->node->get('demo4'); // Doesn't exist for this node
$node3 = $this->node->get('demo0'); // Doesn't exist at all
$node4 = $this->node->get(false); // Sometimes occurs in nature code
$this->assertInstanceOf('navigation_node', $node1);
$this->assertFalse($node2);
$this->assertFalse($node3);
$this->assertFalse($node4);
}
public function test_get_css_type() {
$csstype1 = $this->node->get('demo3')->get_css_type();
$csstype2 = $this->node->get('demo3')->get('demo5')->get_css_type();
$this->node->get('demo3')->get('demo5')->type = 1000;
$csstype3 = $this->node->get('demo3')->get('demo5')->get_css_type();
$this->assertEquals($csstype1, 'type_category');
$this->assertEquals($csstype2, 'type_course');
$this->assertEquals($csstype3, 'type_unknown');
}
public function test_make_active() {
global $CFG;
$node1 = $this->node->add('active node 1', null, navigation_node::TYPE_CUSTOM, null, 'anode1');
$node2 = $this->node->add('active node 2', new moodle_url($CFG->wwwroot), navigation_node::TYPE_COURSE, null, 'anode2');
$node1->make_active();
$this->node->get('anode2')->make_active();
$this->assertTrue($node1->isactive);
$this->assertTrue($this->node->get('anode2')->isactive);
}
public function test_remove() {
$remove1 = $this->node->add('child to remove 1', null, navigation_node::TYPE_CUSTOM, null, 'remove1');
$remove2 = $this->node->add('child to remove 2', null, navigation_node::TYPE_CUSTOM, null, 'remove2');
$remove3 = $remove2->add('child to remove 3', null, navigation_node::TYPE_CUSTOM, null, 'remove3');
$this->assertInstanceOf('navigation_node', $remove1);
$this->assertInstanceOf('navigation_node', $remove2);
$this->assertInstanceOf('navigation_node', $remove3);
$this->assertInstanceOf('navigation_node', $this->node->get('remove1'));
$this->assertInstanceOf('navigation_node', $this->node->get('remove2'));
$this->assertInstanceOf('navigation_node', $remove2->get('remove3'));
$this->assertTrue($remove1->remove());
$this->assertTrue($this->node->get('remove2')->remove());
$this->assertTrue($remove2->get('remove3')->remove());
$this->assertFalse($this->node->get('remove1'));
$this->assertFalse($this->node->get('remove2'));
}
public function test_remove_class() {
$this->node->add_class('testclass');
$this->assertTrue($this->node->remove_class('testclass'));
$this->assertFalse(in_array('testclass', $this->node->classes));
}
}
/**
* This is a dummy object that allows us to call protected methods within the
* global navigation class by prefixing the methods with `exposed_`
*/
class exposed_global_navigation extends global_navigation {
protected $exposedkey = 'exposed_';
public function __construct(moodle_page $page=null) {
global $PAGE;
if ($page === null) {
$page = $PAGE;
}
parent::__construct($page);
$this->cache = new navigation_cache('simpletest_nav');
}
public function __call($method, $arguments) {
if (strpos($method,$this->exposedkey) !== false) {
$method = substr($method, strlen($this->exposedkey));
}
if (method_exists($this, $method)) {
return call_user_func_array(array($this, $method), $arguments);
}
throw new coding_exception('You have attempted to access a method that does not exist for the given object '.$method, DEBUG_DEVELOPER);
}
public function set_initialised() {
$this->initialised = true;
}
}
class mock_initialise_global_navigation extends global_navigation {
static $count = 1;
public function load_for_category() {
$this->add('load_for_category', null, null, null, 'initcall'.self::$count);
self::$count++;
return 0;
}
public function load_for_course() {
$this->add('load_for_course', null, null, null, 'initcall'.self::$count);
self::$count++;
return 0;
}
public function load_for_activity() {
$this->add('load_for_activity', null, null, null, 'initcall'.self::$count);
self::$count++;
return 0;
}
public function load_for_user($user=null, $forceforcontext=false) {
$this->add('load_for_user', null, null, null, 'initcall'.self::$count);
self::$count++;
return 0;
}
}
class global_navigation_testcase extends basic_testcase {
/**
* @var global_navigation
*/
public $node;
protected function setUp() {
parent::setUp();
$this->node = new exposed_global_navigation();
// Create an initial tree structure to work with
$cat1 = $this->node->add('category 1', null, navigation_node::TYPE_CATEGORY, null, 'cat1');
$cat2 = $this->node->add('category 2', null, navigation_node::TYPE_CATEGORY, null, 'cat2');
$cat3 = $this->node->add('category 3', null, navigation_node::TYPE_CATEGORY, null, 'cat3');
$sub1 = $cat2->add('sub category 1', null, navigation_node::TYPE_CATEGORY, null, 'sub1');
$sub2 = $cat2->add('sub category 2', null, navigation_node::TYPE_CATEGORY, null, 'sub2');
$sub3 = $cat2->add('sub category 3', null, navigation_node::TYPE_CATEGORY, null, 'sub3');
$course1 = $sub2->add('course 1', null, navigation_node::TYPE_COURSE, null, 'course1');
$course2 = $sub2->add('course 2', null, navigation_node::TYPE_COURSE, null, 'course2');
$course3 = $sub2->add('course 3', null, navigation_node::TYPE_COURSE, null, 'course3');
$section1 = $course2->add('section 1', null, navigation_node::TYPE_SECTION, null, 'sec1');
$section2 = $course2->add('section 2', null, navigation_node::TYPE_SECTION, null, 'sec2');
$section3 = $course2->add('section 3', null, navigation_node::TYPE_SECTION, null, 'sec3');
$act1 = $section2->add('activity 1', null, navigation_node::TYPE_ACTIVITY, null, 'act1');
$act2 = $section2->add('activity 2', null, navigation_node::TYPE_ACTIVITY, null, 'act2');
$act3 = $section2->add('activity 3', null, navigation_node::TYPE_ACTIVITY, null, 'act3');
$res1 = $section2->add('resource 1', null, navigation_node::TYPE_RESOURCE, null, 'res1');
$res2 = $section2->add('resource 2', null, navigation_node::TYPE_RESOURCE, null, 'res2');
$res3 = $section2->add('resource 3', null, navigation_node::TYPE_RESOURCE, null, 'res3');
}
public function test_format_display_course_content() {
$this->assertTrue($this->node->exposed_format_display_course_content('topic'));
$this->assertFalse($this->node->exposed_format_display_course_content('scorm'));
$this->assertTrue($this->node->exposed_format_display_course_content('dummy'));
}
public function test_module_extends_navigation() {
$this->assertTrue($this->node->exposed_module_extends_navigation('data'));
$this->assertFalse($this->node->exposed_module_extends_navigation('test1'));
}
}
/**
* This is a dummy object that allows us to call protected methods within the
* global navigation class by prefixing the methods with `exposed_`
*/
class exposed_navbar extends navbar {
protected $exposedkey = 'exposed_';
public function __construct(moodle_page $page) {
parent::__construct($page);
$this->cache = new navigation_cache('simpletest_nav');
}
function __call($method, $arguments) {
if (strpos($method,$this->exposedkey) !== false) {
$method = substr($method, strlen($this->exposedkey));
}
if (method_exists($this, $method)) {
return call_user_func_array(array($this, $method), $arguments);
}
throw new coding_exception('You have attempted to access a method that does not exist for the given object '.$method, DEBUG_DEVELOPER);
}
}
class navigation_exposed_moodle_page extends moodle_page {
public function set_navigation(navigation_node $node) {
$this->_navigation = $node;
}
}
class navbar_testcase extends advanced_testcase {
protected $node;
protected $oldnav;
protected function setUp() {
global $PAGE, $SITE;
parent::setUp();
$this->resetAfterTest(true);
$PAGE->set_url('/');
$PAGE->set_course($SITE);
$tempnode = new exposed_global_navigation();
// Create an initial tree structure to work with
$cat1 = $tempnode->add('category 1', null, navigation_node::TYPE_CATEGORY, null, 'cat1');
$cat2 = $tempnode->add('category 2', null, navigation_node::TYPE_CATEGORY, null, 'cat2');
$cat3 = $tempnode->add('category 3', null, navigation_node::TYPE_CATEGORY, null, 'cat3');
$sub1 = $cat2->add('sub category 1', null, navigation_node::TYPE_CATEGORY, null, 'sub1');
$sub2 = $cat2->add('sub category 2', null, navigation_node::TYPE_CATEGORY, null, 'sub2');
$sub3 = $cat2->add('sub category 3', null, navigation_node::TYPE_CATEGORY, null, 'sub3');
$course1 = $sub2->add('course 1', null, navigation_node::TYPE_COURSE, null, 'course1');
$course2 = $sub2->add('course 2', null, navigation_node::TYPE_COURSE, null, 'course2');
$course3 = $sub2->add('course 3', null, navigation_node::TYPE_COURSE, null, 'course3');
$section1 = $course2->add('section 1', null, navigation_node::TYPE_SECTION, null, 'sec1');
$section2 = $course2->add('section 2', null, navigation_node::TYPE_SECTION, null, 'sec2');
$section3 = $course2->add('section 3', null, navigation_node::TYPE_SECTION, null, 'sec3');
$act1 = $section2->add('activity 1', null, navigation_node::TYPE_ACTIVITY, null, 'act1');
$act2 = $section2->add('activity 2', null, navigation_node::TYPE_ACTIVITY, null, 'act2');
$act3 = $section2->add('activity 3', null, navigation_node::TYPE_ACTIVITY, null, 'act3');
$res1 = $section2->add('resource 1', null, navigation_node::TYPE_RESOURCE, null, 'res1');
$res2 = $section2->add('resource 2', null, navigation_node::TYPE_RESOURCE, null, 'res2');
$res3 = $section2->add('resource 3', null, navigation_node::TYPE_RESOURCE, null, 'res3');
$tempnode->find('course2', navigation_node::TYPE_COURSE)->make_active();
$page = new navigation_exposed_moodle_page();
$page->set_url($PAGE->url);
$page->set_context($PAGE->context);
$navigation = new exposed_global_navigation($page);
$navigation->children = $tempnode->children;
$navigation->set_initialised();
$page->set_navigation($navigation);
$this->cache = new navigation_cache('simpletest_nav');
$this->node = new exposed_navbar($page);
}
public function test_add() {
// Add a node with all args set
$this->node->add('test_add_1','http://www.moodle.org/',navigation_node::TYPE_COURSE,'testadd1','testadd1',new pix_icon('i/course', ''));
// Add a node with the minimum args required
$this->node->add('test_add_2','http://www.moodle.org/',navigation_node::TYPE_COURSE,'testadd2','testadd2',new pix_icon('i/course', ''));
$this->assertInstanceOf('navigation_node', $this->node->get('testadd1'));
$this->assertInstanceOf('navigation_node', $this->node->get('testadd2'));
}
public function test_has_items() {
$this->assertTrue($this->node->has_items());
}
}
class navigation_cache_testcase extends basic_testcase {
protected $cache;
protected function setUp() {
parent::setUp();
$this->cache = new navigation_cache('simpletest_nav');
$this->cache->anysetvariable = true;
}
public function test___get() {
$this->assertTrue($this->cache->anysetvariable);
$this->assertEquals($this->cache->notasetvariable, null);
}
public function test___set() {
$this->cache->myname = 'Sam Hemelryk';
$this->assertTrue($this->cache->cached('myname'));
$this->assertEquals($this->cache->myname, 'Sam Hemelryk');
}
public function test_cached() {
$this->assertTrue($this->cache->cached('anysetvariable'));
$this->assertFalse($this->cache->cached('notasetvariable'));
}
public function test_clear() {
$cache = clone($this->cache);
$this->assertTrue($cache->cached('anysetvariable'));
$cache->clear();
$this->assertFalse($cache->cached('anysetvariable'));
}
public function test_set() {
$this->cache->set('software', 'Moodle');
$this->assertTrue($this->cache->cached('software'));
$this->assertEquals($this->cache->software, 'Moodle');
}
}
/**
* This is a dummy object that allows us to call protected methods within the
* global navigation class by prefixing the methods with `exposed_`
*/
class exposed_settings_navigation extends settings_navigation {
protected $exposedkey = 'exposed_';
function __construct() {
global $PAGE;
parent::__construct($PAGE);
$this->cache = new navigation_cache('simpletest_nav');
}
function __call($method, $arguments) {
if (strpos($method,$this->exposedkey) !== false) {
$method = substr($method, strlen($this->exposedkey));
}
if (method_exists($this, $method)) {
return call_user_func_array(array($this, $method), $arguments);
}
throw new coding_exception('You have attempted to access a method that does not exist for the given object '.$method, DEBUG_DEVELOPER);
}
}
class settings_navigation_testcase extends advanced_testcase {
protected $node;
protected $cache;
protected function setUp() {
global $PAGE, $SITE;
parent::setUp();
$this->resetAfterTest(true);
$PAGE->set_url('/');
$PAGE->set_course($SITE);
$this->cache = new navigation_cache('simpletest_nav');
$this->node = new exposed_settings_navigation();
}
public function test___construct() {
$this->node = new exposed_settings_navigation();
}
public function test___initialise() {
$this->node->initialise();
$this->assertEquals($this->node->id, 'settingsnav');
}
public function test_in_alternative_role() {
$this->assertFalse($this->node->exposed_in_alternative_role());
}
}
+232
View File
@@ -0,0 +1,232 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for lib/outputcomponents.php.
*
* @package core
* @category phpunit
* @copyright 2011 David Mudrak <david@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/outputcomponents.php');
/**
* Unit tests for the user_picture class
*/
class user_picture_testcase extends basic_testcase {
public function test_user_picture_fields_aliasing() {
$fields = user_picture::fields();
$fields = array_map('trim', explode(',', $fields));
$this->assertTrue(in_array('id', $fields));
$aliased = array();
foreach ($fields as $field) {
if ($field === 'id') {
$aliased['id'] = 'aliasedid';
} else {
$aliased[$field] = 'prefix'.$field;
}
}
$returned = user_picture::fields('', array('custom1', 'id'), 'aliasedid', 'prefix');
$returned = array_map('trim', explode(',', $returned));
$this->assertEquals(count($returned), count($fields) + 1); // only one extra field added
foreach ($fields as $field) {
if ($field === 'id') {
$expected = "id AS aliasedid";
} else {
$expected = "$field AS prefix$field";
}
$this->assertTrue(in_array($expected, $returned), "Expected pattern '$expected' not returned");
}
$this->assertTrue(in_array("custom1 AS prefixcustom1", $returned), "Expected pattern 'custom1 AS prefixcustom1' not returned");
}
public function test_user_picture_fields_unaliasing() {
$fields = user_picture::fields();
$fields = array_map('trim', explode(',', $fields));
$fakerecord = new stdClass();
$fakerecord->aliasedid = 42;
foreach ($fields as $field) {
if ($field !== 'id') {
$fakerecord->{'prefix'.$field} = "Value of $field";
}
}
$fakerecord->prefixcustom1 = 'Value of custom1';
$returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
$this->assertEquals($returned->id, 42);
foreach ($fields as $field) {
if ($field !== 'id') {
$this->assertEquals($returned->{$field}, "Value of $field");
}
}
$this->assertEquals($returned->custom1, 'Value of custom1');
}
public function test_user_picture_fields_unaliasing_null() {
$fields = user_picture::fields();
$fields = array_map('trim', explode(',', $fields));
$fakerecord = new stdClass();
$fakerecord->aliasedid = 42;
foreach ($fields as $field) {
if ($field !== 'id') {
$fakerecord->{'prefix'.$field} = "Value of $field";
}
}
$fakerecord->prefixcustom1 = 'Value of custom1';
$fakerecord->prefiximagealt = null;
$returned = user_picture::unalias($fakerecord, array('custom1'), 'aliasedid', 'prefix');
$this->assertEquals($returned->id, 42);
$this->assertEquals($returned->imagealt, null);
foreach ($fields as $field) {
if ($field !== 'id' and $field !== 'imagealt') {
$this->assertEquals($returned->{$field}, "Value of $field");
}
}
$this->assertEquals($returned->custom1, 'Value of custom1');
}
}
/**
* Unit tests for the custom_menu class
*/
class custom_menu_testcase extends basic_testcase {
public function test_empty_menu() {
$emptymenu = new custom_menu();
$this->assertTrue($emptymenu instanceof custom_menu);
$this->assertFalse($emptymenu->has_children());
}
public function test_basic_syntax() {
$definition = <<<EOF
Moodle community|http://moodle.org
-Moodle free support|http://moodle.org/support
-Moodle development|http://moodle.org/development
--Moodle Tracker|http://tracker.moodle.org
--Moodle Docs|http://docs.moodle.org
-Moodle News|http://moodle.org/news
Moodle company
-Hosting|http://moodle.com/hosting|Commercial hosting
-Support|http://moodle.com/support|Commercial support
EOF;
$menu = new custom_menu($definition);
$this->assertTrue($menu instanceof custom_menu);
$this->assertTrue($menu->has_children());
$firstlevel = $menu->get_children();
$this->assertTrue(is_array($firstlevel));
$this->assertEquals(2, count($firstlevel));
$item = array_shift($firstlevel);
$this->assertTrue($item instanceof custom_menu_item);
$this->assertTrue($item->has_children());
$this->assertEquals(3, count($item->get_children()));
$this->assertEquals('Moodle community', $item->get_text());
$itemurl = $item->get_url();
$this->assertTrue($itemurl instanceof moodle_url);
$this->assertEquals('http://moodle.org', $itemurl->out());
$this->assertEquals($item->get_text(), $item->get_title()); // implicit title
$item = array_shift($firstlevel);
$this->assertTrue($item->has_children());
$this->assertEquals(2, count($item->get_children()));
$this->assertEquals('Moodle company', $item->get_text());
$this->assertTrue(is_null($item->get_url()));
$children = $item->get_children();
$subitem = array_shift($children);
$this->assertFalse($subitem->has_children());
$this->assertEquals('Hosting', $subitem->get_text());
$this->assertEquals('Commercial hosting', $subitem->get_title());
}
public function test_multilang_support() {
$definition = <<<EOF
Start|http://school.info
Info
-English|http://school.info/en|Information in English|en
-Deutsch|http://school.info/de|Informationen in deutscher Sprache|de,de_du,de_kids
EOF;
// the menu without multilang support
$menu = new custom_menu($definition);
$this->assertTrue($menu->has_children());
$this->assertEquals(2, count($menu->get_children()));
$children = $menu->get_children();
$infomenu = array_pop($children);
$this->assertTrue($infomenu->has_children());
$children = $infomenu->get_children();
$this->assertEquals(2, count($children));
$children = $infomenu->get_children();
$langspecinfo = array_shift($children);
$this->assertEquals('Information in English', $langspecinfo->get_title());
// same menu for English language selected
$menu = new custom_menu($definition, 'en');
$this->assertTrue($menu->has_children());
$this->assertEquals(2, count($menu->get_children()));
$children = $menu->get_children();
$infomenu = array_pop($children);
$this->assertTrue($infomenu->has_children());
$this->assertEquals(1, count($infomenu->get_children()));
$children = $infomenu->get_children();
$langspecinfo = array_shift($children);
$this->assertEquals('Information in English', $langspecinfo->get_title());
// same menu for German (de_du) language selected
$menu = new custom_menu($definition, 'de_du');
$this->assertTrue($menu->has_children());
$this->assertEquals(2, count($menu->get_children()));
$children = $menu->get_children();
$infomenu = array_pop($children);
$this->assertTrue($infomenu->has_children());
$this->assertEquals(1, count($infomenu->get_children()));
$children = $infomenu->get_children();
$langspecinfo = array_shift($children);
$this->assertEquals('Informationen in deutscher Sprache', $langspecinfo->get_title());
// same menu for Czech language selected
$menu = new custom_menu($definition, 'cs');
$this->assertTrue($menu->has_children());
$this->assertEquals(2, count($menu->get_children()));
$children = $infomenu->get_children();
$infomenu = array_pop( $children);
$this->assertFalse($infomenu->has_children());
}
}
+162
View File
@@ -0,0 +1,162 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for (some of) ../outputlib.php.
*
* @package core
* @category phpunit
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later (5)
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/outputlib.php');
/**
* Unit tests for the xhtml_container_stack class.
*
* These tests assume that developer debug mode is on, which, at the time of
* writing, is true. admin/tool/unittest/index.php forces it on.
*
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class xhtml_container_stack_testcase extends basic_testcase {
protected function start_capture() {
ob_start();
}
protected function end_capture() {
$result = ob_get_contents();
ob_end_clean();
return $result;
}
public function test_push_then_pop() {
// Set up.
$stack = new xhtml_container_stack();
// Exercise SUT.
$this->start_capture();
$stack->push('testtype', '</div>');
$html = $stack->pop('testtype');
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('</div>', $html);
$this->assertEquals('', $errors);
}
public function test_mismatched_pop_prints_warning() {
// Set up.
$stack = new xhtml_container_stack();
$stack->push('testtype', '</div>');
// Exercise SUT.
$this->start_capture();
$html = $stack->pop('mismatch');
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('</div>', $html);
$this->assertNotEquals('', $errors);
}
public function test_pop_when_empty_prints_warning() {
// Set up.
$stack = new xhtml_container_stack();
// Exercise SUT.
$this->start_capture();
$html = $stack->pop('testtype');
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('', $html);
$this->assertNotEquals('', $errors);
}
public function test_correct_nesting() {
// Set up.
$stack = new xhtml_container_stack();
// Exercise SUT.
$this->start_capture();
$stack->push('testdiv', '</div>');
$stack->push('testp', '</p>');
$html2 = $stack->pop('testp');
$html1 = $stack->pop('testdiv');
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('</p>', $html2);
$this->assertEquals('</div>', $html1);
$this->assertEquals('', $errors);
}
public function test_pop_all_but_last() {
// Set up.
$stack = new xhtml_container_stack();
$stack->push('test1', '</h1>');
$stack->push('test2', '</h2>');
$stack->push('test3', '</h3>');
// Exercise SUT.
$this->start_capture();
$html = $stack->pop_all_but_last();
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('</h3></h2>', $html);
$this->assertEquals('', $errors);
// Tear down.
$stack->discard();
}
public function test_pop_all_but_last_only_one() {
// Set up.
$stack = new xhtml_container_stack();
$stack->push('test1', '</h1>');
// Exercise SUT.
$this->start_capture();
$html = $stack->pop_all_but_last();
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('', $html);
$this->assertEquals('', $errors);
// Tear down.
$stack->discard();
}
public function test_pop_all_but_last_empty() {
// Set up.
$stack = new xhtml_container_stack();
// Exercise SUT.
$this->start_capture();
$html = $stack->pop_all_but_last();
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('', $html);
$this->assertEquals('', $errors);
}
public function test_discard() {
// Set up.
$stack = new xhtml_container_stack();
$stack->push('test1', '</somethingdistinctive>');
$stack->discard();
// Exercise SUT.
$this->start_capture();
$stack = null;
$errors = $this->end_capture();
// Verify outcome
$this->assertEquals('', $errors);
}
}
+133 -7
View File
@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* PHPunit implementation unit tests
* PHPUnit integration unit tests
*
* @package core
* @category phpunit
@@ -25,8 +25,9 @@
defined('MOODLE_INTERNAL') || die();
/**
* Test integration of PHPUnit and custom Moodle hacks.
* Test basic_testcase extra features and PHPUnit Moodle integration.
*
* @package core
* @category phpunit
@@ -36,7 +37,7 @@ defined('MOODLE_INTERNAL') || die();
class core_phpunit_basic_testcase extends basic_testcase {
/**
* Tests that bootstraping has occurred correctly
* Tests that bootstrapping has occurred correctly
* @return void
*/
public function test_bootstrap() {
@@ -46,13 +47,138 @@ class core_phpunit_basic_testcase extends basic_testcase {
$this->assertEquals($CFG->prefix, $CFG->phpunit_prefix);
}
/*
public function test_borked_tests() {
global $DB;
/**
* This is just a verification if I understand the PHPUnit assert docs right --skodak
* @return void
*/
public function test_assert_behaviour() {
// arrays
$a = array('a', 'b', 'c');
$b = array('a', 'c', 'b');
$c = array('a', 'b', 'c');
$d = array('a', 'b', 'C');
$this->assertNotEquals($a, $b);
$this->assertNotEquals($a, $d);
$this->assertEquals($a, $c);
$this->assertEquals($a, $b, '', 0, 10, true);
// objects
$a = new stdClass();
$a->x = 'x';
$a->y = 'y';
$b = new stdClass(); // switched order
$b->y = 'y';
$b->x = 'x';
$c = $a;
$d = new stdClass();
$d->x = 'x';
$d->y = 'y';
$d->z = 'z';
$this->assertEquals($a, $b);
$this->assertNotSame($a, $b);
$this->assertEquals($a, $c);
$this->assertSame($a, $c);
$this->assertNotEquals($a, $d);
// string comparison
$this->assertEquals(1, '1');
$this->assertEquals(null, '');
$this->assertNotEquals(1, '1 ');
$this->assertNotEquals(0, '');
$this->assertNotEquals(null, '0');
$this->assertNotEquals(array(), '');
// other comparison
$this->assertEquals(null, null);
$this->assertEquals(false, null);
$this->assertEquals(0, null);
// emptiness
$this->assertEmpty(0);
$this->assertEmpty(0.0);
$this->assertEmpty('');
$this->assertEmpty('0');
$this->assertEmpty(false);
$this->assertEmpty(null);
$this->assertEmpty(array());
$this->assertNotEmpty(1);
$this->assertNotEmpty(0.1);
$this->assertNotEmpty(-1);
$this->assertNotEmpty(' ');
$this->assertNotEmpty('0 ');
$this->assertNotEmpty(true);
$this->assertNotEmpty(array(null));
$this->assertNotEmpty(new stdClass());
}
// Uncomment following tests to see logging of unexpected changes in global state and database
/*
public function test_db_modification() {
global $DB;
$DB->set_field('user', 'confirmed', 1, array('id'=>-1));
}
public function test_cfg_modification() {
global $CFG;
$CFG->xx = 'yy';
unset($CFG->admin);
$CFG->rolesactive = 0;
}
public function test_user_modification() {
global $USER;
$USER->id = 10;
}
public function test_course_modification() {
global $COURSE;
$COURSE->id = 10;
}
*/
}
}
/**
* Test advanced_testcase extra features.
*
* @package core
* @category phpunit
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_phpunit_advanced_testcase extends advanced_testcase {
public function test_set_user() {
global $USER, $DB;
$this->assertEquals(0, $USER->id);
$this->assertSame($_SESSION['USER'], $USER);
$user = $DB->get_record('user', array('id'=>2));
$this->setUser($user);
$this->assertEquals(2, $USER->id);
$this->assertEquals(2, $_SESSION['USER']->id);
$this->assertSame($_SESSION['USER'], $USER);
$USER->id = 3;
$this->assertEquals(3, $USER->id);
$this->assertEquals(3, $_SESSION['USER']->id);
$this->assertSame($_SESSION['USER'], $USER);
session_set_user($user);
$this->assertEquals(2, $USER->id);
$this->assertEquals(2, $_SESSION['USER']->id);
$this->assertSame($_SESSION['USER'], $USER);
$USER = $DB->get_record('user', array('id'=>1));
$this->assertEquals(1, $USER->id);
$this->assertEquals(1, $_SESSION['USER']->id);
$this->assertSame($_SESSION['USER'], $USER);
$this->setUser(null);
$this->assertEquals(0, $USER->id);
$this->assertSame($_SESSION['USER'], $USER);
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for (some of) ../questionlib.php.
*
* @package core_question
* @category phpunit
* @copyright 2006 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Unit tests for (some of) ../questionlib.php.
*
* @copyright 2006 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class questionlib_testcase extends basic_testcase {
public function test_question_reorder_qtypes() {
global $CFG;
require_once($CFG->libdir . '/questionlib.php');
$this->assertEquals(question_reorder_qtypes(
array('t1' => '', 't2' => '', 't3' => ''), 't1', +1),
array(0 => 't2', 1 => 't1', 2 => 't3'));
$this->assertEquals(question_reorder_qtypes(
array('t1' => '', 't2' => '', 't3' => ''), 't1', -1),
array(0 => 't1', 1 => 't2', 2 => 't3'));
$this->assertEquals(question_reorder_qtypes(
array('t1' => '', 't2' => '', 't3' => ''), 't2', -1),
array(0 => 't2', 1 => 't1', 2 => 't3'));
$this->assertEquals(question_reorder_qtypes(
array('t1' => '', 't2' => '', 't3' => ''), 't3', +1),
array(0 => 't1', 1 => 't2', 2 => 't3'));
$this->assertEquals(question_reorder_qtypes(
array('t1' => '', 't2' => '', 't3' => ''), 'missing', +1),
array(0 => 't1', 1 => 't2', 2 => 't3'));
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for ../repositorylib.php.
*
* @package core_repository
* @category phpunit
* @author nicolasconnault@gmail.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("$CFG->dirroot/repository/lib.php");
class repositorylib_testcase extends advanced_testcase {
public function test_initialise_filepicker() {
global $PAGE, $SITE;
$this->resetAfterTest(true);
$PAGE->set_url('/');
$PAGE->set_course($SITE);
$this->setUser(2);
$args = new stdClass();
$args->accepted_types = '*';
$args->return_types = array(FILE_EXTERNAL);
$info = initialise_filepicker($args);
$this->assertInstanceOf('stdClass', $info);
$this->assertObjectHasAttribute('defaultlicense', $info);
$this->assertObjectHasAttribute('licenses', $info);
$this->assertObjectHasAttribute('author', $info);
$this->assertObjectHasAttribute('externallink', $info);
$this->assertObjectHasAttribute('accepted_types', $info);
$this->assertObjectHasAttribute('return_types', $info);
}
}
+145
View File
@@ -0,0 +1,145 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* These tests rely on the rsstest.xml file on download.moodle.org,
* from eloys listing:
* rsstest.xml: One valid rss feed.
* md5: 8fd047914863bf9b3a4b1514ec51c32c
* size: 32188
*
* If networking/proxy configuration is wrong these tests will fail..
*
* @package core
* @category phpunit
* @copyright 2009 Dan Poltawski
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir.'/simplepie/moodle_simplepie.php');
class moodlesimplepie_testcase extends basic_testcase {
# A url we know exists and is valid
const VALIDURL = 'http://download.moodle.org/unittest/rsstest.xml';
# A url which we know doesn't exist
const INVALIDURL = 'http://download.moodle.org/unittest/rsstest-which-doesnt-exist.xml';
# This tinyurl redirects to th rsstest.xml file
const REDIRECTURL = 'http://tinyurl.com/lvyslv';
function setUp() {
moodle_simplepie::reset_cache();
}
function test_getfeed() {
$feed = new moodle_simplepie(self::VALIDURL);
$this->assertInstanceOf('moodle_simplepie', $feed);
$this->assertNull($feed->error(), "Failed to load the sample RSS file. Please check your proxy settings in Moodle. %s");
if ($feed->error()) {
return;
}
$this->assertEquals($feed->get_title(), 'Moodle News');
$this->assertEquals($feed->get_link(), 'http://moodle.org/mod/forum/view.php?f=1');
$this->assertEquals($feed->get_description(), "General news about Moodle.\n\nMoodle is a leading open-source course management system (CMS) - a software package designed to help educators create quality online courses. Such e-learning systems are sometimes also called Learning Management Systems (LMS) or Virtual Learning Environments (VLE). One of the main advantages of Moodle over other systems is a strong grounding in social constructionist pedagogy.");
$this->assertEquals($feed->get_copyright(), '&amp;#169; 2007 moodle');
$this->assertEquals($feed->get_image_url(), 'http://moodle.org/pix/i/rsssitelogo.gif');
$this->assertEquals($feed->get_image_title(), 'moodle');
$this->assertEquals($feed->get_image_link(), 'http://moodle.org');
$this->assertEquals($feed->get_image_width(), '140');
$this->assertEquals($feed->get_image_height(), '35');
$this->assertNotEmpty($items = $feed->get_items());
$this->assertEquals(count($items), 15);
$this->assertNotEmpty($itemone = $feed->get_item(0));
if (!$itemone) {
return;
}
$this->assertEquals($itemone->get_title(), 'Google HOP contest encourages pre-University students to work on Moodle');
$this->assertEquals($itemone->get_link(), 'http://moodle.org/mod/forum/discuss.php?d=85629');
$this->assertEquals($itemone->get_id(), 'http://moodle.org/mod/forum/discuss.php?d=85629');
$description = <<<EOD
by Martin Dougiamas. &nbsp;<p><p><img src="http://code.google.com/opensource/ghop/2007-8/images/ghoplogosm.jpg" align="right" style="margin:10px" />After their very successful <a href="http://code.google.com/soc/2007/">Summer of Code</a> program for University students, Google just announced their new <a href="http://code.google.com/opensource/ghop/2007-8/">Highly Open Participation contest</a>, designed to encourage pre-University students to get involved with open source projects via much smaller and diverse contributions.<br />
<br />
I'm very proud that Moodle has been selected as one of only <a href="http://code.google.com/opensource/ghop/2007-8/projects.html">ten open source projects</a> to take part in the inaugural year of this new contest.<br />
<br />
We have a <a href="http://code.google.com/p/google-highly-open-participation-moodle/issues/list">long list of small tasks</a> prepared already for students, but we would definitely like to see the Moodle community come up with more - so if you have any ideas for things you want to see done, please <a href="http://code.google.com/p/google-highly-open-participation-moodle/">send them to us</a>! Just remember they can't take more than five days.<br />
<br />
Google will pay students US$100 for every three tasks they successfully complete, plus send a cool T-shirt. There are also grand prizes including an all-expenses-paid trip to Google HQ in Mountain View, California. If you are (or know) a young student with an interest in Moodle then give it a go! <br />
<br />
You can find out all the details on the <a href="http://code.google.com/p/google-highly-open-participation-moodle/">Moodle/GHOP contest site</a>.</p></p>
EOD;
$this->assertEquals($itemone->get_description(), $description);
// TODO fix this so it uses $CFG by default
$this->assertEquals($itemone->get_date('U'), 1196412453);
// last item
$this->assertNotEmpty($feed->get_item(14));
// Past last item
$this->assertEmpty($feed->get_item(15));
}
/*
* Test retrieving a url which doesn't exist
*/
function test_failurl() {
$feed = @new moodle_simplepie(self::INVALIDURL); // we do not want this in php error log
$this->assertNotEmpty($feed->error());
}
/*
* Test retrieving a url with broken proxy configuration
*/
function test_failproxy() {
global $CFG;
$oldproxy = $CFG->proxyhost;
$CFG->proxyhost = 'xxxxxxxxxxxxxxx.moodle.org';
$feed = new moodle_simplepie(self::VALIDURL);
$this->assertNotEmpty($feed->error());
$this->assertEmpty($feed->get_title());
$CFG->proxyhost = $oldproxy;
}
/*
* Test retrieving a url which sends a redirect to another valid feed
*/
function test_redirect() {
global $CFG;
$feed = new moodle_simplepie(self::REDIRECTURL);
$this->assertNull($feed->error());
$this->assertEquals($feed->get_title(), 'Moodle News');
$this->assertEquals($feed->get_link(), 'http://moodle.org/mod/forum/view.php?f=1');
}
}
+2 -2
View File
@@ -385,7 +385,7 @@ class collatorlib_testcase extends basic_testcase {
* Prepares things for this test case
* @return void
*/
public function setUp() {
protected function setUp() {
global $SESSION;
if (isset($SESSION->lang)) {
$this->initiallang = $SESSION->lang;
@@ -403,7 +403,7 @@ class collatorlib_testcase extends basic_testcase {
* Cleans things up after this test case has run
* @return void
*/
public function tearDown() {
protected function tearDown() {
global $SESSION;
parent::tearDown();
if ($this->initiallang !== null) {
+187
View File
@@ -0,0 +1,187 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* These tests rely on the rsstest.xml file on download.moodle.org,
* from eloys listing:
* rsstest.xml: One valid rss feed.
* md5: 8fd047914863bf9b3a4b1514ec51c32c
* size: 32188
*
* If networking/proxy configuration is wrong these tests will fail..
*
* @package core
* @category phpunit
* @copyright &copy; 2006 The Open University
* @author T.J.Hunt@open.ac.uk
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
defined('MOODLE_INTERNAL') || die();
class web_testcase extends basic_testcase {
function test_format_string() {
global $CFG;
// Ampersands
$this->assertEquals(format_string("& &&&&& &&"), "&amp; &amp;&amp;&amp;&amp;&amp; &amp;&amp;");
$this->assertEquals(format_string("ANother & &&&&& Category"), "ANother &amp; &amp;&amp;&amp;&amp;&amp; Category");
$this->assertEquals(format_string("ANother & &&&&& Category", true), "ANother &amp; &amp;&amp;&amp;&amp;&amp; Category");
$this->assertEquals(format_string("Nick's Test Site & Other things", true), "Nick's Test Site &amp; Other things");
// String entities
$this->assertEquals(format_string("&quot;"), "&quot;");
// Digital entities
$this->assertEquals(format_string("&11234;"), "&11234;");
// Unicode entities
$this->assertEquals(format_string("&#4475;"), "&#4475;");
// < and > signs
$originalformatstringstriptags = $CFG->formatstringstriptags;
$CFG->formatstringstriptags = false;
$this->assertEquals(format_string('x < 1'), 'x &lt; 1');
$this->assertEquals(format_string('x > 1'), 'x &gt; 1');
$this->assertEquals(format_string('x < 1 and x > 0'), 'x &lt; 1 and x &gt; 0');
$CFG->formatstringstriptags = true;
$this->assertEquals(format_string('x < 1'), 'x &lt; 1');
$this->assertEquals(format_string('x > 1'), 'x &gt; 1');
$this->assertEquals(format_string('x < 1 and x > 0'), 'x &lt; 1 and x &gt; 0');
$CFG->formatstringstriptags = $originalformatstringstriptags;
}
function test_s() {
$this->assertEquals(s("This Breaks \" Strict"), "This Breaks &quot; Strict");
$this->assertEquals(s("This Breaks <a>\" Strict</a>"), "This Breaks &lt;a&gt;&quot; Strict&lt;/a&gt;");
}
function test_format_text_email() {
$this->assertEquals("This is a TEST",
format_text_email('<p>This is a <strong>test</strong></p>',FORMAT_HTML));
$this->assertEquals("This is a TEST",
format_text_email('<p class="frogs">This is a <strong class=\'fishes\'>test</strong></p>',FORMAT_HTML));
$this->assertEquals('& so is this',
format_text_email('&amp; so is this',FORMAT_HTML));
$this->assertEquals('Two bullets: '.textlib::code2utf8(8226).' *',
format_text_email('Two bullets: &#x2022; &#8226;',FORMAT_HTML));
$this->assertEquals(textlib::code2utf8(0x7fd2).textlib::code2utf8(0x7fd2),
format_text_email('&#x7fd2;&#x7FD2;',FORMAT_HTML));
}
function test_highlight() {
$this->assertEquals(highlight('good', 'This is good'), 'This is <span class="highlight">good</span>');
$this->assertEquals(highlight('SpaN', 'span'), '<span class="highlight">span</span>');
$this->assertEquals(highlight('span', 'SpaN'), '<span class="highlight">SpaN</span>');
$this->assertEquals(highlight('span', '<span>span</span>'), '<span><span class="highlight">span</span></span>');
$this->assertEquals(highlight('good is', 'He is good'), 'He <span class="highlight">is</span> <span class="highlight">good</span>');
$this->assertEquals(highlight('+good', 'This is good'), 'This is <span class="highlight">good</span>');
$this->assertEquals(highlight('-good', 'This is good'), 'This is good');
$this->assertEquals(highlight('+good', 'This is goodness'), 'This is goodness');
$this->assertEquals(highlight('good', 'This is goodness'), 'This is <span class="highlight">good</span>ness');
}
function test_replace_ampersands() {
$this->assertEquals(replace_ampersands_not_followed_by_entity("This & that &nbsp;"), "This &amp; that &nbsp;");
$this->assertEquals(replace_ampersands_not_followed_by_entity("This &nbsp that &nbsp;"), "This &amp;nbsp that &nbsp;");
}
function test_strip_links() {
$this->assertEquals(strip_links('this is a <a href="http://someaddress.com/query">link</a>'), 'this is a link');
}
function test_wikify_links() {
$this->assertEquals(wikify_links('this is a <a href="http://someaddress.com/query">link</a>'), 'this is a link [ http://someaddress.com/query ]');
}
function test_moodle_url_round_trip() {
$strurl = 'http://moodle.org/course/view.php?id=5';
$url = new moodle_url($strurl);
$this->assertEquals($strurl, $url->out(false));
$strurl = 'http://moodle.org/user/index.php?contextid=53&sifirst=M&silast=D';
$url = new moodle_url($strurl);
$this->assertEquals($strurl, $url->out(false));
}
function test_moodle_url_round_trip_array_params() {
$strurl = 'http://example.com/?a%5B1%5D=1&a%5B2%5D=2';
$url = new moodle_url($strurl);
$this->assertEquals($strurl, $url->out(false));
$url = new moodle_url('http://example.com/?a[1]=1&a[2]=2');
$this->assertEquals($strurl, $url->out(false));
// For un-keyed array params, we expect 0..n keys to be returned
$strurl = 'http://example.com/?a%5B0%5D=0&a%5B1%5D=1';
$url = new moodle_url('http://example.com/?a[]=0&a[]=1');
$this->assertEquals($strurl, $url->out(false));
}
function test_compare_url() {
$url1 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2));
$url2 = new moodle_url('index2.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
$this->assertFalse($url1->compare($url2, URL_MATCH_BASE));
$this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
$this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
$url2 = new moodle_url('index.php', array('var1' => 1, 'var3' => 3));
$this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
$this->assertFalse($url1->compare($url2, URL_MATCH_PARAMS));
$this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
$url2 = new moodle_url('index.php', array('var1' => 1, 'var2' => 2, 'var3' => 3));
$this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
$this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
$this->assertFalse($url1->compare($url2, URL_MATCH_EXACT));
$url2 = new moodle_url('index.php', array('var2' => 2, 'var1' => 1));
$this->assertTrue($url1->compare($url2, URL_MATCH_BASE));
$this->assertTrue($url1->compare($url2, URL_MATCH_PARAMS));
$this->assertTrue($url1->compare($url2, URL_MATCH_EXACT));
}
function test_out_as_local_url() {
$url1 = new moodle_url('/lib/tests/weblib_test.php');
$this->assertEquals('/lib/tests/weblib_test.php', $url1->out_as_local_url());
}
/**
* @expectedException coding_exception
* @return void
*/
function test_out_as_local_url_error() {
$url2 = new moodle_url('http://www.google.com/lib/simpletest/testweblib.php');
$url2->out_as_local_url();
}
public function test_clean_text() {
$text = "lala <applet>xx</applet>";
$this->assertEquals($text, clean_text($text, FORMAT_PLAIN));
$this->assertEquals('lala xx', clean_text($text, FORMAT_MARKDOWN));
$this->assertEquals('lala xx', clean_text($text, FORMAT_MOODLE));
$this->assertEquals('lala xx', clean_text($text, FORMAT_HTML));
}
}
+2 -2
View File
@@ -2776,7 +2776,7 @@ function debugging($message = '', $level = DEBUG_NORMAL, $backtrace = null) {
$forcedebug = in_array($USER->id, $debugusers);
}
if (!$forcedebug and (empty($CFG->debug) || $CFG->debug < $level)) {
if (!$forcedebug and (empty($CFG->debug) || ($CFG->debug != -1 and $CFG->debug < $level))) {
return false;
}
@@ -2789,7 +2789,7 @@ function debugging($message = '', $level = DEBUG_NORMAL, $backtrace = null) {
$backtrace = debug_backtrace();
}
$from = format_backtrace($backtrace, CLI_SCRIPT);
if (PHPUNITTEST) {
if (PHPUNIT_TEST) {
echo 'Debugging: ' . $message . "\n" . $from;
} else if (!empty($UNITTEST->running)) {
@@ -1,70 +0,0 @@
<?php
require_once("$CFG->libdir/simpletest/portfolio_testclass.php");
require_once("$CFG->dirroot/mod/assignment/lib.php");
require_once("$CFG->dirroot/mod/assignment/locallib.php");
Mock::generate('assignment_portfolio_caller', 'mock_caller');
Mock::generate('portfolio_exporter', 'mock_exporter');
class testAssignmentPortfolioCallers extends portfoliolib_test {
public static $includecoverage = array('lib/portfoliolib.php', 'mod/assignment/lib.php');
public $module_type = 'assignment';
public $modules = array();
public $entries = array();
public $caller;
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*
public function setUp() {
global $DB, $USER;
parent::setUp();
$assignment_types = new stdClass();
$assignment_types->type = GENERATOR_SEQUENCE;
$assignment_types->options = array('online');
$settings = array('quiet' => 1,
'modules_list' => array($this->module_type), 'assignment_grades' => true,
'assignment_type' => $assignment_types,
'number_of_students' => 5, 'students_per_course' => 5, 'number_of_sections' => 1,
'number_of_modules' => 3, 'questions_per_course' => 0);
generator_generate_data($settings);
$this->modules = $DB->get_records($this->module_type);
$first_module = reset($this->modules);
$cm = get_coursemodule_from_instance($this->module_type, $first_module->id);
$submissions = $DB->get_records('assignment_submissions', array('assignment' => $first_module->id));
$first_submission = reset($submissions);
$this->caller = parent::setup_caller('assignment_portfolio_caller', array('id' => $cm->id), $first_submission->userid);
}
public function tearDown() {
parent::tearDown();
}
public function test_caller_sha1() {
$sha1 = $this->caller->get_sha1();
$this->caller->prepare_package();
$this->assertEqual($sha1, $this->caller->get_sha1());
}
public function test_caller_with_plugins() {
parent::test_caller_with_plugins();
}
*/
}
@@ -1,59 +0,0 @@
<?php
require_once("$CFG->libdir/simpletest/portfolio_testclass.php");
require_once("$CFG->dirroot/mod/chat/lib.php");
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*/
Mock::generate('chat_portfolio_caller', 'mock_caller');
Mock::generate('portfolio_exporter', 'mock_exporter');
class testChatPortfolioCallers extends portfoliolib_test {
/*
public static $includecoverage = array('lib/portfoliolib.php', 'mod/chat/lib.php');
public $module_type = 'chat';
public $modules = array();
public $entries = array();
public $caller;
public function setUp() {
global $DB, $USER;
parent::setUp();
$settings = array('quiet' => 1, 'pre_cleanup' => 1,
'modules_list' => array($this->module_type),
'number_of_students' => 15, 'students_per_course' => 15, 'number_of_sections' => 1,
'number_of_modules' => 1, 'messages_per_chat' => 15);
generator_generate_data($settings);
$this->modules = $DB->get_records($this->module_type);
$first_module = reset($this->modules);
$cm = get_coursemodule_from_instance($this->module_type, $first_module->id);
$userid = $DB->get_field('chat_users', 'userid', array('chatid' => $first_module->id));
$this->caller = parent::setup_caller('chat_portfolio_caller', array('id' => $cm->id), $userid);
}
public function test_caller_sha1() {
$sha1 = $this->caller->get_sha1();
$this->caller->prepare_package();
$this->assertEqual($sha1, $this->caller->get_sha1());
}
public function test_caller_with_plugins() {
parent::test_caller_with_plugins();
}
*/
}
@@ -1,86 +0,0 @@
<?php
require_once("$CFG->libdir/simpletest/portfolio_testclass.php");
require_once("$CFG->dirroot/mod/data/lib.php");
require_once("$CFG->dirroot/mod/data/locallib.php");
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*/
Mock::generate('data_portfolio_caller', 'mock_caller');
Mock::generate('portfolio_exporter', 'mock_exporter');
class testDataPortfolioCallers extends portfoliolib_test {
/*
public static $includecoverage = array('lib/portfoliolib.php', 'mod/data/lib.php');
public $module_type = 'data';
public $modules = array();
public $entries = array();
public $caller_single;
public $caller;
public function setUp() {
global $DB, $USER;
parent::setUp();
$settings = array('quiet' => 1,
'pre_cleanup' => 0,
'modules_list' => array($this->module_type),
'number_of_students' => 5,
'students_per_course' => 5,
'number_of_sections' => 1,
'number_of_modules' => 1,
'questions_per_course' => 0);
generator_generate_data($settings);
$this->modules = $DB->get_records($this->module_type);
$first_module = reset($this->modules);
$cm = get_coursemodule_from_instance($this->module_type, $first_module->id);
$fields = $DB->get_records('data_fields', array('dataid' => $first_module->id));
$recordid = data_add_record($first_module);
foreach ($fields as $field) {
$content->recordid = $recordid;
$content->fieldid = $field->id;
$content->content = 'test content';
$content->content1 = 'test content 1';
$content->content2 = 'test content 2';
$DB->insert_record('data_content',$content);
}
// Callback args required: id, record, delimiter_name, exporttype
$this->caller_single = parent::setup_caller('data_portfolio_caller', array('id' => $cm->id, 'record' => $recordid));
$this->caller = parent::setup_caller('data_portfolio_caller', array('id' => $cm->id));
}
public function tearDown() {
parent::tearDown();
}
public function test_caller_sha1() {
$sha1 = $this->caller->get_sha1();
$this->caller->prepare_package();
$this->assertEqual($sha1, $this->caller->get_sha1());
$sha1 = $this->caller_single->get_sha1();
$this->caller_single->prepare_package();
$this->assertEqual($sha1, $this->caller_single->get_sha1());
}
public function test_caller_with_plugins() {
parent::test_caller_with_plugins();
}
*/
}
-65
View File
@@ -1,65 +0,0 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Unit tests for mod/data/preset_class.php.
*
* @author nicolas@moodle.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package mod_data
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->dirroot . '/mod/data/lib.php');
class data_preset_test extends UnitTestCase {
public static $includecoverage = array('mod/data/lib.php');
function setUp() {
}
function tearDown() {
}
function test_address_in_subnet() {
}
/**
* Modifies $_SERVER['HTTP_USER_AGENT'] manually to check if check_browser_version
* works as expected.
*/
function test_check_browser_version()
{
}
function test_optional_param()
{
}
}
@@ -1,112 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Code fragment to define the module version etc.
* This fragment is called by /admin/index.php
*
* @package mod-forum
* @copyright 2008 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once("$CFG->libdir/simpletest/portfolio_testclass.php");
require_once("$CFG->dirroot/mod/forum/lib.php");
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*/
Mock::generate('forum_portfolio_caller', 'mock_caller');
Mock::generate('portfolio_exporter', 'mock_exporter');
class testForumPortfolioCallers extends portfoliolib_test {
/*
public static $includecoverage = array('lib/portfoliolib.php', 'mod/forum/lib.php');
public $module_type = 'forum';
public $modules = array();
public $entries = array();
public $postcaller;
public $discussioncaller;
public function setUp() {
global $DB, $USER;
parent::setUp();
$settings = array('quiet' => 1,
'verbose' => 0,
'pre_cleanup' => 0,
'post_cleanup' => 0,
'modules_list' => array($this->module_type),
'discussions_per_forum' => 5,
'posts_per_discussion' => 10,
'number_of_students' => 5,
'students_per_course' => 5,
'number_of_sections' => 1,
'number_of_modules' => 1,
'questions_per_course' => 0);
generator_generate_data($settings);
$this->modules = $DB->get_records($this->module_type);
$first_module = reset($this->modules);
$cm = get_coursemodule_from_instance($this->module_type, $first_module->id);
$discussions = $DB->get_records('forum_discussions', array('forum' => $first_module->id));
$first_discussion = reset($discussions);
$posts = $DB->get_records('forum_posts', array('discussion' => $first_discussion->id));
$first_post = reset($posts);
$callbackargs = array('postid' => $first_post->id, 'discussionid' => $first_discussion->id);
$this->postcaller = parent::setup_caller('forum_portfolio_caller', $callbackargs, $first_post->userid);
unset($callbackargs['postid']);
$this->discussioncaller = parent::setup_caller('forum_portfolio_caller', $callbackargs, $first_post->userid);
}
public function tearDown() {
parent::tearDown();
}
public function test_caller_sha1() {
$sha1 = $this->postcaller->get_sha1();
$this->postcaller->prepare_package();
$this->assertEqual($sha1, $this->postcaller->get_sha1());
$sha1 = $this->discussioncaller->get_sha1();
$this->discussioncaller->prepare_package();
$this->assertEqual($sha1, $this->discussioncaller->get_sha1());
}
public function test_caller_with_plugins() {
parent::test_caller_with_plugins();
}
*/
}
-62
View File
@@ -1,62 +0,0 @@
<?php
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.org //
// //
// Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/**
* Unit tests for (some of) ../mod/forum/lib.php.
*
* @copyright &copy; 2006 The Open University
* @author T.J.Hunt@open.ac.uk
* @author nicolas@moodle.com
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package mod-forum
*/
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
}
require_once($CFG->dirroot . '/mod/forum/lib.php');
class modforumlib_test extends UnitTestCase {
public static $includecoverage = array('mod/forum/lib.php');
function setUp() {
}
function tearDown() {
}
function test_forum_cron() {
// watch out: forum_cron() should not be called from here,
// it relies on special environment setup used in admin/cron.php,
// mainly special cookieless session and $USER object
/*
forum_cron();
$this->assertTrue(false);
*/
}
}
@@ -1,74 +0,0 @@
<?php
require_once("$CFG->libdir/simpletest/portfolio_testclass.php");
require_once("$CFG->dirroot/mod/glossary/lib.php");
require_once("$CFG->dirroot/mod/glossary/locallib.php");
/*
* TODO: The portfolio unit tests were obselete and did not work.
* They have been commented out so that they do not break the
* unit tests in Moodle 2.
*
* At some point:
* 1. These tests should be audited to see which ones were valuable.
* 2. The useful ones should be rewritten using the current standards
* for writing test cases.
*
* This might be left until Moodle 2.1 when the test case framework
* is due to change.
*/
Mock::generate('glossary_entry_portfolio_caller', 'mock_entry_caller');
Mock::generate('glossary_csv_portfolio_caller', 'mock_csv_caller');
Mock::generate('portfolio_exporter', 'mock_exporter');
class testGlossaryPortfolioCallers extends portfoliolib_test {
/*
public static $includecoverage = array('lib/portfoliolib.php', 'mod/glossary/lib.php');
public $glossaries = array();
public $entries = array();
public $entry_caller;
public $csv_caller;
public function setUp() {
global $DB;
parent::setUp();
$settings = array('tiny' => 1, 'quiet' => 1, 'pre_cleanup' => 1,
'modules_list' => array('glossary'), 'entries_per_glossary' => 20,
'number_of_students' => 5, 'students_per_course' => 5, 'number_of_sections' => 1,
'number_of_modules' => 1, 'questions_per_course' => 0);
generator_generate_data($settings);
$this->glossaries = $DB->get_records('glossary');
$first_glossary = reset($this->glossaries);
$cm = get_coursemodule_from_instance('glossary', $first_glossary->id);
$this->entries = $DB->get_records('glossary_entries', array('glossaryid' => $first_glossary->id));
$first_entry = reset($this->entries);
$callbackargs = array('id' => $cm->id, 'entryid' => $first_entry->id);
$this->entry_caller = parent::setup_caller('glossary_entry_portfolio_caller', $callbackargs);
$this->csv_caller = parent::setup_caller('glossary_csv_portfolio_caller', $callbackargs);
}
public function tearDown() {
parent::tearDown();
}
public function test_entry_caller_sha1() {
$entry_sha1 = $this->entry_caller->get_sha1();
$this->entry_caller->prepare_package();
$this->assertEqual($entry_sha1, $this->entry_caller->get_sha1());
}
public function test_csv_caller_sha1() {
$csv_sha1 = $this->csv_caller->get_sha1();
$this->csv_caller->prepare_package();
$this->assertEqual($csv_sha1, $this->csv_caller->get_sha1());
}
public function test_caller_with_plugins() {
parent::test_caller_with_plugins();
}
*/
}
+142
View File
@@ -0,0 +1,142 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
//
// This file is part of BasicLTI4Moodle
//
// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)
// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web
// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI
// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS
// are already supporting or going to support BasicLTI. This project Implements the consumer
// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.
// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem
// at the GESSI research group at UPC.
// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI
// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a
// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.
//
// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis
// of the Universitat Politecnica de Catalunya http://www.upc.edu
// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu
/**
* This file contains unit tests for (some of) lti/locallib.php
*
* @package mod_lti
* @category phpunit
* @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis
* @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu
* @author Charles Severance csev@unmich.edu
* @author Marc Alier (marc.alier@upc.edu)
* @author Jordi Piguillem
* @author Nikolas Galanis
* @author Chris Scribner
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
global $CFG;
require_once($CFG->dirroot . '/mod/lti/locallib.php');
require_once($CFG->dirroot . '/mod/lti/servicelib.php');
class mod_lti_locallib_testcase extends basic_testcase {
public function test_split_custom_parameters() {
$this->assertEquals(lti_split_custom_parameters("x=1\ny=2"),
array('custom_x' => '1', 'custom_y'=> '2'));
$this->assertEquals(lti_split_custom_parameters('x=1;y=2'),
array('custom_x' => '1', 'custom_y'=> '2'));
$this->assertEquals(lti_split_custom_parameters('Review:Chapter=1.2.56'),
array('custom_review_chapter' => '1.2.56'));
$this->assertEquals(lti_split_custom_parameters('Complex!@#$^*(){}[]KEY=Complex!@#$^*(){}[]Value'),
array('custom_complex____________key' => 'Complex!@#$^*(){}[]Value'));
}
/**
* This test has been disabled because the test-tool is
* being moved and probably it won't work anymore for this.
* We should be testing here local stuff only and leave
* outside-checks to the conformance tests. MDL-30347
*/
public function disabled_test_sign_parameters() {
$correct = array ( 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing', 'ext_submit' => 'Click Me', 'lti_message_type' => 'basic-lti-launch-request', 'lti_version' => 'LTI-1p0', 'oauth_consumer_key' => 'lmsng.school.edu', 'oauth_nonce' => '47458148e33a8f9dafb888c3684cf476', 'oauth_signature' => 'qWgaBIezihCbeHgcwUy14tZcyDQ=', 'oauth_signature_method' => 'HMAC-SHA1', 'oauth_timestamp' => '1307141660', 'oauth_version' => '1.0', 'resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'roles' => 'Learner', 'tool_consumer_instance_guid' => 'lmsng.school.edu', 'user_id' => '789');
$requestparams = array('resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'user_id' => '789', 'roles' => 'Learner', 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing');
$parms = lti_sign_parameters($requestparams, 'http://www.imsglobal.org/developer/LTI/tool.php', 'POST',
'lmsng.school.edu', 'secret', 'Click Me', 'lmsng.school.edu' /*, $org_desc*/);
$this->assertTrue(isset($parms['oauth_nonce']));
$this->assertTrue(isset($parms['oauth_signature']));
$this->assertTrue(isset($parms['oauth_timestamp']));
// Those things that are hard to mock
$correct['oauth_nonce'] = $parms['oauth_nonce'];
$correct['oauth_signature'] = $parms['oauth_signature'];
$correct['oauth_timestamp'] = $parms['oauth_timestamp'];
ksort($parms);
ksort($correct);
$this->assertEquals($parms, $correct);
}
/**
* This test has been disabled because, since its creation,
* the sourceId generation has changed and surely this is outdated.
* Some day these should be replaced by proper tests, but until then
* conformance tests say this is working. MDL-30347
*/
public function disabled_test_parse_grade_replace_message() {
$message = '
<imsx_POXEnvelopeRequest xmlns = "http://www.imsglobal.org/lis/oms1p0/pox">
<imsx_POXHeader>
<imsx_POXRequestHeaderInfo>
<imsx_version>V1.0</imsx_version>
<imsx_messageIdentifier>999998123</imsx_messageIdentifier>
</imsx_POXRequestHeaderInfo>
</imsx_POXHeader>
<imsx_POXBody>
<replaceResultRequest>
<resultRecord>
<sourcedGUID>
<sourcedId>{&quot;data&quot;:{&quot;instanceid&quot;:&quot;2&quot;,&quot;userid&quot;:&quot;2&quot;},&quot;hash&quot;:&quot;0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b&quot;}</sourcedId>
</sourcedGUID>
<result>
<resultScore>
<language>en-us</language>
<textString>0.92</textString>
</resultScore>
</result>
</resultRecord>
</replaceResultRequest>
</imsx_POXBody>
</imsx_POXEnvelopeRequest>
';
$parsed = lti_parse_grade_replace_message(new SimpleXMLElement($message));
$this->assertEquals($parsed->userid, '2');
$this->assertEquals($parsed->instanceid, '2');
$this->assertEquals($parsed->sourcedidhash, '0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b');
$ltiinstance = (object)array('servicesalt' => '4e5fcc06de1d58.44963230');
lti_verify_sourcedid($ltiinstance, $parsed);
}
}
@@ -0,0 +1,289 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_delaybetweenattempts plugin.
*
* @package quizaccess
* @subpackage delaybetweenattempts
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/delaybetweenattempts/rule.php');
/**
* Unit tests for the quizaccess_delaybetweenattempts plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_delaybetweenattempts_testcase extends basic_testcase {
public function test_just_first_delay() {
$quiz = new stdClass();
$quiz->attempts = 3;
$quiz->timelimit = 0;
$quiz->delay1 = 1000;
$quiz->delay2 = 0;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->timefinish = 10000;
$rule = new quizaccess_delaybetweenattempts($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$attempt->timefinish = 9000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$attempt->timefinish = 9001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
}
public function test_just_second_delay() {
$quiz = new stdClass();
$quiz->attempts = 5;
$quiz->timelimit = 0;
$quiz->delay1 = 0;
$quiz->delay2 = 1000;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->timefinish = 10000;
$rule = new quizaccess_delaybetweenattempts($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->prevent_new_attempt(5, $attempt));
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertEquals($rule->prevent_new_attempt(3, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$attempt->timefinish = 9000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timefinish = 9001;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertEquals($rule->prevent_new_attempt(4, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
}
public function test_just_both_delays() {
$quiz = new stdClass();
$quiz->attempts = 5;
$quiz->timelimit = 0;
$quiz->delay1 = 2000;
$quiz->delay2 = 1000;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->timefinish = 10000;
$rule = new quizaccess_delaybetweenattempts($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->prevent_new_attempt(5, $attempt));
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(12000)));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertEquals($rule->prevent_new_attempt(3, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$attempt->timefinish = 8000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timefinish = 8001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(4, $attempt));
$attempt->timefinish = 9000;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timefinish = 9001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11001)));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertEquals($rule->prevent_new_attempt(4, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
}
public function test_with_close_date() {
$quiz = new stdClass();
$quiz->attempts = 5;
$quiz->timelimit = 0;
$quiz->delay1 = 2000;
$quiz->delay2 = 1000;
$quiz->timeclose = 15000;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->timefinish = 13000;
$rule = new quizaccess_delaybetweenattempts($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$attempt->timefinish = 13000;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(15000)));
$attempt->timefinish = 13001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youcannotwait', 'quizaccess_delaybetweenattempts'));
$attempt->timefinish = 14000;
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(15000)));
$attempt->timefinish = 14001;
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youcannotwait', 'quizaccess_delaybetweenattempts'));
$rule = new quizaccess_delaybetweenattempts($quizobj, 15000);
$attempt->timefinish = 13000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$attempt->timefinish = 13001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youcannotwait', 'quizaccess_delaybetweenattempts'));
$attempt->timefinish = 14000;
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$attempt->timefinish = 14001;
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youcannotwait', 'quizaccess_delaybetweenattempts'));
$rule = new quizaccess_delaybetweenattempts($quizobj, 15001);
$attempt->timefinish = 13000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$attempt->timefinish = 13001;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$attempt->timefinish = 14000;
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$attempt->timefinish = 14001;
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
}
public function test_time_limit_and_overdue() {
$quiz = new stdClass();
$quiz->attempts = 5;
$quiz->timelimit = 100;
$quiz->delay1 = 2000;
$quiz->delay2 = 1000;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->timestart = 9900;
$attempt->timefinish = 10100;
$rule = new quizaccess_delaybetweenattempts($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->prevent_new_attempt(5, $attempt));
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(12000)));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertEquals($rule->prevent_new_attempt(3, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$attempt->timestart = 7950;
$attempt->timefinish = 8000;
$this->assertFalse($rule->prevent_new_attempt(1, $attempt));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timestart = 7950;
$attempt->timefinish = 8001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(4, $attempt));
$attempt->timestart = 8950;
$attempt->timefinish = 9000;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timestart = 8950;
$attempt->timefinish = 9001;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11001)));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertEquals($rule->prevent_new_attempt(4, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$attempt->timestart = 8900;
$attempt->timefinish = 9100;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11000)));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertFalse($rule->prevent_new_attempt(3, $attempt));
$attempt->timestart = 8901;
$attempt->timefinish = 9100;
$this->assertEquals($rule->prevent_new_attempt(1, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(11001)));
$this->assertEquals($rule->prevent_new_attempt(2, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
$this->assertEquals($rule->prevent_new_attempt(4, $attempt),
get_string('youmustwait', 'quizaccess_delaybetweenattempts', userdate(10001)));
}
}
@@ -0,0 +1,73 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_ipaddress plugin.
*
* @package quizaccess
* @subpackage ipaddress
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/ipaddress/rule.php');
/**
* Unit tests for the quizaccess_ipaddress plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_ipaddress_testcase extends basic_testcase {
public function test_ipaddress_access_rule() {
$quiz = new stdClass();
$attempt = new stdClass();
$cm = new stdClass();
$cm->id = 0;
// Test the allowed case by getting the user's IP address. However, this
// does not always work, for example using the mac install package on my laptop.
$quiz->subnet = getremoteaddr(null);
if (!empty($quiz->subnet)) {
$quiz->questions = '';
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_ipaddress($quizobj, 0);
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->description());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 1));
}
$quiz->subnet = '0.0.0.0';
$quiz->questions = '';
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_ipaddress($quizobj, 0);
$this->assertNotEmpty($rule->prevent_access());
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 1));
}
}
@@ -0,0 +1,69 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_numattempts plugin.
*
* @package quizaccess
* @subpackage numattempts
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/numattempts/rule.php');
/**
* Unit tests for the quizaccess_numattempts plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_numattempts_testcase extends basic_testcase {
public function test_num_attempts_access_rule() {
$quiz = new stdClass();
$quiz->attempts = 3;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_numattempts($quizobj, 0);
$attempt = new stdClass();
$this->assertEquals($rule->description(),
get_string('attemptsallowedn', 'quizaccess_numattempts', 3));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->prevent_new_attempt(2, $attempt));
$this->assertEquals($rule->prevent_new_attempt(3, $attempt),
get_string('nomoreattempts', 'quiz'));
$this->assertEquals($rule->prevent_new_attempt(666, $attempt),
get_string('nomoreattempts', 'quiz'));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->is_finished(2, $attempt));
$this->assertTrue($rule->is_finished(3, $attempt));
$this->assertTrue($rule->is_finished(666, $attempt));
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->time_left($attempt, 1));
}
}
@@ -0,0 +1,180 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_openclosedate plugin.
*
* @package quizaccess
* @subpackage openclosedate
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/openclosedate/rule.php');
/**
* Unit tests for the quizaccess_openclosedate plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_openclosedate_testcase extends basic_testcase {
public function test_no_dates() {
$quiz = new stdClass();
$quiz->timeopen = 0;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->preview = 0;
$rule = new quizaccess_openclosedate($quizobj, 10000);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 10000));
$this->assertFalse($rule->time_left($attempt, 0));
$rule = new quizaccess_openclosedate($quizobj, 0);
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
}
public function test_start_date() {
$quiz = new stdClass();
$quiz->timeopen = 10000;
$quiz->timeclose = 0;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->preview = 0;
$rule = new quizaccess_openclosedate($quizobj, 9999);
$this->assertEquals($rule->description(),
array(get_string('quiznotavailable', 'quizaccess_openclosedate', userdate(10000))));
$this->assertEquals($rule->prevent_access(),
get_string('notavailable', 'quizaccess_openclosedate'));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
$rule = new quizaccess_openclosedate($quizobj, 10000);
$this->assertEquals($rule->description(),
array(get_string('quizopenedon', 'quiz', userdate(10000))));
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 0));
}
public function test_close_date() {
$quiz = new stdClass();
$quiz->timeopen = 0;
$quiz->timeclose = 20000;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->preview = 0;
$rule = new quizaccess_openclosedate($quizobj, 20000);
$this->assertEquals($rule->description(),
array(get_string('quizcloseson', 'quiz', userdate(20000))));
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 20000 - QUIZ_SHOW_TIME_BEFORE_DEADLINE));
$this->assertEquals($rule->time_left($attempt, 19900), 100);
$this->assertEquals($rule->time_left($attempt, 20000), 0);
$this->assertEquals($rule->time_left($attempt, 20100), -100);
$rule = new quizaccess_openclosedate($quizobj, 20001);
$this->assertEquals($rule->description(),
array(get_string('quizclosed', 'quiz', userdate(20000))));
$this->assertEquals($rule->prevent_access(),
get_string('notavailable', 'quizaccess_openclosedate'));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertTrue($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 20000 - QUIZ_SHOW_TIME_BEFORE_DEADLINE));
$this->assertEquals($rule->time_left($attempt, 19900), 100);
$this->assertEquals($rule->time_left($attempt, 20000), 0);
$this->assertEquals($rule->time_left($attempt, 20100), -100);
}
public function test_both_dates() {
$quiz = new stdClass();
$quiz->timeopen = 10000;
$quiz->timeclose = 20000;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$attempt = new stdClass();
$attempt->preview = 0;
$rule = new quizaccess_openclosedate($quizobj, 9999);
$this->assertEquals($rule->description(),
array(get_string('quiznotavailable', 'quizaccess_openclosedate', userdate(10000))));
$this->assertEquals($rule->prevent_access(),
get_string('notavailable', 'quizaccess_openclosedate'));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$rule = new quizaccess_openclosedate($quizobj, 10000);
$this->assertEquals($rule->description(),
array(get_string('quizopenedon', 'quiz', userdate(10000)),
get_string('quizcloseson', 'quiz', userdate(20000))));
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$rule = new quizaccess_openclosedate($quizobj, 20000);
$this->assertEquals($rule->description(),
array(get_string('quizopenedon', 'quiz', userdate(10000)),
get_string('quizcloseson', 'quiz', userdate(20000))));
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$rule = new quizaccess_openclosedate($quizobj, 20001);
$this->assertEquals($rule->description(),
array(get_string('quizclosed', 'quiz', userdate(20000))));
$this->assertEquals($rule->prevent_access(),
get_string('notavailable', 'quizaccess_openclosedate'));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertTrue($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 20000 - QUIZ_SHOW_TIME_BEFORE_DEADLINE));
$this->assertEquals($rule->time_left($attempt, 19900), 100);
$this->assertEquals($rule->time_left($attempt, 20000), 0);
$this->assertEquals($rule->time_left($attempt, 20100), -100);
}
}
@@ -0,0 +1,58 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_password plugin.
*
* @package quizaccess
* @subpackage password
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/password/rule.php');
/**
* Unit tests for the quizaccess_password plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_password_testcase extends basic_testcase {
public function test_password_access_rule() {
$quiz = new stdClass();
$quiz->password = 'frog';
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_password($quizobj, 0);
$attempt = new stdClass();
$this->assertFalse($rule->prevent_access());
$this->assertEquals($rule->description(),
get_string('requirepasswordmessage', 'quizaccess_password'));
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 1));
}
}
@@ -0,0 +1,63 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_safebrowser plugin.
*
* @package quizaccess
* @subpackage safebrowser
* @category phpunit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/safebrowser/rule.php');
/**
* Unit tests for the quizaccess_safebrowser plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_safebrowser_testcase extends basic_testcase {
// Nothing very testable in this class, just test that it obeys the general access rule contact.
public function test_safebrowser_access_rule() {
$quiz = new stdClass();
$quiz->browsersecurity = 'safebrowser';
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_safebrowser($quizobj, 0);
$attempt = new stdClass();
// This next test assumes the unit tests are not being run using Safe Exam Browser!
$_SERVER['HTTP_USER_AGENT'] = 'unknonw browser';
$this->assertEquals(get_string('safebrowsererror', 'quizaccess_safebrowser'),
$rule->prevent_access());
$this->assertEquals(get_string('safebrowsernotice', 'quizaccess_safebrowser'),
$rule->description());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 1));
}
}
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_securewindow plugin.
*
* @package quizaccess
* @subpackage securewindow
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/securewindow/rule.php');
/**
* Unit tests for the quizaccess_securewindow plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_securewindow_testcase extends basic_testcase {
public static $includecoverage = array('mod/quiz/accessrule/securewindow/rule.php');
// Nothing very testable in this class, just test that it obeys the general access rule contact.
public function test_securewindow_access_rule() {
$quiz = new stdClass();
$quiz->browsersecurity = 'securewindow';
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_securewindow($quizobj, 0);
$attempt = new stdClass();
$this->assertFalse($rule->prevent_access());
$this->assertEmpty($rule->description());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
$this->assertFalse($rule->time_left($attempt, 1));
}
}
@@ -0,0 +1,62 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the quizaccess_timelimit plugin.
*
* @package quizaccess
* @subpackage timelimit
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/quiz/accessrule/timelimit/rule.php');
/**
* Unit tests for the quizaccess_timelimit plugin.
*
* @copyright 2008 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class quizaccess_timelimit_testcase extends basic_testcase {
public function test_time_limit_access_rule() {
$quiz = new stdClass();
$quiz->timelimit = 3600;
$quiz->questions = '';
$cm = new stdClass();
$cm->id = 0;
$quizobj = new quiz($quiz, $cm, null);
$rule = new quizaccess_timelimit($quizobj, 10000);
$attempt = new stdClass();
$this->assertEquals($rule->description(),
get_string('quiztimelimit', 'quizaccess_timelimit', format_time(3600)));
$attempt->timestart = 10000;
$this->assertEquals($rule->time_left($attempt, 10000), 3600);
$this->assertEquals($rule->time_left($attempt, 12000), 1600);
$this->assertEquals($rule->time_left($attempt, 14000), -400);
$this->assertFalse($rule->prevent_access());
$this->assertFalse($rule->prevent_new_attempt(0, $attempt));
$this->assertFalse($rule->is_finished(0, $attempt));
}
}

Some files were not shown because too many files have changed in this diff Show More