Skip to content

Commit

Permalink
MDL-49497 curl: keep api private and test it using reflection.
Browse files Browse the repository at this point in the history
While strictly we should not be testing private APIs, in order
to get this backported to stables without changing visibility
we use reflection to access to such private properties and methods.

Also added one exttest to verify user agent is properly sent.

Finally, fix some wrong whitespace and changed the helper class name
to better alternative.
  • Loading branch information
stronk7 committed Jun 23, 2015
1 parent cbb7c6a commit 9a1adda
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 13 deletions.
4 changes: 2 additions & 2 deletions lib/filelib.php
Expand Up @@ -2683,7 +2683,7 @@ class curl {
public $emulateredirects = null;

/** @var array cURL options */
protected $options;
private $options;

/** @var string Proxy host */
private $proxy_host = '';
Expand Down Expand Up @@ -2976,7 +2976,7 @@ private function formatHeader($ch, $header) {
* @param array $options
* @return resource The curl handle
*/
protected function apply_opt($curl, $options) {
private function apply_opt($curl, $options) {
// Clean up
$this->cleanopt();
// set cookie
Expand Down
62 changes: 51 additions & 11 deletions lib/tests/filelib_test.php
Expand Up @@ -883,7 +883,7 @@ public function test_get_mimetypes_array() {
* Test curl agent settings.
*/
public function test_curl_useragent() {
$curl = new curl_extended();
$curl = new testable_curl();
$options = $curl->get_options();
$this->assertNotEmpty($options);

Expand All @@ -910,48 +910,88 @@ public function test_curl_useragent() {
$curl->unset_option('CURLOPT_USERAGENT');
$curl->call_apply_opt();
$this->assertTrue(in_array('User-Agent: MoodleBot/1.0', $curl->header));

// Finally, test it via exttests, to ensure the agent is sent properly.
// Matching.
$testurl = $this->getExternalTestFileUrl('/test_agent.php');
$extcurl = new curl();
$contents = $extcurl->get($testurl, array(), array('CURLOPT_USERAGENT' => 'AnotherUserAgent/1.2'));
$response = $extcurl->getResponse();
$this->assertSame('200 OK', reset($response));
$this->assertSame(0, $extcurl->get_errno());
$this->assertSame('OK', $contents);
// Not matching.
$contents = $extcurl->get($testurl, array(), array('CURLOPT_USERAGENT' => 'NonMatchingUserAgent/1.2'));
$response = $extcurl->getResponse();
$this->assertSame('200 OK', reset($response));
$this->assertSame(0, $extcurl->get_errno());
$this->assertSame('', $contents);
}
}

/**
* Test-specific class to allow easier testing of curl functions.
*
* @copyright 2015 Dave Cooper
*
* @copyright 2015 Dave Cooper
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class curl_extended extends curl {
class testable_curl extends curl {
/**
* Accessor for options array.
* Accessor for private options array using reflection.
*
* @return array
*/
public function get_options() {
return $this->options;
// Access to private property.
$rp = new ReflectionProperty('curl', 'options');
$rp->setAccessible(true);
return $rp->getValue($this);
}

/**
* Setter for private options array using reflection.
*
* @param array $options
*/
public function set_options($options) {
// Access to private property.
$rp = new ReflectionProperty('curl', 'options');
$rp->setAccessible(true);
$rp->setValue($this, $options);
}

/**
* Setter for options array.
* Setter for individual option.
* @param string $option
* @param string $value
*/
public function set_option($option, $value) {
$this->options[$option] = $value;
$options = $this->get_options();
$options[$option] = $value;
$this->set_options($options);
}

/**
* Unsets an option on the curl object
* @param string $option
*/
public function unset_option($option) {
unset($this->options[$option]);
$options = $this->get_options();
unset($options[$option]);
$this->set_options($options);
}

/**
* Wrapper to access the curl::apply_opt() function
* Wrapper to access the private curl::apply_opt() method using reflection.
*
* @param array $options
* @return resource The curl handle
*/
public function call_apply_opt($options = null) {
// Access to private method.
$rm = new ReflectionMethod('curl', 'apply_opt');
$rm->setAccessible(true);
$ch = curl_init();
return $this->apply_opt($ch, $options);
return $rm->invoke($this, $ch, $options);
}
}

0 comments on commit 9a1adda

Please sign in to comment.