Search moodle.org's
Developer Documentation

   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: