closure_061.phpt 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. --TEST--
  2. Rebinding of ::getClosure()s
  3. --FILE--
  4. <?php
  5. use SplDoublyLinkedList as DLL;
  6. function func($arg) { }
  7. class Cls {
  8. public function method() {}
  9. public static function staticMethod($arg) {}
  10. }
  11. class ClsChild extends Cls {}
  12. class ClsUnrelated {}
  13. /* Format: [Function, [Obj, Scope]] */
  14. $tests = [
  15. ['func', [
  16. [null, null],
  17. [new Cls, null],
  18. [new Cls, 'Cls'],
  19. [null, 'Cls'],
  20. [null, 'stdClass'],
  21. [new stdClass, null],
  22. ]],
  23. ['strlen', [
  24. [null, null],
  25. [new Cls, null],
  26. [new Cls, 'Cls'],
  27. [null, 'Cls'],
  28. [null, 'stdClass'],
  29. [new stdClass, null],
  30. ]],
  31. [['Cls', 'staticMethod'], [
  32. [null, 'Cls'],
  33. [new Cls, null],
  34. [new Cls, 'Cls'],
  35. [null, null],
  36. [null, 'ClsChild'],
  37. [null, 'ClsUnrelated'],
  38. ]],
  39. [[new Cls, 'method'], [
  40. [null, 'Cls'],
  41. [new Cls, 'Cls'],
  42. [new ClsChild, 'Cls'],
  43. [new ClsUnrelated, 'Cls'],
  44. [new Cls, null],
  45. [new Cls, 'ClsUnrelated'],
  46. [new Cls, 'ClsChild'],
  47. ]],
  48. [[new DLL, 'count'], [
  49. [new DLL, DLL::class],
  50. [new SplStack, DLL::class],
  51. [new ClsUnrelated, DLL::class],
  52. [null, null],
  53. [null, DLL::class],
  54. [new DLL, null],
  55. [new DLL, ClsUnrelated::class],
  56. ]],
  57. [function() {}, [
  58. [null, null],
  59. [new Cls, null],
  60. [new Cls, 'Cls'],
  61. [null, 'Cls'],
  62. [null, 'stdClass'],
  63. [new stdClass, null],
  64. ]],
  65. ];
  66. set_error_handler(function($errno, $errstr) {
  67. echo "$errstr\n\n";
  68. });
  69. foreach ($tests as list($fn, $bindings)) {
  70. if (is_array($fn)) {
  71. $r = new ReflectionMethod($fn[0], $fn[1]);
  72. $c = $r->getClosure(is_object($fn[0]) ? $fn[0] : null);
  73. $fnStr = is_object($fn[0]) ? "(new " . get_class($fn[0]) . ")->$fn[1]" : "$fn[0]::$fn[1]";
  74. } else {
  75. $c = (new ReflectionFunction($fn))->getClosure();
  76. $fnStr = $fn;
  77. }
  78. if ($fn instanceof Closure) {
  79. $fnStr = "(function() {})";
  80. }
  81. echo "$fnStr()\n" . str_repeat('-', strlen($fnStr) + 2), "\n\n";
  82. foreach ($bindings as list($obj, $scope)) {
  83. $objStr = $obj ? "new " . get_class($obj) : "null";
  84. $scopeStr = $scope ? "$scope::class" : "null";
  85. echo "bindTo($objStr, $scopeStr):\n";
  86. $ret = $c->bindTo($obj, $scope);
  87. if ($ret !== null) {
  88. echo "Success!\n\n";
  89. }
  90. }
  91. }
  92. ?>
  93. --EXPECT--
  94. func()
  95. ------
  96. bindTo(null, null):
  97. Success!
  98. bindTo(new Cls, null):
  99. Success!
  100. bindTo(new Cls, Cls::class):
  101. Cannot rebind scope of closure created from function
  102. bindTo(null, Cls::class):
  103. Cannot rebind scope of closure created from function
  104. bindTo(null, stdClass::class):
  105. Cannot bind closure to scope of internal class stdClass
  106. bindTo(new stdClass, null):
  107. Success!
  108. strlen()
  109. --------
  110. bindTo(null, null):
  111. Success!
  112. bindTo(new Cls, null):
  113. Success!
  114. bindTo(new Cls, Cls::class):
  115. Cannot rebind scope of closure created from function
  116. bindTo(null, Cls::class):
  117. Cannot rebind scope of closure created from function
  118. bindTo(null, stdClass::class):
  119. Cannot bind closure to scope of internal class stdClass
  120. bindTo(new stdClass, null):
  121. Success!
  122. Cls::staticMethod()
  123. -------------------
  124. bindTo(null, Cls::class):
  125. Success!
  126. bindTo(new Cls, null):
  127. Cannot bind an instance to a static closure
  128. bindTo(new Cls, Cls::class):
  129. Cannot bind an instance to a static closure
  130. bindTo(null, null):
  131. Cannot rebind scope of closure created from method
  132. bindTo(null, ClsChild::class):
  133. Cannot rebind scope of closure created from method
  134. bindTo(null, ClsUnrelated::class):
  135. Cannot rebind scope of closure created from method
  136. (new Cls)->method()
  137. -------------------
  138. bindTo(null, Cls::class):
  139. Cannot unbind $this of method
  140. bindTo(new Cls, Cls::class):
  141. Success!
  142. bindTo(new ClsChild, Cls::class):
  143. Success!
  144. bindTo(new ClsUnrelated, Cls::class):
  145. Cannot bind method Cls::method() to object of class ClsUnrelated
  146. bindTo(new Cls, null):
  147. Cannot rebind scope of closure created from method
  148. bindTo(new Cls, ClsUnrelated::class):
  149. Cannot rebind scope of closure created from method
  150. bindTo(new Cls, ClsChild::class):
  151. Cannot rebind scope of closure created from method
  152. (new SplDoublyLinkedList)->count()
  153. ----------------------------------
  154. bindTo(new SplDoublyLinkedList, SplDoublyLinkedList::class):
  155. Success!
  156. bindTo(new SplStack, SplDoublyLinkedList::class):
  157. Success!
  158. bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
  159. Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
  160. bindTo(null, null):
  161. Cannot unbind $this of method
  162. bindTo(null, SplDoublyLinkedList::class):
  163. Cannot unbind $this of method
  164. bindTo(new SplDoublyLinkedList, null):
  165. Cannot rebind scope of closure created from method
  166. bindTo(new SplDoublyLinkedList, ClsUnrelated::class):
  167. Cannot rebind scope of closure created from method
  168. (function() {})()
  169. -----------------
  170. bindTo(null, null):
  171. Success!
  172. bindTo(new Cls, null):
  173. Success!
  174. bindTo(new Cls, Cls::class):
  175. Success!
  176. bindTo(null, Cls::class):
  177. Success!
  178. bindTo(null, stdClass::class):
  179. Cannot bind closure to scope of internal class stdClass
  180. bindTo(new stdClass, null):
  181. Success!