PageRenderTime 34ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/src/test/php/pdepend/reflection/BaseTest.php

http://github.com/manuelpichler/staticReflection
PHP | 347 lines | 176 code | 31 blank | 140 comment | 14 complexity | 9bd904830eec4d4fd5feef96c377e4c1 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * This file is part of the static reflection component.
  4. *
  5. * PHP Version 5
  6. *
  7. * Copyright (c) 2009-2011, Manuel Pichler <mapi@pdepend.org>.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in
  19. * the documentation and/or other materials provided with the
  20. * distribution.
  21. *
  22. * * Neither the name of Manuel Pichler nor the names of his
  23. * contributors may be used to endorse or promote products derived
  24. * from this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  27. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  28. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  29. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  30. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  31. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  32. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  33. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  34. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  36. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * @category PHP
  40. * @package pdepend\reflection
  41. * @author Manuel Pichler <mapi@pdepend.org>
  42. * @copyright 2009-2011 Manuel Pichler. All rights reserved.
  43. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  44. * @version SVN: $Id$
  45. * @link http://pdepend.org/
  46. */
  47. namespace pdepend\reflection;
  48. /**
  49. * Base test case for this component.
  50. *
  51. * @category PHP
  52. * @package pdepend\reflection
  53. * @author Manuel Pichler <mapi@pdepend.org>
  54. * @copyright 2009-2011 Manuel Pichler. All rights reserved.
  55. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  56. * @version Release: @package_version@
  57. * @link http://pdepend.org/
  58. */
  59. abstract class BaseTest extends \PHPUnit_Framework_TestCase
  60. {
  61. /**
  62. * Is autoloading already initialized?
  63. *
  64. * @var boolean
  65. */
  66. private static $_initialized = false;
  67. /**
  68. * List of methods that will be added to the list of expected object
  69. *
  70. * @var array(string)
  71. */
  72. protected $methodBackwardsCompatibilityList = array();
  73. /**
  74. * Constructs a new test instance.
  75. */
  76. public function __construct()
  77. {
  78. parent::__construct();
  79. if ( self::$_initialized === false )
  80. {
  81. self::$_initialized = true;
  82. spl_autoload_register( array( __CLASS__, 'autoload' ) );
  83. }
  84. }
  85. /**
  86. * Helper method to allow PHPUnit versions < 3.5.x
  87. *
  88. * @param string $expected
  89. * @param mixed $actual
  90. * @param string $message
  91. * @since Method available since Release 3.5.0
  92. */
  93. public static function assertInstanceOf( $expected, $actual, $message = '' )
  94. {
  95. if ( is_callable( get_parent_class( __CLASS__ ) . '::' ) . __FUNCTION__ )
  96. {
  97. return parent::assertInstanceOf( $expected, $actual, $message );
  98. }
  99. return parent::assertType( $expected, $actual, $message );
  100. }
  101. /**
  102. * Helper method to allow PHPUnit versions < 3.5.x
  103. *
  104. * @param string $expected
  105. * @param mixed $actual
  106. * @param string $message
  107. * @since Method available since Release 3.5.0
  108. */
  109. public static function assertInternalType( $expected, $actual, $message = '' )
  110. {
  111. if ( is_callable( get_parent_class( __CLASS__ ) . '::' ) . __FUNCTION__ )
  112. {
  113. return parent::assertInternalType( $expected, $actual, $message );
  114. }
  115. return parent::assertType( $expected, $actual, $message );
  116. }
  117. /**
  118. * Asserts that the public api of the given classes is equal.
  119. *
  120. * @param string $classExpected
  121. * @param string $classActual
  122. *
  123. * @return void
  124. */
  125. protected function assertPublicApiEquals( $classExpected, $classActual )
  126. {
  127. $expected = $this->getPublicMethods( $classExpected );
  128. $actual = $this->getPublicMethods( $classActual );
  129. self::assertEquals( $expected, $actual );
  130. }
  131. /**
  132. * @param string $className
  133. *
  134. * @return array(string)
  135. */
  136. protected function getPublicMethods( $className )
  137. {
  138. $phpversion =
  139. $reflection = new \ReflectionClass( $className );
  140. $methods = array();
  141. foreach ( $reflection->getMethods( \ReflectionMethod::IS_PUBLIC ) as $method )
  142. {
  143. $comment = $method->getDocComment();
  144. if ( !$method->isPublic()
  145. || $method->isStatic()
  146. || $reflection->isUserDefined() !== $method->isUserDefined()
  147. || $reflection->isInternal() !== $method->isInternal()
  148. || is_int( strpos( $comment, '@access private' ) )
  149. ) {
  150. continue;
  151. }
  152. $regexp = '(@since\s+PHP (\d+\.\d+\.\d+(\-dev|RC\d+|alpha\d+|beta\d+)?))';
  153. if (preg_match( $regexp, $comment, $match )
  154. && version_compare( phpversion(), $match[1] ) < 0
  155. ) {
  156. continue;
  157. }
  158. $methods[] = $method->getName();
  159. }
  160. sort( $methods );
  161. return $methods;
  162. }
  163. /**
  164. * Includes the searched class into the runtime scope.
  165. *
  166. * @param string $className Name of the searched class.
  167. *
  168. * void
  169. */
  170. protected function includeClass( $className )
  171. {
  172. $includePath = get_include_path();
  173. set_include_path( $includePath . PATH_SEPARATOR . __DIR__ . '/../../../resources/files' );
  174. include_once $this->getPathnameForClass( $className );
  175. set_include_path( $includePath );
  176. }
  177. /**
  178. * This method will return <b>true</b> a source file for the given class
  179. * name exists.
  180. *
  181. * @param string $className Name of the searched class.
  182. *
  183. * @return string
  184. */
  185. public function hasPathnameForClass( $className )
  186. {
  187. $localName = explode( '\\', $className );
  188. $localName = array_pop( $localName );
  189. $files = new \RecursiveIteratorIterator(
  190. new \RecursiveDirectoryIterator( __DIR__ . '/../../../resources/files' )
  191. );
  192. foreach ( $files as $file )
  193. {
  194. if ( pathinfo( $file->getFilename(), PATHINFO_FILENAME ) == $localName )
  195. {
  196. return true;
  197. }
  198. }
  199. return false;
  200. }
  201. /**
  202. * This method will return the pathname of the source file for the given
  203. * class.
  204. *
  205. * @param string $className Name of the searched class.
  206. *
  207. * @return string
  208. */
  209. public function getPathnameForClass( $className )
  210. {
  211. $localName = explode( '\\', $className );
  212. $localName = array_pop( $localName );
  213. $files = new \RecursiveIteratorIterator(
  214. new \RecursiveDirectoryIterator( __DIR__ . '/../../../resources/files' )
  215. );
  216. foreach ( $files as $file )
  217. {
  218. if ( pathinfo( $file->getFilename(), PATHINFO_FILENAME ) == $localName )
  219. {
  220. return $file->getRealpath();
  221. }
  222. }
  223. throw new \ErrorException( 'Cannot locate pathname for class: ' . $className );
  224. }
  225. /**
  226. * Will trigger an additional parsing process for the given class.
  227. *
  228. * @param string $className Name of the searched class.
  229. *
  230. * @return \ReflectionClass
  231. */
  232. public function getClassByName( $className )
  233. {
  234. $parser = new parser\Parser( $this->createContext() );
  235. $classes = $parser->parseFile( $this->getPathnameForClass( $className ) );
  236. foreach ( $classes as $class )
  237. {
  238. if ( $class->getName() === $className )
  239. {
  240. return $class;
  241. }
  242. }
  243. }
  244. /**
  245. * Creates a mocked reflection factory instance.
  246. *
  247. * @return \pdepend\reflection\interfaces\ReflectionClassFactory
  248. */
  249. protected function createFactory()
  250. {
  251. $factory = $this->getMock( 'pdepend\reflection\interfaces\ReflectionClassFactory' );
  252. $factory->expects( $this->any() )
  253. ->method( 'createClass' )
  254. ->will( $this->returnCallback( array( $this, 'getClassByName' ) ) );
  255. return $factory;
  256. }
  257. /**
  258. * Creates a mocked parser context instance.
  259. *
  260. * @return \pdepend\reflection\interfaces\ParserContext
  261. */
  262. protected function createContext()
  263. {
  264. $session = $this->getMock( 'pdepend\reflection\interfaces\ParserContext' );
  265. $session->expects( $this->any() )
  266. ->method( 'getClassReference' )
  267. ->will( $this->returnCallback( array( $this, 'getClassByName' ) ) );
  268. return $session;
  269. }
  270. /**
  271. * Creates a mocked source resolver instance.
  272. *
  273. * @return \pdepend\reflection\interfaces\SourceResolver
  274. */
  275. protected function createResolver()
  276. {
  277. $resolver = $this->getMock( 'pdepend\reflection\interfaces\SourceResolver' );
  278. $resolver->expects( $this->any() )
  279. ->method( 'getPathnameForClass' )
  280. ->will( $this->returnCallback( array( $this, 'getPathnameForClass' ) ) );
  281. return $resolver;
  282. }
  283. /**
  284. * Creates a mocked reflection session instance
  285. *
  286. * @return \pdepend\reflection\ReflectionSession
  287. */
  288. protected function createSession()
  289. {
  290. return $this->getMock( 'pdepend\reflection\ReflectionSession' );
  291. }
  292. public static function autoload( $className )
  293. {
  294. if ( strpos( $className, __NAMESPACE__ ) !== 0 )
  295. {
  296. return;
  297. }
  298. $filename = sprintf( '%s.php', strtr( $className, '\\', '/' ) );
  299. $pathname = sprintf( '%s/../../../../main/php/%s', __DIR__, $filename );
  300. if ( file_exists( $pathname ) === false )
  301. {
  302. $pathname = sprintf( '%s/../../../resources/files/%s', __DIR__, $filename );
  303. }
  304. if ( file_exists( $pathname ) === false )
  305. {
  306. return false;
  307. }
  308. include $pathname;
  309. return true;
  310. }
  311. }