From 44f726a7b1d351b39bb2a6a30c1b30027fabd000 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Thu, 26 Jun 2014 10:48:02 +0100 Subject: [PATCH] MDL-46148 qtype_calculated: unit tests + fixes for validation --- question/type/calculated/questiontype.php | 7 +- .../tests/formula_validation_test.php | 86 +++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 question/type/calculated/tests/formula_validation_test.php diff --git a/question/type/calculated/questiontype.php b/question/type/calculated/questiontype.php index b2e3b2a207b..3bfa25bc36d 100644 --- a/question/type/calculated/questiontype.php +++ b/question/type/calculated/questiontype.php @@ -1890,6 +1890,11 @@ function qtype_calculated_calculate_answer($formula, $individualdata, } +/** + * Validate a forumula. + * @param string $formula the formula to validate. + * @return string|boolean false if there are no problems. Otherwise a string error message. + */ function qtype_calculated_find_formula_errors($formula) { // Validates the formula submitted from the question edit page. // Returns false if everything is alright @@ -1918,7 +1923,7 @@ function qtype_calculated_find_formula_errors($formula) { // Zero argument functions. case 'pi': - if ($regs[3]) { + if (array_key_exists(3, $regs)) { return get_string('functiontakesnoargs', 'qtype_calculated', $regs[2]); } break; diff --git a/question/type/calculated/tests/formula_validation_test.php b/question/type/calculated/tests/formula_validation_test.php new file mode 100644 index 00000000000..e9f52e1c1b8 --- /dev/null +++ b/question/type/calculated/tests/formula_validation_test.php @@ -0,0 +1,86 @@ +. + +/** + * Unit tests for formula validation code. + * + * @package qtype_calculated + * @copyright 2014 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 . '/question/type/calculated/questiontype.php'); + + +/** + * Unit tests for formula validation code. + * + * @copyright 2014 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_calculated_formula_validation_testcase extends basic_testcase { + protected function assert_nonempty_string($actual) { + $this->assertInternalType('string', $actual); + $this->assertNotEquals('', $actual); + } + + public function test_simple_equations_ok() { + $this->assertFalse(qtype_calculated_find_formula_errors(1)); + $this->assertFalse(qtype_calculated_find_formula_errors('1 + 1')); + $this->assertFalse(qtype_calculated_find_formula_errors('{x} + {y}')); + $this->assertFalse(qtype_calculated_find_formula_errors('{x}*{y}')); + } + + public function test_safe_functions_ok() { + $this->assertFalse(qtype_calculated_find_formula_errors('abs(-1)')); + $this->assertFalse(qtype_calculated_find_formula_errors('tan(pi())')); + $this->assertFalse(qtype_calculated_find_formula_errors('log(10)')); + $this->assertFalse(qtype_calculated_find_formula_errors('log(64, 2)')); + $this->assertFalse(qtype_calculated_find_formula_errors('atan2(1.0, 1.0)')); + $this->assertFalse(qtype_calculated_find_formula_errors('max(1.0, 1.0)')); + $this->assertFalse(qtype_calculated_find_formula_errors('max(1.0, 1.0, 2.0)')); + $this->assertFalse(qtype_calculated_find_formula_errors('max(1.0, 1.0, 2, 3)')); + } + + public function test_dangerous_functions_blocked() { + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('eval(1)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('system(1)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('base64_decode(1)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('unserialize(1)')); + + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('cos(tan(1) + abs(cos(eval)) * pi())')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('eval (CONSTANTREADASSTRING)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors("eval \t ()")); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('"eval"()')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('?>assert_nonempty_string(qtype_calculated_find_formula_errors('?>assert_nonempty_string(qtype_calculated_find_formula_errors('abs(-1, 1)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('abs()')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('pi(1)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('log()')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('log(64, 2, 3)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('atan2(1.0)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('atan2(1.0, 1.0, 2.0)')); + $this->assert_nonempty_string(qtype_calculated_find_formula_errors('max(1.0)')); + } +} -- 2.43.0