PageRenderTime 25ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/core/src/test/php/net/xp_framework/unittest/reflection/ClassLoaderTest.class.php

https://github.com/ghiata/xp-framework
PHP | 401 lines | 177 code | 37 blank | 187 comment | 1 complexity | 174805031eb1beccfc5f9cfb926adb95 MD5 | raw file
  1. <?php namespace net\xp_framework\unittest\reflection;
  2. use unittest\TestCase;
  3. use lang\archive\Archive;
  4. /**
  5. * TestCase for classloading
  6. *
  7. * Makes use of the following classes in the package
  8. * net.xp_framework.unittest.reflection.classes:
  9. * <ul>
  10. * <li>ClassOne, ClassTwo - exist in the same directory as this class</li>
  11. * <li>ClassThree, ClassFour - exist in "lib/three-and-four.xar"</li>
  12. * <li>ClassFive - exists in "contained.xar" within "lib/three-and-four.xar"</li>
  13. * </ul>
  14. *
  15. * @see xp://lang.ClassLoader
  16. * @see xp://lang.XPClass#getClassLoader
  17. * @purpose Unittest
  18. */
  19. class ClassLoaderTest extends TestCase {
  20. protected
  21. $libraryLoader = null,
  22. $brokenLoader = null,
  23. $containedLoader = null;
  24. /**
  25. * Setup this test. Registeres class loaders deleates for the
  26. * afforementioned XARs
  27. *
  28. */
  29. public function setUp() {
  30. $this->libraryLoader= \lang\ClassLoader::registerLoader(new \lang\archive\ArchiveClassLoader(new Archive(\lang\XPClass::forName(\xp::nameOf(__CLASS__))
  31. ->getPackage()
  32. ->getPackage('lib')
  33. ->getResourceAsStream('three-and-four.xar')
  34. )));
  35. $this->brokenLoader= \lang\ClassLoader::registerLoader(new \lang\archive\ArchiveClassLoader(new Archive(\lang\XPClass::forName(\xp::nameOf(__CLASS__))
  36. ->getPackage()
  37. ->getPackage('lib')
  38. ->getResourceAsStream('broken.xar')
  39. )));
  40. $this->containedLoader= \lang\ClassLoader::registerLoader(new \lang\archive\ArchiveClassLoader(new Archive($this
  41. ->libraryLoader
  42. ->getResourceAsStream('contained.xar')
  43. )));
  44. }
  45. /**
  46. * Tear down this test. Removes classloader delegates registered
  47. * during setUp()
  48. *
  49. */
  50. public function tearDown() {
  51. \lang\ClassLoader::removeLoader($this->libraryLoader);
  52. \lang\ClassLoader::removeLoader($this->containedLoader);
  53. \lang\ClassLoader::removeLoader($this->brokenLoader);
  54. }
  55. /**
  56. * Helper method
  57. *
  58. * @param string name
  59. * @param lang.XPClass class
  60. * @throws unittest.AssertionFailedError
  61. */
  62. protected function assertXPClass($name, $class) {
  63. $this->assertClass($class, 'lang.XPClass');
  64. $this->assertEquals($name, $class->getName());
  65. }
  66. /**
  67. * Display some information
  68. *
  69. * Annotate this method w/ @test to retrieve debug information.
  70. */
  71. public function classLoaderInformation() {
  72. with ($p= \lang\reflect\Package::forName('net.xp_framework.unittest.reflection.classes')); {
  73. \util\cmd\Console::writeLine('Object : ', \lang\XPClass::forName('lang.Object')->getClassLoader());
  74. \util\cmd\Console::writeLine('This : ', $this->getClass()->getClassLoader());
  75. \util\cmd\Console::writeLine('ClassOne : ', $p->loadClass('ClassOne')->getClassLoader());
  76. \util\cmd\Console::writeLine('ClassTwo : ', $p->loadClass('ClassTwo')->getClassLoader());
  77. \util\cmd\Console::writeLine('ClassThree : ', $p->loadClass('ClassThree')->getClassLoader());
  78. \util\cmd\Console::writeLine('ClassFour : ', $p->loadClass('ClassFour')->getClassLoader());
  79. \util\cmd\Console::writeLine('ClassFive : ', $p->loadClass('ClassFive')->getClassLoader());
  80. }
  81. }
  82. /**
  83. * Test "ClassOne" class is loaded from the same class loader
  84. * as this class (it exists in the same directory).
  85. *
  86. */
  87. #[@test]
  88. public function sameClassLoader() {
  89. $this->assertEquals(
  90. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassOne')->getClassLoader(),
  91. $this->getClass()->getClassLoader()
  92. );
  93. }
  94. /**
  95. * Test class loaders are equal for two classes loaded from the
  96. * same place (both exist in the same directory).
  97. *
  98. */
  99. #[@test]
  100. public function twoClassesFromSamePlace() {
  101. $this->assertEquals(
  102. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassOne')->getClassLoader(),
  103. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassTwo')->getClassLoader()
  104. );
  105. }
  106. /**
  107. * Test "ClassThree" is loaded from the archive in "lib"
  108. *
  109. */
  110. #[@test]
  111. public function archiveClassLoader() {
  112. $this->assertClass(
  113. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassThree')->getClassLoader(),
  114. 'lang.archive.ArchiveClassLoader'
  115. );
  116. }
  117. /**
  118. * Test "ClassFive" is loaded from an archive
  119. *
  120. */
  121. #[@test]
  122. public function containedArchiveClassLoader() {
  123. $this->assertClass(
  124. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassFive')->getClassLoader(),
  125. 'lang.archive.ArchiveClassLoader'
  126. );
  127. }
  128. /**
  129. * Test class loaders are equal for two classes loaded from the
  130. * archive in "lib"
  131. *
  132. */
  133. #[@test]
  134. public function twoClassesFromArchive() {
  135. $this->assertEquals(
  136. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassThree')->getClassLoader(),
  137. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassFour')->getClassLoader()
  138. );
  139. }
  140. /**
  141. * Loads a class that has been loaded before
  142. *
  143. */
  144. #[@test]
  145. public function loadClass() {
  146. $this->assertXPClass('lang.Object', \lang\ClassLoader::getDefault()->loadClass('lang.Object'));
  147. }
  148. /**
  149. * Tests the findClass() method
  150. *
  151. */
  152. #[@test]
  153. public function findThisClass() {
  154. $this->assertEquals(
  155. $this->getClass()->getClassLoader(),
  156. \lang\ClassLoader::getDefault()->findClass($this->getClassName())
  157. );
  158. }
  159. /**
  160. * Tests the findClass() method
  161. *
  162. */
  163. #[@test]
  164. public function findNullClass() {
  165. $this->assertEquals(\xp::null(), \lang\ClassLoader::getDefault()->findClass(null));
  166. }
  167. /**
  168. * Loads a class that has *not* been loaded before. Makes sure the
  169. * static initializer is called.
  170. *
  171. */
  172. #[@test]
  173. public function initializerCalled() {
  174. $name= 'net.xp_framework.unittest.reflection.LoaderTestClass';
  175. if (class_exists(\xp::reflect($name), false)) {
  176. return $this->fail('Class "'.$name.'" may not exist!');
  177. }
  178. $this->assertXPClass($name, \lang\ClassLoader::getDefault()->loadClass($name));
  179. $this->assertTrue(LoaderTestClass::initializerCalled());
  180. }
  181. /**
  182. * Tests the loadClass() method throws a ClassNotFoundException when given
  183. * a name of a class that cannot be found.
  184. *
  185. */
  186. #[@test, @expect('lang.ClassNotFoundException')]
  187. public function loadNonExistantClass() {
  188. \lang\ClassLoader::getDefault()->loadClass('@@NON-EXISTANT@@');
  189. }
  190. /**
  191. * Loads a class file that does not declare a class
  192. *
  193. */
  194. #[@test, @expect('lang.ClassFormatException')]
  195. public function loadClassFileWithoutDeclaration() {
  196. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.broken.NoClass');
  197. }
  198. /**
  199. * Loads a class file that does not declare a class
  200. *
  201. */
  202. #[@test, @expect('lang.ClassFormatException')]
  203. public function loadClassFileWithIncorrectDeclaration() {
  204. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.broken.FalseClass');
  205. }
  206. /**
  207. * Loads a class file that loads a file that is broken
  208. *
  209. */
  210. #[@test, @expect('lang.ClassDependencyException')]
  211. public function loadClassWithBrokenDependency() {
  212. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.broken.BrokenDependencyClass');
  213. }
  214. /**
  215. * Loads a class file whose class extends a class that cannot be
  216. * loaded and the class cannot be declared.
  217. *
  218. */
  219. #[@test, @expect('lang.ClassLinkageException')]
  220. public function loadClassWithMissingDefinition() {
  221. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.broken.MissingDefinitionClass');
  222. }
  223. /**
  224. * Test
  225. *
  226. */
  227. #[@test]
  228. public function loadClassFileWithRecusionInStaticBlock() {
  229. with ($p= \lang\reflect\Package::forName('net.xp_framework.unittest.reflection.classes')); {
  230. $two= $p->loadClass('StaticRecursionTwo');
  231. $one= $p->loadClass('StaticRecursionOne');
  232. $this->assertEquals($two, $one->getField('two')->get(null));
  233. }
  234. }
  235. /**
  236. * Test (mis-)using the public constructor does not lead to a
  237. * ReflectionException surfacing
  238. *
  239. */
  240. #[@test, @expect('lang.IllegalStateException')]
  241. public function newInstance() {
  242. new \lang\XPClass('DoesNotExist');
  243. }
  244. /**
  245. * Test (mis-)using the public constructor does not lead to a
  246. * ReflectionException surfacing
  247. *
  248. */
  249. #[@test, @expect('lang.IllegalArgumentException')]
  250. public function newInstance__PHP_Incomplete_Class() {
  251. new \lang\XPClass(unserialize('O:12:"DoesNotExist":0:{}'));
  252. }
  253. /**
  254. * Test archive delivers the correct contents
  255. *
  256. */
  257. #[@test]
  258. public function packageContents() {
  259. $this->assertEquals(
  260. array('net/', 'META-INF/', 'contained.xar'),
  261. $this->libraryLoader->packageContents('')
  262. );
  263. }
  264. /**
  265. * Test archive correctly detects delivered packages
  266. *
  267. */
  268. #[@test]
  269. public function providesPackage() {
  270. $this->assertTrue($this->libraryLoader->providesPackage('net.xp_framework'));
  271. }
  272. /**
  273. * Test archive checks full path for package names
  274. *
  275. */
  276. #[@test]
  277. public function doesNotProvideAPackage() {
  278. $this->assertFalse($this->libraryLoader->providesPackage('net.xp_frame'));
  279. }
  280. /**
  281. * Test "Classone" class is not provided
  282. *
  283. * @see https://github.com/xp-framework/xp-framework/pull/235
  284. */
  285. #[@test]
  286. public function doesNotProvideClassone() {
  287. $this->assertFalse(\lang\ClassLoader::getDefault()
  288. ->providesClass('net.xp_framework.unittest.reflection.classes.Classone')
  289. );
  290. }
  291. /**
  292. * Test "Classone" class is not provided
  293. *
  294. * @see https://github.com/xp-framework/xp-framework/pull/235
  295. */
  296. #[@test, @expect('lang.ClassNotFoundException')]
  297. public function loadingClassoneFails() {
  298. \lang\ClassLoader::getDefault()
  299. ->loadClass('net.xp_framework.unittest.reflection.classes.Classone')
  300. ;
  301. }
  302. /**
  303. * Test providesUri()
  304. *
  305. */
  306. #[@test]
  307. public function providesExistantUri() {
  308. $this->assertTrue(
  309. \lang\ClassLoader::getDefault()->providesUri('net/xp_framework/unittest/reflection/classes/ClassOne.class.php')
  310. );
  311. }
  312. /**
  313. * Test providesUri()
  314. *
  315. */
  316. #[@test]
  317. public function doesNotProvideNonExistantUri() {
  318. $this->assertFalse(
  319. \lang\ClassLoader::getDefault()->providesUri('non/existant/Class.class.php')
  320. );
  321. }
  322. /**
  323. * Test findUri()
  324. *
  325. */
  326. #[@test]
  327. public function findExistantUri() {
  328. $cl= \lang\ClassLoader::getDefault();
  329. $this->assertEquals(
  330. $cl->findClass('net.xp_framework.unittest.reflection.classes.ClassOne'),
  331. $cl->findUri('net/xp_framework/unittest/reflection/classes/ClassOne.class.php')
  332. );
  333. }
  334. /**
  335. * Test findUri()
  336. *
  337. */
  338. #[@test]
  339. public function cannotFindNontExistantUri() {
  340. $this->assertEquals(
  341. \xp::null(),
  342. \lang\ClassLoader::getDefault()->findUri('non/existant/Class.class.php')
  343. );
  344. }
  345. /**
  346. * Test loadUri()
  347. *
  348. */
  349. #[@test]
  350. public function loadUri() {
  351. $this->assertEquals(
  352. \lang\XPClass::forName('net.xp_framework.unittest.reflection.classes.ClassOne'),
  353. \lang\ClassLoader::getDefault()->loadUri('net/xp_framework/unittest/reflection/classes/ClassOne.class.php')
  354. );
  355. }
  356. /**
  357. * Test loadUri()
  358. *
  359. */
  360. #[@test, @expect('lang.ClassNotFoundException')]
  361. public function loadNonExistantUri() {
  362. \lang\ClassLoader::getDefault()->loadUri('non/existant/Class.class.php');
  363. }
  364. }