Skip to content

Commit 9771abb

Browse files
committed
Assert that cURL handles are correctly closed
1 parent d8faea6 commit 9771abb

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

src/Transport/Curl.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,9 @@ public function request($url, $headers = array(), $data = array(), $options = ar
201201
$response = $this->response_data;
202202
}
203203

204-
if (true === $options['blocking']) {
204+
if (! isset($options['blocking']) || $options['blocking'] !== false) {
205205
// Need to remove the $this reference from the curl handle.
206-
// Otherwise \WpOrg\Requests\Transport\Curl wont be garbage collected and the curl_close() will never be called.
206+
// Otherwise \WpOrg\Requests\Transport\Curl won't be garbage collected and the curl_close() will never be called.
207207
curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null);
208208
curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null);
209209
}

tests/Transport/BaseTestCase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ abstract class BaseTestCase extends TestCase {
1616

1717
protected $skip_https = false;
1818

19-
public function set_up() {
19+
protected function set_up() {
2020
$callback = array($this->transport, 'test');
2121
$supported = call_user_func($callback);
2222

tests/Transport/CurlTest.php

+82
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,63 @@
33
namespace WpOrg\Requests\Tests\Transport;
44

55
use WpOrg\Requests\Exception;
6+
use WpOrg\Requests\Hooks;
67
use WpOrg\Requests\Requests;
78
use WpOrg\Requests\Tests\Transport\BaseTestCase;
89
use WpOrg\Requests\Transport\Curl;
910

1011
final class CurlTest extends BaseTestCase {
1112
protected $transport = Curl::class;
1213

14+
/**
15+
* Temporary storage of the cURL handle to assert against.
16+
*
17+
* @var null|resource|\CurlHandle
18+
*/
19+
protected $curl_handle;
20+
21+
/**
22+
* Get the options to use for the cURL tests.
23+
*
24+
* This adds a hook on curl.before_request to store the cURL handle. This is
25+
* needed for asserting after the test scenarios that the cURL handle was
26+
* correctly closed.
27+
*
28+
* @param array $other
29+
* @return array
30+
*/
31+
protected function getOptions($other = array()) {
32+
$options = parent::getOptions($other);
33+
34+
$this->curl_handle = null;
35+
36+
$hooks = new Hooks();
37+
$hooks->register(
38+
'curl.before_request',
39+
function ($handle) {
40+
$this->curl_handle = $handle;
41+
}
42+
);
43+
44+
$options['hooks'] = $hooks;
45+
46+
return $options;
47+
}
48+
49+
/**
50+
* Post condition asserts to run after each scenario.
51+
*
52+
* This is used for asserting that cURL handles are not leaking memory.
53+
*/
54+
protected function assert_post_conditions( ) {
55+
if ($this->curl_handle === null) {
56+
// No cURL handle was used during this particular test scenario.
57+
return;
58+
}
59+
60+
$this->assertCurlHandleIsClosed($this->curl_handle);
61+
}
62+
1363
public function testBadIP() {
1464
$this->expectException(Exception::class);
1565
$this->expectExceptionMessage('t resolve host');
@@ -136,4 +186,36 @@ public function testSetsEmptyExpectHeaderIfBodySmallerThan1Mb() {
136186

137187
$this->assertFalse(isset($result['headers']['Expect']));
138188
}
189+
190+
/**
191+
* Assert that a provided cURL handle was properly closed.
192+
*
193+
* For PHP 8.0+, the cURL handle is not a resource that needs to be closed,
194+
* but rather a \CurlHandle object. The assertion just skips these.
195+
*
196+
* @param resource|\CurlHandle $handle CURL handle to check.
197+
*/
198+
private function assertCurlHandleIsClosed($handle) {
199+
if ($handle instanceof \CurlHandle) {
200+
// CURL handles have been changed from resources into CurlHandle
201+
// objects starting with PHP 8.0, which don;t need to be closed.
202+
return;
203+
}
204+
205+
self::assertThat(
206+
in_array(
207+
gettype($handle),
208+
array('resource', 'resource (closed)'),
209+
true
210+
),
211+
self::isTrue(),
212+
'Failed asserting that stored cURL handle was a resource.'
213+
);
214+
215+
self::assertThat(
216+
is_resource($handle) === false,
217+
self::isTrue(),
218+
'Failed asserting that stored cURL handle was properly closed.'
219+
);
220+
}
139221
}

0 commit comments

Comments
 (0)