Search moodle.org's
Developer Documentation


  • Bug fixes for general core bugs in 2.8.x ended 9 November 2015 (12 months).
  • Bug fixes for security issues in 2.8.x ended 9 May 2016 (18 months).
  • minimum PHP 5.4.4 (always use latest PHP 5.4.x or 5.5.x on Windows - http://windows.php.net/download/), PHP 7 is NOT supported
  • Differences Between: [Versions 28 and 29] [Versions 28 and 30] [Versions 28 and 31] [Versions 28 and 32] [Versions 28 and 33] [Versions 28 and 34] [Versions 28 and 35] [Versions 28 and 36] [Versions 28 and 37]

       1  <?php
       2  // This file is part of Moodle - http://moodle.org/
       3  //
       4  // Moodle is free software: you can redistribute it and/or modify
       5  // it under the terms of the GNU General Public License as published by
       6  // the Free Software Foundation, either version 3 of the License, or
       7  // (at your option) any later version.
       8  //
       9  // Moodle is distributed in the hope that it will be useful,
      10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12  // GNU General Public License for more details.
      13  //
      14  // You should have received a copy of the GNU General Public License
      15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
      16  
      17  /**
      18   * Unit tests for /lib/externallib.php.
      19   *
      20   * @package    core
      21   * @subpackage phpunit
      22   * @copyright  2009 Petr Skoda {@link http://skodak.org}
      23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
      24   */
      25  
      26  defined('MOODLE_INTERNAL') || die();
      27  
      28  global $CFG;
      29  require_once($CFG->libdir . '/externallib.php');
      30  
      31  
      32  class core_externallib_testcase extends advanced_testcase {
      33      public function test_validate_params() {
      34          $params = array('text'=>'aaa', 'someid'=>'6');
      35          $description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value'),
      36              'text'   => new external_value(PARAM_ALPHA, 'Some text value')));
      37          $result = external_api::validate_parameters($description, $params);
      38          $this->assertCount(2, $result);
      39          reset($result);
      40          $this->assertSame('someid', key($result));
      41          $this->assertSame(6, $result['someid']);
      42          $this->assertSame('aaa', $result['text']);
      43  
      44          $params = array('someids'=>array('1', 2, 'a'=>'3'), 'scalar'=>666);
      45          $description = new external_function_parameters(array('someids' => new external_multiple_structure(new external_value(PARAM_INT, 'Some ID')),
      46              'scalar'  => new external_value(PARAM_ALPHANUM, 'Some text value')));
      47          $result = external_api::validate_parameters($description, $params);
      48          $this->assertCount(2, $result);
      49          reset($result);
      50          $this->assertSame('someids', key($result));
      51          $this->assertEquals(array(0=>1, 1=>2, 2=>3), $result['someids']);
      52          $this->assertSame('666', $result['scalar']);
      53  
      54          $params = array('text'=>'aaa');
      55          $description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value', false),
      56              'text'   => new external_value(PARAM_ALPHA, 'Some text value')));
      57          $result = external_api::validate_parameters($description, $params);
      58          $this->assertCount(2, $result);
      59          reset($result);
      60          $this->assertSame('someid', key($result));
      61          $this->assertNull($result['someid']);
      62          $this->assertSame('aaa', $result['text']);
      63  
      64          $params = array('text'=>'aaa');
      65          $description = new external_function_parameters(array('someid' => new external_value(PARAM_INT, 'Some int value', false, 6),
      66              'text'   => new external_value(PARAM_ALPHA, 'Some text value')));
      67          $result = external_api::validate_parameters($description, $params);
      68          $this->assertCount(2, $result);
      69          reset($result);
      70          $this->assertSame('someid', key($result));
      71          $this->assertSame(6, $result['someid']);
      72          $this->assertSame('aaa', $result['text']);
      73      }
      74  
      75      /**
      76       * Test for clean_returnvalue().
      77       */
      78      public function test_clean_returnvalue() {
      79  
      80          // Build some return value decription.
      81          $returndesc = new external_multiple_structure(
      82              new external_single_structure(
      83                  array(
      84                      'object' => new external_single_structure(
      85                                  array('value1' => new external_value(PARAM_INT, 'this is a int'))),
      86                      'value2' => new external_value(PARAM_TEXT, 'some text', VALUE_OPTIONAL))
      87              ));
      88  
      89          // Clean an object (it should be cast into an array).
      90          $object = new stdClass();
      91          $object->value1 = 1;
      92          $singlestructure['object'] = $object;
      93          $singlestructure['value2'] = 'Some text';
      94          $testdata = array($singlestructure);
      95          $cleanedvalue = external_api::clean_returnvalue($returndesc, $testdata);
      96          $cleanedsinglestructure = array_pop($cleanedvalue);
      97          $this->assertSame($object->value1, $cleanedsinglestructure['object']['value1']);
      98          $this->assertSame($singlestructure['value2'], $cleanedsinglestructure['value2']);
      99  
     100          // Missing VALUE_OPTIONAL.
     101          $object = new stdClass();
     102          $object->value1 = 1;
     103          $singlestructure = new stdClass();
     104          $singlestructure->object = $object;
     105          $testdata = array($singlestructure);
     106          $cleanedvalue = external_api::clean_returnvalue($returndesc, $testdata);
     107          $cleanedsinglestructure = array_pop($cleanedvalue);
     108          $this->assertSame($object->value1, $cleanedsinglestructure['object']['value1']);
     109          $this->assertArrayNotHasKey('value2', $cleanedsinglestructure);
     110  
     111          // Unknown attribute (the value should be ignored).
     112          $object = array();
     113          $object['value1'] = 1;
     114          $singlestructure = array();
     115          $singlestructure['object'] = $object;
     116          $singlestructure['value2'] = 'Some text';
     117          $singlestructure['unknownvalue'] = 'Some text to ignore';
     118          $testdata = array($singlestructure);
     119          $cleanedvalue = external_api::clean_returnvalue($returndesc, $testdata);
     120          $cleanedsinglestructure = array_pop($cleanedvalue);
     121          $this->assertSame($object['value1'], $cleanedsinglestructure['object']['value1']);
     122          $this->assertSame($singlestructure['value2'], $cleanedsinglestructure['value2']);
     123          $this->assertArrayNotHasKey('unknownvalue', $cleanedsinglestructure);
     124  
     125          // Missing required value (an exception is thrown).
     126          $object = array();
     127          $singlestructure = array();
     128          $singlestructure['object'] = $object;
     129          $singlestructure['value2'] = 'Some text';
     130          $testdata = array($singlestructure);
     131          $this->setExpectedException('invalid_response_exception');
     132          $cleanedvalue = external_api::clean_returnvalue($returndesc, $testdata);
     133      }
     134      /*
     135       * Test external_api::get_context_from_params().
     136       */
     137      public function test_get_context_from_params() {
     138          $this->resetAfterTest(true);
     139          $course = $this->getDataGenerator()->create_course();
     140          $realcontext = context_course::instance($course->id);
     141  
     142          // Use context id.
     143          $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextid" => $realcontext->id));
     144          $this->assertEquals($realcontext, $fetchedcontext);
     145  
     146          // Use context level and instance id.
     147          $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextlevel" => "course", "instanceid" => $course->id));
     148          $this->assertEquals($realcontext, $fetchedcontext);
     149  
     150          // Passing empty values.
     151          try {
     152              $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextid" => 0));
     153              $this->fail('Exception expected from get_context_wrapper()');
     154          } catch (moodle_exception $e) {
     155              $this->assertInstanceOf('invalid_parameter_exception', $e);
     156          }
     157  
     158          try {
     159              $fetchedcontext = test_exernal_api::get_context_wrapper(array("instanceid" => 0));
     160              $this->fail('Exception expected from get_context_wrapper()');
     161          } catch (moodle_exception $e) {
     162              $this->assertInstanceOf('invalid_parameter_exception', $e);
     163          }
     164  
     165          try {
     166              $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextid" => null));
     167              $this->fail('Exception expected from get_context_wrapper()');
     168          } catch (moodle_exception $e) {
     169              $this->assertInstanceOf('invalid_parameter_exception', $e);
     170          }
     171  
     172          // Tests for context with instanceid equal to 0 (System context).
     173          $realcontext = context_system::instance();
     174          $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextlevel" => "system", "instanceid" => 0));
     175          $this->assertEquals($realcontext, $fetchedcontext);
     176  
     177          // Passing wrong level.
     178          $this->setExpectedException('invalid_parameter_exception');
     179          $fetchedcontext = test_exernal_api::get_context_wrapper(array("contextlevel" => "random", "instanceid" => $course->id));
     180      }
     181  
     182      /*
     183       * Test external_api::get_context()_from_params parameter validation.
     184       */
     185      public function test_get_context_params() {
     186          global $USER;
     187  
     188          // Call without correct context details.
     189          $this->setExpectedException('invalid_parameter_exception');
     190          test_exernal_api::get_context_wrapper(array('roleid' => 3, 'userid' => $USER->id));
     191      }
     192  
     193      /*
     194       * Test external_api::get_context()_from_params parameter validation.
     195       */
     196      public function test_get_context_params2() {
     197          global $USER;
     198  
     199          // Call without correct context details.
     200          $this->setExpectedException('invalid_parameter_exception');
     201          test_exernal_api::get_context_wrapper(array('roleid' => 3, 'userid' => $USER->id, 'contextlevel' => "course"));
     202      }
     203  
     204      /*
     205       * Test external_api::get_context()_from_params parameter validation.
     206       */
     207      public function test_get_context_params3() {
     208          global $USER;
     209  
     210          // Call without correct context details.
     211          $this->resetAfterTest(true);
     212          $course = self::getDataGenerator()->create_course();
     213          $this->setExpectedException('invalid_parameter_exception');
     214          test_exernal_api::get_context_wrapper(array('roleid' => 3, 'userid' => $USER->id, 'instanceid' => $course->id));
     215      }
     216  
     217      public function all_external_info_provider() {
     218          global $DB;
     219  
     220          // We are testing here that all the external function descriptions can be generated without
     221          // producing warnings. E.g. misusing optional params will generate a debugging message which
     222          // will fail this test.
     223          $functions = $DB->get_records('external_functions', array(), 'name');
     224          $return = array();
     225          foreach ($functions as $f) {
     226              $return[$f->name] = array($f);
     227          }
     228          return $return;
     229      }
     230  
     231      /**
     232       * @dataProvider all_external_info_provider
     233       */
     234      public function test_all_external_info($f) {
     235          $desc = external_function_info($f);
     236          $this->assertNotEmpty($desc->name);
     237          $this->assertNotEmpty($desc->classname);
     238          $this->assertNotEmpty($desc->methodname);
     239          $this->assertEquals($desc->component, clean_param($desc->component, PARAM_COMPONENT));
     240          $this->assertInstanceOf('external_function_parameters', $desc->parameters_desc);
     241          if ($desc->returns_desc != null) {
     242              $this->assertInstanceOf('external_description', $desc->returns_desc);
     243          }
     244      }
     245  }
     246  
     247  /*
     248   * Just a wrapper to access protected apis for testing
     249   */
     250  class test_exernal_api extends external_api {
     251  
     252      public static function get_context_wrapper($params) {
     253          return self::get_context_from_params($params);
     254      }
     255  }
    

    Search This Site: