/core/src/test/php/net/xp_framework/unittest/core/NewInstanceTest.class.php

https://github.com/treuter/xp-framework · PHP · 242 lines · 135 code · 19 blank · 88 comment · 4 complexity · 52f600fbbd6caef0bcc343a2d241973d MD5 · raw file

  1. <?php
  2. /* This class is part of the XP framework
  3. *
  4. * $Id$
  5. */
  6. uses(
  7. 'unittest.TestCase',
  8. 'lang.Runnable',
  9. 'lang.Runtime',
  10. 'net.xp_framework.unittest.core.PackagedClass',
  11. 'net.xp_framework.unittest.core.NamespacedClass',
  12. 'net.xp_framework.unittest.core.NamespacedInterface'
  13. );
  14. /**
  15. * TestCase for newinstance() functionality
  16. *
  17. */
  18. class NewInstanceTest extends TestCase {
  19. /**
  20. * Skips tests if process execution has been disabled.
  21. */
  22. #[@beforeClass]
  23. public static function verifyProcessExecutionEnabled() {
  24. if (Process::$DISABLED) {
  25. throw new PrerequisitesNotMetError('Process execution disabled', NULL, array('enabled'));
  26. }
  27. }
  28. /**
  29. * Issues a uses() command inside a new runtime for every class given
  30. * and returns a line indicating success or failure for each of them.
  31. *
  32. * @param string[] uses
  33. * @param string src
  34. * @return var[] an array with three elements: exitcode, stdout and stderr contents
  35. */
  36. protected function runInNewRuntime($uses, $src) {
  37. with ($out= $err= '', $p= Runtime::getInstance()->newInstance(NULL, 'class', 'xp.runtime.Evaluate', array())); {
  38. $uses && $p->in->write('uses("'.implode('", "', $uses).'");');
  39. $p->in->write($src);
  40. $p->in->close();
  41. // Read output
  42. while ($b= $p->out->read()) { $out.= $b; }
  43. while ($b= $p->err->read()) { $err.= $b; }
  44. // Close child process
  45. $exitv= $p->close();
  46. }
  47. return array($exitv, $out, $err);
  48. }
  49. /**
  50. * Test constructing a class instance
  51. *
  52. */
  53. #[@test]
  54. public function newObject() {
  55. $o= newinstance('lang.Object', array(), '{}');
  56. $this->assertInstanceOf('lang.Object', $o);
  57. }
  58. /**
  59. * Test constructing an interface instance
  60. *
  61. */
  62. #[@test]
  63. public function newRunnable() {
  64. $o= newinstance('lang.Runnable', array(), '{ public function run() { } }');
  65. $this->assertInstanceOf('lang.Runnable', $o);
  66. }
  67. /**
  68. * Test arguments are passed constructor
  69. *
  70. */
  71. #[@test]
  72. public function argumentsArePassedToConstructor() {
  73. $instance= newinstance('lang.Object', array($this), '{
  74. public $test= NULL;
  75. public function __construct($test) {
  76. $this->test= $test;
  77. }
  78. }');
  79. $this->assertEquals($this, $instance->test);
  80. }
  81. /**
  82. * Test constructing an interface instance without implementing all
  83. * required methods raises a fatal
  84. *
  85. */
  86. #[@test]
  87. public function missingMethodImplementationFatals() {
  88. $r= $this->runInNewRuntime(array('lang.Runnable'), '
  89. newinstance("lang.Runnable", array(), "{}");
  90. ');
  91. $this->assertEquals(255, $r[0], 'exitcode');
  92. $this->assertTrue(
  93. (bool)strstr($r[1].$r[2], 'Fatal error:'),
  94. xp::stringOf(array('out' => $r[1], 'err' => $r[2]))
  95. );
  96. }
  97. /**
  98. * Test invalid syntax raises a fatal.
  99. *
  100. */
  101. #[@test]
  102. public function syntaxErrorFatals() {
  103. $r= $this->runInNewRuntime(array('lang.Runnable'), '
  104. newinstance("lang.Runnable", array(), "{ @__SYNTAX ERROR__@ }");
  105. ');
  106. $this->assertEquals(255, $r[0], 'exitcode');
  107. $this->assertTrue(
  108. (bool)strstr($r[1].$r[2], 'Parse error:'),
  109. xp::stringOf(array('out' => $r[1], 'err' => $r[2]))
  110. );
  111. }
  112. /**
  113. * Test using a non-existant class in newinstance() causes a fatal error.
  114. *
  115. */
  116. #[@test]
  117. public function missingClassFatals() {
  118. $r= $this->runInNewRuntime(array(), '
  119. newinstance("lang.NonExistantClass", array(), "{}");
  120. ');
  121. $this->assertEquals(255, $r[0], 'exitcode');
  122. $this->assertTrue(
  123. (bool)strstr($r[1].$r[2], 'Class "lang.NonExistantClass" could not be found'),
  124. xp::stringOf(array('out' => $r[1], 'err' => $r[2]))
  125. );
  126. }
  127. /**
  128. * Test using a not previously defined class is loaded
  129. *
  130. */
  131. #[@test]
  132. public function notPreviouslyDefinedClassIsLoaded() {
  133. $r= $this->runInNewRuntime(array(), '
  134. if (isset(xp::$cl["lang.Runnable"])) {
  135. xp::error("Class lang.Runnable may not have been previously loaded");
  136. }
  137. $r= newinstance("lang.Runnable", array(), "{ public function run() { echo \"Hi\"; } }");
  138. $r->run();
  139. ');
  140. $this->assertEquals(0, $r[0], 'exitcode');
  141. $this->assertTrue(
  142. (bool)strstr($r[1].$r[2], 'Hi'),
  143. xp::stringOf(array('out' => $r[1], 'err' => $r[2]))
  144. );
  145. }
  146. /**
  147. * Tests package retrieval on newinstance() created namespaced class
  148. *
  149. */
  150. #[@test]
  151. public function packageOfNewInstancedClass() {
  152. $i= newinstance('lang.Object', array(), '{}');
  153. $this->assertEquals(
  154. Package::forName('lang'),
  155. $i->getClass()->getPackage()
  156. );
  157. }
  158. /**
  159. * Tests package retrieval on newinstance() created namespaced class
  160. *
  161. */
  162. #[@test]
  163. public function packageOfNewInstancedFullyQualifiedClass() {
  164. $i= newinstance('net.xp_framework.unittest.core.PackagedClass', array(), '{}');
  165. $this->assertEquals(
  166. Package::forName('net.xp_framework.unittest.core'),
  167. $i->getClass()->getPackage()
  168. );
  169. }
  170. /**
  171. * Tests package retrieval on newinstance() created namespaced class
  172. *
  173. */
  174. #[@test]
  175. public function packageOfNewInstancedNamespacedClass() {
  176. $i= newinstance('net.xp_framework.unittest.core.NamespacedClass', array(), '{}');
  177. $this->assertEquals(
  178. Package::forName('net.xp_framework.unittest.core'),
  179. $i->getClass()->getPackage()
  180. );
  181. }
  182. /**
  183. * Tests package retrieval on newinstance() created namespaced class
  184. *
  185. */
  186. #[@test]
  187. public function packageOfNewInstancedNamespacedInterface() {
  188. $i= newinstance('net.xp_framework.unittest.core.NamespacedInterface', array(), '{}');
  189. $this->assertEquals(
  190. Package::forName('net.xp_framework.unittest.core'),
  191. $i->getClass()->getPackage()
  192. );
  193. }
  194. /**
  195. * Test class name of a anonymous generic instance
  196. *
  197. */
  198. #[@test]
  199. public function className() {
  200. $instance= newinstance('Object', array(), '{ }');
  201. $n= $instance->getClassName();
  202. $this->assertEquals(
  203. 'lang.Object',
  204. substr($n, 0, strrpos($n, '·')),
  205. $n
  206. );
  207. }
  208. /**
  209. * Test class name of a anonymous generic instance
  210. *
  211. */
  212. #[@test]
  213. public function classNameWithFullyQualifiedClassName() {
  214. $instance= newinstance('lang.Object', array(), '{ }');
  215. $n= $instance->getClassName();
  216. $this->assertEquals(
  217. 'lang.Object',
  218. substr($n, 0, strrpos($n, '·')),
  219. $n
  220. );
  221. }
  222. }
  223. ?>