File indexing completed on 2024-12-29 05:28:07

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Test
0017  * @subpackage PHPUnit
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * Response header PHPUnit Constraint
0025  *
0026  * @uses       PHPUnit_Framework_Constraint
0027  * @category   Zend
0028  * @package    Zend_Test
0029  * @subpackage PHPUnit
0030  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0031  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0032  */
0033 class Zend_Test_PHPUnit_Constraint_ResponseHeader41 extends PHPUnit_Framework_Constraint
0034 {
0035     /**#@+
0036      * Assertion type constants
0037      */
0038     const ASSERT_RESPONSE_CODE   = 'assertResponseCode';
0039     const ASSERT_HEADER          = 'assertHeader';
0040     const ASSERT_HEADER_CONTAINS = 'assertHeaderContains';
0041     const ASSERT_HEADER_REGEX    = 'assertHeaderRegex';
0042     /**#@-*/
0043 
0044     /**
0045      * Current assertion type
0046      * @var string
0047      */
0048     protected $_assertType      = null;
0049 
0050     /**
0051      * Available assertion types
0052      * @var array
0053      */
0054     protected $_assertTypes     = array(
0055         self::ASSERT_RESPONSE_CODE,
0056         self::ASSERT_HEADER,
0057         self::ASSERT_HEADER_CONTAINS,
0058         self::ASSERT_HEADER_REGEX,
0059     );
0060 
0061     /**
0062      * @var int Response code
0063      */
0064     protected $_code              = 200;
0065     
0066     /**
0067      * @var int Actual response code
0068      */
0069     protected $_actualCode        = null;
0070 
0071     /**
0072      * @var string Header
0073      */
0074     protected $_header            = null;
0075 
0076     /**
0077      * @var string pattern against which to compare header content
0078      */
0079     protected $_match             = null;
0080 
0081     /**
0082      * Whether or not assertion is negated
0083      * @var bool
0084      */
0085     protected $_negate            = false;
0086 
0087     /**
0088      * Constructor; setup constraint state
0089      *
0090      * @return void
0091      */
0092     public function __construct()
0093     {
0094     }
0095 
0096     /**
0097      * Indicate negative match
0098      *
0099      * @param  bool $flag
0100      * @return void
0101      */
0102     public function setNegate($flag = true)
0103     {
0104         $this->_negate = $flag;
0105     }
0106 
0107     /**
0108      * Evaluate an object to see if it fits the constraints
0109      *
0110      * @param  object       of Zend_Controller_Response_Abstract to be evaluated
0111      * @param  null|string  Assertion type
0112      * @param  int|string   HTTP response code to evaluate against | header string (haystack)
0113      * @param  string       (optional) match (needle), may be required depending on assertion type
0114      * @return bool
0115      * NOTE:
0116      * Drastic changes up to PHPUnit 3.5.15 this was:
0117      *     public function evaluate($other, $assertType = null)
0118      * In PHPUnit 3.6.0 they changed the interface into this:
0119      *     public function evaluate($other, $description = '', $returnResult = FALSE)
0120      * We use the new interface for PHP-strict checking, but emulate the old one
0121      */
0122     public function evaluate($response, $assertType = '', $variable = FALSE)
0123     {
0124         if (!$response instanceof Zend_Controller_Response_Abstract) {
0125             // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0126             throw new Zend_Test_PHPUnit_Constraint_Exception('Header constraint assertions require a response object');
0127         }
0128 
0129         if (strstr($assertType, 'Not')) {
0130             $this->setNegate(true);
0131             $assertType = str_replace('Not', '', $assertType);
0132         }
0133 
0134         if (!in_array($assertType, $this->_assertTypes)) {
0135             // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0136             throw new Zend_Test_PHPUnit_Constraint_Exception(sprintf('Invalid assertion type "%s" provided to %s constraint', $assertType, __CLASS__));
0137         }
0138 
0139         $this->_assertType = $assertType;
0140 
0141         $argv     = func_get_args();
0142         $argc     = func_num_args();
0143 
0144         switch ($assertType) {
0145             case self::ASSERT_RESPONSE_CODE:
0146                 if (3 > $argc) {
0147                     // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0148                     throw new Zend_Test_PHPUnit_Constraint_Exception('No response code provided against which to match');
0149                 }
0150                 $this->_code = $code = $argv[2];
0151                 return ($this->_negate)
0152                     ? $this->_notCode($response, $code)
0153                     : $this->_code($response, $code);
0154             case self::ASSERT_HEADER:
0155                 if (3 > $argc) {
0156                     // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0157                     throw new Zend_Test_PHPUnit_Constraint_Exception('No header provided against which to match');
0158                 }
0159                 $this->_header = $header = $argv[2];
0160                 return ($this->_negate)
0161                     ? $this->_notHeader($response, $header)
0162                     : $this->_header($response, $header);
0163             case self::ASSERT_HEADER_CONTAINS:
0164                 if (4 > $argc) {
0165                     // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0166                     throw new Zend_Test_PHPUnit_Constraint_Exception('Both a header name and content to match are required for ' . $assertType);
0167                 }
0168                 $this->_header = $header = $argv[2];
0169                 $this->_match  = $match  = $argv[3];
0170                 return ($this->_negate)
0171                     ? $this->_notHeaderContains($response, $header, $match)
0172                     : $this->_headerContains($response, $header, $match);
0173             case self::ASSERT_HEADER_REGEX:
0174                 if (4 > $argc) {
0175                     // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0176                     throw new Zend_Test_PHPUnit_Constraint_Exception('Both a header name and content to match are required for ' . $assertType);
0177                 }
0178                 $this->_header = $header = $argv[2];
0179                 $this->_match  = $match  = $argv[3];
0180                 return ($this->_negate)
0181                     ? $this->_notHeaderRegex($response, $header, $match)
0182                     : $this->_headerRegex($response, $header, $match);
0183             default:
0184                 // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0185                 throw new Zend_Test_PHPUnit_Constraint_Exception('Invalid assertion type ' . $assertType);
0186         }
0187     }
0188 
0189     /**
0190      * Report Failure
0191      *
0192      * @see    PHPUnit_Framework_Constraint for implementation details
0193      * @param  mixed    CSS selector path
0194      * @param  string   Failure description
0195      * @param  object   Cannot be used, null
0196      * @return void
0197      * @throws PHPUnit_Framework_ExpectationFailedException
0198      * NOTE:
0199      * Drastic changes up to PHPUnit 3.5.15 this was:
0200      *     public function fail($other, $description, $not = false)
0201      * In PHPUnit 3.6.0 they changed the interface into this:
0202      *     protected function fail($other, $description, PHPUnit_Framework_ComparisonFailure $comparisonFailure = NULL)
0203      * We use the new interface for PHP-strict checking
0204      * NOTE 2:
0205      * Interface changed again in PHPUnit 4.1.0 because of refactoring to SebastianBergmann\Comparator
0206      */
0207     public function fail($other, $description, \SebastianBergmann\Comparator\ComparisonFailure $cannot_be_used = NULL)
0208     {
0209         // require_once 'Zend/Test/PHPUnit/Constraint/Exception.php';
0210         switch ($this->_assertType) {
0211             case self::ASSERT_RESPONSE_CODE:
0212                 $failure = 'Failed asserting response code "%s"';
0213                 if ($this->_negate) {
0214                     $failure = 'Failed asserting response code IS NOT "%s"';
0215                 }
0216                 $failure = sprintf($failure, $this->_code);
0217                 if (!$this->_negate && $this->_actualCode) {
0218                     $failure .= sprintf(PHP_EOL . 'Was "%s"', $this->_actualCode);
0219                 }
0220                 break;
0221             case self::ASSERT_HEADER:
0222                 $failure = 'Failed asserting response header "%s" found';
0223                 if ($this->_negate) {
0224                     $failure = 'Failed asserting response response header "%s" WAS NOT found';
0225                 }
0226                 $failure = sprintf($failure, $this->_header);
0227                 break;
0228             case self::ASSERT_HEADER_CONTAINS:
0229                 $failure = 'Failed asserting response header "%s" exists and contains "%s"';
0230                 if ($this->_negate) {
0231                     $failure = 'Failed asserting response header "%s" DOES NOT CONTAIN "%s"';
0232                 }
0233                 $failure = sprintf($failure, $this->_header, $this->_match);
0234                 break;
0235             case self::ASSERT_HEADER_REGEX:
0236                 $failure = 'Failed asserting response header "%s" exists and matches regex "%s"';
0237                 if ($this->_negate) {
0238                     $failure = 'Failed asserting response header "%s" DOES NOT MATCH regex "%s"';
0239                 }
0240                 $failure = sprintf($failure, $this->_header, $this->_match);
0241                 break;
0242             default:
0243                 throw new Zend_Test_PHPUnit_Constraint_Exception('Invalid assertion type ' . __FUNCTION__);
0244         }
0245 
0246         if (!empty($description)) {
0247             $failure = $description . "\n" . $failure;
0248         }
0249 
0250         throw new Zend_Test_PHPUnit_Constraint_Exception($failure);
0251     }
0252 
0253     /**
0254      * Complete implementation
0255      *
0256      * @return string
0257      */
0258     public function toString()
0259     {
0260         return '';
0261     }
0262 
0263     /**
0264      * Compare response code for positive match
0265      *
0266      * @param  Zend_Controller_Response_Abstract $response
0267      * @param  int $code
0268      * @return bool
0269      */
0270     protected function _code(Zend_Controller_Response_Abstract $response, $code)
0271     {
0272         $test = $this->_getCode($response);
0273         $this->_actualCode = $test;
0274         return ($test == $code);
0275     }
0276 
0277     /**
0278      * Compare response code for negative match
0279      *
0280      * @param  Zend_Controller_Response_Abstract $response
0281      * @param  int $code
0282      * @return bool
0283      */
0284     protected function _notCode(Zend_Controller_Response_Abstract $response, $code)
0285     {
0286         $test = $this->_getCode($response);
0287         return ($test != $code);
0288     }
0289 
0290     /**
0291      * Retrieve response code
0292      *
0293      * @param  Zend_Controller_Response_Abstract $response
0294      * @return int
0295      */
0296     protected function _getCode(Zend_Controller_Response_Abstract $response)
0297     {
0298         $test = $response->getHttpResponseCode();
0299         if (null === $test) {
0300             $test = 200;
0301         }
0302         return $test;
0303     }
0304 
0305     /**
0306      * Positive check for response header presence
0307      *
0308      * @param  Zend_Controller_Response_Abstract $response
0309      * @param  string $header
0310      * @return bool
0311      */
0312     protected function _header(Zend_Controller_Response_Abstract $response, $header)
0313     {
0314         return (null !== $this->_getHeader($response, $header));
0315     }
0316 
0317     /**
0318      * Negative check for response header presence
0319      *
0320      * @param  Zend_Controller_Response_Abstract $response
0321      * @param  string $header
0322      * @return bool
0323      */
0324     protected function _notHeader(Zend_Controller_Response_Abstract $response, $header)
0325     {
0326         return (null === $this->_getHeader($response, $header));
0327     }
0328 
0329     /**
0330      * Retrieve response header
0331      *
0332      * @param  Zend_Controller_Response_Abstract $response
0333      * @param  string $header
0334      * @return string|null
0335      */
0336     protected function _getHeader(Zend_Controller_Response_Abstract $response, $header)
0337     {
0338         $headers = $response->sendHeaders();
0339         $header  = strtolower($header);
0340         if (array_key_exists($header, $headers)) {
0341             return $headers[$header];
0342         }
0343         return null;
0344     }
0345 
0346     /**
0347      * Positive check for header contents matching pattern
0348      *
0349      * @param  Zend_Controller_Response_Abstract $response
0350      * @param  string $header
0351      * @param  string $match
0352      * @return bool
0353      */
0354     protected function _headerContains(Zend_Controller_Response_Abstract $response, $header, $match)
0355     {
0356         if (null === ($fullHeader = $this->_getHeader($response, $header))) {
0357             return false;
0358         }
0359 
0360         $contents = str_replace($header . ': ', '', $fullHeader);
0361 
0362         return (strstr($contents, $match) !== false);
0363     }
0364 
0365     /**
0366      * Negative check for header contents matching pattern
0367      *
0368      * @param  Zend_Controller_Response_Abstract $response
0369      * @param  string $header
0370      * @param  string $match
0371      * @return bool
0372      */
0373     protected function _notHeaderContains(Zend_Controller_Response_Abstract $response, $header, $match)
0374     {
0375         if (null === ($fullHeader = $this->_getHeader($response, $header))) {
0376             return true;
0377         }
0378 
0379         $contents = str_replace($header . ': ', '', $fullHeader);
0380 
0381         return (strstr($contents, $match) === false);
0382     }
0383 
0384     /**
0385      * Positive check for header contents matching regex
0386      *
0387      * @param  Zend_Controller_Response_Abstract $response
0388      * @param  string $header
0389      * @param  string $pattern
0390      * @return bool
0391      */
0392     protected function _headerRegex(Zend_Controller_Response_Abstract $response, $header, $pattern)
0393     {
0394         if (null === ($fullHeader = $this->_getHeader($response, $header))) {
0395             return false;
0396         }
0397 
0398         $contents = str_replace($header . ': ', '', $fullHeader);
0399 
0400         return preg_match($pattern, $contents);
0401     }
0402 
0403     /**
0404      * Negative check for header contents matching regex
0405      *
0406      * @param  Zend_Controller_Response_Abstract $response
0407      * @param  string $header
0408      * @param  string $pattern
0409      * @return bool
0410      */
0411     protected function _notHeaderRegex(Zend_Controller_Response_Abstract $response, $header, $pattern)
0412     {
0413         if (null === ($fullHeader = $this->_getHeader($response, $header))) {
0414             return true;
0415         }
0416 
0417         $contents = str_replace($header . ': ', '', $fullHeader);
0418 
0419         return !preg_match($pattern, $contents);
0420     }
0421 }