PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/tests/PHPUnit/Util/Test.php

https://github.com/item/sugarcrm_dev
PHP | 371 lines | 244 code | 29 blank | 98 comment | 24 complexity | ae5ec64399e3000efb6624df7017dd3d MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.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. * @category Testing
  38. * @package PHPUnit
  39. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  40. * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.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.0.0
  44. */
  45. require_once 'PHPUnit/Util/Filter.php';
  46. PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
  47. /**
  48. * Test helpers.
  49. *
  50. * @category Testing
  51. * @package PHPUnit
  52. * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
  53. * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
  54. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  55. * @version Release: 3.3.17
  56. * @link http://www.phpunit.de/
  57. * @since Class available since Release 3.0.0
  58. */
  59. class PHPUnit_Util_Test
  60. {
  61. const REGEX_COVERS = '/@covers[\s]+([\!<>\:\.\w]+)([\s]+<extended>)?/';
  62. const REGEX_DATA_PROVIDER = '/@dataProvider\s+([a-zA-Z0-9._:-\\\]+)/';
  63. const REGEX_EXPECTED_EXCEPTION = '(@expectedException\s+([:.\w\\\]+)(?:[\t ]+(\S*))?(?:[\t ]+(\S*))?\s*$)m';
  64. const REGEX_GROUP = '/@group\s+([a-zA-Z0-9._-]+)/';
  65. /**
  66. * @param PHPUnit_Framework_Test $test
  67. * @param boolean $asString
  68. * @return mixed
  69. */
  70. public static function describe(PHPUnit_Framework_Test $test, $asString = TRUE)
  71. {
  72. if ($asString) {
  73. if ($test instanceof PHPUnit_Framework_SelfDescribing) {
  74. return $test->toString();
  75. } else {
  76. return get_class($test);
  77. }
  78. } else {
  79. if ($test instanceof PHPUnit_Framework_TestCase) {
  80. return array(
  81. get_class($test), $test->getName()
  82. );
  83. }
  84. else if ($test instanceof PHPUnit_Framework_SelfDescribing) {
  85. return array('', $test->toString());
  86. }
  87. else {
  88. return array('', get_class($test));
  89. }
  90. }
  91. }
  92. /**
  93. * @param PHPUnit_Framework_Test $test
  94. * @param PHPUnit_Framework_TestResult $result
  95. * @return mixed
  96. */
  97. public static function lookupResult(PHPUnit_Framework_Test $test, PHPUnit_Framework_TestResult $result)
  98. {
  99. $testName = self::describe($test);
  100. foreach ($result->errors() as $error) {
  101. if ($testName == self::describe($error->failedTest())) {
  102. return $error;
  103. }
  104. }
  105. foreach ($result->failures() as $failure) {
  106. if ($testName == self::describe($failure->failedTest())) {
  107. return $failure;
  108. }
  109. }
  110. foreach ($result->notImplemented() as $notImplemented) {
  111. if ($testName == self::describe($notImplemented->failedTest())) {
  112. return $notImplemented;
  113. }
  114. }
  115. foreach ($result->skipped() as $skipped) {
  116. if ($testName == self::describe($skipped->failedTest())) {
  117. return $skipped;
  118. }
  119. }
  120. return PHPUnit_Runner_BaseTestRunner::STATUS_PASSED;
  121. }
  122. /**
  123. * Returns the files and lines a test method wants to cover.
  124. *
  125. * @param string $className
  126. * @param string $methodName
  127. * @return array
  128. * @since Method available since Release 3.2.0
  129. */
  130. public static function getLinesToBeCovered($className, $methodName)
  131. {
  132. $result = array();
  133. $codeToCoverList = array();
  134. if (($pos = strpos($methodName, ' ')) !== FALSE) {
  135. $methodName = substr($methodName, 0, $pos);
  136. }
  137. try {
  138. $class = new ReflectionClass($className);
  139. $method = new ReflectionMethod($className, $methodName);
  140. $docComment = $class->getDocComment() . $method->getDocComment();
  141. if (preg_match_all(self::REGEX_COVERS, $docComment, $matches)) {
  142. foreach ($matches[1] as $i => $method) {
  143. $codeToCoverList = array_merge(
  144. $codeToCoverList,
  145. self::resolveCoversToReflectionObjects($method, !empty($matches[2][$i]))
  146. );
  147. }
  148. foreach ($codeToCoverList as $codeToCover) {
  149. $fileName = $codeToCover->getFileName();
  150. $startLine = $codeToCover->getStartLine();
  151. $endLine = $codeToCover->getEndLine();
  152. if (!isset($result[$fileName])) {
  153. $result[$fileName] = array();
  154. }
  155. $result[$fileName] = array_unique(
  156. array_merge($result[$fileName], range($startLine, $endLine))
  157. );
  158. }
  159. }
  160. }
  161. catch (ReflectionException $e) {
  162. }
  163. return $result;
  164. }
  165. /**
  166. * Returns the expected exception for a test.
  167. *
  168. * @param string $docComment
  169. * @return array
  170. * @since Method available since Release 3.3.6
  171. */
  172. public static function getExpectedException($docComment)
  173. {
  174. if (preg_match(self::REGEX_EXPECTED_EXCEPTION, $docComment, $matches)) {
  175. $class = $matches[1];
  176. $code = 0;
  177. $message = '';
  178. if (isset($matches[2])) {
  179. $message = trim($matches[2]);
  180. }
  181. if (isset($matches[3])) {
  182. $code = (int)$matches[3];
  183. }
  184. return array(
  185. 'class' => $class, 'code' => $code, 'message' => $message
  186. );
  187. }
  188. return FALSE;
  189. }
  190. /**
  191. * Returns the groups for a test class or method.
  192. *
  193. * @param string $docComment
  194. * @param array $groups
  195. * @return array
  196. * @since Method available since Release 3.2.0
  197. */
  198. public static function getGroups($docComment, array $groups = array())
  199. {
  200. if (preg_match_all(self::REGEX_GROUP, $docComment, $matches)) {
  201. $groups = array_unique(array_merge($groups, $matches[1]));
  202. }
  203. return $groups;
  204. }
  205. /**
  206. * Returns the provided data for a method.
  207. *
  208. * @param string $className
  209. * @param string $methodName
  210. * @param string $docComment
  211. * @return array
  212. * @since Method available since Release 3.2.0
  213. */
  214. public static function getProvidedData($className, $methodName, $docComment)
  215. {
  216. if (preg_match(self::REGEX_DATA_PROVIDER, $docComment, $matches)) {
  217. try {
  218. $dataProviderMethodNameNamespace = explode('\\', $matches[1]);
  219. $leaf = explode('::', array_pop($dataProviderMethodNameNamespace));
  220. $dataProviderMethodName = array_pop($leaf);
  221. if (!empty($dataProviderMethodNameNamespace)) {
  222. $dataProviderMethodNameNamespace = join('\\', $dataProviderMethodNameNamespace) . '\\';
  223. } else {
  224. $dataProviderMethodNameNamespace = '';
  225. }
  226. if (!empty($leaf)) {
  227. $dataProviderClassName = $dataProviderMethodNameNamespace . array_pop($leaf);
  228. } else {
  229. $dataProviderClassName = $className;
  230. }
  231. $dataProviderClass = new ReflectionClass($dataProviderClassName);
  232. $dataProviderMethod = $dataProviderClass->getMethod(
  233. $dataProviderMethodName
  234. );
  235. if ($dataProviderMethod->isStatic()) {
  236. $object = NULL;
  237. } else {
  238. $object = $dataProviderClass->newInstance();
  239. }
  240. if ($dataProviderMethod->getNumberOfParameters() == 0) {
  241. return $dataProviderMethod->invoke($object);
  242. } else {
  243. return $dataProviderMethod->invoke($object, $methodName);
  244. }
  245. }
  246. catch (ReflectionException $e) {
  247. }
  248. }
  249. }
  250. /**
  251. * Returns the files and lines a test method wants to cover.
  252. *
  253. * @param string $method
  254. * @param boolean $extended
  255. * @return array
  256. * @since Method available since Release 3.3.0
  257. */
  258. private static function resolveCoversToReflectionObjects($method, $extended)
  259. {
  260. $codeToCoverList = array();
  261. if (strpos($method, '::') !== FALSE) {
  262. list($className, $methodName) = explode('::', $method);
  263. if ($methodName{0} == '<') {
  264. $classes = array($className);
  265. if ($extended) {
  266. $classes = array_merge(
  267. $classes,
  268. class_implements($className),
  269. class_parents($className)
  270. );
  271. }
  272. foreach ($classes as $className)
  273. {
  274. $class = new ReflectionClass($className);
  275. $methods = $class->getMethods();
  276. $inverse = isset($methodName{1}) && $methodName{1} == '!';
  277. if (strpos($methodName, 'protected')) {
  278. $visibility = 'isProtected';
  279. }
  280. else if (strpos($methodName, 'private')) {
  281. $visibility = 'isPrivate';
  282. }
  283. else if (strpos($methodName, 'public')) {
  284. $visibility = 'isPublic';
  285. }
  286. foreach ($methods as $method) {
  287. if ($inverse && !$method->$visibility()) {
  288. $codeToCoverList[] = $method;
  289. }
  290. else if (!$inverse && $method->$visibility()) {
  291. $codeToCoverList[] = $method;
  292. }
  293. }
  294. }
  295. } else {
  296. $classes = array($className);
  297. if ($extended) {
  298. $classes = array_merge($classes, class_parents($className));
  299. }
  300. foreach ($classes as $className) {
  301. $codeToCoverList[] = new ReflectionMethod($className, $methodName);
  302. }
  303. }
  304. } else {
  305. $classes = array($method);
  306. if ($extended) {
  307. $classes = array_merge(
  308. $classes,
  309. class_implements($method),
  310. class_parents($method)
  311. );
  312. }
  313. foreach ($classes as $className) {
  314. $codeToCoverList[] = new ReflectionClass($className);
  315. }
  316. }
  317. return $codeToCoverList;
  318. }
  319. }
  320. ?>