summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2015-10-09 23:38:25 +0200
committerNikita Popov <nikic@php.net>2015-10-12 20:37:14 +0200
commit7597a065623c4437ff29004d87a5d45f1bfe50fe (patch)
treeeea796c89b90e983751738697ceaa51485a3e160
parent23b372d358577c8146e4c35e936413e5a43043d9 (diff)
downloadphp-git-7597a065623c4437ff29004d87a5d45f1bfe50fe.tar.gz
Add more tests for closure binding
-rw-r--r--Zend/tests/bug70685.phpt2
-rw-r--r--Zend/tests/closure_061.phpt208
2 files changed, 209 insertions, 1 deletions
diff --git a/Zend/tests/bug70685.phpt b/Zend/tests/bug70685.phpt
index e286e58e7d..7a49ff1825 100644
--- a/Zend/tests/bug70685.phpt
+++ b/Zend/tests/bug70685.phpt
@@ -18,5 +18,5 @@ var_dump($c);
Warning: Cannot bind internal method SplDoublyLinkedList::count() to object of class cls in %s on line %d
NULL
-Warning: Cannot bind function SplDoublyLinkedList::count to scope class cls in %s on line %d
+Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
NULL
diff --git a/Zend/tests/closure_061.phpt b/Zend/tests/closure_061.phpt
new file mode 100644
index 0000000000..a87303498e
--- /dev/null
+++ b/Zend/tests/closure_061.phpt
@@ -0,0 +1,208 @@
+--TEST--
+Rebinding of ::getClosure()s
+--FILE--
+<?php
+
+use SplDoublyLinkedList as DLL;
+
+function func($arg) { }
+
+class Cls {
+ public function method() {}
+ public static function staticMethod($arg) {}
+}
+
+class ClsChild extends Cls {}
+
+class ClsUnrelated {}
+
+/* Format: [Function, [Obj, Scope]] */
+$tests = [
+ ['func', [
+ [null, null],
+ [new Cls, null],
+ [new Cls, 'Cls'],
+ [null, 'Cls'],
+ [null, 'stdClass'],
+ [new stdClass, null],
+ ]],
+
+ ['strlen', [
+ [null, null],
+ [new Cls, null],
+ [new Cls, 'Cls'],
+ [null, 'Cls'],
+ [null, 'stdClass'],
+ [new stdClass, null],
+ ]],
+
+ [['Cls', 'staticMethod'], [
+ [null, 'Cls'],
+ [new Cls, null],
+ [new Cls, 'Cls'],
+ [null, null],
+ [null, 'ClsChild'],
+ [null, 'ClsUnrelated'],
+ ]],
+
+ [[new Cls, 'method'], [
+ [null, 'Cls'],
+ [new Cls, 'Cls'],
+ [new ClsChild, 'Cls'],
+ [new ClsUnrelated, 'Cls'],
+ [new Cls, null],
+ [new Cls, 'ClsUnrelated'],
+ [new Cls, 'ClsChild'],
+ ]],
+
+ [[new DLL, 'count'], [
+ [new DLL, DLL::class],
+ [new SplStack, DLL::class],
+ [new ClsUnrelated, DLL::class],
+ [null, null],
+ [null, DLL::class],
+ [new DLL, null],
+ [new DLL, ClsUnrelated::class],
+ ]],
+];
+
+set_error_handler(function($errno, $errstr) {
+ echo "$errstr\n\n";
+});
+
+foreach ($tests as list($fn, $bindings)) {
+ if (is_array($fn)) {
+ $r = new ReflectionMethod($fn[0], $fn[1]);
+ $c = $r->getClosure(is_object($fn[0]) ? $fn[0] : null);
+ $fnStr = is_object($fn[0]) ? "(new " . get_class($fn[0]) . ")->$fn[1]" : "$fn[0]::$fn[1]";
+ } else {
+ $c = (new ReflectionFunction($fn))->getClosure();
+ $fnStr = $fn;
+ }
+
+ echo "$fnStr()\n" . str_repeat('-', strlen($fnStr) + 2), "\n\n";
+
+ foreach ($bindings as list($obj, $scope)) {
+ $objStr = $obj ? "new " . get_class($obj) : "null";
+ $scopeStr = $scope ? "$scope::class" : "null";
+ echo "bindTo($objStr, $scopeStr):\n";
+
+ $ret = $c->bindTo($obj, $scope);
+ if ($ret !== null) {
+ echo "Success!\n\n";
+ }
+ }
+}
+
+?>
+--EXPECT--
+func()
+------
+
+bindTo(null, null):
+Success!
+
+bindTo(new Cls, null):
+Success!
+
+bindTo(new Cls, Cls::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, Cls::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, stdClass::class):
+Cannot bind closure to scope of internal class stdClass
+
+bindTo(new stdClass, null):
+Success!
+
+strlen()
+--------
+
+bindTo(null, null):
+Success!
+
+bindTo(new Cls, null):
+Success!
+
+bindTo(new Cls, Cls::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, Cls::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, stdClass::class):
+Cannot bind closure to scope of internal class stdClass
+
+bindTo(new stdClass, null):
+Success!
+
+Cls::staticMethod()
+-------------------
+
+bindTo(null, Cls::class):
+Success!
+
+bindTo(new Cls, null):
+Cannot bind an instance to a static closure
+
+bindTo(new Cls, Cls::class):
+Cannot bind an instance to a static closure
+
+bindTo(null, null):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, ClsChild::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(null, ClsUnrelated::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+(new Cls)->method()
+-------------------
+
+bindTo(null, Cls::class):
+Success!
+
+bindTo(new Cls, Cls::class):
+Success!
+
+bindTo(new ClsChild, Cls::class):
+Success!
+
+bindTo(new ClsUnrelated, Cls::class):
+Success!
+
+bindTo(new Cls, null):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(new Cls, ClsUnrelated::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(new Cls, ClsChild::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+(new SplDoublyLinkedList)->count()
+----------------------------------
+
+bindTo(new SplDoublyLinkedList, SplDoublyLinkedList::class):
+Success!
+
+bindTo(new SplStack, SplDoublyLinkedList::class):
+Success!
+
+bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
+Cannot bind internal method SplDoublyLinkedList::count() to object of class ClsUnrelated
+
+bindTo(null, null):
+Cannot unbind $this of internal method
+
+bindTo(null, SplDoublyLinkedList::class):
+Cannot unbind $this of internal method
+
+bindTo(new SplDoublyLinkedList, null):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
+
+bindTo(new SplDoublyLinkedList, ClsUnrelated::class):
+Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()