├── src ├── exceptions │ ├── Exception.php │ └── InvalidArgumentException.php └── XHProfTestListener.php ├── composer.json └── LICENSE /src/exceptions/Exception.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace PHPUnit\XHProfTestListener; 12 | 13 | interface Exception 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/exceptions/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace PHPUnit\XHProfTestListener; 12 | 13 | class InvalidArgumentException extends \InvalidArgumentException implements Exception 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phpunit/test-listener-xhprof", 3 | "description": "A TestListener for PHPUnit that uses XHProf for automated profiling of the tested code", 4 | "type": "library", 5 | "keywords": [ 6 | "phpunit", 7 | "xhprof" 8 | ], 9 | "homepage": "https://github.com/phpunit/phpunit-testlistener-xhprof", 10 | "license": "BSD-3-Clause", 11 | "authors": [ 12 | { 13 | "name": "Sebastian Bergmann", 14 | "email": "sb@sebastian-bergmann.de", 15 | "role": "lead" 16 | }, 17 | { 18 | "name": "Benjamin Eberlei", 19 | "email": "kontakt@beberlei.de", 20 | "role": "lead" 21 | } 22 | ], 23 | "support": { 24 | "issues": "https://github.com/phpunit/phpunit-testlistener-xhprof/issues" 25 | }, 26 | "require": { 27 | "php": ">=5.3.3", 28 | "phpunit/phpunit": "~4.0" 29 | }, 30 | "autoload": { 31 | "classmap": [ 32 | "src/" 33 | ] 34 | }, 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "1.0.x-dev" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | PHPUnit_TestListener_XHProf 2 | 3 | Copyright (c) 2010-2015, Sebastian Bergmann . 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions 8 | are met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in 15 | the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | * Neither the name of Sebastian Bergmann nor the names of his 19 | contributors may be used to endorse or promote products derived 20 | from this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | POSSIBILITY OF SUCH DAMAGE. 34 | -------------------------------------------------------------------------------- /src/XHProfTestListener.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | 11 | namespace PHPUnit\XHProfTestListener; 12 | 13 | /** 14 | * A TestListener that integrates with XHProf. 15 | * 16 | * Here is an example XML configuration for activating this listener: 17 | * 18 | * 19 | * 20 | * 21 | * 22 | * 23 | * 24 | * /var/www/xhprof_lib/utils/xhprof_lib.php 25 | * 26 | * 27 | * /var/www/xhprof_lib/utils/xhprof_runs.php 28 | * 29 | * 30 | * http://localhost/xhprof_html/index.php 31 | * 32 | * 33 | * Doctrine2 34 | * 35 | * 36 | * XHPROF_FLAGS_CPU,XHPROF_FLAGS_MEMORY 37 | * 38 | * 39 | * call_user_func,call_user_func_array 40 | * 41 | * 42 | * 43 | * 44 | * 45 | * 46 | * 47 | * @author Benjamin Eberlei 48 | * @author Sebastian Bergmann 49 | * @copyright 2011-2015 Sebastian Bergmann 50 | * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License 51 | * @link http://www.phpunit.de/ 52 | * @since Class available since Release 1.0.0 53 | */ 54 | class XHProfTestListener implements \PHPUnit_Framework_TestListener 55 | { 56 | /** 57 | * @var array 58 | */ 59 | protected $runs = array(); 60 | 61 | /** 62 | * @var array 63 | */ 64 | protected $options = array(); 65 | 66 | /** 67 | * @var integer 68 | */ 69 | protected $suites = 0; 70 | 71 | /** 72 | * Constructor. 73 | * 74 | * @param array $options 75 | */ 76 | public function __construct(array $options = array()) 77 | { 78 | if (!isset($options['appNamespace'])) { 79 | throw new InvalidArgumentException( 80 | 'The "appNamespace" option is not set.' 81 | ); 82 | } 83 | 84 | if (!isset($options['xhprofLibFile']) || 85 | !file_exists($options['xhprofLibFile'])) { 86 | throw new InvalidArgumentException( 87 | 'The "xhprofLibFile" option is not set or the configured file does not exist' 88 | ); 89 | } 90 | 91 | if (!isset($options['xhprofRunsFile']) || 92 | !file_exists($options['xhprofRunsFile'])) { 93 | throw new InvalidArgumentException( 94 | 'The "xhprofRunsFile" option is not set or the configured file does not exist' 95 | ); 96 | } 97 | 98 | require_once $options['xhprofLibFile']; 99 | require_once $options['xhprofRunsFile']; 100 | 101 | $this->options = $options; 102 | } 103 | 104 | /** 105 | * An error occurred. 106 | * 107 | * @param \PHPUnit_Framework_Test $test 108 | * @param \Exception $e 109 | * @param float $time 110 | */ 111 | public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time) 112 | { 113 | } 114 | 115 | /** 116 | * A failure occurred. 117 | * 118 | * @param \PHPUnit_Framework_Test $test 119 | * @param \PHPUnit_Framework_AssertionFailedError $e 120 | * @param float $time 121 | */ 122 | public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time) 123 | { 124 | } 125 | 126 | /** 127 | * Incomplete test. 128 | * 129 | * @param \PHPUnit_Framework_Test $test 130 | * @param \Exception $e 131 | * @param float $time 132 | */ 133 | public function addIncompleteTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) 134 | { 135 | } 136 | 137 | /** 138 | * Skipped test. 139 | * 140 | * @param \PHPUnit_Framework_Test $test 141 | * @param \Exception $e 142 | * @param float $time 143 | */ 144 | public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) 145 | { 146 | } 147 | 148 | /** 149 | * Risky test. 150 | * 151 | * @param \PHPUnit_Framework_Test $test 152 | * @param \Exception $e 153 | * @param float $time 154 | */ 155 | public function addRiskyTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) 156 | { 157 | } 158 | 159 | /** 160 | * A test started. 161 | * 162 | * @param \PHPUnit_Framework_Test $test 163 | */ 164 | public function startTest(\PHPUnit_Framework_Test $test) 165 | { 166 | if (!isset($this->options['xhprofFlags'])) { 167 | $flags = XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY; 168 | } else { 169 | $flags = 0; 170 | 171 | foreach (explode(',', $this->options['xhprofFlags']) as $flag) { 172 | $flags += constant($flag); 173 | } 174 | } 175 | 176 | xhprof_enable($flags, array( 177 | 'ignored_functions' => explode(',', $this->options['xhprofIgnore']) 178 | )); 179 | } 180 | 181 | /** 182 | * A test ended. 183 | * 184 | * @param \PHPUnit_Framework_Test $test 185 | * @param float $time 186 | */ 187 | public function endTest(\PHPUnit_Framework_Test $test, $time) 188 | { 189 | $data = xhprof_disable(); 190 | $runs = new \XHProfRuns_Default; 191 | $run = $runs->save_run($data, $this->options['appNamespace']); 192 | $test_name = get_class($test) . '::' . $test->getName(); 193 | $this->runs[$test_name] = $this->options['xhprofWeb'] . '?run=' . $run . 194 | '&source=' . $this->options['appNamespace']; 195 | } 196 | 197 | /** 198 | * A test suite started. 199 | * 200 | * @param \PHPUnit_Framework_TestSuite $suite 201 | */ 202 | public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) 203 | { 204 | $this->suites++; 205 | } 206 | 207 | /** 208 | * A test suite ended. 209 | * 210 | * @param \PHPUnit_Framework_TestSuite $suite 211 | */ 212 | public function endTestSuite(\PHPUnit_Framework_TestSuite $suite) 213 | { 214 | $this->suites--; 215 | 216 | if ($this->suites == 0) { 217 | print "\n\nXHProf runs: " . count($this->runs) . "\n"; 218 | 219 | foreach ($this->runs as $test => $run) { 220 | print ' * ' . $test . "\n " . $run . "\n\n"; 221 | } 222 | 223 | print "\n"; 224 | } 225 | } 226 | } 227 | --------------------------------------------------------------------------------