use GuzzleHttp\Event\EndEvent;
use GuzzleHttp\Message\RequestInterface;
use GuzzleHttp\Message\Response;
use GuzzleHttp\Message\ResponseInterface;
use GuzzleHttp\Pool;
use GuzzleHttp\Subscriber\Mock;
use paslandau\GuzzleRotatingProxySubscriber\Exceptions\NoProxiesLeftException;
use paslandau\GuzzleRotatingProxySubscriber\Proxy\RotatingProxy;
use paslandau\GuzzleRotatingProxySubscriber\ProxyRotator;
use paslandau\GuzzleRotatingProxySubscriber\RotatingProxySubscriber;
require_once __DIR__ . '/bootstrap.php';
$proxy1 = new RotatingProxy("username:password@111.111.111.111:4711");
$proxy2 = new RotatingProxy("username:password@112.112.112.112:4711");
$proxy3 = new RotatingProxy("username:password@113.113.113.113:4711");
$proxies = [$proxy1, $proxy2, $proxy3];
$rotator = new ProxyRotator($proxies);
$sub = new RotatingProxySubscriber($rotator);
$client = new Client(["defaults" => ["headers" => ["User-Agent" => null]]]);
$client->getEmitter()->attach($sub);
// lets prepare 20 responses
$num = 20;
$responses = [];
for ($i = 0; $i < $num; $i++) {
    $responses[] = new Response(200);
}
$mock = new Mock($responses);
$client->getEmitter()->attach($mock);
// lets execute 20 requests
$requests = [];
$url = "http://localhost/";
for ($i = 0; $i < $num; $i++) {
 public function test_ShouldReuseSameProxyOnRedirect()
 {
     $proxyMock = $this->getRotatingProxyMock("test", true);
     $proxyMock->expects($this->once())->method("setupRequest")->willReturnArgument(0);
     $proxies = [$proxyMock];
     $useOwnIp = false;
     $rotator = new ProxyRotator($proxies, $useOwnIp);
     $rotator->setReuseSameProxyOnRedirect(true);
     $client = new Client();
     $request = $client->createRequest("GET", "/");
     $request->getConfig()->set("redirect_count", 1);
     $rotator->setupRequest($request);
     // setupRequest will not be called
     $request->getConfig()->remove("redirect_count");
     $rotator->setupRequest($request);
     // setupRequest will be called
 }
 /**
  * Test if redirect requests use the same proxy
  */
 public function test_integration_RedirectingRequestsShouldUseTheSameProxy()
 {
     $client = new Client();
     $proxy0 = new RotatingProxy("0", null, null, null, null);
     $proxy1 = new RotatingProxy("1", null, null, null, null);
     $proxies = [0 => $proxy0, 1 => $proxy1];
     $success = true;
     $redirect = false;
     $responses2Proxy = [[$success, $proxy1], [$redirect, $proxy1], [$success, null], [$success, $proxy0]];
     $randKeys = [];
     $responses = [];
     foreach ($responses2Proxy as $key => $val) {
         if ($val[1] !== null) {
             $randKeys[$key] = array_search($val[1], $proxies);
         }
         $responses[$key] = $val[0] ? new Response(200) : new Response(301, ["Location" => "http://localhost/"]);
     }
     $h = $this->getHelper(null, null, $randKeys);
     $useOwnIp = false;
     $rotator = new ProxyRotator($proxies, $useOwnIp, $h->getRandomMock());
     $rotator->setReuseSameProxyOnRedirect(true);
     $sub = new RotatingProxySubscriber($rotator);
     $mock = new Mock($responses);
     // Add the mock subscriber to the client.
     $client->getEmitter()->attach($mock);
     $client->getEmitter()->attach($sub);
     // build requests - we need to do this _after_ the $mock hast been attached to the client,
     // otherwise a real request is sent.
     $req1 = $client->createRequest("GET");
     $req2 = $client->createRequest("GET");
     $req3 = $client->createRequest("GET");
     $requests = [$req1, $req2, $req3];
     // making only 3 requests but will receive all 4 responses (verified because $proxy0 will have 1 total request)
     //        $options = [
     //            "before" => function(BeforeEvent $ev){
     //                echo "Before: Proxy ".$ev->getRequest()->getConfig()->get("proxy")."\n";
     //            },
     //            "complete" => function(CompleteEvent $ev){
     //                echo "Complete: Proxy ".$ev->getRequest()->getConfig()->get("proxy")."\n";
     //            },
     //            "error" => function(ErrorEvent $ev){
     //                echo "Error: Proxy ".$ev->getRequest()->getConfig()->get("proxy")."\n";
     //            },
     //            "end" => function(EndEvent $ev){
     //                echo "End: Proxy ".$ev->getRequest()->getConfig()->get("proxy")."\n";
     //            },
     //        ];
     $pool = new Pool($client, $requests);
     $pool->wait();
     $this->assertEquals(2, $proxy1->getTotalRequests(), "Proxy {$proxy1->getProxyString()} should have 2 total request");
     $this->assertEquals(0, $proxy1->getCurrentTotalFails(), "Proxy {$proxy1->getProxyString()} should have 0 failed requests");
     $this->assertEquals(1, $proxy0->getTotalRequests(), "Proxy {$proxy0->getProxyString()} should have 1 total request");
 }