From 8df3db566a3a937b45ebf11adb90d265e6f5e2d4 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 17 Nov 2019 20:45:02 +0100 Subject: initial checking of customized version 1.0rc9 --- .../Guzzle/Tests/Plugin/Cache/CachePluginTest.php | 441 +++++++++++++++++++++ .../Plugin/Cache/CallbackCanCacheStrategyTest.php | 72 ++++ .../Tests/Plugin/Cache/DefaultCacheStorageTest.php | 193 +++++++++ .../Plugin/Cache/DefaultCanCacheStrategyTest.php | 40 ++ .../Tests/Plugin/Cache/DefaultRevalidationTest.php | 248 ++++++++++++ .../Tests/Plugin/Cache/DenyRevalidationTest.php | 19 + .../Tests/Plugin/Cache/SkipRevalidationTest.php | 19 + 7 files changed, 1032 insertions(+) create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CachePluginTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CallbackCanCacheStrategyTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCacheStorageTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCanCacheStrategyTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultRevalidationTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DenyRevalidationTest.php create mode 100644 vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/SkipRevalidationTest.php (limited to 'vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache') diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CachePluginTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CachePluginTest.php new file mode 100644 index 0000000..69da60a --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CachePluginTest.php @@ -0,0 +1,441 @@ +assertInstanceOf('Guzzle\Plugin\Cache\CacheStorageInterface', $this->readAttribute($plugin, 'storage')); + } + + public function testAddsDefaultCollaborators() + { + $this->assertNotEmpty(CachePlugin::getSubscribedEvents()); + $plugin = new CachePlugin(array( + 'storage' => $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface')->getMockForAbstractClass() + )); + $this->assertInstanceOf('Guzzle\Plugin\Cache\CacheStorageInterface', $this->readAttribute($plugin, 'storage')); + $this->assertInstanceOf( + 'Guzzle\Plugin\Cache\CanCacheStrategyInterface', + $this->readAttribute($plugin, 'canCache') + ); + $this->assertInstanceOf( + 'Guzzle\Plugin\Cache\RevalidationInterface', + $this->readAttribute($plugin, 'revalidation') + ); + } + + public function testAddsCallbackCollaborators() + { + $this->assertNotEmpty(CachePlugin::getSubscribedEvents()); + $plugin = new CachePlugin(array('can_cache' => function () {})); + $this->assertInstanceOf( + 'Guzzle\Plugin\Cache\CallbackCanCacheStrategy', + $this->readAttribute($plugin, 'canCache') + ); + } + + public function testCanPassCacheAsOnlyArgumentToConstructor() + { + $p = new CachePlugin(new DoctrineCacheAdapter(new ArrayCache())); + $p = new CachePlugin(new DefaultCacheStorage(new DoctrineCacheAdapter(new ArrayCache()))); + } + + public function testUsesCreatedCacheStorage() + { + $plugin = new CachePlugin(array( + 'adapter' => $this->getMockBuilder('Guzzle\Cache\CacheAdapterInterface')->getMockForAbstractClass() + )); + $this->assertInstanceOf('Guzzle\Plugin\Cache\CacheStorageInterface', $this->readAttribute($plugin, 'storage')); + } + + public function testUsesProvidedOptions() + { + $can = $this->getMockBuilder('Guzzle\Plugin\Cache\CanCacheStrategyInterface')->getMockForAbstractClass(); + $revalidate = $this->getMockBuilder('Guzzle\Plugin\Cache\RevalidationInterface')->getMockForAbstractClass(); + $plugin = new CachePlugin(array( + 'storage' => $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface')->getMockForAbstractClass(), + 'can_cache' => $can, + 'revalidation' => $revalidate + )); + $this->assertSame($can, $this->readAttribute($plugin, 'canCache')); + $this->assertSame($revalidate, $this->readAttribute($plugin, 'revalidation')); + } + + public function satisfyProvider() + { + $req1 = new Request('GET', 'http://foo.com', array('Cache-Control' => 'no-cache')); + + return array( + // The response is too old to satisfy the request + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-age=20')), new Response(200, array('Age' => 100)), false, false), + // The response cannot satisfy the request because it is stale + array(new Request('GET', 'http://foo.com'), new Response(200, array('Cache-Control' => 'max-age=10', 'Age' => 100)), false, false), + // Allows the expired response to satisfy the request because of the max-stale + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-stale=15')), new Response(200, array('Cache-Control' => 'max-age=90', 'Age' => 100)), true, false), + // Max stale is > than the allowed staleness + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-stale=5')), new Response(200, array('Cache-Control' => 'max-age=90', 'Age' => 100)), false, false), + // Performs cache revalidation + array($req1, new Response(200), true, true), + // Performs revalidation due to ETag on the response and no cache-control on the request + array(new Request('GET', 'http://foo.com'), new Response(200, array( + 'ETag' => 'ABC', + 'Expires' => date('c', strtotime('+1 year')) + )), true, true), + ); + } + + /** + * @dataProvider satisfyProvider + */ + public function testChecksIfResponseCanSatisfyRequest($request, $response, $can, $revalidates) + { + $didRevalidate = false; + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface')->getMockForAbstractClass(); + $revalidate = $this->getMockBuilder('Guzzle\Plugin\Cache\DefaultRevalidation') + ->setMethods(array('revalidate')) + ->setConstructorArgs(array($storage)) + ->getMockForAbstractClass(); + + $revalidate->expects($this->any()) + ->method('revalidate') + ->will($this->returnCallback(function () use (&$didRevalidate) { + $didRevalidate = true; + return true; + })); + + $plugin = new CachePlugin(array( + 'storage' => $storage, + 'revalidation' => $revalidate + )); + + $this->assertEquals($can, $plugin->canResponseSatisfyRequest($request, $response)); + $this->assertEquals($didRevalidate, $revalidates); + } + + public function satisfyFailedProvider() + { + return array( + // Neither has stale-if-error + array(new Request('GET', 'http://foo.com', array()), new Response(200, array('Age' => 100)), false), + // Request has stale-if-error + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'stale-if-error')), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50')), true), + // Request has valid stale-if-error + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'stale-if-error=50')), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50')), true), + // Request has expired stale-if-error + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'stale-if-error=20')), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50')), false), + // Response has permanent stale-if-error + array(new Request('GET', 'http://foo.com', array()), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50, stale-if-error', )), true), + // Response has valid stale-if-error + array(new Request('GET', 'http://foo.com', array()), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50, stale-if-error=50')), true), + // Response has expired stale-if-error + array(new Request('GET', 'http://foo.com', array()), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50, stale-if-error=20')), false), + // Request has valid stale-if-error but response does not + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'stale-if-error=50')), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50, stale-if-error=20')), false), + // Response has valid stale-if-error but request does not + array(new Request('GET', 'http://foo.com', array('Cache-Control' => 'stale-if-error=20')), new Response(200, array('Age' => 100, 'Cache-Control' => 'max-age=50, stale-if-error=50')), false), + ); + } + + /** + * @dataProvider satisfyFailedProvider + */ + public function testChecksIfResponseCanSatisfyFailedRequest($request, $response, $can) + { + $plugin = new CachePlugin(); + + $this->assertEquals($can, $plugin->canResponseSatisfyFailedRequest($request, $response)); + } + + public function testDoesNothingWhenRequestIsNotCacheable() + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + $storage->expects($this->never())->method('fetch'); + + $plugin = new CachePlugin(array( + 'storage' => $storage, + 'can_cache' => new CallbackCanCacheStrategy(function () { return false; }) + )); + + $plugin->onRequestBeforeSend(new Event(array( + 'request' => new Request('GET', 'http://foo.com') + ))); + } + + public function satisfiableProvider() + { + $date = new \DateTime('-10 seconds'); + + return array( + // Fresh response + array(new Response(200, array(), 'foo')), + // Stale response + array(new Response(200, array('Date' => $date->format('c'), 'Cache-Control' => 'max-age=5'), 'foo')) + ); + } + + /** + * @dataProvider satisfiableProvider + */ + public function testInjectsSatisfiableResponses($response) + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + + $storage->expects($this->once())->method('fetch')->will($this->returnValue($response)); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-stale')); + $plugin->onRequestBeforeSend(new Event(array('request' => $request))); + $plugin->onRequestSent(new Event(array('request' => $request, 'response' => $request->getResponse()))); + $this->assertEquals($response->getStatusCode(), $request->getResponse()->getStatusCode()); + $this->assertEquals((string) $response->getBody(), (string) $request->getResponse()->getBody()); + $this->assertTrue($request->getResponse()->hasHeader('Age')); + if ($request->getResponse()->isFresh() === false) { + $this->assertContains('110', (string) $request->getResponse()->getHeader('Warning')); + } + $this->assertSame( + sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION), + (string) $request->getHeader('Via') + ); + $this->assertSame( + sprintf('%s GuzzleCache/%s',$request->getProtocolVersion(), Version::VERSION), + (string) $request->getResponse()->getHeader('Via') + ); + $this->assertTrue($request->getParams()->get('cache.lookup')); + $this->assertTrue($request->getParams()->get('cache.hit')); + $this->assertTrue($request->getResponse()->hasHeader('X-Cache-Lookup')); + $this->assertTrue($request->getResponse()->hasHeader('X-Cache')); + $this->assertEquals('HIT from GuzzleCache', (string) $request->getResponse()->getHeader('X-Cache')); + $this->assertEquals('HIT from GuzzleCache', (string) $request->getResponse()->getHeader('X-Cache-Lookup')); + } + + public function satisfiableOnErrorProvider() + { + $date = new \DateTime('-10 seconds'); + return array( + array( + new Response(200, array( + 'Date' => $date->format('c'), + 'Cache-Control' => 'max-age=5, stale-if-error' + ), 'foo'), + ) + ); + } + + /** + * @dataProvider satisfiableOnErrorProvider + */ + public function testInjectsSatisfiableResponsesOnError($cacheResponse) + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + $storage->expects($this->exactly(2))->method('fetch')->will($this->returnValue($cacheResponse)); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-stale')); + $plugin->onRequestBeforeSend(new Event(array('request' => $request))); + $plugin->onRequestError( + $event = new Event(array( + 'request' => $request, + 'response' => $request->getResponse(), + )) + ); + $response = $event['response']; + $this->assertEquals($cacheResponse->getStatusCode(), $response->getStatusCode()); + $this->assertEquals((string) $cacheResponse->getBody(), (string) $response->getBody()); + $this->assertTrue($response->hasHeader('Age')); + if ($response->isFresh() === false) { + $this->assertContains('110', (string) $response->getHeader('Warning')); + } + $this->assertSame(sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION), (string) $request->getHeader('Via')); + $this->assertSame(sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION), (string) $response->getHeader('Via')); + $this->assertTrue($request->getParams()->get('cache.lookup')); + $this->assertSame('error', $request->getParams()->get('cache.hit')); + $this->assertTrue($response->hasHeader('X-Cache-Lookup')); + $this->assertTrue($response->hasHeader('X-Cache')); + $this->assertEquals('HIT from GuzzleCache', (string) $response->getHeader('X-Cache-Lookup')); + $this->assertEquals('HIT_ERROR from GuzzleCache', (string) $response->getHeader('X-Cache')); + } + + /** + * @dataProvider satisfiableOnErrorProvider + */ + public function testInjectsSatisfiableResponsesOnException($cacheResponse) + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + $storage->expects($this->exactly(2))->method('fetch')->will($this->returnValue($cacheResponse)); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', array('Cache-Control' => 'max-stale')); + $plugin->onRequestBeforeSend(new Event(array( + 'request' => $request + ))); + $plugin->onRequestException( + new Event(array( + 'request' => $request, + 'response' => $request->getResponse(), + 'exception' => $this->getMock('Guzzle\Http\Exception\CurlException'), + )) + ); + $plugin->onRequestSent( + new Event(array( + 'request' => $request, + 'response' => $response = $request->getResponse(), + )) + ); + $this->assertEquals($cacheResponse->getStatusCode(), $response->getStatusCode()); + $this->assertEquals((string) $cacheResponse->getBody(), (string) $response->getBody()); + $this->assertTrue($response->hasHeader('Age')); + if ($response->isFresh() === false) { + $this->assertContains('110', (string) $response->getHeader('Warning')); + } + $this->assertSame(sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION), (string) $request->getHeader('Via')); + $this->assertSame(sprintf('%s GuzzleCache/%s', $request->getProtocolVersion(), Version::VERSION), (string) $response->getHeader('Via')); + $this->assertTrue($request->getParams()->get('cache.lookup')); + $this->assertSame('error', $request->getParams()->get('cache.hit')); + $this->assertTrue($response->hasHeader('X-Cache-Lookup')); + $this->assertTrue($response->hasHeader('X-Cache')); + $this->assertEquals('HIT from GuzzleCache', (string) $response->getHeader('X-Cache-Lookup')); + $this->assertEquals('HIT_ERROR from GuzzleCache', (string) $response->getHeader('X-Cache')); + } + + public function unsatisfiableOnErrorProvider() + { + $date = new \DateTime('-10 seconds'); + + return array( + // no-store on request + array( + false, + array('Cache-Control' => 'no-store'), + new Response(200, array('Date' => $date->format('D, d M Y H:i:s T'), 'Cache-Control' => 'max-age=5, stale-if-error'), 'foo'), + ), + // request expired + array( + true, + array('Cache-Control' => 'stale-if-error=4'), + new Response(200, array('Date' => $date->format('D, d M Y H:i:s T'), 'Cache-Control' => 'max-age=5, stale-if-error'), 'foo'), + ), + // response expired + array( + true, + array('Cache-Control' => 'stale-if-error'), + new Response(200, array('Date' => $date->format('D, d M Y H:i:s T'), 'Cache-Control' => 'max-age=5, stale-if-error=4'), 'foo'), + ), + ); + } + + /** + * @dataProvider unsatisfiableOnErrorProvider + */ + public function testDoesNotInjectUnsatisfiableResponsesOnError($requestCanCache, $requestHeaders, $cacheResponse) + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + $storage->expects($this->exactly($requestCanCache ? 2 : 0))->method('fetch')->will($this->returnValue($cacheResponse)); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', $requestHeaders); + $plugin->onRequestBeforeSend(new Event(array( + 'request' => $request + ))); + $plugin->onRequestError( + $event = new Event(array( + 'request' => $request, + 'response' => $response = $request->getResponse(), + )) + ); + + $this->assertSame($response, $event['response']); + } + + /** + * @dataProvider unsatisfiableOnErrorProvider + */ + public function testDoesNotInjectUnsatisfiableResponsesOnException($requestCanCache, $requestHeaders, $responseParts) + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + $storage->expects($this->exactly($requestCanCache ? 2 : 0))->method('fetch')->will($this->returnValue($responseParts)); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', $requestHeaders); + $plugin->onRequestBeforeSend(new Event(array( + 'request' => $request + ))); + $plugin->onRequestException( + $event = new Event(array( + 'request' => $request, + 'response' => $response = $request->getResponse(), + 'exception' => $this->getMock('Guzzle\Http\Exception\CurlException'), + )) + ); + + $this->assertSame($response, $request->getResponse()); + } + + public function testCachesResponsesWhenCacheable() + { + $cache = new ArrayCache(); + $plugin = new CachePlugin($cache); + + $request = new Request('GET', 'http://foo.com'); + $response = new Response(200, array(), 'Foo'); + $plugin->onRequestBeforeSend(new Event(array( + 'request' => $request + ))); + $plugin->onRequestSent(new Event(array( + 'request' => $request, + 'response' => $response + ))); + $data = $this->readAttribute($cache, 'data'); + $this->assertNotEmpty($data); + } + + public function testPurgesRequests() + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('purge')) + ->getMockForAbstractClass(); + $storage->expects($this->atLeastOnce())->method('purge'); + $plugin = new CachePlugin(array('storage' => $storage)); + $request = new Request('GET', 'http://foo.com', array('X-Foo' => 'Bar')); + $plugin->purge($request); + } + + public function testAutoPurgesRequests() + { + $storage = $this->getMockBuilder('Guzzle\Plugin\Cache\CacheStorageInterface') + ->setMethods(array('purge')) + ->getMockForAbstractClass(); + $storage->expects($this->atLeastOnce())->method('purge'); + $plugin = new CachePlugin(array('storage' => $storage, 'auto_purge' => true)); + $client = new Client(); + $request = $client->put('http://foo.com', array('X-Foo' => 'Bar')); + $request->addSubscriber($plugin); + $request->setResponse(new Response(200), true); + $request->send(); + } +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CallbackCanCacheStrategyTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CallbackCanCacheStrategyTest.php new file mode 100644 index 0000000..f3d9baf --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/CallbackCanCacheStrategyTest.php @@ -0,0 +1,72 @@ +assertTrue($c->canCacheRequest(new Request('DELETE', 'http://www.foo.com'))); + } + + /** + * The following is a bit of an integration test to ensure that the CachePlugin honors a + * custom can cache strategy. + */ + public function testIntegrationWithCachePlugin() + { + $c = new CallbackCanCacheStrategy( + function ($request) { return true; }, + function ($response) { return true; } + ); + + // Make a request and response that have no business being cached + $request = new Request('DELETE', 'http://www.foo.com'); + $response = Response::fromMessage( + "HTTP/1.1 200 OK\r\n" + . "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" + . "Last-Modified: Wed, 09 Jan 2013 08:48:53 GMT\r\n" + . "Content-Length: 2\r\n" + . "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\n\r\n" + . "hi" + ); + + $this->assertTrue($c->canCacheRequest($request)); + $this->assertTrue($c->canCacheResponse($response)); + + $s = $this->getMockBuilder('Guzzle\Plugin\Cache\DefaultCacheStorage') + ->setConstructorArgs(array(new DoctrineCacheAdapter(new ArrayCache()))) + ->setMethods(array('fetch')) + ->getMockForAbstractClass(); + + $s->expects($this->once()) + ->method('fetch') + ->will($this->returnValue($response)); + + $plugin = new CachePlugin(array('can_cache' => $c, 'storage' => $s)); + $plugin->onRequestBeforeSend(new Event(array('request' => $request))); + + $this->assertEquals(200, $request->getResponse()->getStatusCode()); + $this->assertEquals('hi', $request->getResponse()->getBody(true)); + } +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCacheStorageTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCacheStorageTest.php new file mode 100644 index 0000000..701a015 --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCacheStorageTest.php @@ -0,0 +1,193 @@ + 'application/json')); + $response = new Response(200, array( + 'Content-Type' => 'application/json', + 'Connection' => 'close', + 'X-Foo' => 'Bar', + 'Vary' => 'Accept' + ), 'test'); + $s->cache($request, $response); + $data = $this->readAttribute($a, 'data'); + + return array( + 'cache' => $a, + 'adapter' => $c, + 'storage' => $s, + 'request' => $request, + 'response' => $response, + 'serialized' => end($data) + ); + } + + public function testReturnsNullForCacheMiss() + { + $cache = $this->getCache(); + $this->assertNull($cache['storage']->fetch(new Request('GET', 'http://test.com'))); + } + + public function testCachesRequests() + { + $cache = $this->getCache(); + $foundRequest = $foundBody = $bodyKey = false; + foreach ($this->readAttribute($cache['cache'], 'data') as $key => $v) { + if (strpos($v, 'foo.com')) { + $foundRequest = true; + $data = unserialize($v); + $bodyKey = $data[0][3]; + $this->assertInternalType('integer', $data[0][4]); + $this->assertFalse(isset($data[0][0]['connection'])); + $this->assertEquals('foo.com', $data[0][0]['host']); + } elseif ($v == 'test') { + $foundBody = $key; + } + } + $this->assertContains($bodyKey, $foundBody); + $this->assertTrue($foundRequest); + } + + public function testFetchesResponse() + { + $cache = $this->getCache(); + $response = $cache['storage']->fetch($cache['request']); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertFalse($response->hasHeader('Connection')); + $this->assertEquals('Bar', (string) $response->getHeader('X-Foo')); + $this->assertEquals('test', (string) $response->getBody()); + $this->assertTrue(in_array($cache['serialized'], $this->readAttribute($cache['cache'], 'data'))); + } + + public function testDeletesRequestItemsAndBody() + { + $cache = $this->getCache(); + $cache['storage']->delete($cache['request']); + $this->assertFalse(in_array('test', $this->readAttribute($cache['cache'], 'data'))); + $this->assertFalse(in_array($cache['serialized'], $this->readAttribute($cache['cache'], 'data'))); + } + + public function testCachesMultipleRequestsWithVary() + { + $cache = $this->getCache(); + $cache['request']->setHeader('Accept', 'application/xml'); + $response = $cache['response']->setHeader('Content-Type', 'application/xml'); + $response->setBody('123'); + $cache['storage']->cache($cache['request'], $response); + $data = $this->readAttribute($cache['cache'], 'data'); + foreach ($data as $v) { + if (strpos($v, 'foo.com')) { + $u = unserialize($v); + $this->assertEquals(2, count($u)); + $this->assertEquals($u[0][0]['accept'], 'application/xml'); + $this->assertEquals($u[0][1]['content-type'], 'application/xml'); + $this->assertEquals($u[1][0]['accept'], 'application/json'); + $this->assertEquals($u[1][1]['content-type'], 'application/json'); + $this->assertNotSame($u[0][3], $u[1][3]); + break; + } + } + } + + public function testPurgeRemovesAllMethodCaches() + { + $cache = $this->getCache(); + foreach (array('HEAD', 'POST', 'PUT', 'DELETE') as $method) { + $request = RequestFactory::getInstance()->cloneRequestWithMethod($cache['request'], $method); + $cache['storage']->cache($request, $cache['response']); + } + $cache['storage']->purge('http://foo.com'); + $this->assertFalse(in_array('test', $this->readAttribute($cache['cache'], 'data'))); + $this->assertFalse(in_array($cache['serialized'], $this->readAttribute($cache['cache'], 'data'))); + $this->assertEquals( + array('DoctrineNamespaceCacheKey[]'), + array_keys($this->readAttribute($cache['cache'], 'data')) + ); + } + + public function testRemovesExpiredResponses() + { + $cache = $this->getCache(); + $request = new Request('GET', 'http://xyz.com'); + $response = new Response(200, array('Age' => 1000, 'Cache-Control' => 'max-age=-10000')); + $cache['storage']->cache($request, $response); + $this->assertNull($cache['storage']->fetch($request)); + $data = $this->readAttribute($cache['cache'], 'data'); + $this->assertFalse(in_array('xyz.com', $data)); + $this->assertTrue(in_array($cache['serialized'], $data)); + } + + public function testUsesVaryToDetermineResult() + { + $cache = $this->getCache(); + $this->assertInstanceOf('Guzzle\Http\Message\Response', $cache['storage']->fetch($cache['request'])); + $request = new Request('GET', 'http://foo.com', array('Accept' => 'application/xml')); + $this->assertNull($cache['storage']->fetch($request)); + } + + public function testEnsuresResponseIsStillPresent() + { + $cache = $this->getCache(); + $data = $this->readAttribute($cache['cache'], 'data'); + $key = array_search('test', $data); + $cache['cache']->delete(substr($key, 1, -4)); + $this->assertNull($cache['storage']->fetch($cache['request'])); + } + + public function staleProvider() + { + return array( + array( + new Request('GET', 'http://foo.com', array('Accept' => 'foo')), + new Response(200, array('Cache-Control' => 'stale-if-error=100', 'Vary' => 'Accept')) + ), + array( + new Request('GET', 'http://foo.com', array('Accept' => 'foo')), + new Response(200, array('Cache-Control' => 'stale-if-error', 'Vary' => 'Accept')) + ) + ); + } + + /** + * @dataProvider staleProvider + */ + public function testUsesStaleTimeDirectiveForTtd($request, $response) + { + $cache = $this->getCache(); + $cache['storage']->cache($request, $response); + $data = $this->readAttribute($cache['cache'], 'data'); + foreach ($data as $v) { + if (strpos($v, 'foo.com')) { + $u = unserialize($v); + $this->assertGreaterThan($u[1][4], $u[0][4]); + break; + } + } + } + + public function testCanFilterCacheKeys() + { + $cache = $this->getCache(); + $cache['request']->getQuery()->set('auth', 'foo'); + $this->assertNull($cache['storage']->fetch($cache['request'])); + $cache['request']->getParams()->set('cache.key_filter', 'auth'); + $this->assertNotNull($cache['storage']->fetch($cache['request'])); + } +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCanCacheStrategyTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCanCacheStrategyTest.php new file mode 100644 index 0000000..de4d182 --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultCanCacheStrategyTest.php @@ -0,0 +1,40 @@ +assertTrue($strategy->canCacheRequest($request)); + } + + public function testDoesNotCacheNoStore() + { + $strategy = new DefaultCanCacheStrategy(); + $request = new Request('GET', 'http://foo.com', array('cache-control' => 'no-store')); + $this->assertFalse($strategy->canCacheRequest($request)); + } + + public function testCanCacheResponse() + { + $response = $this->getMockBuilder('Guzzle\Http\Message\Response') + ->setMethods(array('canCache')) + ->setConstructorArgs(array(200)) + ->getMock(); + $response->expects($this->once()) + ->method('canCache') + ->will($this->returnValue(true)); + $strategy = new DefaultCanCacheStrategy(); + $this->assertTrue($strategy->canCacheResponse($response)); + } +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultRevalidationTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultRevalidationTest.php new file mode 100644 index 0000000..0699cb2 --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DefaultRevalidationTest.php @@ -0,0 +1,248 @@ +getHttpDate('-100 hours') . "\r\nContent-Length: 4\r\n\r\nData", + "HTTP/1.1 304 NOT MODIFIED\r\nCache-Control: max-age=2000000\r\nContent-Length: 0\r\n\r\n", + ), + // Forces revalidation that overwrites what is in cache + array( + false, + "\r\n", + "HTTP/1.1 200 OK\r\nCache-Control: must-revalidate, no-cache\r\nDate: " . $this->getHttpDate('-10 hours') . "\r\nContent-Length: 4\r\n\r\nData", + "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nDatas", + "HTTP/1.1 200 OK\r\nContent-Length: 5\r\nDate: " . $this->getHttpDate('now') . "\r\n\r\nDatas" + ), + // Throws an exception during revalidation + array( + false, + "\r\n", + "HTTP/1.1 200 OK\r\nCache-Control: no-cache\r\nDate: " . $this->getHttpDate('-3 hours') . "\r\n\r\nData", + "HTTP/1.1 500 INTERNAL SERVER ERROR\r\nContent-Length: 0\r\n\r\n" + ), + // ETag mismatch + array( + false, + "\r\n", + "HTTP/1.1 200 OK\r\nCache-Control: no-cache\r\nETag: \"123\"\r\nDate: " . $this->getHttpDate('-10 hours') . "\r\n\r\nData", + "HTTP/1.1 304 NOT MODIFIED\r\nETag: \"123456\"\r\n\r\n", + ), + ); + } + + /** + * @dataProvider cacheRevalidationDataProvider + */ + public function testRevalidatesResponsesAgainstOriginServer($can, $request, $response, $validate = null, $result = null) + { + // Send some responses to the test server for cache validation + $server = $this->getServer(); + $server->flush(); + + if ($validate) { + $server->enqueue($validate); + } + + $request = RequestFactory::getInstance()->fromMessage("GET / HTTP/1.1\r\nHost: 127.0.0.1:" . $server->getPort() . "\r\n" . $request); + $response = Response::fromMessage($response); + $request->setClient(new Client()); + + $plugin = new CachePlugin(new DoctrineCacheAdapter(new ArrayCache())); + $this->assertEquals( + $can, + $plugin->canResponseSatisfyRequest($request, $response), + '-> ' . $request . "\n" . $response + ); + + if ($result) { + $result = Response::fromMessage($result); + $result->removeHeader('Date'); + $request->getResponse()->removeHeader('Date'); + $request->getResponse()->removeHeader('Connection'); + // Get rid of dates + $this->assertEquals((string) $result, (string) $request->getResponse()); + } + + if ($validate) { + $this->assertEquals(1, count($server->getReceivedRequests())); + } + } + + public function testHandles404RevalidationResponses() + { + $request = new Request('GET', 'http://foo.com'); + $request->setClient(new Client()); + $badResponse = new Response(404, array(), 'Oh no!'); + $badRequest = clone $request; + $badRequest->setResponse($badResponse, true); + $response = new Response(200, array(), 'foo'); + + // Seed the cache + $s = new DefaultCacheStorage(new DoctrineCacheAdapter(new ArrayCache())); + $s->cache($request, $response); + $this->assertNotNull($s->fetch($request)); + + $rev = $this->getMockBuilder('Guzzle\Plugin\Cache\DefaultRevalidation') + ->setConstructorArgs(array($s)) + ->setMethods(array('createRevalidationRequest')) + ->getMock(); + + $rev->expects($this->once()) + ->method('createRevalidationRequest') + ->will($this->returnValue($badRequest)); + + try { + $rev->revalidate($request, $response); + $this->fail('Should have thrown an exception'); + } catch (BadResponseException $e) { + $this->assertSame($badResponse, $e->getResponse()); + $this->assertNull($s->fetch($request)); + } + } + + public function testCanRevalidateWithPlugin() + { + $this->getServer()->flush(); + $this->getServer()->enqueue(array( + "HTTP/1.1 200 OK\r\n" . + "Date: Mon, 12 Nov 2012 03:06:37 GMT\r\n" . + "Cache-Control: private, s-maxage=0, max-age=0, must-revalidate\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Content-Length: 2\r\n\r\nhi", + "HTTP/1.0 304 Not Modified\r\n" . + "Date: Mon, 12 Nov 2012 03:06:38 GMT\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Age: 6302\r\n\r\n", + "HTTP/1.0 304 Not Modified\r\n" . + "Date: Mon, 12 Nov 2012 03:06:38 GMT\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Age: 6302\r\n\r\n", + )); + $client = new Client($this->getServer()->getUrl()); + $client->addSubscriber(new CachePlugin()); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $this->assertEquals(3, count($this->getServer()->getReceivedRequests())); + } + + public function testCanHandleRevalidationFailures() + { + $client = new Client($this->getServer()->getUrl()); + $lm = gmdate('c', time() - 60); + $mock = new MockPlugin(array( + new Response(200, array( + 'Date' => $lm, + 'Cache-Control' => 'max-age=100, must-revalidate, stale-if-error=9999', + 'Last-Modified' => $lm, + 'Content-Length' => 2 + ), 'hi'), + new CurlException('Bleh'), + new CurlException('Bleh') + )); + $client->addSubscriber(new CachePlugin()); + $client->addSubscriber($mock); + $client->get()->send(); + $response = $client->get()->send(); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('hi', $response->getBody(true)); + $this->assertEquals(3, count($mock->getReceivedRequests())); + $this->assertEquals(0, count($mock->getQueue())); + } + + public function testCanHandleStaleIfErrorWhenRevalidating() + { + $lm = gmdate('c', time() - 60); + $mock = new MockPlugin(array( + new Response(200, array( + 'Date' => $lm, + 'Cache-Control' => 'must-revalidate, max-age=0, stale-if-error=1200', + 'Last-Modified' => $lm, + 'Content-Length' => 2 + ), 'hi'), + new CurlException('Oh no!'), + new CurlException('Oh no!') + )); + $cache = new CachePlugin(); + $client = new Client('http://www.example.com'); + $client->addSubscriber($cache); + $client->addSubscriber($mock); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $response = $client->get()->send(); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertCount(0, $mock); + $this->assertEquals('HIT from GuzzleCache', (string) $response->getHeader('X-Cache-Lookup')); + $this->assertEquals('HIT_ERROR from GuzzleCache', (string) $response->getHeader('X-Cache')); + } + + /** + * @group issue-437 + */ + public function testDoesNotTouchClosureListeners() + { + $this->getServer()->flush(); + $this->getServer()->enqueue(array( + "HTTP/1.1 200 OK\r\n" . + "Date: Mon, 12 Nov 2012 03:06:37 GMT\r\n" . + "Cache-Control: private, s-maxage=0, max-age=0, must-revalidate\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Content-Length: 2\r\n\r\nhi", + "HTTP/1.0 304 Not Modified\r\n" . + "Date: Mon, 12 Nov 2012 03:06:38 GMT\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Age: 6302\r\n\r\n", + "HTTP/1.0 304 Not Modified\r\n" . + "Date: Mon, 12 Nov 2012 03:06:38 GMT\r\n" . + "Content-Type: text/html; charset=UTF-8\r\n" . + "Last-Modified: Mon, 12 Nov 2012 02:53:38 GMT\r\n" . + "Age: 6302\r\n\r\n", + )); + $client = new Client($this->getServer()->getUrl()); + $client->addSubscriber(new CachePlugin()); + $client->getEventDispatcher()->addListener('command.after_send', function(){}); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + $this->assertEquals(200, $client->get()->send()->getStatusCode()); + } + +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DenyRevalidationTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DenyRevalidationTest.php new file mode 100644 index 0000000..9af80f2 --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/DenyRevalidationTest.php @@ -0,0 +1,19 @@ +assertFalse($deny->revalidate(new Request('GET', 'http://foo.com'), new Response(200))); + } +} diff --git a/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/SkipRevalidationTest.php b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/SkipRevalidationTest.php new file mode 100644 index 0000000..4bcc04b --- /dev/null +++ b/vendor/guzzle/guzzle/tests/Guzzle/Tests/Plugin/Cache/SkipRevalidationTest.php @@ -0,0 +1,19 @@ +assertTrue($skip->revalidate(new Request('GET', 'http://foo.com'), new Response(200))); + } +} -- cgit v1.2.3-54-g00ecf