add tests
authorMichael Wallner <mike@php.net>
Mon, 22 Aug 2016 09:55:45 +0000 (11:55 +0200)
committerMichael Wallner <mike@php.net>
Mon, 22 Aug 2016 09:55:45 +0000 (11:55 +0200)
package.xml
tests/client029.phpt [new file with mode: 0644]
tests/gh-issue48.phpt [new file with mode: 0644]

index 27f2fc1160a1d9009b7757f375584a20fdf0e46f..d22b029e58748474f6699ed42f56d285e75c2947 100644 (file)
@@ -31,18 +31,39 @@ https://mdref.m6w6.name/http
   <email>mike@php.net</email>
   <active>yes</active>
  </lead>
- <date>2016-03-31</date>
+ <date>2016-08-22</date>
  <version>
-  <release>2.6.0</release>
+  <release>2.6.0beta1</release>
   <api>2.6.0</api>
  </version>
  <stability>
-  <release>stable</release>
+  <release>beta</release>
   <api>stable</api>
  </stability>
  <license uri="http://copyfree.org/content/standard/licenses/2bsd/license.txt">BSD-2-Clause</license>
  <notes><![CDATA[
++ Added http\Client\Curl\User interface for userland event loops
++ Added http\Url::IGNORE_ERRORS, http\Url::SILENT_ERRORS and http\Url::STDFLAGS
++ Added http\Client::setDebug(callable $debug)
++ Added http\Client\Curl\FEATURES constants and namespace
++ Added http\Client\Curl\VERSIONS constants and namespace
++ Added share_cookies and share_ssl (libcurl >= 7.23.0) options to http\Client::configure()
++ http\Client uses curl_share handles to properly share cookies and SSL/TLS sessions between requests
++ Improved configure checks for default CA bundles
++ Improved negotiation precision
+* Fixed regression introduced by http\Params::PARSE_RFC5987: negotiation using the params parser would receive param keys without the trailing asterisk, stripped by http\Params::PARSE_RFC5987.
+* Fix gh-issue #50: http\Client::dequeue() within http\Client::setDebug() causes segfault (Mike, Maik Wagner)
+* Fix gh-issue #47: http\Url: Null pointer deref in sanitize_value() (Mike, @rc0r)
+* Fix gh-issue #45: HTTP/2 response message parsing broken with libcurl >= 7.49.1 (Mike)
+* Fix gh-issue #43: Joining query with empty original variable in query (Mike, Sander Backus)
+* Fix gh-issue #42: fatal error when using punycode in URLs (Mike, Sebastian Thielen)
+* Fix gh-issue #41: Use curl_version_info_data.features when initializing options (Mike)
+* Fix gh-issue #40: determinde the SSL backend used by curl at runtime (Mike, @rcanavan)
+* Fix gh-issue #39: Notice: http\Client::enqueue(): Could not set option proxy_service_name (Mike, @rcanavan)
+* Fix gh-issue #38: Persistent curl handles: error code not properly reset (Mike, @afflerbach)
+* Fix gh-issue #36: Unexpected cookies sent if persistent_handle_id is used (Mike, @rcanavan, @afflerbach)
 * Fix gh-issue #34: allow setting multiple headers with the same name (Mike, @rcanavan)
+* Fix gh-issue #33: allow setting prodyhost request option to NULL (Mike, @rcanavan)
 * Fix gh-issue #31: add/improve configure checks for default CA bundle/path (Mike, @rcanavan) 
 ]]></notes>
  <contents>
@@ -69,6 +90,10 @@ https://mdref.m6w6.name/http
     <file role="src" name="php_http_client.h"/>
     <file role="src" name="php_http_client_curl.c"/>
     <file role="src" name="php_http_client_curl.h"/>
+    <file role="src" name="php_http_client_curl_event.c"/>
+    <file role="src" name="php_http_client_curl_event.h"/>
+    <file role="src" name="php_http_client_curl_user.c"/>
+    <file role="src" name="php_http_client_curl_user.h"/>
     <file role="src" name="php_http_client_request.c"/>
     <file role="src" name="php_http_client_request.h"/>
     <file role="src" name="php_http_client_response.c"/>
@@ -182,6 +207,9 @@ https://mdref.m6w6.name/http
      <file role="test" name="client024.phpt"/>
      <file role="test" name="client025.phpt"/>
      <file role="test" name="client026.phpt"/>
+     <file role="test" name="client027.phpt"/>
+     <file role="test" name="client028.phpt"/>
+     <file role="test" name="client029.phpt"/>
      <file role="test" name="clientrequest001.phpt"/>
      <file role="test" name="clientrequest002.phpt"/>
      <file role="test" name="clientrequest003.phpt"/>
@@ -247,6 +275,10 @@ https://mdref.m6w6.name/http
      <file role="test" name="gh-issue6.phpt"/>
      <file role="test" name="gh-issue7.phpt"/>
      <file role="test" name="gh-issue12.phpt"/>
+     <file role="test" name="gh-issue42.phpt"/>
+     <file role="test" name="gh-issue47.phpt"/>
+     <file role="test" name="gh-issue48.phpt"/>
+     <file role="test" name="gh-issue50.phpt"/>
      <file role="test" name="header001.phpt"/>
      <file role="test" name="header002.phpt"/>
      <file role="test" name="header003.phpt"/>
diff --git a/tests/client029.phpt b/tests/client029.phpt
new file mode 100644 (file)
index 0000000..2ed6d79
--- /dev/null
@@ -0,0 +1,124 @@
+--TEST--
+client curl user handler
+--SKIPIF--
+<?php 
+include "skipif.inc";
+skip_client_test();
+_ext("ev");
+
+?> 
+--FILE--
+<?php 
+echo "Test\n";
+
+class UserHandler implements http\Client\Curl\User
+{
+       private $client;
+       private $run;
+       private $ios = [];
+       private $timeout;
+
+
+       function __construct(http\Client $client) {
+               $this->client = $client;
+       }
+       
+       function init(callable $run) {
+               $this->run = $run;
+       }
+       
+       function timer($timeout_ms) {
+               echo "T";
+               if (isset($this->timeout)) {
+                       $this->timeout->set($timeout_ms/1000, 0);
+                       $this->timeout->start();
+               } else {
+                       $this->timeout = new EvTimer($timeout_ms/1000, 0, function() {
+                               if (!call_user_func($this->run, $this->client)) {
+                                       if ($this->timeout) {
+                                               $this->timeout->stop();
+                                               $this->timeout = null;
+                                       }
+                               }
+                       });
+               }
+       }
+       
+       function socket($socket, $action) {
+               echo "S";
+               
+               switch ($action) {
+               case self::POLL_NONE:
+                       break;
+               case self::POLL_REMOVE:
+                       if (isset($this->ios[(int) $socket])) {
+                               echo "U";
+                               $this->ios[(int) $socket]->stop();
+                               unset($this->ios[(int) $socket]);
+                       }
+                       break;
+                       
+               default:
+                       $ev = 0;
+                       if ($action & self::POLL_IN) {
+                               $ev |= Ev::READ;
+                       }
+                       if ($action & self::POLL_OUT) {
+                               $ev |= Ev::WRITE;
+                       }
+                       if (isset($this->ios[(int) $socket])) {
+                               $this->ios[(int) $socket]->set($socket, $ev);
+                       } else {
+                               $this->ios[(int) $socket] = new EvIo($socket, $ev, function($watcher, $events) use($socket) {
+                                       $action = 0;
+                                       if ($events & Ev::READ) {
+                                               $action |= self::POLL_IN;
+                                       }
+                                       if ($events & Ev::WRITE) {
+                                               $action |= self::POLL_OUT;
+                                       }
+                                       if (!call_user_func($this->run, $this->client, $socket, $action)) {
+                                               if ($this->timeout) {
+                                                       $this->timeout->stop();
+                                                       $this->timeout = null;
+                                               }
+                                       }
+                               });
+                       }
+                       break;
+               }
+       }
+       
+       function once() {
+               throw new BadMethodCallException("this test uses Ev::run()");
+       }
+       
+       function wait($timeout_ms = null) {
+               throw new BadMethodCallException("this test uses Ev::run()");
+       }
+       
+       function send() {
+               throw new BadMethodCallException("this test uses Ev::run()");
+       }
+}
+
+
+include "helper/server.inc";
+
+server("proxy.inc", function($port) {
+       $client = new http\Client;
+       $client->configure([
+                       "use_eventloop" => new UserHandler($client)
+       ]);
+       $client->enqueue(new http\Client\Request("GET", "http://localhost:$port/"), function($r) {
+               var_dump($r->getResponseCode());
+       });
+       Ev::run();
+});
+
+?>
+===DONE===
+--EXPECTREGEX--
+Test
+T[ST]+U+int\(200\)
+===DONE===
diff --git a/tests/gh-issue48.phpt b/tests/gh-issue48.phpt
new file mode 100644 (file)
index 0000000..ae12825
--- /dev/null
@@ -0,0 +1,177 @@
+--TEST--
+url errors
+--SKIPIF--
+<?php
+include "skipif.inc";
+?>
+--FILE--
+<?php
+echo "Test\n";
+
+function test($url, $flags = 0) {
+       echo "# DEFAULT\n";
+       try {
+               echo new http\Url($url, null, $flags), "\n";
+       } catch (Exception $e) {
+               echo $e->getMessage(), "\n";
+       } 
+       
+       echo "# IGNORE\n";
+       echo new http\Url($url, null, $flags|http\Url::IGNORE_ERRORS), "\n";
+       
+       echo "# SILENT\n";
+       echo new http\Url($url, null, $flags|http\Url::SILENT_ERRORS), "\n";
+       
+       echo "# IGNORE|SILENT\n";
+       echo new http\Url($url, null, $flags|http\Url::IGNORE_ERRORS|http\Url::SILENT_ERRORS), "\n";
+       echo "==========\n";
+}
+
+test("http://.foo.bar/?q=1");
+test("http://..foo.bar/i.x");
+test("http://foo..bar/i..x");
+test("http://-foo.bar");
+test("http://--foo.bar");
+test("http://f--oo.bar");
+test("htto://foo.bar/?q=%");
+test("htto://foo.bar/?q=%", http\Url::PARSE_TOPCT);
+test("http://a\xc3\xc3b");
+test("http://[foobar]:123");
+test("#/?foo=&#", http\Url::PARSE_MBUTF8);
+
+?>
+
+===DONE===
+--EXPECTF--
+Test
+# DEFAULT
+http\Url::__construct(): Failed to parse host; unexpected '.' at pos 0 in '.foo.bar/?q=1'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '.' at pos 0 in '.foo.bar/?q=1' in %sgh-issue48.php on line %d
+http://foo.bar/?q=1
+# SILENT
+
+# IGNORE|SILENT
+http://foo.bar/?q=1
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse host; unexpected '.' at pos 0 in '..foo.bar/i.x'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '.' at pos 0 in '..foo.bar/i.x' in %sgh-issue48.php on line %d
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '.' at pos 1 in '..foo.bar/i.x' in %sgh-issue48.php on line %d
+http://foo.bar/i.x
+# SILENT
+
+# IGNORE|SILENT
+http://foo.bar/i.x
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse host; unexpected '.' at pos 4 in 'foo..bar/i..x'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '.' at pos 4 in 'foo..bar/i..x' in %sgh-issue48.php on line %d
+http://foo.bar/i..x
+# SILENT
+
+# IGNORE|SILENT
+http://foo.bar/i..x
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse host; unexpected '-' at pos 0 in '-foo.bar'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '-' at pos 0 in '-foo.bar' in %sgh-issue48.php on line %d
+http://foo.bar/
+# SILENT
+
+# IGNORE|SILENT
+http://foo.bar/
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse host; unexpected '-' at pos 0 in '--foo.bar'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '-' at pos 0 in '--foo.bar' in %sgh-issue48.php on line %d
+
+Warning: http\Url::__construct(): Failed to parse host; unexpected '-' at pos 1 in '--foo.bar' in %sgh-issue48.php on line %d
+http://foo.bar/
+# SILENT
+
+# IGNORE|SILENT
+http://foo.bar/
+==========
+# DEFAULT
+http://f--oo.bar/
+# IGNORE
+http://f--oo.bar/
+# SILENT
+http://f--oo.bar/
+# IGNORE|SILENT
+http://f--oo.bar/
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse query; invalid percent encoding at pos 2 in 'q=%'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse query; invalid percent encoding at pos 2 in 'q=%' in %sgh-issue48.php on line %d
+htto://foo.bar/?q=%
+# SILENT
+
+# IGNORE|SILENT
+htto://foo.bar/?q=%
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse query; invalid percent encoding at pos 2 in 'q=%'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse query; invalid percent encoding at pos 2 in 'q=%' in %sgh-issue48.php on line %d
+htto://foo.bar/?q=%25
+# SILENT
+
+# IGNORE|SILENT
+htto://foo.bar/?q=%25
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse hostinfo; unexpected byte 0xc3 at pos 1 in 'a%c%cb'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse hostinfo; unexpected byte 0xc3 at pos 1 in 'a%c%cb' in %sgh-issue48.php on line %d
+
+Warning: http\Url::__construct(): Failed to parse hostinfo; unexpected byte 0xc3 at pos 2 in 'a%c%cb' in %sgh-issue48.php on line %d
+http://ab/
+# SILENT
+
+# IGNORE|SILENT
+http://ab/
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse hostinfo; unexpected '[' at pos 0 in '[foobar]:123'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse hostinfo; unexpected '[' at pos 0 in '[foobar]:123' in %sgh-issue48.php on line %d
+
+Warning: http\Url::__construct(): Failed to parse hostinfo; unexpected byte 0x5b at pos 0 in '[foobar]:123' in %sgh-issue48.php on line %d
+
+Warning: http\Url::__construct(): Failed to parse hostinfo; unexpected byte 0x5d at pos 7 in '[foobar]:123' in %sgh-issue48.php on line %d
+http://foobar:123/
+# SILENT
+
+# IGNORE|SILENT
+http://foobar:123/
+==========
+# DEFAULT
+http\Url::__construct(): Failed to parse fragment; invalid fragment identifier at pos 7 in '/?foo=&#'
+# IGNORE
+
+Warning: http\Url::__construct(): Failed to parse fragment; invalid fragment identifier at pos 7 in '/?foo=&#' in /home/mike/src/ext-http.git/tests/gh-issue48.php on line 13
+#/?foo=&#
+# SILENT
+
+# IGNORE|SILENT
+#/?foo=&#
+==========
+
+===DONE===