PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/cpanel/common/lib/vendor/PHPUnit/Util/Skeleton/Class.php

https://github.com/aflexi/thirdparty
PHP | 317 lines | 183 code | 41 blank | 93 comment | 45 complexity | 4550dd49980ff491959bf505382cfb87 MD5 | raw file
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2002-2010, Sebastian Bergmann <sebastian@phpunit.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @package PHPUnit
  38. * @subpackage Util_Skeleton
  39. * @author Sebastian Bergmann <sebastian@phpunit.de>
  40. * @copyright 2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
  41. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42. * @link http://www.phpunit.de/
  43. * @since File available since Release 3.3.0
  44. */
  45. /**
  46. * Generator for class skeletons from test classes.
  47. *
  48. * @package PHPUnit
  49. * @subpackage Util_Skeleton
  50. * @author Sebastian Bergmann <sebastian@phpunit.de>
  51. * @copyright 2002-2010 Sebastian Bergmann <sebastian@phpunit.de>
  52. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  53. * @version Release: @package_version@
  54. * @link http://www.phpunit.de/
  55. * @since Class available since Release 3.3.0
  56. */
  57. class PHPUnit_Util_Skeleton_Class extends PHPUnit_Util_Skeleton
  58. {
  59. /**
  60. * Constructor.
  61. *
  62. * @param string $inClassName
  63. * @param string $inSourceFile
  64. * @param string $outClassName
  65. * @param string $outSourceFile
  66. * @throws RuntimeException
  67. */
  68. public function __construct($inClassName, $inSourceFile = '', $outClassName = '', $outSourceFile = '')
  69. {
  70. if (empty($inSourceFile)) {
  71. $inSourceFile = $inClassName . '.php';
  72. }
  73. if (!is_file($inSourceFile)) {
  74. throw new PHPUnit_Framework_Exception(
  75. sprintf(
  76. '"%s" could not be opened.',
  77. $inSourceFile
  78. )
  79. );
  80. }
  81. if (empty($outClassName)) {
  82. $outClassName = substr($inClassName, 0, strlen($inClassName) - 4);
  83. }
  84. if (empty($outSourceFile)) {
  85. $outSourceFile = dirname($inSourceFile) . DIRECTORY_SEPARATOR .
  86. $outClassName . '.php';
  87. }
  88. parent::__construct(
  89. $inClassName, $inSourceFile, $outClassName, $outSourceFile
  90. );
  91. }
  92. /**
  93. * Generates the class' source.
  94. *
  95. * @return mixed
  96. */
  97. public function generate()
  98. {
  99. $methods = '';
  100. foreach ($this->findTestedMethods() as $method) {
  101. $methodTemplate = new Text_Template(
  102. sprintf(
  103. '%s%sTemplate%sMethod.tpl',
  104. dirname(__FILE__),
  105. DIRECTORY_SEPARATOR,
  106. DIRECTORY_SEPARATOR
  107. )
  108. );
  109. $methodTemplate->setVar(
  110. array(
  111. 'methodName' => $method,
  112. )
  113. );
  114. $methods .= $methodTemplate->render();
  115. }
  116. $classTemplate = new Text_Template(
  117. sprintf(
  118. '%s%sTemplate%sClass.tpl',
  119. dirname(__FILE__),
  120. DIRECTORY_SEPARATOR,
  121. DIRECTORY_SEPARATOR
  122. )
  123. );
  124. $classTemplate->setVar(
  125. array(
  126. 'className' => $this->outClassName['fullyQualifiedClassName'],
  127. 'methods' => $methods,
  128. 'date' => date('Y-m-d'),
  129. 'time' => date('H:i:s')
  130. )
  131. );
  132. return $classTemplate->render();
  133. }
  134. /**
  135. * Returns the methods of the class under test
  136. * that are called from the test methods.
  137. *
  138. * @return array
  139. */
  140. protected function findTestedMethods()
  141. {
  142. $setUpVariables = array();
  143. $testedMethods = array();
  144. $classes = PHPUnit_Util_File::getClassesInFile(
  145. $this->inSourceFile
  146. );
  147. $testMethods = $classes[$this->inClassName['fullyQualifiedClassName']]['methods'];
  148. unset($classes);
  149. foreach ($testMethods as $name => $testMethod) {
  150. if (strtolower($name) == 'setup') {
  151. $setUpVariables = $this->findVariablesThatReferenceClass(
  152. $testMethod['tokens']
  153. );
  154. break;
  155. }
  156. }
  157. foreach ($testMethods as $name => $testMethod) {
  158. $argVariables = array();
  159. if (strtolower($name) == 'setup') {
  160. continue;
  161. }
  162. $start = strpos($testMethod['signature'], '(') + 1;
  163. $end = strlen($testMethod['signature']) - $start - 1;
  164. $args = substr($testMethod['signature'], $start, $end);
  165. foreach (explode(',', $args) as $arg) {
  166. list($type, $var) = explode(' ', $arg);
  167. if ($type == $this->outClassName['fullyQualifiedClassName']) {
  168. $argVariables[] = $var;
  169. }
  170. }
  171. $variables = array_unique(
  172. array_merge(
  173. $setUpVariables,
  174. $argVariables,
  175. $this->findVariablesThatReferenceClass($testMethod['tokens'])
  176. )
  177. );
  178. foreach ($testMethod['tokens'] as $i => $token) {
  179. // Class::method()
  180. if (is_array($token) && $token[0] == T_DOUBLE_COLON &&
  181. is_array($testMethod['tokens'][$i-1]) &&
  182. $testMethod['tokens'][$i-1][0] == T_STRING &&
  183. $testMethod['tokens'][$i-1][1] == $this->outClassName['fullyQualifiedClassName'] &&
  184. is_array($testMethod['tokens'][$i+1]) &&
  185. $testMethod['tokens'][$i+1][0] == T_STRING &&
  186. $testMethod['tokens'][$i+2] == '(') {
  187. $testedMethods[] = $testMethod['tokens'][$i+1][1];
  188. }
  189. // $this->object->method()
  190. else if (is_array($token) && $token[0] == T_OBJECT_OPERATOR &&
  191. in_array($this->findVariableName($testMethod['tokens'], $i), $variables) &&
  192. is_array($testMethod['tokens'][$i+2]) &&
  193. $testMethod['tokens'][$i+2][0] == T_OBJECT_OPERATOR &&
  194. is_array($testMethod['tokens'][$i+3]) &&
  195. $testMethod['tokens'][$i+3][0] == T_STRING &&
  196. $testMethod['tokens'][$i+4] == '(') {
  197. $testedMethods[] = $testMethod['tokens'][$i+3][1];
  198. }
  199. // $object->method()
  200. else if (is_array($token) && $token[0] == T_OBJECT_OPERATOR &&
  201. in_array($this->findVariableName($testMethod['tokens'], $i), $variables) &&
  202. is_array($testMethod['tokens'][$i+1]) &&
  203. $testMethod['tokens'][$i+1][0] == T_STRING &&
  204. $testMethod['tokens'][$i+2] == '(') {
  205. $testedMethods[] = $testMethod['tokens'][$i+1][1];
  206. }
  207. }
  208. }
  209. $testedMethods = array_unique($testedMethods);
  210. sort($testedMethods);
  211. return $testedMethods;
  212. }
  213. /**
  214. * Returns the variables used in test methods
  215. * that reference the class under test.
  216. *
  217. * @param array $tokens
  218. * @return array
  219. */
  220. protected function findVariablesThatReferenceClass(array $tokens)
  221. {
  222. $inNew = FALSE;
  223. $variables = array();
  224. foreach ($tokens as $i => $token) {
  225. if (is_string($token)) {
  226. if (trim($token) == ';') {
  227. $inNew = FALSE;
  228. }
  229. continue;
  230. }
  231. list ($token, $value) = $token;
  232. switch ($token) {
  233. case T_NEW: {
  234. $inNew = TRUE;
  235. }
  236. break;
  237. case T_STRING: {
  238. if ($inNew) {
  239. if ($value == $this->outClassName['fullyQualifiedClassName']) {
  240. $variables[] = $this->findVariableName(
  241. $tokens, $i
  242. );
  243. }
  244. }
  245. $inNew = FALSE;
  246. }
  247. break;
  248. }
  249. }
  250. return $variables;
  251. }
  252. /**
  253. * Finds the variable name of the object for the method call
  254. * that is currently being processed.
  255. *
  256. * @param array $tokens
  257. * @param integer $start
  258. * @return mixed
  259. */
  260. protected function findVariableName(array $tokens, $start)
  261. {
  262. for ($i = $start - 1; $i >= 0; $i--) {
  263. if (is_array($tokens[$i]) && $tokens[$i][0] == T_VARIABLE) {
  264. $variable = $tokens[$i][1];
  265. if (is_array($tokens[$i+1]) &&
  266. $tokens[$i+1][0] == T_OBJECT_OPERATOR &&
  267. $tokens[$i+2] != '(' &&
  268. $tokens[$i+3] != '(') {
  269. $variable .= '->' . $tokens[$i+2][1];
  270. }
  271. return $variable;
  272. }
  273. }
  274. return FALSE;
  275. }
  276. }