/library/Zend/Test/PHPUnit/Constraint/ResponseHeader.php

https://bitbucket.org/DragonBe/zfform · PHP · 409 lines · 205 code · 39 blank · 165 comment · 24 complexity · cc4f00aaee305f2cbf9773138bfae95e MD5 · raw file

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