HttpTest.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Controller
  17. * @subpackage UnitTests
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. // Call Zend_Controller_Response_HttpTest::main() if this source file is executed directly.
  23. if (!defined('PHPUnit_MAIN_METHOD')) {
  24. define('PHPUnit_MAIN_METHOD', 'Zend_Controller_Response_HttpTest::main');
  25. }
  26. require_once 'Zend/Controller/Response/Http.php';
  27. require_once 'Zend/Controller/Response/Exception.php';
  28. /**
  29. * @category Zend
  30. * @package Zend_Controller
  31. * @subpackage UnitTests
  32. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. * @group Zend_Controller
  35. * @group Zend_Controller_Response
  36. */
  37. class Zend_Controller_Response_HttpTest extends PHPUnit_Framework_TestCase
  38. {
  39. /**
  40. * @var Zend_Http_Response
  41. */
  42. protected $_response;
  43. /**
  44. * Runs the test methods of this class.
  45. *
  46. * @access public
  47. * @static
  48. */
  49. public static function main()
  50. {
  51. $suite = new PHPUnit_Framework_TestSuite("Zend_Controller_Response_HttpTest");
  52. $result = PHPUnit_TextUI_TestRunner::run($suite);
  53. }
  54. public function setUp()
  55. {
  56. $this->_response = new Zend_Controller_Response_Http();
  57. $this->_response->headersSentThrowsException = false;
  58. }
  59. public function tearDown()
  60. {
  61. unset($this->_response);
  62. }
  63. public function testSetHeader()
  64. {
  65. $expected = array(array('name' => 'Content-Type', 'value' => 'text/xml', 'replace' => false));
  66. $this->_response->setHeader('Content-Type', 'text/xml');
  67. $this->assertSame($expected, $this->_response->getHeaders());
  68. $expected[] =array('name' => 'Content-Type', 'value' => 'text/html', 'replace' => false);
  69. $this->_response->setHeader('Content-Type', 'text/html');
  70. $this->assertSame($expected, $this->_response->getHeaders());
  71. $expected = array(array('name' => 'Content-Type', 'value' => 'text/plain', 'replace' => true));
  72. $this->_response->setHeader('Content-Type', 'text/plain', true);
  73. $count = 0;
  74. foreach ($this->_response->getHeaders() as $header) {
  75. if ('Content-Type' == $header['name']) {
  76. if ('text/plain' == $header['value']) {
  77. ++$count;
  78. } else {
  79. $this->fail('Found header, but incorrect value');
  80. }
  81. }
  82. }
  83. $this->assertEquals(1, $count);
  84. }
  85. public function testNoDuplicateLocationHeader()
  86. {
  87. $this->_response->setRedirect('http://www.example.com/foo/bar');
  88. $this->_response->setRedirect('http://www.example.com/bar/baz');
  89. $headers = $this->_response->getHeaders();
  90. $location = 0;
  91. foreach ($headers as $header) {
  92. if ('Location' == $header['name']) {
  93. ++$location;
  94. }
  95. }
  96. $this->assertEquals(1, $location);
  97. }
  98. public function testClearHeaders()
  99. {
  100. $this->_response->setHeader('Content-Type', 'text/xml');
  101. $headers = $this->_response->getHeaders();
  102. $this->assertEquals(1, count($headers));
  103. $this->_response->clearHeaders();
  104. $headers = $this->_response->getHeaders();
  105. $this->assertEquals(0, count($headers));
  106. }
  107. /**
  108. * @group ZF-6038
  109. */
  110. public function testClearHeader()
  111. {
  112. $this->_response->setHeader('Connection', 'keep-alive');
  113. $original_headers = $this->_response->getHeaders();
  114. $this->_response->clearHeader('Connection');
  115. $updated_headers = $this->_response->getHeaders();
  116. $this->assertFalse($original_headers == $updated_headers);
  117. }
  118. public function testSetRawHeader()
  119. {
  120. $this->_response->setRawHeader('HTTP/1.0 404 Not Found');
  121. $headers = $this->_response->getRawHeaders();
  122. $this->assertContains('HTTP/1.0 404 Not Found', $headers);
  123. }
  124. public function testClearRawHeaders()
  125. {
  126. $this->_response->setRawHeader('HTTP/1.0 404 Not Found');
  127. $headers = $this->_response->getRawHeaders();
  128. $this->assertContains('HTTP/1.0 404 Not Found', $headers);
  129. $this->_response->clearRawHeaders();
  130. $headers = $this->_response->getRawHeaders();
  131. $this->assertTrue(empty($headers));
  132. }
  133. /**
  134. * @group ZF-6038
  135. */
  136. public function testClearRawHeader()
  137. {
  138. $this->_response->setRawHeader('HTTP/1.0 404 Not Found');
  139. $this->_response->setRawHeader('HTTP/1.0 401 Unauthorized');
  140. $originalHeadersRaw = $this->_response->getRawHeaders();
  141. $this->_response->clearRawHeader('HTTP/1.0 404 Not Found');
  142. $updatedHeadersRaw = $this->_response->getRawHeaders();
  143. $this->assertFalse($originalHeadersRaw == $updatedHeadersRaw);
  144. }
  145. public function testClearAllHeaders()
  146. {
  147. $this->_response->setRawHeader('HTTP/1.0 404 Not Found');
  148. $this->_response->setHeader('Content-Type', 'text/xml');
  149. $headers = $this->_response->getHeaders();
  150. $this->assertFalse(empty($headers));
  151. $headers = $this->_response->getRawHeaders();
  152. $this->assertFalse(empty($headers));
  153. $this->_response->clearAllHeaders();
  154. $headers = $this->_response->getHeaders();
  155. $this->assertTrue(empty($headers));
  156. $headers = $this->_response->getRawHeaders();
  157. $this->assertTrue(empty($headers));
  158. }
  159. public function testSetHttpResponseCode()
  160. {
  161. $this->assertEquals(200, $this->_response->getHttpResponseCode());
  162. $this->_response->setHttpResponseCode(302);
  163. $this->assertEquals(302, $this->_response->getHttpResponseCode());
  164. }
  165. public function testSetBody()
  166. {
  167. $expected = 'content for the response body';
  168. $this->_response->setBody($expected);
  169. $this->assertEquals($expected, $this->_response->getBody());
  170. $expected = 'new content';
  171. $this->_response->setBody($expected);
  172. $this->assertEquals($expected, $this->_response->getBody());
  173. }
  174. public function testAppendBody()
  175. {
  176. $expected = 'content for the response body';
  177. $this->_response->setBody($expected);
  178. $additional = '; and then there was more';
  179. $this->_response->appendBody($additional);
  180. $this->assertEquals($expected . $additional, $this->_response->getBody());
  181. }
  182. /**
  183. * SKIPPED - This test is untestable in the CLI environment. PHP ignores all
  184. * header() calls (which are used by Http_Abstract::setHeader()), thus, anything
  185. * that is expected to be found in http headers when inserted via header(), will
  186. * not be found. In addition, headers_sent() should always return false, until
  187. * real output is sent to the console.
  188. */
  189. public function test__toString()
  190. {
  191. $skipHeadersTest = headers_sent();
  192. if ($skipHeadersTest) {
  193. $this->markTestSkipped('Unable to run Zend_Controller_Response_Http::__toString() test as headers have already been sent');
  194. return;
  195. }
  196. $this->_response->setHeader('Content-Type', 'text/plain');
  197. $this->_response->setBody('Content');
  198. $this->_response->appendBody('; and more content.');
  199. $expected = 'Content; and more content.';
  200. $result = $this->_response->__toString();
  201. $this->assertSame($expected, $result);
  202. return;
  203. // header checking will not work
  204. if (!$skipHeadersTest) {
  205. $this->assertTrue(headers_sent());
  206. $headers = headers_list();
  207. $found = false;
  208. foreach ($headers as $header) {
  209. if ('Content-Type: text/plain' == $header) {
  210. $found = true;
  211. }
  212. }
  213. $this->assertTrue($found, var_export($headers, 1));
  214. }
  215. }
  216. public function testRenderExceptions()
  217. {
  218. $this->assertFalse($this->_response->renderExceptions());
  219. $this->assertTrue($this->_response->renderExceptions(true));
  220. $this->assertTrue($this->_response->renderExceptions());
  221. $this->assertFalse($this->_response->renderExceptions(false));
  222. $this->assertFalse($this->_response->renderExceptions());
  223. }
  224. public function testGetException()
  225. {
  226. $e = new Exception('Test');
  227. $this->_response->setException($e);
  228. $test = $this->_response->getException();
  229. $found = false;
  230. foreach ($test as $t) {
  231. if ($t === $e) {
  232. $found = true;
  233. }
  234. }
  235. $this->assertTrue($found);
  236. }
  237. public function testSendResponseWithExceptions()
  238. {
  239. $e = new Exception('Test exception rendering');
  240. $this->_response->setException($e);
  241. $this->_response->renderExceptions(true);
  242. ob_start();
  243. $this->_response->sendResponse();
  244. $string = ob_get_clean();
  245. $this->assertContains('Test exception rendering', $string);
  246. }
  247. public function testSetResponseCodeThrowsExceptionWithBadCode()
  248. {
  249. try {
  250. $this->_response->setHttpResponseCode(99);
  251. $this->fail('Should not accept response codes < 100');
  252. } catch (Exception $e) {
  253. }
  254. try {
  255. $this->_response->setHttpResponseCode(600);
  256. $this->fail('Should not accept response codes > 599');
  257. } catch (Exception $e) {
  258. }
  259. try {
  260. $this->_response->setHttpResponseCode('bogus');
  261. $this->fail('Should not accept non-integer response codes');
  262. } catch (Exception $e) {
  263. }
  264. }
  265. /**
  266. * Same problem as test__toString()
  267. *
  268. * Specifically for this test, headers_sent will always be false, so canSentHeaders() will
  269. * never actually throw an exception since the conditional exception code will never trigger
  270. */
  271. public function testCanSendHeadersIndicatesFileAndLine()
  272. {
  273. $this->markTestSkipped();
  274. return;
  275. $this->_response->headersSentThrowsException = true;
  276. try {
  277. $this->_response->canSendHeaders(true);
  278. $this->fail('canSendHeaders() should throw exception');
  279. } catch (Exception $e) {
  280. var_dump($e->getMessage());
  281. $this->assertRegExp('/headers already sent in .+, line \d+$/', $e->getMessage());
  282. }
  283. }
  284. public function testAppend()
  285. {
  286. $this->_response->append('some', "some content\n");
  287. $this->_response->append('more', "more content\n");
  288. $content = $this->_response->getBody(true);
  289. $this->assertTrue(is_array($content));
  290. $expected = array(
  291. 'some' => "some content\n",
  292. 'more' => "more content\n"
  293. );
  294. $this->assertEquals($expected, $content);
  295. }
  296. public function testAppendUsingExistingSegmentOverwrites()
  297. {
  298. $this->_response->append('some', "some content\n");
  299. $this->_response->append('some', "more content\n");
  300. $content = $this->_response->getBody(true);
  301. $this->assertTrue(is_array($content));
  302. $expected = array(
  303. 'some' => "more content\n"
  304. );
  305. $this->assertEquals($expected, $content);
  306. }
  307. public function testPrepend()
  308. {
  309. $this->_response->prepend('some', "some content\n");
  310. $this->_response->prepend('more', "more content\n");
  311. $content = $this->_response->getBody(true);
  312. $this->assertTrue(is_array($content));
  313. $expected = array(
  314. 'more' => "more content\n",
  315. 'some' => "some content\n"
  316. );
  317. $this->assertEquals($expected, $content);
  318. }
  319. public function testPrependUsingExistingSegmentOverwrites()
  320. {
  321. $this->_response->prepend('some', "some content\n");
  322. $this->_response->prepend('some', "more content\n");
  323. $content = $this->_response->getBody(true);
  324. $this->assertTrue(is_array($content));
  325. $expected = array(
  326. 'some' => "more content\n"
  327. );
  328. $this->assertEquals($expected, $content);
  329. }
  330. public function testInsert()
  331. {
  332. $this->_response->append('some', "some content\n");
  333. $this->_response->append('more', "more content\n");
  334. $this->_response->insert('foobar', "foobar content\n", 'some');
  335. $content = $this->_response->getBody(true);
  336. $this->assertTrue(is_array($content));
  337. $expected = array(
  338. 'some' => "some content\n",
  339. 'foobar' => "foobar content\n",
  340. 'more' => "more content\n"
  341. );
  342. $this->assertSame($expected, $content);
  343. }
  344. public function testInsertBefore()
  345. {
  346. $this->_response->append('some', "some content\n");
  347. $this->_response->append('more', "more content\n");
  348. $this->_response->insert('foobar', "foobar content\n", 'some', true);
  349. $content = $this->_response->getBody(true);
  350. $this->assertTrue(is_array($content));
  351. $expected = array(
  352. 'foobar' => "foobar content\n",
  353. 'some' => "some content\n",
  354. 'more' => "more content\n"
  355. );
  356. $this->assertSame($expected, $content);
  357. }
  358. public function testInsertWithFalseParent()
  359. {
  360. $this->_response->append('some', "some content\n");
  361. $this->_response->append('more', "more content\n");
  362. $this->_response->insert('foobar', "foobar content\n", 'baz', true);
  363. $content = $this->_response->getBody(true);
  364. $this->assertTrue(is_array($content));
  365. $expected = array(
  366. 'some' => "some content\n",
  367. 'more' => "more content\n",
  368. 'foobar' => "foobar content\n"
  369. );
  370. $this->assertSame($expected, $content);
  371. }
  372. public function testSetBodyNamedSegment()
  373. {
  374. $this->_response->append('some', "some content\n");
  375. $this->_response->setBody("more content\n", 'some');
  376. $content = $this->_response->getBody(true);
  377. $this->assertTrue(is_array($content));
  378. $expected = array(
  379. 'some' => "more content\n"
  380. );
  381. $this->assertEquals($expected, $content);
  382. }
  383. public function testSetBodyOverwritesWithDefaultSegment()
  384. {
  385. $this->_response->append('some', "some content\n");
  386. $this->_response->setBody("more content\n");
  387. $content = $this->_response->getBody(true);
  388. $this->assertTrue(is_array($content));
  389. $expected = array(
  390. 'default' => "more content\n"
  391. );
  392. $this->assertEquals($expected, $content);
  393. }
  394. public function testAppendBodyAppendsDefaultSegment()
  395. {
  396. $this->_response->setBody("some content\n");
  397. $this->_response->appendBody("more content\n");
  398. $content = $this->_response->getBody(true);
  399. $this->assertTrue(is_array($content));
  400. $expected = array(
  401. 'default' => "some content\nmore content\n"
  402. );
  403. $this->assertEquals($expected, $content);
  404. }
  405. public function testAppendBodyAppendsExistingSegment()
  406. {
  407. $this->_response->setBody("some content\n", 'some');
  408. $this->_response->appendBody("more content\n", 'some');
  409. $content = $this->_response->getBody(true);
  410. $this->assertTrue(is_array($content));
  411. $expected = array(
  412. 'some' => "some content\nmore content\n"
  413. );
  414. $this->assertEquals($expected, $content);
  415. }
  416. public function testGetBodyNamedSegment()
  417. {
  418. $this->_response->append('some', "some content\n");
  419. $this->_response->append('more', "more content\n");
  420. $this->assertEquals("more content\n", $this->_response->getBody('more'));
  421. $this->assertEquals("some content\n", $this->_response->getBody('some'));
  422. }
  423. public function testGetBodyAsArray()
  424. {
  425. $string1 = 'content for the response body';
  426. $string2 = 'more content for the response body';
  427. $string3 = 'even more content for the response body';
  428. $this->_response->appendBody($string1, 'string1');
  429. $this->_response->appendBody($string2, 'string2');
  430. $this->_response->appendBody($string3, 'string3');
  431. $expected = array(
  432. 'string1' => $string1,
  433. 'string2' => $string2,
  434. 'string3' => $string3
  435. );
  436. $this->assertEquals($expected, $this->_response->getBody(true));
  437. }
  438. public function testClearBody()
  439. {
  440. $this->_response->append('some', "some content\n");
  441. $this->assertTrue($this->_response->clearBody());
  442. $body = $this->_response->getBody(true);
  443. $this->assertTrue(is_array($body));
  444. $this->assertEquals(0, count($body));
  445. }
  446. public function testClearBodySegment()
  447. {
  448. $this->_response->append('some', "some content\n");
  449. $this->_response->append('more', "more content\n");
  450. $this->_response->append('superfluous', "superfluous content\n");
  451. $this->assertFalse($this->_response->clearBody('many'));
  452. $this->assertTrue($this->_response->clearBody('more'));
  453. $body = $this->_response->getBody(true);
  454. $this->assertTrue(is_array($body));
  455. $this->assertEquals(2, count($body));
  456. $this->assertTrue(isset($body['some']));
  457. $this->assertTrue(isset($body['superfluous']));
  458. }
  459. public function testIsRedirectInitiallyFalse()
  460. {
  461. $this->assertFalse($this->_response->isRedirect());
  462. }
  463. public function testIsRedirectWhenRedirectSet()
  464. {
  465. $this->_response->setRedirect('http://framework.zend.com/');
  466. $this->assertTrue($this->_response->isRedirect());
  467. }
  468. public function testIsRedirectWhenRawLocationHeaderSet()
  469. {
  470. $this->_response->setRawHeader('Location: http://framework.zend.com/');
  471. $this->assertTrue($this->_response->isRedirect());
  472. }
  473. public function testIsRedirectWhen3xxResponseCodeSet()
  474. {
  475. $this->_response->setHttpResponseCode(301);
  476. $this->assertTrue($this->_response->isRedirect());
  477. }
  478. public function testIsNotRedirectWithSufficientlyLarge3xxResponseCodeSet()
  479. {
  480. $this->_response->setHttpResponseCode(309);
  481. $this->assertFalse($this->_response->isRedirect());
  482. }
  483. public function testHasExceptionOfType()
  484. {
  485. $this->assertFalse($this->_response->hasExceptionOfType('Zend_Controller_Response_Exception'));
  486. $this->_response->setException(new Zend_Controller_Response_Exception());
  487. $this->assertTrue($this->_response->hasExceptionOfType('Zend_Controller_Response_Exception'));
  488. }
  489. public function testHasExceptionOfMessage()
  490. {
  491. $this->assertFalse($this->_response->hasExceptionOfMessage('FooBar'));
  492. $this->_response->setException(new Zend_Controller_Response_Exception('FooBar'));
  493. $this->assertTrue($this->_response->hasExceptionOfMessage('FooBar'));
  494. }
  495. public function testHasExceptionOfCode()
  496. {
  497. $this->assertFalse($this->_response->hasExceptionOfCode(200));
  498. $this->_response->setException(new Zend_Controller_Response_Exception('FooBar', 200));
  499. $this->assertTrue($this->_response->hasExceptionOfCode(200));
  500. }
  501. public function testGetExceptionByType()
  502. {
  503. $this->assertFalse($this->_response->getExceptionByType('Zend_Controller_Response_Exception'));
  504. $this->_response->setException(new Zend_Controller_Response_Exception());
  505. $exceptions = $this->_response->getExceptionByType('Zend_Controller_Response_Exception');
  506. $this->assertTrue(0 < count($exceptions));
  507. $this->assertTrue($exceptions[0] instanceof Zend_Controller_Response_Exception);
  508. }
  509. public function testGetExceptionByMessage()
  510. {
  511. $this->assertFalse($this->_response->getExceptionByMessage('FooBar'));
  512. $this->_response->setException(new Zend_Controller_Response_Exception('FooBar'));
  513. $exceptions = $this->_response->getExceptionByMessage('FooBar');
  514. $this->assertTrue(0 < count($exceptions));
  515. $this->assertEquals('FooBar', $exceptions[0]->getMessage());
  516. }
  517. public function testGetExceptionByCode()
  518. {
  519. $this->assertFalse($this->_response->getExceptionByCode(200));
  520. $this->_response->setException(new Zend_Controller_Response_Exception('FooBar', 200));
  521. $exceptions = $this->_response->getExceptionByCode(200);
  522. $this->assertTrue(0 < count($exceptions));
  523. $this->assertEquals(200, $exceptions[0]->getCode());
  524. }
  525. public function testHeaderNamesAreCaseInsensitive()
  526. {
  527. $this->_response->setHeader('X-Foo_Bar-Baz', 'value');
  528. $this->_response->setHeader('X-FOO_bar-bAz', 'bat');
  529. $headers = $this->_response->getHeaders();
  530. $names = array();
  531. foreach ($headers as $header) {
  532. $names[] = $header['name'];
  533. }
  534. $this->assertTrue(in_array('X-Foo-Bar-Baz', $names), var_export($headers, 1));
  535. $this->assertFalse(in_array('X-Foo_Bar-Baz', $names));
  536. $this->assertFalse(in_array('X-FOO_bar-bAz', $names));
  537. }
  538. }
  539. require_once 'Zend/Controller/Action.php';
  540. class Zend_Controller_Response_HttpTest_Action extends Zend_Controller_Action
  541. {}
  542. // Call Zend_Controller_Response_HttpTest::main() if this source file is executed directly.
  543. if (PHPUnit_MAIN_METHOD == "Zend_Controller_Response_HttpTest::main") {
  544. Zend_Controller_Response_HttpTest::main();
  545. }