ResponseHeader34.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  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_Test
  17. * @subpackage PHPUnit
  18. * @copyright Copyright (c) 2005-2014 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. if (version_compare(PHPUnit_Runner_Version::id(), '4.0.0', '<')) {
  23. /** @see PHPUnit_Framework_Constraint */
  24. require_once 'PHPUnit/Framework/Constraint.php';
  25. }
  26. /**
  27. * Response header PHPUnit Constraint
  28. *
  29. * @uses PHPUnit_Framework_Constraint
  30. * @category Zend
  31. * @package Zend_Test
  32. * @subpackage PHPUnit
  33. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  34. * @license http://framework.zend.com/license/new-bsd New BSD License
  35. */
  36. class Zend_Test_PHPUnit_Constraint_ResponseHeader extends PHPUnit_Framework_Constraint
  37. {
  38. /**#@+
  39. * Assertion type constants
  40. */
  41. const ASSERT_RESPONSE_CODE = 'assertResponseCode';
  42. const ASSERT_HEADER = 'assertHeader';
  43. const ASSERT_HEADER_CONTAINS = 'assertHeaderContains';
  44. const ASSERT_HEADER_REGEX = 'assertHeaderRegex';
  45. /**#@-*/
  46. /**
  47. * Current assertion type
  48. * @var string
  49. */
  50. protected $_assertType = null;
  51. /**
  52. * Available assertion types
  53. * @var array
  54. */
  55. protected $_assertTypes = array(
  56. self::ASSERT_RESPONSE_CODE,
  57. self::ASSERT_HEADER,
  58. self::ASSERT_HEADER_CONTAINS,
  59. self::ASSERT_HEADER_REGEX,
  60. );
  61. /**
  62. * @var int Response code
  63. */
  64. protected $_code = 200;
  65. /**
  66. * @var int Actual response code
  67. */
  68. protected $_actualCode = null;
  69. /**
  70. * @var string Header
  71. */
  72. protected $_header = null;
  73. /**
  74. * @var string pattern against which to compare header content
  75. */
  76. protected $_match = null;
  77. /**
  78. * Whether or not assertion is negated
  79. * @var bool
  80. */
  81. protected $_negate = false;
  82. /**
  83. * Constructor; setup constraint state
  84. *
  85. * @return void
  86. */
  87. public function __construct()
  88. {
  89. }
  90. /**
  91. * Indicate negative match
  92. *
  93. * @param bool $flag
  94. * @return void
  95. */
  96. public function setNegate($flag = true)
  97. {
  98. $this->_negate = $flag;
  99. }
  100. /**
  101. * Evaluate an object to see if it fits the constraints
  102. *
  103. * @param Zend_Controller_Response_Abstract $other String to examine
  104. * @param null|string Assertion type
  105. * @return bool
  106. */
  107. public function evaluate($other, $assertType = null)
  108. {
  109. if (!$other instanceof Zend_Controller_Response_Abstract) {
  110. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  111. throw new Zend_Test_PHPUnit_Constraint_Exception('Header constraint assertions require a response object');
  112. }
  113. if (strstr($assertType, 'Not')) {
  114. $this->setNegate(true);
  115. $assertType = str_replace('Not', '', $assertType);
  116. }
  117. if (!in_array($assertType, $this->_assertTypes)) {
  118. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  119. throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__));
  120. }
  121. $this->_assertType = $assertType;
  122. $response = $other;
  123. $argv = func_get_args();
  124. $argc = func_num_args();
  125. switch ($assertType) {
  126. case self::ASSERT_RESPONSE_CODE:
  127. if (3 > $argc) {
  128. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  129. throw new Zend_Test_PHPUnit_Constraint_Exception('No response code provided against which to match');
  130. }
  131. $this->_code = $code = $argv[2];
  132. return ($this->_negate)
  133. ? $this->_notCode($response, $code)
  134. : $this->_code($response, $code);
  135. case self::ASSERT_HEADER:
  136. if (3 > $argc) {
  137. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  138. throw new Zend_Test_PHPUnit_Constraint_Exception('No header provided against which to match');
  139. }
  140. $this->_header = $header = $argv[2];
  141. return ($this->_negate)
  142. ? $this->_notHeader($response, $header)
  143. : $this->_header($response, $header);
  144. case self::ASSERT_HEADER_CONTAINS:
  145. if (4 > $argc) {
  146. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  147. throw new Zend_Test_PHPUnit_Constraint_Exception('Both a header name and content to match are required for ' . __FUNCTION__);
  148. }
  149. $this->_header = $header = $argv[2];
  150. $this->_match = $match = $argv[3];
  151. return ($this->_negate)
  152. ? $this->_notHeaderContains($response, $header, $match)
  153. : $this->_headerContains($response, $header, $match);
  154. case self::ASSERT_HEADER_REGEX:
  155. if (4 > $argc) {
  156. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  157. throw new Zend_Test_PHPUnit_Constraint_Exception('Both a header name and content to match are required for ' . __FUNCTION__);
  158. }
  159. $this->_header = $header = $argv[2];
  160. $this->_match = $match = $argv[3];
  161. return ($this->_negate)
  162. ? $this->_notHeaderRegex($response, $header, $match)
  163. : $this->_headerRegex($response, $header, $match);
  164. default:
  165. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  166. throw new Zend_Test_PHPUnit_Constraint_Exception('Invalid assertion type ' . __FUNCTION__);
  167. }
  168. }
  169. /**
  170. * Report Failure
  171. *
  172. * @see PHPUnit_Framework_Constraint for implementation details
  173. * @param mixed $other
  174. * @param string $description Additional message to display
  175. * @param bool $not
  176. * @return void
  177. * @throws PHPUnit_Framework_ExpectationFailedException
  178. */
  179. public function fail($other, $description, $not = false)
  180. {
  181. require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
  182. switch ($this->_assertType) {
  183. case self::ASSERT_RESPONSE_CODE:
  184. $failure = 'Failed asserting response code "%s"';
  185. if ($this->_negate) {
  186. $failure = 'Failed asserting response code IS NOT "%s"';
  187. }
  188. $failure = sprintf($failure, $this->_code);
  189. if (!$this->_negate && $this->_actualCode) {
  190. $failure .= sprintf(PHP_EOL . 'Was "%s"', $this->_actualCode);
  191. }
  192. break;
  193. case self::ASSERT_HEADER:
  194. $failure = 'Failed asserting response header "%s" found';
  195. if ($this->_negate) {
  196. $failure = 'Failed asserting response response header "%s" WAS NOT found';
  197. }
  198. $failure = sprintf($failure, $this->_header);
  199. break;
  200. case self::ASSERT_HEADER_CONTAINS:
  201. $failure = 'Failed asserting response header "%s" exists and contains "%s"';
  202. if ($this->_negate) {
  203. $failure = 'Failed asserting response header "%s" DOES NOT CONTAIN "%s"';
  204. }
  205. $failure = sprintf($failure, $this->_header, $this->_match);
  206. break;
  207. case self::ASSERT_HEADER_REGEX:
  208. $failure = 'Failed asserting response header "%s" exists and matches regex "%s"';
  209. if ($this->_negate) {
  210. $failure = 'Failed asserting response header "%s" DOES NOT MATCH regex "%s"';
  211. }
  212. $failure = sprintf($failure, $this->_header, $this->_match);
  213. break;
  214. default:
  215. throw new Zend_Test_PHPUnit_Constraint_Exception('Invalid assertion type ' . __FUNCTION__);
  216. }
  217. if (!empty($description)) {
  218. $failure = $description . "\n" . $failure;
  219. }
  220. throw new Zend_Test_PHPUnit_Constraint_Exception($failure);
  221. }
  222. /**
  223. * Complete implementation
  224. *
  225. * @return string
  226. */
  227. public function toString()
  228. {
  229. return '';
  230. }
  231. /**
  232. * Compare response code for positive match
  233. *
  234. * @param Zend_Controller_Response_Abstract $response
  235. * @param int $code
  236. * @return bool
  237. */
  238. protected function _code(Zend_Controller_Response_Abstract $response, $code)
  239. {
  240. $test = $this->_getCode($response);
  241. $this->_actualCode = $test;
  242. return ($test == $code);
  243. }
  244. /**
  245. * Compare response code for negative match
  246. *
  247. * @param Zend_Controller_Response_Abstract $response
  248. * @param int $code
  249. * @return bool
  250. */
  251. protected function _notCode(Zend_Controller_Response_Abstract $response, $code)
  252. {
  253. $test = $this->_getCode($response);
  254. return ($test != $code);
  255. }
  256. /**
  257. * Retrieve response code
  258. *
  259. * @param Zend_Controller_Response_Abstract $response
  260. * @return int
  261. */
  262. protected function _getCode(Zend_Controller_Response_Abstract $response)
  263. {
  264. $test = $response->getHttpResponseCode();
  265. if (null === $test) {
  266. $test = 200;
  267. }
  268. return $test;
  269. }
  270. /**
  271. * Positive check for response header presence
  272. *
  273. * @param Zend_Controller_Response_Abstract $response
  274. * @param string $header
  275. * @return bool
  276. */
  277. protected function _header(Zend_Controller_Response_Abstract $response, $header)
  278. {
  279. return (null !== $this->_getHeader($response, $header));
  280. }
  281. /**
  282. * Negative check for response header presence
  283. *
  284. * @param Zend_Controller_Response_Abstract $response
  285. * @param string $header
  286. * @return bool
  287. */
  288. protected function _notHeader(Zend_Controller_Response_Abstract $response, $header)
  289. {
  290. return (null === $this->_getHeader($response, $header));
  291. }
  292. /**
  293. * Retrieve response header
  294. *
  295. * @param Zend_Controller_Response_Abstract $response
  296. * @param string $header
  297. * @return string|null
  298. */
  299. protected function _getHeader(Zend_Controller_Response_Abstract $response, $header)
  300. {
  301. $headers = $response->sendHeaders();
  302. $header = strtolower($header);
  303. if (array_key_exists($header, $headers)) {
  304. return $headers[$header];
  305. }
  306. return null;
  307. }
  308. /**
  309. * Positive check for header contents matching pattern
  310. *
  311. * @param Zend_Controller_Response_Abstract $response
  312. * @param string $header
  313. * @param string $match
  314. * @return bool
  315. */
  316. protected function _headerContains(Zend_Controller_Response_Abstract $response, $header, $match)
  317. {
  318. if (null === ($fullHeader = $this->_getHeader($response, $header))) {
  319. return false;
  320. }
  321. $contents = str_replace($header . ': ', '', $fullHeader);
  322. return (strstr($contents, $match) !== false);
  323. }
  324. /**
  325. * Negative check for header contents matching pattern
  326. *
  327. * @param Zend_Controller_Response_Abstract $response
  328. * @param string $header
  329. * @param string $match
  330. * @return bool
  331. */
  332. protected function _notHeaderContains(Zend_Controller_Response_Abstract $response, $header, $match)
  333. {
  334. if (null === ($fullHeader = $this->_getHeader($response, $header))) {
  335. return true;
  336. }
  337. $contents = str_replace($header . ': ', '', $fullHeader);
  338. return (strstr($contents, $match) === false);
  339. }
  340. /**
  341. * Positive check for header contents matching regex
  342. *
  343. * @param Zend_Controller_Response_Abstract $response
  344. * @param string $header
  345. * @param string $pattern
  346. * @return bool
  347. */
  348. protected function _headerRegex(Zend_Controller_Response_Abstract $response, $header, $pattern)
  349. {
  350. if (null === ($fullHeader = $this->_getHeader($response, $header))) {
  351. return false;
  352. }
  353. $contents = str_replace($header . ': ', '', $fullHeader);
  354. return preg_match($pattern, $contents);
  355. }
  356. /**
  357. * Negative check for header contents matching regex
  358. *
  359. * @param Zend_Controller_Response_Abstract $response
  360. * @param string $header
  361. * @param string $pattern
  362. * @return bool
  363. */
  364. protected function _notHeaderRegex(Zend_Controller_Response_Abstract $response, $header, $pattern)
  365. {
  366. if (null === ($fullHeader = $this->_getHeader($response, $header))) {
  367. return true;
  368. }
  369. $contents = str_replace($header . ': ', '', $fullHeader);
  370. return !preg_match($pattern, $contents);
  371. }
  372. }