2
0

ResponseHeader.php 12 KB

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