Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace qtype_calculated;
  18  
  19  use qtype_calculated_variable_substituter;
  20  
  21  defined('MOODLE_INTERNAL') || die();
  22  
  23  global $CFG;
  24  require_once($CFG->dirroot . '/question/type/calculated/question.php');
  25  require_once($CFG->dirroot . '/question/type/calculated/questiontype.php');
  26  
  27  /**
  28   * Unit tests for {@link qtype_calculated_variable_substituter}.
  29   *
  30   * @package    qtype_calculated
  31   * @copyright  2011 The Open University
  32   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class variablesubstituter_test extends \advanced_testcase {
  35      public function test_simple_expression() {
  36          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  37          $this->assertEquals(3, $vs->calculate('{a} + {b}'));
  38      }
  39  
  40      public function test_simple_expression_negatives() {
  41          $vs = new qtype_calculated_variable_substituter(array('a' => -1, 'b' => -2), '.');
  42          $this->assertEquals(1, $vs->calculate('{a}-{b}'));
  43      }
  44  
  45      public function test_cannot_use_nonnumbers() {
  46          $this->expectException(\moodle_exception::class);
  47          $vs = new qtype_calculated_variable_substituter(array('a' => 'frog', 'b' => -2), '.');
  48      }
  49  
  50      public function test_invalid_expression() {
  51          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  52          $this->expectException(\moodle_exception::class);
  53          $vs->calculate('{a} + {b}?');
  54      }
  55  
  56      public function test_tricky_invalid_expression() {
  57          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  58          $this->expectException(\moodle_exception::class);
  59          $vs->calculate('{a}{b}'); // Have to make sure this does not just evaluate to 12.
  60      }
  61  
  62      public function test_division_by_zero_expression() {
  63  
  64          if (intval(PHP_VERSION) < 7) {
  65              $this->markTestSkipped('Division by zero triggers a PHP warning before PHP 7.');
  66          }
  67  
  68          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 0), '.');
  69          $this->expectException(\moodle_exception::class);
  70          $vs->calculate('{a} / {b}');
  71      }
  72  
  73      public function test_replace_expressions_in_text_simple_var() {
  74          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  75          $this->assertEquals('1 + 2', $vs->replace_expressions_in_text('{a} + {b}'));
  76      }
  77  
  78      public function test_replace_expressions_in_confusing_text() {
  79          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  80          $this->assertEquals("(1) 1\n(2) 2", $vs->replace_expressions_in_text("(1) {a}\n(2) {b}"));
  81      }
  82  
  83      public function test_replace_expressions_in_text_formula() {
  84          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  85          $this->assertEquals('= 3', $vs->replace_expressions_in_text('= {={a} + {b}}'));
  86      }
  87  
  88      public function test_expression_has_unmapped_placeholder() {
  89          $this->expectException('moodle_exception');
  90          $this->expectExceptionMessage(get_string('illegalformulasyntax', 'qtype_calculated', '{c}'));
  91          $vs = new qtype_calculated_variable_substituter(array('a' => 1, 'b' => 2), '.');
  92          $vs->calculate('{c} - {a} + {b}');
  93      }
  94  
  95      public function test_replace_expressions_in_text_negative() {
  96          $vs = new qtype_calculated_variable_substituter(array('a' => -1, 'b' => 2), '.');
  97          $this->assertEquals('temperatures -1 and 2',
  98                  $vs->replace_expressions_in_text('temperatures {a} and {b}'));
  99      }
 100  
 101      public function test_replace_expressions_in_text_commas_for_decimals() {
 102          $vs = new qtype_calculated_variable_substituter(
 103                  array('phi' => 1.61803399, 'pi' => 3.14159265), ',');
 104          $this->assertEquals('phi (1,61803399) + pi (3,14159265) = 4,75962664',
 105                  $vs->replace_expressions_in_text('phi ({phi}) + pi ({pi}) = {={phi} + {pi}}'));
 106      }
 107  
 108      public function test_format_float_dot() {
 109          $vs = new qtype_calculated_variable_substituter(array('a' => -1, 'b' => 2), '.');
 110          $this->assertSame('0.12345', $vs->format_float(0.12345));
 111  
 112          $this->assertSame('0', $vs->format_float(0.12345, 0, 1));
 113          $this->assertSame('0.12', $vs->format_float(0.12345, 2, 1));
 114          $this->assertSame('0.1235', $vs->format_float(0.12345, 4, 1));
 115  
 116          $this->assertSame('0.12', $vs->format_float(0.12345, 2, 2));
 117          $this->assertSame('0.0012', $vs->format_float(0.0012345, 4, 1));
 118      }
 119  
 120      public function test_format_float_comma() {
 121          $vs = new qtype_calculated_variable_substituter(array('a' => -1, 'b' => 2), ',');
 122          $this->assertSame('0,12345', $vs->format_float(0.12345));
 123  
 124          $this->assertSame('0', $vs->format_float(0.12345, 0, 1));
 125          $this->assertSame('0,12', $vs->format_float(0.12345, 2, 1));
 126          $this->assertSame('0,1235', $vs->format_float(0.12345, 4, 1));
 127  
 128          $this->assertSame('0,12', $vs->format_float(0.12345, 2, 2));
 129          $this->assertSame('0,0012', $vs->format_float(0.0012345, 4, 1));
 130      }
 131  
 132      public function test_format_float_nan_inf() {
 133          $vs = new qtype_calculated_variable_substituter([ ], '.');
 134  
 135          $this->assertSame('NAN', $vs->format_float(NAN));
 136          $this->assertSame('INF', $vs->format_float(INF));
 137          $this->assertSame('-INF', $vs->format_float(-INF));
 138      }
 139  }