SocketHttpAdapterTest.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <?php
  2. /**
  3. * This file is part of the HttpAdapter library.
  4. *
  5. * (c) Antoine Corcy <contact@sbin.dk>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Tests\HttpAdapter;
  11. use HttpAdapter\SocketHttpAdapter;
  12. /**
  13. * @author Markus Bachmann <markus.bachmann@bachi.biz>
  14. * @author Antoine Corcy <contact@sbin.dk>
  15. */
  16. class SocketHttpAdapterTest extends \PHPUnit_Framework_TestCase
  17. {
  18. protected $adapter;
  19. protected function setUp()
  20. {
  21. $this->adapter = new SocketHttpAdapter();
  22. }
  23. public function testGetName()
  24. {
  25. $this->assertEquals('socket', $this->adapter->getName());
  26. }
  27. public function testGetContent()
  28. {
  29. try {
  30. $content = $this->adapter->getContent('http://www.google.de');
  31. } catch (\Exception $e) {
  32. $this->fail('Exception catched: ' . $e->getMessage());
  33. }
  34. $this->assertNotNull($content);
  35. $this->assertContains('google', $content);
  36. }
  37. public function testGetContentHandlesQueryString()
  38. {
  39. $url = 'http://example.com/foobar?my=query&string=true';
  40. $adapter = new SocketHttpAdapterThrowsException();
  41. try {
  42. $adapter->getContent($url);
  43. $this->fail('It should throw an exception');
  44. } catch (\Exception $e) {
  45. // expected result
  46. }
  47. $this->assertEquals('/foobar?my=query&string=true', $adapter->path);
  48. $this->assertEquals('example.com', $adapter->hostname);
  49. }
  50. /**
  51. * @expectedException \RuntimeException
  52. * @expectedExceptionMessage Could not send the request.
  53. */
  54. public function testGetContentCouldNotSendRequest()
  55. {
  56. $adapter = new SocketHttpAdapterBuildNullRequest();
  57. $adapter->getContent('http://exemple.com/');
  58. }
  59. /**
  60. * @expectedException \RuntimeException
  61. * @expectedExceptionMessage Too Many Redirects.
  62. */
  63. public function testGetContentGetStatus301AndLocation()
  64. {
  65. $adapter = new SocketHttpAdapterReturnsStatus301AndLocation();
  66. var_dump($adapter->getContent('http://exemple.com/'));
  67. }
  68. /**
  69. * @expectedException \RuntimeException
  70. * @expectedExceptionMessage The server return a 404 status.
  71. */
  72. public function testGetContentGetStatusNot200()
  73. {
  74. $adapter = new SocketHttpAdapterReturnsStatusNot200();
  75. var_dump($adapter->getContent('http://exemple.com/'));
  76. }
  77. /**
  78. * @expectedException \RuntimeException
  79. * @expectedExceptionMessage Could not connect to socket. (Failed to parse address "foo")
  80. */
  81. public function testT()
  82. {
  83. $method = new \ReflectionMethod(
  84. $this->adapter, 'createSocket'
  85. );
  86. $method->setAccessible(true);
  87. var_dump($method->invoke($this->adapter, 'foo', 0, 0));
  88. }
  89. /**
  90. * NOTE ON REFLECTION:
  91. * Not a great idea but the alternative would be to create a new class for
  92. * HTTP parsing or set the method public. I don't like either of these much.
  93. */
  94. public function testBuildRequest()
  95. {
  96. $method = new \ReflectionMethod(
  97. $this->adapter, 'buildHttpRequest'
  98. );
  99. $method->setAccessible(true);
  100. $ex_host = 'www.google.com';
  101. $ex_path = '/';
  102. $ex_body = array();
  103. $ex_body[] = "GET $ex_path HTTP/1.1";
  104. $ex_body[] = "Host: $ex_host";
  105. $ex_body[] = "Connection: Close";
  106. $ex_body[] = "User-Agent: HttpAdapter PHP-Library";
  107. $ex_body[] = "\r\n";
  108. $this->assertEquals(
  109. implode("\r\n", $ex_body), $method->invoke($this->adapter, $ex_path, $ex_host)
  110. );
  111. }
  112. public function testParseHtmlResponse()
  113. {
  114. $method = new \ReflectionMethod(
  115. $this->adapter, 'getParsedHttpResponse'
  116. );
  117. $method->setAccessible(true);
  118. // create a file in memory
  119. $tempFileHandle = fopen('php://memory', 'r+');
  120. fwrite($tempFileHandle, 'HTTP/1.1 200 OK
  121. Date: Mon, 01 Oct 2012 20:58:51 GMT
  122. Expires: -1
  123. Cache-Control: private, max-age=0
  124. Content-Type: text/html; charset=ISO-8859-1
  125. X-Frame-Options: SAMEORIGIN
  126. Connection: close
  127. <!doctype html>
  128. <html itemscope="itemscope" itemtype="http://schema.org/WebPage">
  129. <head>
  130. <title>Foo</title>
  131. </head>
  132. <body>
  133. <p>Bar</p>
  134. </body>
  135. </html>
  136. ');
  137. // get a parsed response
  138. rewind($tempFileHandle);
  139. $httpResponse = $method->invoke($this->adapter, $tempFileHandle);
  140. // does it look like what we went it?
  141. $this->assertEquals('200', $httpResponse['headers']['status']);
  142. $this->assertEquals('Mon, 01 Oct 2012 20:58:51 GMT', $httpResponse['headers']['date']);
  143. $this->assertEquals('-1', $httpResponse['headers']['expires']);
  144. $this->assertEquals('private, max-age=0', $httpResponse['headers']['cache-control']);
  145. $this->assertEquals('text/html; charset=ISO-8859-1', $httpResponse['headers']['content-type']);
  146. $this->assertEquals('SAMEORIGIN', $httpResponse['headers']['x-frame-options']);
  147. $this->assertEquals('close', $httpResponse['headers']['connection']);
  148. $this->assertContains('<p>Bar</p>', $httpResponse['content']);
  149. }
  150. /**
  151. * @group isolate
  152. */
  153. public function testParseJson()
  154. {
  155. $method = new \ReflectionMethod(
  156. $this->adapter, 'getParsedHttpResponse'
  157. );
  158. $method->setAccessible(true);
  159. // create a file in memory
  160. $tempFileHandle = fopen('php://memory', 'r+');
  161. fwrite($tempFileHandle, 'HTTP/1.1 200 OK
  162. Foo: bar
  163. Baz: cat
  164. {"foo":"bar","baz":"cat"}
  165. ');
  166. // get a parsed response
  167. rewind($tempFileHandle);
  168. $httpResponse = $method->invoke($this->adapter, $tempFileHandle);
  169. // don't bother testing all this stuff again
  170. $this->assertEquals('200', $httpResponse['headers']['status']);
  171. $this->assertEquals('bar', $httpResponse['headers']['foo']);
  172. $this->assertEquals('cat', $httpResponse['headers']['baz']);
  173. $this->assertContains('{"foo":"bar","baz":"cat"}', $httpResponse['content']);
  174. }
  175. }
  176. class SocketHttpAdapterThrowsException extends SocketHttpAdapter
  177. {
  178. public $path;
  179. public $hostname;
  180. public function buildHttpRequest($path, $hostname)
  181. {
  182. $this->path = $path;
  183. $this->hostname = $hostname;
  184. throw new \Exception();
  185. }
  186. }
  187. class SocketHttpAdapterBuildNullRequest extends SocketHttpAdapter
  188. {
  189. public function buildHttpRequest($path, $hostname)
  190. {
  191. return null;
  192. }
  193. }
  194. class SocketHttpAdapterReturnsStatus301AndLocation extends SocketHttpAdapter
  195. {
  196. protected function getParsedHttpResponse($socketHandle)
  197. {
  198. return array(
  199. 'headers' => array(
  200. 'status' => 301,
  201. 'location' => 'http://exemple.com/',
  202. )
  203. );
  204. }
  205. }
  206. class SocketHttpAdapterReturnsStatusNot200 extends SocketHttpAdapter
  207. {
  208. protected function getParsedHttpResponse($socketHandle)
  209. {
  210. return array(
  211. 'headers' => array(
  212. 'status' => 404,
  213. )
  214. );
  215. }
  216. }