1
0
mirror of https://github.com/guzzle/guzzle.git synced 2025-02-25 10:33:18 +01:00
guzzle/tests/Adapter/Curl/BatchContextTest.php
Michael Dowling d68dc43283 Accounting for random connection issues in multi-adapter
This commit updates the MultiAdapter to account for connecitons
being closed unexpectedly and then retried. When this occurs, curl
attempts to rewind the stream before sending. Because we use a
callback function to stream large payloads, curl fails to rewind
the stream and fails the transaction without associating the correct
error code. This commit checks if a transaction has a response
before processing. If a transaction doesn't have a response, then
we attempt to retry the request transparently (without emitting
another set of before events, essentially doing exactly what
curl would have done if it was possible to rewind the stream). If
the request did not have a body, then an error event is emitted as
it is a very weird error. If the request had a body but wasn't
rewindable, then an error event is emitted. If the request had a
body and a rewindable stream, then it is rewound and retried.

This change also updates the MultiAdapter and BatchContext to
transfer until the number of open handles in the BatchContext
reaches 0. This removes some complexity from the main transfer loop
that had to account for pending transactions.

Closes #710
2014-07-31 21:02:29 -07:00

96 lines
3.0 KiB
PHP

<?php
namespace GuzzleHttp\Tests\Adapter\Curl;
use GuzzleHttp\Adapter\Curl\BatchContext;
use GuzzleHttp\Adapter\Transaction;
use GuzzleHttp\Client;
use GuzzleHttp\Message\Request;
/**
* @covers GuzzleHttp\Adapter\Curl\BatchContext
*/
class BatchContextTest extends \PHPUnit_Framework_TestCase
{
public function testProvidesGetters()
{
$m = curl_multi_init();
$b = new BatchContext($m, true);
$this->assertTrue($b->throwsExceptions());
$this->assertSame($m, $b->getMultiHandle());
$this->assertFalse($b->hasPending());
curl_multi_close($m);
}
public function testValidatesTransactionsAreNotAddedTwice()
{
$m = curl_multi_init();
$b = new BatchContext($m, true);
$h = curl_init();
$t = new Transaction(
new Client(),
new Request('GET', 'http://httbin.org')
);
$b->addTransaction($t, $h);
try {
$b->addTransaction($t, $h);
$this->fail('Did not throw');
} catch (\RuntimeException $e) {
curl_close($h);
curl_multi_close($m);
}
}
public function testManagesHandles()
{
$m = curl_multi_init();
$b = new BatchContext($m, true);
$h = curl_init();
$t = new Transaction(
new Client(),
new Request('GET', 'http://httbin.org')
);
$b->addTransaction($t, $h);
$this->assertTrue($b->isActive());
$this->assertSame($t, $b->findTransaction($h));
$b->removeTransaction($t);
$this->assertFalse($b->isActive());
try {
$this->assertEquals([], $b->findTransaction($h));
$this->fail('Did not throw');
} catch (\RuntimeException $e) {}
curl_multi_close($m);
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Transaction not registered
*/
public function testThrowsWhenRemovingNonExistentTransaction()
{
$b = new BatchContext('foo', false);
$t = new Transaction(
new Client(),
new Request('GET', 'http://httbin.org')
);
$b->removeTransaction($t);
}
public function testReturnsPendingAsIteratorTypeObject()
{
$t1 = new Transaction(new Client(), new Request('GET', 'http://t.com'));
$t2 = new Transaction(new Client(), new Request('GET', 'http://t.com'));
$t3 = new Transaction(new Client(), new Request('GET', 'http://t.com'));
$iter = new \ArrayIterator([$t1, $t2, $t3]);
$b = new BatchContext('foo', false, $iter);
$this->assertTrue($b->hasPending());
$this->assertSame($t1, $b->nextPending());
$this->assertTrue($b->hasPending());
$this->assertSame($t2, $b->nextPending());
$this->assertTrue($b->hasPending());
$this->assertSame($t3, $b->nextPending());
$this->assertFalse($b->hasPending());
$this->assertNull($b->nextPending());
}
}