PageRenderTime 40ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/test/php/net/xp_framework/unittest/peer/http/HttpResponseTest.class.php

https://github.com/treuter/xp-framework
PHP | 373 lines | 181 code | 31 blank | 161 comment | 1 complexity | cf66f7a1db25330dea4e48735f9ed970 MD5 | raw file
  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses(
  7. 'unittest.TestCase',
  8. 'peer.http.HttpResponse',
  9. 'io.streams.MemoryInputStream'
  10. );
  11. /**
  12. * TestCase for HTTP responses
  13. *
  14. * @see xp://peer.http.HttpResponse
  15. * @purpose Unittest
  16. */
  17. class HttpResponseTest extends TestCase {
  18. /**
  19. * Get a response with the specified headers and body
  20. *
  21. * @param string[] headers
  22. * @param string body default ''
  23. * @return peer.http.HttpResponse
  24. */
  25. protected function newResponse(array $headers, $body= '') {
  26. return new HttpResponse(new MemoryInputStream(implode("\r\n", $headers)."\r\n\r\n".$body));
  27. }
  28. /**
  29. * Test non-empty response
  30. *
  31. */
  32. #[@test]
  33. public function errorDocument() {
  34. $body= '<h1>File not found</h1>';
  35. $response= $this->newResponse(array('HTTP/1.0 404 OK', 'Content-Length: 23', 'Content-Type: text/html'), $body);
  36. $this->assertEquals(404, $response->statusCode());
  37. $this->assertEquals(array('23'), $response->header('Content-Length'));
  38. $this->assertEquals(array('text/html'), $response->header('Content-Type'));
  39. $this->assertEquals($body, $response->readData());
  40. }
  41. /**
  42. * Test empty response
  43. *
  44. */
  45. #[@test]
  46. public function emptyDocument() {
  47. $response= $this->newResponse(array('HTTP/1.0 204 No content'));
  48. $this->assertEquals(204, $response->statusCode());
  49. }
  50. /**
  51. * Test chunked transfer-encoding
  52. *
  53. */
  54. #[@test]
  55. public function chunkedDocument() {
  56. $body= '<h1>File not found</h1>';
  57. $response= $this->newResponse(array('HTTP/1.0 404 OK', 'Transfer-Encoding: chunked'), "17\r\n".$body."\r\n0\r\n");
  58. $this->assertEquals(404, $response->statusCode());
  59. $this->assertEquals(array('chunked'), $response->header('Transfer-Encoding'));
  60. $this->assertEquals($body, $response->readData());
  61. }
  62. /**
  63. * Test chunked transfer-encoding
  64. *
  65. */
  66. #[@test]
  67. public function multipleChunkedDocument() {
  68. $response= $this->newResponse(
  69. array('HTTP/1.0 404 OK', 'Transfer-Encoding: chunked'),
  70. "17\r\n<h1>File not found</h1>\r\n13\r\nDid my best, sorry.\r\n0\r\n"
  71. );
  72. $this->assertEquals(404, $response->statusCode());
  73. $this->assertEquals(array('chunked'), $response->header('Transfer-Encoding'));
  74. // Read data & test body contents
  75. $buffer= ''; while ($l= $response->readData()) { $buffer.= $l; }
  76. $this->assertEquals('<h1>File not found</h1>Did my best, sorry.', $buffer);
  77. }
  78. /**
  79. * Test HTTP 100 Continue
  80. *
  81. */
  82. #[@test]
  83. public function httpContinue() {
  84. $response= $this->newResponse(array('HTTP/1.0 100 Continue', '', 'HTTP/1.0 200 OK', 'Content-Length: 4'), 'Test');
  85. $this->assertEquals(200, $response->statusCode());
  86. $this->assertEquals(array('4'), $response->header('Content-Length'));
  87. $this->assertEquals('Test', $response->readData());
  88. }
  89. /**
  90. * Test status code with message string
  91. *
  92. */
  93. #[@test]
  94. public function statusCodeWithMessage() {
  95. $response= $this->newResponse(array('HTTP/1.1 404 Not Found'), 'File Not Found');
  96. $this->assertEquals(404, $response->statusCode());
  97. $this->assertEquals('Not Found', $response->message());
  98. $this->assertEquals('File Not Found', $response->readData());
  99. }
  100. /**
  101. * Test status code without message string
  102. *
  103. */
  104. #[@test]
  105. public function statusCodeWithoutMessage() {
  106. $response= $this->newResponse(array('HTTP/1.1 404'), 'File Not Found');
  107. $this->assertEquals(404, $response->statusCode());
  108. $this->assertEquals('', $response->message());
  109. $this->assertEquals('File Not Found', $response->readData());
  110. }
  111. /**
  112. * Test what happens when the server responds with an incorrect protocol
  113. *
  114. */
  115. #[@test, @expect('lang.FormatException')]
  116. public function incorrectProtocol() {
  117. $this->newResponse(array('* OK IMAP server ready H mimap20 68140'));
  118. }
  119. /**
  120. * Test getHeader()
  121. *
  122. * @deprecated HttpResponse::getHeader() is deprecated
  123. */
  124. #[@test]
  125. public function getHeader() {
  126. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  127. $this->assertEquals('6100', $response->getHeader('X-Binford'));
  128. $this->assertEquals('text/html', $response->getHeader('Content-Type'));
  129. }
  130. /**
  131. * Test getHeader()
  132. *
  133. * @deprecated HttpResponse::getHeader() is deprecated
  134. */
  135. #[@test]
  136. public function getHeaderIsCaseInsensitive() {
  137. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  138. $this->assertEquals('6100', $response->getHeader('x-binford'), 'all-lowercase');
  139. $this->assertEquals('text/html', $response->getHeader('CONTENT-TYPE'), 'all-uppercase');
  140. }
  141. /**
  142. * Test getHeader()
  143. *
  144. * @deprecated HttpResponse::getHeader() is deprecated
  145. */
  146. #[@test]
  147. public function nonExistantGetHeader() {
  148. $response= $this->newResponse(array('HTTP/1.0 204 No Content'));
  149. $this->assertNull($response->getHeader('Via'));
  150. }
  151. /**
  152. * Test getHeader()
  153. *
  154. * @deprecated HttpResponse::getHeader() is deprecated
  155. */
  156. #[@test]
  157. public function multipleCookiesInGetHeader() {
  158. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'Set-Cookie: color=green; path=/', 'Set-Cookie: make=example; path=/'));
  159. $this->assertEquals(
  160. 'make=example; path=/',
  161. $response->getHeader('Set-Cookie')
  162. );
  163. }
  164. /**
  165. * Test getHeaders()
  166. *
  167. * @deprecated HttpResponse::getHeaders() is deprecated
  168. */
  169. #[@test]
  170. public function getHeaders() {
  171. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  172. $this->assertEquals(
  173. array('X-Binford' => '6100', 'Content-Type' => 'text/html'),
  174. $response->getHeaders()
  175. );
  176. }
  177. /**
  178. * Test getHeaders()
  179. *
  180. * @deprecated HttpResponse::getHeaders() is deprecated
  181. */
  182. #[@test]
  183. public function emptyGetHeaders() {
  184. $response= $this->newResponse(array('HTTP/1.0 204 No Content'));
  185. $this->assertEquals(
  186. array(),
  187. $response->getHeaders()
  188. );
  189. }
  190. /**
  191. * Test getHeaders()
  192. *
  193. * @deprecated HttpResponse::getHeaders() is deprecated
  194. */
  195. #[@test]
  196. public function multipleCookiesInGetHeaders() {
  197. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'Set-Cookie: color=green; path=/', 'Set-Cookie: make=example; path=/'));
  198. $this->assertEquals(
  199. array('Set-Cookie' => 'make=example; path=/'),
  200. $response->getHeaders('Set-Cookie')
  201. );
  202. }
  203. /**
  204. * Test header()
  205. *
  206. */
  207. #[@test]
  208. public function header() {
  209. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  210. $this->assertEquals(array('6100'), $response->header('X-Binford'));
  211. $this->assertEquals(array('text/html'), $response->header('Content-Type'));
  212. }
  213. /**
  214. * Test header()
  215. *
  216. */
  217. #[@test]
  218. public function headerIsCaseInsensitive() {
  219. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  220. $this->assertEquals(array('6100'), $response->header('x-binford'), 'all-lowercase');
  221. $this->assertEquals(array('text/html'), $response->header('CONTENT-TYPE'), 'all-uppercase');
  222. }
  223. /**
  224. * Test header()
  225. *
  226. */
  227. #[@test]
  228. public function nonExistantHeader() {
  229. $response= $this->newResponse(array('HTTP/1.0 204 No Content'));
  230. $this->assertNull($response->header('Via'));
  231. }
  232. /**
  233. * Test header()
  234. *
  235. */
  236. #[@test]
  237. public function multipleCookiesInHeader() {
  238. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'Set-Cookie: color=green; path=/', 'Set-Cookie: make=example; path=/'));
  239. $this->assertEquals(
  240. array('color=green; path=/', 'make=example; path=/'),
  241. $response->header('Set-Cookie')
  242. );
  243. }
  244. /**
  245. * Test headers()
  246. *
  247. */
  248. #[@test]
  249. public function multipleCookiesInHeaders() {
  250. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'Set-Cookie: color=green; path=/', 'Set-Cookie: make=example; path=/'));
  251. $this->assertEquals(
  252. array('Set-Cookie' => array('color=green; path=/', 'make=example; path=/')),
  253. $response->headers()
  254. );
  255. }
  256. /**
  257. * Test headers()
  258. *
  259. */
  260. #[@test]
  261. public function headers() {
  262. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Binford: 6100', 'Content-Type: text/html'));
  263. $this->assertEquals(
  264. array('X-Binford' => array('6100'), 'Content-Type' => array('text/html')),
  265. $response->headers()
  266. );
  267. }
  268. /**
  269. * Test headers()
  270. *
  271. */
  272. #[@test]
  273. public function emptyHeaders() {
  274. $response= $this->newResponse(array('HTTP/1.0 204 No Content'));
  275. $this->assertEquals(
  276. array(),
  277. $response->headers()
  278. );
  279. }
  280. /**
  281. * Test headers() with inconsistent casing in response
  282. *
  283. */
  284. #[@test]
  285. public function multipleHeadersWithDifferentCasing() {
  286. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Example: K', 'x-example: V'));
  287. $this->assertEquals(
  288. array('X-Example' => array('K', 'V')),
  289. $response->headers()
  290. );
  291. }
  292. /**
  293. * Test header() with inconsistent casing in response
  294. *
  295. */
  296. #[@test]
  297. public function multipleHeaderWithDifferentCasing() {
  298. $response= $this->newResponse(array('HTTP/1.0 200 OK', 'X-Example: K', 'x-example: V'));
  299. $this->assertEquals(
  300. array('K', 'V'),
  301. $response->header('X-Example')
  302. );
  303. }
  304. /**
  305. * Test getHeaderString()
  306. *
  307. */
  308. #[@test]
  309. public function headerString() {
  310. $response= $this->newResponse(array('HTTP/1.1 200 OK', 'Content-Type: application/json', 'Content-Length: 0'));
  311. $this->assertEquals(
  312. "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 0\r\n\r\n",
  313. $response->getHeaderString()
  314. );
  315. }
  316. /**
  317. * Test getHeaderString()
  318. *
  319. */
  320. #[@test]
  321. public function headerStringDoesNotIncludeContent() {
  322. $response= $this->newResponse(array('HTTP/1.1 200 OK', 'Content-Type: application/json', 'Content-Length: 21'), '{ "hello" : "world" }');
  323. $this->assertEquals(
  324. "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 21\r\n\r\n",
  325. $response->getHeaderString()
  326. );
  327. }
  328. /**
  329. * GitHub sometimes sends empty cache-control headers. This should not corrupt
  330. * reading!
  331. *
  332. */
  333. #[@test]
  334. public function headerWithoutValue() {
  335. $body= '.';
  336. $response= $this->newResponse(array('HTTP/1.1 401 Unauthorized', 'Cache-Control: '), $body);
  337. $this->assertEquals(401, $response->statusCode());
  338. $this->assertEquals(array(NULL), $response->header('Cache-Control'));
  339. $this->assertEquals($body, $response->readData());
  340. }
  341. }
  342. ?>