diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2013-03-14 05:42:27 +0000 |
---|---|---|
committer | <> | 2013-04-03 16:25:08 +0000 |
commit | c4dd7a1a684490673e25aaf4fabec5df138854c4 (patch) | |
tree | 4d57c44caae4480efff02b90b9be86f44bf25409 /tests/classes | |
download | php2-master.tar.gz |
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'tests/classes')
280 files changed, 10893 insertions, 0 deletions
diff --git a/tests/classes/__call_001.phpt b/tests/classes/__call_001.phpt new file mode 100644 index 0000000..f9708e0 --- /dev/null +++ b/tests/classes/__call_001.phpt @@ -0,0 +1,42 @@ +--TEST-- +ZE2 __call() +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Caller { + public $x = array(1, 2, 3); + + function __call($m, $a) { + echo "Method $m called:\n"; + var_dump($a); + return $this->x; + } +} + +$foo = new Caller(); +$a = $foo->test(1, '2', 3.4, true); +var_dump($a); + +?> +--EXPECT-- +Method test called: +array(4) { + [0]=> + int(1) + [1]=> + string(1) "2" + [2]=> + float(3.4) + [3]=> + bool(true) +} +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/tests/classes/__call_002.phpt b/tests/classes/__call_002.phpt new file mode 100644 index 0000000..53a179f --- /dev/null +++ b/tests/classes/__call_002.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 __call() signature check +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Test { + function __call() { + } +} + +?> +--EXPECTF-- +Fatal error: Method Test::__call() must take exactly 2 arguments in %s__call_002.php on line %d diff --git a/tests/classes/__call_003.phpt b/tests/classes/__call_003.phpt new file mode 100644 index 0000000..c7aa95c --- /dev/null +++ b/tests/classes/__call_003.phpt @@ -0,0 +1,33 @@ +--TEST-- +Force pass-by-reference to __call +--FILE-- +<?php + class C + { + function __call($name, $values) + { + $values[0][0] = 'changed'; + } + } + + $a = array('original'); + + $b = array('original'); + $hack =& $b[0]; + + $c = new C; + $c->f($a); + $c->f($b); + + var_dump($a, $b); +?> +--EXPECTF-- +array(1) { + [0]=> + string(8) "original" +} +array(1) { + [0]=> + &string(7) "changed" +} + diff --git a/tests/classes/__call_004.phpt b/tests/classes/__call_004.phpt new file mode 100644 index 0000000..2072112 --- /dev/null +++ b/tests/classes/__call_004.phpt @@ -0,0 +1,41 @@ +--TEST-- +When __call() is invoked via ::, ensure current scope's __call() is favoured over the specified class's __call(). +--FILE-- +<?php +class A { + function __call($strMethod, $arrArgs) { + echo "In " . __METHOD__ . "($strMethod, array(" . implode(',',$arrArgs) . "))\n"; + var_dump($this); + } +} + +class B extends A { + function __call($strMethod, $arrArgs) { + echo "In " . __METHOD__ . "($strMethod, array(" . implode(',',$arrArgs) . "))\n"; + var_dump($this); + } + + function test() { + A::test1(1,'a'); + B::test2(1,'a'); + self::test3(1,'a'); + parent::test4(1,'a'); + } +} + +$b = new B(); +$b->test(); +?> +--EXPECTF-- +In B::__call(test1, array(1,a)) +object(B)#1 (0) { +} +In B::__call(test2, array(1,a)) +object(B)#1 (0) { +} +In B::__call(test3, array(1,a)) +object(B)#1 (0) { +} +In B::__call(test4, array(1,a)) +object(B)#1 (0) { +}
\ No newline at end of file diff --git a/tests/classes/__call_005.phpt b/tests/classes/__call_005.phpt new file mode 100644 index 0000000..6e15848 --- /dev/null +++ b/tests/classes/__call_005.phpt @@ -0,0 +1,37 @@ +--TEST-- +When __call() is invoked via ::, ensure private implementation of __call() in superclass is accessed without error. +--FILE-- +<?php +class A { + private function __call($strMethod, $arrArgs) { + echo "In " . __METHOD__ . "($strMethod, array(" . implode(',',$arrArgs) . "))\n"; + var_dump($this); + } +} + +class B extends A { + function test() { + A::test1(1,'a'); + B::test2(1,'a'); + self::test3(1,'a'); + parent::test4(1,'a'); + } +} + +$b = new B(); +$b->test(); +?> +--EXPECTF-- +Warning: The magic method __call() must have public visibility and cannot be static in %s__call_005.php on line 3 +In A::__call(test1, array(1,a)) +object(B)#1 (0) { +} +In A::__call(test2, array(1,a)) +object(B)#1 (0) { +} +In A::__call(test3, array(1,a)) +object(B)#1 (0) { +} +In A::__call(test4, array(1,a)) +object(B)#1 (0) { +} diff --git a/tests/classes/__call_006.phpt b/tests/classes/__call_006.phpt new file mode 100644 index 0000000..a65fafb --- /dev/null +++ b/tests/classes/__call_006.phpt @@ -0,0 +1,77 @@ +--TEST-- +Ensure exceptions are handled properly when thrown in __call. +--FILE-- +<?php +class A { + function __call($strMethod, $arrArgs) { + var_dump($this); + throw new Exception; + echo "You should not see this"; + } + function test() { + A::unknownCalledWithSRO(1,2,3); + } +} + +class B extends A { + function test() { + B::unknownCalledWithSROFromChild(1,2,3); + } +} + +$a = new A(); + +echo "---> Invoke __call via simple method call.\n"; +try { + $a->unknown(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via scope resolution operator within instance.\n"; +try { + $a->test(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via scope resolution operator within child instance.\n"; +$b = new B(); +try { + $b->test(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via callback.\n"; +try { + call_user_func(array($b, 'unknownCallback'), 1,2,3); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} +?> +==DONE== +--EXPECTF-- +---> Invoke __call via simple method call. +object(A)#%d (0) { +} +Exception caught OK; continuing. + + +---> Invoke __call via scope resolution operator within instance. +object(A)#%d (0) { +} +Exception caught OK; continuing. + + +---> Invoke __call via scope resolution operator within child instance. +object(B)#%d (0) { +} +Exception caught OK; continuing. + + +---> Invoke __call via callback. +object(B)#%d (0) { +} +Exception caught OK; continuing. +==DONE==
\ No newline at end of file diff --git a/tests/classes/__call_007.phpt b/tests/classes/__call_007.phpt new file mode 100644 index 0000000..d79dba3 --- /dev/null +++ b/tests/classes/__call_007.phpt @@ -0,0 +1,74 @@ +--TEST-- +Ensure exceptions are handled properly when thrown in a statically declared __call. +--FILE-- +<?php +class A { + static function __call($strMethod, $arrArgs) { + @var_dump($this); + throw new Exception; + echo "You should not see this"; + } + function test() { + A::unknownCalledWithSRO(1,2,3); + } +} + +class B extends A { + function test() { + B::unknownCalledWithSROFromChild(1,2,3); + } +} + +$a = new A(); + +echo "---> Invoke __call via simple method call.\n"; +try { + $a->unknown(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via scope resolution operator within instance.\n"; +try { + $a->test(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via scope resolution operator within child instance.\n"; +$b = new B(); +try { + $b->test(); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} + +echo "\n\n---> Invoke __call via callback.\n"; +try { + call_user_func(array($b, 'unknownCallback'), 1,2,3); +} catch (Exception $e) { + echo "Exception caught OK; continuing.\n"; +} +?> +==DONE== +--EXPECTF-- +Warning: The magic method __call() must have public visibility and cannot be static in %s on line 3 +---> Invoke __call via simple method call. +NULL +Exception caught OK; continuing. + + +---> Invoke __call via scope resolution operator within instance. +NULL +Exception caught OK; continuing. + + +---> Invoke __call via scope resolution operator within child instance. +NULL +Exception caught OK; continuing. + + +---> Invoke __call via callback. +NULL +Exception caught OK; continuing. +==DONE==
\ No newline at end of file diff --git a/tests/classes/__set__get_001.phpt b/tests/classes/__set__get_001.phpt new file mode 100644 index 0000000..beb688c --- /dev/null +++ b/tests/classes/__set__get_001.phpt @@ -0,0 +1,72 @@ +--TEST-- +ZE2 __set() and __get() +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class setter { + public $n; + public $x = array('a' => 1, 'b' => 2, 'c' => 3); + + function __get($nm) { + echo "Getting [$nm]\n"; + + if (isset($this->x[$nm])) { + $r = $this->x[$nm]; + echo "Returning: $r\n"; + return $r; + } + else { + echo "Nothing!\n"; + } + } + + function __set($nm, $val) { + echo "Setting [$nm] to $val\n"; + + if (isset($this->x[$nm])) { + $this->x[$nm] = $val; + echo "OK!\n"; + } + else { + echo "Not OK!\n"; + } + } +} + +$foo = new Setter(); + +// this doesn't go through __set()... should it? +$foo->n = 1; + +// the rest are fine... +$foo->a = 100; +$foo->a++; +$foo->z++; +var_dump($foo); + +?> +--EXPECTF-- +Setting [a] to 100 +OK! +Getting [a] +Returning: 100 +Setting [a] to 101 +OK! +Getting [z] +Nothing! +Setting [z] to 1 +Not OK! +object(setter)#%d (2) { + ["n"]=> + int(1) + ["x"]=> + array(3) { + ["a"]=> + int(101) + ["b"]=> + int(2) + ["c"]=> + int(3) + } +} diff --git a/tests/classes/__set__get_002.phpt b/tests/classes/__set__get_002.phpt new file mode 100644 index 0000000..71111cc --- /dev/null +++ b/tests/classes/__set__get_002.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 __get() signature check +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class Test { + function __get($x,$y) { + } +} + +?> +--EXPECTF-- +Fatal error: Method Test::__get() must take exactly 1 argument in %s__set__get_002.php on line %d diff --git a/tests/classes/__set__get_003.phpt b/tests/classes/__set__get_003.phpt new file mode 100644 index 0000000..390d303 --- /dev/null +++ b/tests/classes/__set__get_003.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 __set() signature check +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class Test { + function __set() { + } +} + +?> +--EXPECTF-- +Fatal error: Method Test::__set() must take exactly 2 arguments in %s__set__get_003.php on line %d diff --git a/tests/classes/__set__get_004.phpt b/tests/classes/__set__get_004.phpt new file mode 100644 index 0000000..e3061da --- /dev/null +++ b/tests/classes/__set__get_004.phpt @@ -0,0 +1,39 @@ +--TEST-- +ZE2 __set() and __get() +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class Test { + protected $x; + + function __get($name) { + if (isset($this->x[$name])) { + return $this->x[$name]; + } + else + { + return NULL; + } + } + + function __set($name, $val) { + $this->x[$name] = $val; + } +} + +$foo = new Test(); +$bar = new Test(); +$bar->baz = "Check"; + +$foo->bar = $bar; + +var_dump($bar->baz); +var_dump($foo->bar->baz); + +?> +===DONE=== +--EXPECTF-- +string(5) "Check" +string(5) "Check" +===DONE=== diff --git a/tests/classes/__set__get_005.phpt b/tests/classes/__set__get_005.phpt new file mode 100644 index 0000000..d8bbad3 --- /dev/null +++ b/tests/classes/__set__get_005.phpt @@ -0,0 +1,68 @@ +--TEST-- +ZE2 __set() and __get() +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class Test +{ + protected $x; + + function __get($name) { + echo __METHOD__ . "\n"; + if (isset($this->x[$name])) { + return $this->x[$name]; + } + else + { + return NULL; + } + } + + function __set($name, $val) { + echo __METHOD__ . "\n"; + $this->x[$name] = $val; + } +} + +class AutoGen +{ + protected $x; + + function __get($name) { + echo __METHOD__ . "\n"; + if (!isset($this->x[$name])) { + $this->x[$name] = new Test(); + } + return $this->x[$name]; + } + + function __set($name, $val) { + echo __METHOD__ . "\n"; + $this->x[$name] = $val; + } +} + +$foo = new AutoGen(); +$foo->bar->baz = "Check"; + +var_dump($foo->bar); +var_dump($foo->bar->baz); + +?> +===DONE=== +--EXPECTF-- +AutoGen::__get +Test::__set +AutoGen::__get +object(Test)#%d (1) { + ["x":protected]=> + array(1) { + ["baz"]=> + string(5) "Check" + } +} +AutoGen::__get +Test::__get +string(5) "Check" +===DONE=== diff --git a/tests/classes/__set_data_corrupt.phpt b/tests/classes/__set_data_corrupt.phpt new file mode 100644 index 0000000..6a52bd4 --- /dev/null +++ b/tests/classes/__set_data_corrupt.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 Data corruption in __set +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 is needed'); ?> +--FILE-- +<?php +$f = 'c="foo"'; +class foo { + const foobar=1; + public $pp = array('t'=>null); + + function bar() { + echo $this->t ='f'; + } + function __get($prop) + { + return $this->pp[$prop]; + } + function __set($prop, $val) + { + echo "__set"; + $this->pp[$prop] = ''; + } +} +$f = new foo; +$f->bar(); +?> +--EXPECT-- +__setf diff --git a/tests/classes/abstract.phpt b/tests/classes/abstract.phpt new file mode 100644 index 0000000..fbebf4d --- /dev/null +++ b/tests/classes/abstract.phpt @@ -0,0 +1,30 @@ +--TEST-- +ZE2 An abstract method may not be called +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +abstract class fail { + abstract function show(); +} + +class pass extends fail { + function show() { + echo "Call to function show()\n"; + } + function error() { + parent::show(); + } +} + +$t = new pass(); +$t->show(); +$t->error(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call to function show() + +Fatal error: Cannot call abstract method fail::show() in %s on line %d diff --git a/tests/classes/abstract_by_interface_001.phpt b/tests/classes/abstract_by_interface_001.phpt new file mode 100644 index 0000000..7565fdf --- /dev/null +++ b/tests/classes/abstract_by_interface_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 An abstract method may not be called +--FILE-- +<?php + +class Root { +} + +interface MyInterface +{ + function MyInterfaceFunc(); +} + +abstract class Derived extends Root implements MyInterface { +} + +class Leaf extends Derived +{ + function MyInterfaceFunc() {} +} + +var_dump(new Leaf); + +class Fails extends Root implements MyInterface { +} + +?> +===DONE=== +--EXPECTF-- +object(Leaf)#%d (0) { +} + +Fatal error: Class Fails contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (MyInterface::MyInterfaceFunc) in %sabstract_by_interface_001.php on line %d diff --git a/tests/classes/abstract_by_interface_002.phpt b/tests/classes/abstract_by_interface_002.phpt new file mode 100644 index 0000000..77c5619 --- /dev/null +++ b/tests/classes/abstract_by_interface_002.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 An abstract method may not be called +--FILE-- +<?php + +class Root { +} + +interface MyInterface +{ + static function MyInterfaceFunc(); +} + +abstract class Derived extends Root implements MyInterface { +} + +class Leaf extends Derived +{ + static function MyInterfaceFunc() {} +} + +var_dump(new Leaf); + +class Fails extends Root implements MyInterface { +} + +?> +===DONE=== +--EXPECTF-- +object(Leaf)#%d (0) { +} + +Fatal error: Class Fails contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (MyInterface::MyInterfaceFunc) in %sabstract_by_interface_002.php on line %d diff --git a/tests/classes/abstract_class.phpt b/tests/classes/abstract_class.phpt new file mode 100644 index 0000000..571a9b9 --- /dev/null +++ b/tests/classes/abstract_class.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 An abstract class cannot be instantiated +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +abstract class fail { + abstract function show(); +} + +class pass extends fail { + function show() { + echo "Call to function show()\n"; + } +} + +$t2 = new pass(); +$t2->show(); + +$t = new fail(); +$t->show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call to function show() + +Fatal error: Cannot instantiate abstract class fail in %s on line %d diff --git a/tests/classes/abstract_derived.phpt b/tests/classes/abstract_derived.phpt new file mode 100644 index 0000000..0feceac --- /dev/null +++ b/tests/classes/abstract_derived.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 A derived class with an abstract method must be abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class base { +} + +class derived extends base { + abstract function show(); +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- + +Fatal error: Class derived contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (derived::show) in %sabstract_derived.php on line %d diff --git a/tests/classes/abstract_final.phpt b/tests/classes/abstract_final.phpt new file mode 100644 index 0000000..20c7ae3 --- /dev/null +++ b/tests/classes/abstract_final.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZE2 A final method cannot be abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class fail { + abstract final function show(); +} + +echo "Done\n"; // Shouldn't be displayed +?> +--EXPECTF-- + +Fatal error: Cannot use the final modifier on an abstract class member in %s on line %d diff --git a/tests/classes/abstract_inherit.phpt b/tests/classes/abstract_inherit.phpt new file mode 100644 index 0000000..362ccb0 --- /dev/null +++ b/tests/classes/abstract_inherit.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 A class that inherits an abstract method is abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +abstract class pass { + abstract function show(); +} + +abstract class fail extends pass { +} + +$t = new fail(); +$t = new pass(); + +echo "Done\n"; // Shouldn't be displayed +?> +--EXPECTF-- + +Fatal error: Cannot instantiate abstract class fail in %s on line %d diff --git a/tests/classes/abstract_not_declared.phpt b/tests/classes/abstract_not_declared.phpt new file mode 100644 index 0000000..3b81cd4 --- /dev/null +++ b/tests/classes/abstract_not_declared.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 An abstract class must be declared abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class fail { + abstract function show(); +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Class fail contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (fail::show) in %s on line %d diff --git a/tests/classes/abstract_redeclare.phpt b/tests/classes/abstract_redeclare.phpt new file mode 100644 index 0000000..9a0a1ed --- /dev/null +++ b/tests/classes/abstract_redeclare.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 A method cannot be redeclared abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + function show() { + echo "Call to function show()\n"; + } +} + +class fail extends pass { + abstract function show(); +} + +echo "Done\n"; // Shouldn't be displayed +?> +--EXPECTF-- + +Fatal error: Class fail contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (fail::show) in %sabstract_redeclare.php on line %d diff --git a/tests/classes/abstract_static.phpt b/tests/classes/abstract_static.phpt new file mode 100644 index 0000000..bcebec5 --- /dev/null +++ b/tests/classes/abstract_static.phpt @@ -0,0 +1,36 @@ +--TEST-- +ZE2 A static abstract methods +--FILE-- +<?php + +interface showable +{ + static function show(); +} + +class pass implements showable +{ + static function show() { + echo "Call to function show()\n"; + } +} + +pass::show(); + +eval(' +class fail +{ + abstract static function func(); +} +'); + +fail::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call to function show() + +Strict Standards: Static function fail::func() should not be abstract in %sabstract_static.php(%d) : eval()'d code on line %d + +Fatal error: Class fail contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (fail::func) in %sabstract_static.php(%d) : eval()'d code on line %d diff --git a/tests/classes/abstract_user_call.phpt b/tests/classes/abstract_user_call.phpt new file mode 100644 index 0000000..0e1ddbe --- /dev/null +++ b/tests/classes/abstract_user_call.phpt @@ -0,0 +1,30 @@ +--TEST-- +ZE2 An abstrcat method cannot be called indirectly +--FILE-- +<?php + +abstract class test_base +{ + abstract function func(); +} + +class test extends test_base +{ + function func() + { + echo __METHOD__ . "()\n"; + } +} + +$o = new test; + +$o->func(); + +call_user_func(array($o, 'test_base::func')); + +?> +===DONE=== +--EXPECTF-- +test::func() + +Fatal error: Cannot call abstract method test_base::func() in %s on line %d diff --git a/tests/classes/array_access_001.phpt b/tests/classes/array_access_001.phpt new file mode 100644 index 0000000..feed3fb --- /dev/null +++ b/tests/classes/array_access_001.phpt @@ -0,0 +1,198 @@ +--TEST-- +ZE2 ArrayAccess +--FILE-- +<?php +class object implements ArrayAccess { + + public $a = array('1st', 1, 2=>'3rd', '4th'=>4); + + function offsetExists($index) { + echo __METHOD__ . "($index)\n"; + return array_key_exists($index, $this->a); + } + function offsetGet($index) { + echo __METHOD__ . "($index)\n"; + return $this->a[$index]; + } + function offsetSet($index, $newval) { + echo __METHOD__ . "($index,$newval)\n"; + return $this->a[$index] = $newval; + } + function offsetUnset($index) { + echo __METHOD__ . "($index)\n"; + unset($this->a[$index]); + } +} + +$obj = new Object; + +var_dump($obj->a); + +echo "===EMPTY===\n"; +var_dump(empty($obj[0])); +var_dump(empty($obj[1])); +var_dump(empty($obj[2])); +var_dump(empty($obj['4th'])); +var_dump(empty($obj['5th'])); +var_dump(empty($obj[6])); + +echo "===isset===\n"; +var_dump(isset($obj[0])); +var_dump(isset($obj[1])); +var_dump(isset($obj[2])); +var_dump(isset($obj['4th'])); +var_dump(isset($obj['5th'])); +var_dump(isset($obj[6])); + +echo "===offsetGet===\n"; +var_dump($obj[0]); +var_dump($obj[1]); +var_dump($obj[2]); +var_dump($obj['4th']); +var_dump($obj['5th']); +var_dump($obj[6]); + +echo "===offsetSet===\n"; +echo "WRITE 1\n"; +$obj[1] = 'Changed 1'; +var_dump($obj[1]); +echo "WRITE 2\n"; +$obj['4th'] = 'Changed 4th'; +var_dump($obj['4th']); +echo "WRITE 3\n"; +$obj['5th'] = 'Added 5th'; +var_dump($obj['5th']); +echo "WRITE 4\n"; +$obj[6] = 'Added 6'; +var_dump($obj[6]); + +var_dump($obj[0]); +var_dump($obj[2]); + +$x = $obj[6] = 'changed 6'; +var_dump($obj[6]); +var_dump($x); + +echo "===unset===\n"; +var_dump($obj->a); +unset($obj[2]); +unset($obj['4th']); +unset($obj[7]); +unset($obj['8th']); +var_dump($obj->a); + +?> +===DONE=== +--EXPECTF-- +array(4) { + [0]=> + string(3) "1st" + [1]=> + int(1) + [2]=> + string(3) "3rd" + ["4th"]=> + int(4) +} +===EMPTY=== +object::offsetExists(0) +object::offsetGet(0) +bool(false) +object::offsetExists(1) +object::offsetGet(1) +bool(false) +object::offsetExists(2) +object::offsetGet(2) +bool(false) +object::offsetExists(4th) +object::offsetGet(4th) +bool(false) +object::offsetExists(5th) +bool(true) +object::offsetExists(6) +bool(true) +===isset=== +object::offsetExists(0) +bool(true) +object::offsetExists(1) +bool(true) +object::offsetExists(2) +bool(true) +object::offsetExists(4th) +bool(true) +object::offsetExists(5th) +bool(false) +object::offsetExists(6) +bool(false) +===offsetGet=== +object::offsetGet(0) +string(3) "1st" +object::offsetGet(1) +int(1) +object::offsetGet(2) +string(3) "3rd" +object::offsetGet(4th) +int(4) +object::offsetGet(5th) + +Notice: Undefined index: 5th in %sarray_access_001.php on line %d +NULL +object::offsetGet(6) + +Notice: Undefined offset: 6 in %sarray_access_001.php on line %d +NULL +===offsetSet=== +WRITE 1 +object::offsetSet(1,Changed 1) +object::offsetGet(1) +string(9) "Changed 1" +WRITE 2 +object::offsetSet(4th,Changed 4th) +object::offsetGet(4th) +string(11) "Changed 4th" +WRITE 3 +object::offsetSet(5th,Added 5th) +object::offsetGet(5th) +string(9) "Added 5th" +WRITE 4 +object::offsetSet(6,Added 6) +object::offsetGet(6) +string(7) "Added 6" +object::offsetGet(0) +string(3) "1st" +object::offsetGet(2) +string(3) "3rd" +object::offsetSet(6,changed 6) +object::offsetGet(6) +string(9) "changed 6" +string(9) "changed 6" +===unset=== +array(6) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + [2]=> + string(3) "3rd" + ["4th"]=> + string(11) "Changed 4th" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} +object::offsetUnset(2) +object::offsetUnset(4th) +object::offsetUnset(7) +object::offsetUnset(8th) +array(4) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} +===DONE=== diff --git a/tests/classes/array_access_002.phpt b/tests/classes/array_access_002.phpt new file mode 100644 index 0000000..68640c8 --- /dev/null +++ b/tests/classes/array_access_002.phpt @@ -0,0 +1,198 @@ +--TEST-- +ZE2 ArrayAccess::offsetSet without return +--FILE-- +<?php +class object implements ArrayAccess { + + public $a = array('1st', 1, 2=>'3rd', '4th'=>4); + + function offsetExists($index) { + echo __METHOD__ . "($index)\n"; + return array_key_exists($index, $this->a); + } + function offsetGet($index) { + echo __METHOD__ . "($index)\n"; + return $this->a[$index]; + } + function offsetSet($index, $newval) { + echo __METHOD__ . "($index,$newval)\n"; + /*return*/ $this->a[$index] = $newval; + } + function offsetUnset($index) { + echo __METHOD__ . "($index)\n"; + unset($this->a[$index]); + } +} + +$obj = new Object; + +var_dump($obj->a); + +echo "===EMPTY===\n"; +var_dump(empty($obj[0])); +var_dump(empty($obj[1])); +var_dump(empty($obj[2])); +var_dump(empty($obj['4th'])); +var_dump(empty($obj['5th'])); +var_dump(empty($obj[6])); + +echo "===isset===\n"; +var_dump(isset($obj[0])); +var_dump(isset($obj[1])); +var_dump(isset($obj[2])); +var_dump(isset($obj['4th'])); +var_dump(isset($obj['5th'])); +var_dump(isset($obj[6])); + +echo "===offsetGet===\n"; +var_dump($obj[0]); +var_dump($obj[1]); +var_dump($obj[2]); +var_dump($obj['4th']); +var_dump($obj['5th']); +var_dump($obj[6]); + +echo "===offsetSet===\n"; +echo "WRITE 1\n"; +$obj[1] = 'Changed 1'; +var_dump($obj[1]); +echo "WRITE 2\n"; +$obj['4th'] = 'Changed 4th'; +var_dump($obj['4th']); +echo "WRITE 3\n"; +$obj['5th'] = 'Added 5th'; +var_dump($obj['5th']); +echo "WRITE 4\n"; +$obj[6] = 'Added 6'; +var_dump($obj[6]); + +var_dump($obj[0]); +var_dump($obj[2]); + +$x = $obj[6] = 'changed 6'; +var_dump($obj[6]); +var_dump($x); + +echo "===unset===\n"; +var_dump($obj->a); +unset($obj[2]); +unset($obj['4th']); +unset($obj[7]); +unset($obj['8th']); +var_dump($obj->a); + +?> +===DONE=== +--EXPECTF-- +array(4) { + [0]=> + string(3) "1st" + [1]=> + int(1) + [2]=> + string(3) "3rd" + ["4th"]=> + int(4) +} +===EMPTY=== +object::offsetExists(0) +object::offsetGet(0) +bool(false) +object::offsetExists(1) +object::offsetGet(1) +bool(false) +object::offsetExists(2) +object::offsetGet(2) +bool(false) +object::offsetExists(4th) +object::offsetGet(4th) +bool(false) +object::offsetExists(5th) +bool(true) +object::offsetExists(6) +bool(true) +===isset=== +object::offsetExists(0) +bool(true) +object::offsetExists(1) +bool(true) +object::offsetExists(2) +bool(true) +object::offsetExists(4th) +bool(true) +object::offsetExists(5th) +bool(false) +object::offsetExists(6) +bool(false) +===offsetGet=== +object::offsetGet(0) +string(3) "1st" +object::offsetGet(1) +int(1) +object::offsetGet(2) +string(3) "3rd" +object::offsetGet(4th) +int(4) +object::offsetGet(5th) + +Notice: Undefined index: 5th in %sarray_access_002.php on line %d +NULL +object::offsetGet(6) + +Notice: Undefined offset: 6 in %sarray_access_002.php on line %d +NULL +===offsetSet=== +WRITE 1 +object::offsetSet(1,Changed 1) +object::offsetGet(1) +string(9) "Changed 1" +WRITE 2 +object::offsetSet(4th,Changed 4th) +object::offsetGet(4th) +string(11) "Changed 4th" +WRITE 3 +object::offsetSet(5th,Added 5th) +object::offsetGet(5th) +string(9) "Added 5th" +WRITE 4 +object::offsetSet(6,Added 6) +object::offsetGet(6) +string(7) "Added 6" +object::offsetGet(0) +string(3) "1st" +object::offsetGet(2) +string(3) "3rd" +object::offsetSet(6,changed 6) +object::offsetGet(6) +string(9) "changed 6" +string(9) "changed 6" +===unset=== +array(6) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + [2]=> + string(3) "3rd" + ["4th"]=> + string(11) "Changed 4th" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} +object::offsetUnset(2) +object::offsetUnset(4th) +object::offsetUnset(7) +object::offsetUnset(8th) +array(4) { + [0]=> + string(3) "1st" + [1]=> + string(9) "Changed 1" + ["5th"]=> + string(9) "Added 5th" + [6]=> + string(9) "changed 6" +} +===DONE=== diff --git a/tests/classes/array_access_003.phpt b/tests/classes/array_access_003.phpt new file mode 100644 index 0000000..3e63112 --- /dev/null +++ b/tests/classes/array_access_003.phpt @@ -0,0 +1,59 @@ +--TEST-- +ZE2 ArrayAccess::offsetGet ambiguties +--INI-- +error_reporting=4095 +--FILE-- +<?php +class object implements ArrayAccess { + + public $a = array('1st', 1, 2=>'3rd', '4th'=>4); + + function offsetExists($index) { + echo __METHOD__ . "($index)\n"; + return array_key_exists($index, $this->a); + } + function offsetGet($index) { + echo __METHOD__ . "($index)\n"; + switch($index) { + case 1: + $a = 'foo'; + return $a . 'Bar'; + case 2: + static $a=1; + return $a; + } + return $this->a[$index]; + } + function offsetSet($index, $newval) { + echo __METHOD__ . "($index,$newval)\n"; + if ($index==3) { + $this->cnt = $newval; + } + return $this->a[$index] = $newval; + } + function offsetUnset($index) { + echo __METHOD__ . "($index)\n"; + unset($this->a[$index]); + } +} + +$obj = new Object; + +var_dump($obj[1]); +var_dump($obj[2]); +$obj[2]++; +var_dump($obj[2]); + +?> +===DONE=== +--EXPECTF-- +object::offsetGet(1) +string(6) "fooBar" +object::offsetGet(2) +int(1) +object::offsetGet(2) + +Notice: Indirect modification of overloaded element of object has no effect in %sarray_access_003.php on line 39 +object::offsetGet(2) +int(1) +===DONE=== diff --git a/tests/classes/array_access_004.phpt b/tests/classes/array_access_004.phpt new file mode 100644 index 0000000..7874967 --- /dev/null +++ b/tests/classes/array_access_004.phpt @@ -0,0 +1,57 @@ +--TEST-- +ZE2 ArrayAccess::offsetGet ambiguties +--FILE-- +<?php +class object implements ArrayAccess { + + public $a = array('1st', 1, 2=>'3rd', '4th'=>4); + + function offsetExists($index) { + echo __METHOD__ . "($index)\n"; + return array_key_exists($index, $this->a); + } + function offsetGet($index) { + echo __METHOD__ . "($index)\n"; + switch($index) { + case 1: + $a = 'foo'; + return $a . 'Bar'; + case 2: + static $a=1; + return $a; + } + return $this->a[$index]; + } + function offsetSet($index, $newval) { + echo __METHOD__ . "($index,$newval)\n"; + if ($index==3) { + $this->cnt = $newval; + } + return $this->a[$index] = $newval; + } + function offsetUnset($index) { + echo __METHOD__ . "($index)\n"; + unset($this->a[$index]); + } +} + +$obj = new Object; + +var_dump($obj[1]); +var_dump($obj[2]); +$obj[2]++; +var_dump($obj[2]); + +?> +===DONE=== +--EXPECTF-- +object::offsetGet(1) +string(6) "fooBar" +object::offsetGet(2) +int(1) +object::offsetGet(2) + +Notice: Indirect modification of overloaded element of object has no effect in %sarray_access_004.php on line 39 +object::offsetGet(2) +int(1) +===DONE=== diff --git a/tests/classes/array_access_005.phpt b/tests/classes/array_access_005.phpt new file mode 100644 index 0000000..dcb873f --- /dev/null +++ b/tests/classes/array_access_005.phpt @@ -0,0 +1,77 @@ +--TEST-- +ZE2 ArrayAccess and sub Arrays +--FILE-- +<?php + +class Peoples implements ArrayAccess { + public $person; + + function __construct() { + $this->person = array(array('name'=>'Joe')); + } + + function offsetExists($index) { + return array_key_exists($this->person, $index); + } + + function offsetGet($index) { + return $this->person[$index]; + } + + function offsetSet($index, $value) { + $this->person[$index] = $value; + } + + function offsetUnset($index) { + unset($this->person[$index]); + } +} + +$people = new Peoples; + +var_dump($people->person[0]['name']); +$people->person[0]['name'] = $people->person[0]['name'] . 'Foo'; +var_dump($people->person[0]['name']); +$people->person[0]['name'] .= 'Bar'; +var_dump($people->person[0]['name']); + +echo "---ArrayOverloading---\n"; + +$people = new Peoples; + +var_dump($people[0]); +var_dump($people[0]['name']); +var_dump($people->person[0]['name'] . 'Foo'); // impossible to assign this since we don't return references here +$x = $people[0]; // creates a copy +$x['name'] .= 'Foo'; +$people[0] = $x; +var_dump($people[0]); +$people[0]['name'] = 'JoeFoo'; +var_dump($people[0]['name']); +$people[0]['name'] = 'JoeFooBar'; +var_dump($people[0]['name']); + +?> +===DONE=== +--EXPECTF-- +string(3) "Joe" +string(6) "JoeFoo" +string(9) "JoeFooBar" +---ArrayOverloading--- +array(1) { + ["name"]=> + string(3) "Joe" +} +string(3) "Joe" +string(6) "JoeFoo" +array(1) { + ["name"]=> + string(6) "JoeFoo" +} + +Notice: Indirect modification of overloaded element of Peoples has no effect in %sarray_access_005.php on line 46 +string(6) "JoeFoo" + +Notice: Indirect modification of overloaded element of Peoples has no effect in %sarray_access_005.php on line 48 +string(6) "JoeFoo" +===DONE=== diff --git a/tests/classes/array_access_006.phpt b/tests/classes/array_access_006.phpt new file mode 100644 index 0000000..342a7e5 --- /dev/null +++ b/tests/classes/array_access_006.phpt @@ -0,0 +1,37 @@ +--TEST-- +ZE2 ArrayAccess and ASSIGN_OP operators (+=) +--FILE-- +<?php + +class OverloadedArray implements ArrayAccess { + public $realArray; + + function __construct() { + $this->realArray = array(1,2,3); + } + + function offsetExists($index) { + return array_key_exists($this->realArray, $index); + } + + function offsetGet($index) { + return $this->realArray[$index]; + } + + function offsetSet($index, $value) { + $this->realArray[$index] = $value; + } + + function offsetUnset($index) { + unset($this->realArray[$index]); + } +} + +$a = new OverloadedArray; +$a[1] += 10; +var_dump($a[1]); +echo "---Done---\n"; +?> +--EXPECT-- +int(12) +---Done--- diff --git a/tests/classes/array_access_007.phpt b/tests/classes/array_access_007.phpt new file mode 100644 index 0000000..42187fe --- /dev/null +++ b/tests/classes/array_access_007.phpt @@ -0,0 +1,57 @@ +--TEST-- +ZE2 ArrayAccess and [] assignment +--FILE-- +<?php + +class OverloadedArray implements ArrayAccess { + public $realArray; + + function __construct() { + $this->realArray = array(); + } + + function offsetExists($index) { + return array_key_exists($this->realArray, $index); + } + + function offsetGet($index) { + return $this->realArray[$index]; + } + + function offsetSet($index, $value) { + if (is_null($index)) { + $this->realArray[] = $value; + } else { + $this->realArray[$index] = $value; + } + } + + function offsetUnset($index) { + unset($this->realArray[$index]); + } + + function dump() { + var_dump($this->realArray); + } +} + +$a = new OverloadedArray; +$a[] = 1; +$a[1] = 2; +$a[2] = 3; +$a[] = 4; +$a->dump(); +?> +===DONE=== +--EXPECT-- +array(4) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + [3]=> + int(4) +} +===DONE=== diff --git a/tests/classes/array_access_008.phpt b/tests/classes/array_access_008.phpt new file mode 100644 index 0000000..9979889 --- /dev/null +++ b/tests/classes/array_access_008.phpt @@ -0,0 +1,67 @@ +--TEST-- +ZE2 ArrayAccess and ASSIGN_OP operators (.=) +--FILE-- +<?php + +class Peoples implements ArrayAccess { + public $person; + + function __construct() { + $this->person = array(array('name'=>'Foo')); + } + + function offsetExists($index) { + return array_key_exists($this->person, $index); + } + + function offsetGet($index) { + return $this->person[$index]; + } + + function offsetSet($index, $value) { + $this->person[$index] = $value; + } + + function offsetUnset($index) { + unset($this->person[$index]); + } +} + +$people = new Peoples; + +var_dump($people->person[0]['name']); +$people->person[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people->person[0]['name']); +$people->person[0]['name'] .= 'Baz'; +var_dump($people->person[0]['name']); + +echo "===ArrayOverloading===\n"; + +$people = new Peoples; + +var_dump($people[0]['name']); +$people[0]['name'] = 'FooBar'; +var_dump($people[0]['name']); +$people[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people[0]['name']); +$people[0]['name'] .= 'Baz'; +var_dump($people[0]['name']); + +?> +===DONE=== +--EXPECTF-- +string(3) "Foo" +string(6) "FooBar" +string(9) "FooBarBaz" +===ArrayOverloading=== +string(3) "Foo" + +Notice: Indirect modification of overloaded element of Peoples has no effect in %sarray_access_008.php on line 40 +string(3) "Foo" + +Notice: Indirect modification of overloaded element of Peoples has no effect in %sarray_access_008.php on line 42 +string(3) "Foo" + +Notice: Indirect modification of overloaded element of Peoples has no effect in %sarray_access_008.php on line 44 +string(3) "Foo" +===DONE=== diff --git a/tests/classes/array_access_009.phpt b/tests/classes/array_access_009.phpt new file mode 100644 index 0000000..3862240 --- /dev/null +++ b/tests/classes/array_access_009.phpt @@ -0,0 +1,190 @@ +--TEST-- +ZE2 ArrayAccess and ArrayProxyAccess, ArrayProxy +--FILE-- +<?php + +// NOTE: This will become part of SPL + +interface ArrayProxyAccess extends ArrayAccess +{ + function proxyGet($element); + function proxySet($element, $index, $value); + function proxyUnset($element, $index); +} + +class ArrayProxy implements ArrayAccess +{ + private $object; + private $element; + + function __construct(ArrayProxyAccess $object, $element) + { + echo __METHOD__ . "($element)\n"; + if (!$object->offsetExists($element)) + { + $object[$element] = array(); + } + $this->object = $object; + $this->element = $element; + } + + function offsetExists($index) { + echo __METHOD__ . "($this->element, $index)\n"; + return array_key_exists($index, $this->object->proxyGet($this->element)); + } + + function offsetGet($index) { + echo __METHOD__ . "($this->element, $index)\n"; + $tmp = $this->object->proxyGet($this->element); + return isset($tmp[$index]) ? $tmp[$index] : NULL; + } + + function offsetSet($index, $value) { + echo __METHOD__ . "($this->element, $index, $value)\n"; + $this->object->proxySet($this->element, $index, $value); + } + + function offsetUnset($index) { + echo __METHOD__ . "($this->element, $index)\n"; + $this->object->proxyUnset($this->element, $index); + } +} + +class Peoples implements ArrayProxyAccess +{ + public $person; + + function __construct() + { + $this->person = array(array('name'=>'Foo')); + } + + function offsetExists($index) + { + return array_key_exists($index, $this->person); + } + + function offsetGet($index) + { + return new ArrayProxy($this, $index); + } + + function offsetSet($index, $value) + { + $this->person[$index] = $value; + } + + function offsetUnset($index) + { + unset($this->person[$index]); + } + + function proxyGet($element) + { + return $this->person[$element]; + } + + function proxySet($element, $index, $value) + { + $this->person[$element][$index] = $value; + } + + function proxyUnset($element, $index) + { + unset($this->person[$element][$index]); + } +} + +$people = new Peoples; + +var_dump($people->person[0]['name']); +$people->person[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people->person[0]['name']); +$people->person[0]['name'] .= 'Baz'; +var_dump($people->person[0]['name']); + +echo "===ArrayOverloading===\n"; + +$people = new Peoples; + +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'FooBar'; +var_dump($people[0]['name']); +$people[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people[0]['name']); +$people[0]['name'] .= 'Baz'; +var_dump($people[0]['name']); +unset($people[0]['name']); +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'BlaBla'; +var_dump($people[0]['name']); + +?> +===DONE=== +--EXPECTF-- +string(3) "Foo" +string(6) "FooBar" +string(9) "FooBarBaz" +===ArrayOverloading=== +ArrayProxy::__construct(0) +object(ArrayProxy)#%d (2) { + ["object":"ArrayProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + array(1) { + [0]=> + array(1) { + ["name"]=> + string(3) "Foo" + } + } + } + ["element":"ArrayProxy":private]=> + int(0) +} +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +string(3) "Foo" +ArrayProxy::__construct(0) +ArrayProxy::offsetSet(0, name, FooBar) +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +string(6) "FooBar" +ArrayProxy::__construct(0) +ArrayProxy::offsetSet(0, name, FooBarBar) +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +string(9) "FooBarBar" +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +ArrayProxy::offsetSet(0, name, FooBarBarBaz) +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +string(12) "FooBarBarBaz" +ArrayProxy::__construct(0) +ArrayProxy::offsetUnset(0, name) +ArrayProxy::__construct(0) +object(ArrayProxy)#%d (2) { + ["object":"ArrayProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + array(1) { + [0]=> + array(0) { + } + } + } + ["element":"ArrayProxy":private]=> + int(0) +} +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +NULL +ArrayProxy::__construct(0) +ArrayProxy::offsetSet(0, name, BlaBla) +ArrayProxy::__construct(0) +ArrayProxy::offsetGet(0, name) +string(6) "BlaBla" +===DONE=== diff --git a/tests/classes/array_access_010.phpt b/tests/classes/array_access_010.phpt new file mode 100644 index 0000000..ad374d2 --- /dev/null +++ b/tests/classes/array_access_010.phpt @@ -0,0 +1,168 @@ +--TEST-- +ZE2 ArrayAccess and ArrayReferenceProxy with references +--FILE-- +<?php + +// NOTE: This will become part of SPL + +class ArrayReferenceProxy implements ArrayAccess +{ + private $object; + private $element; + + function __construct(ArrayAccess $object, array &$element) + { + echo __METHOD__ . "(Array)\n"; + $this->object = $object; + $this->element = &$element; + } + + function offsetExists($index) { + echo __METHOD__ . "($this->element, $index)\n"; + return array_key_exists($index, $this->element); + } + + function offsetGet($index) { + echo __METHOD__ . "(Array, $index)\n"; + return isset($this->element[$index]) ? $this->element[$index] : NULL; + } + + function offsetSet($index, $value) { + echo __METHOD__ . "(Array, $index, $value)\n"; + $this->element[$index] = $value; + } + + function offsetUnset($index) { + echo __METHOD__ . "(Array, $index)\n"; + unset($this->element[$index]); + } +} + +class Peoples implements ArrayAccess +{ + public $person; + + function __construct() + { + $this->person = array(array('name'=>'Foo')); + } + + function offsetExists($index) + { + return array_key_exists($index, $this->person); + } + + function offsetGet($index) + { + return new ArrayReferenceProxy($this, $this->person[$index]); + } + + function offsetSet($index, $value) + { + $this->person[$index] = $value; + } + + function offsetUnset($index) + { + unset($this->person[$index]); + } +} + +$people = new Peoples; + +var_dump($people->person[0]['name']); +$people->person[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people->person[0]['name']); +$people->person[0]['name'] .= 'Baz'; +var_dump($people->person[0]['name']); + +echo "===ArrayOverloading===\n"; + +$people = new Peoples; + +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'FooBar'; +var_dump($people[0]['name']); +$people[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people[0]['name']); +$people[0]['name'] .= 'Baz'; +var_dump($people[0]['name']); +unset($people[0]['name']); +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'BlaBla'; +var_dump($people[0]['name']); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +string(3) "Foo" +string(6) "FooBar" +string(9) "FooBarBaz" +===ArrayOverloading=== +ArrayReferenceProxy::__construct(Array) +object(ArrayReferenceProxy)#%d (2) { + ["object":"ArrayReferenceProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + array(1) { + [0]=> + &array(1) { + ["name"]=> + string(3) "Foo" + } + } + } + ["element":"ArrayReferenceProxy":private]=> + &array(1) { + ["name"]=> + string(3) "Foo" + } +} +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +string(3) "Foo" +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetSet(Array, name, FooBar) +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +string(6) "FooBar" +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetSet(Array, name, FooBarBar) +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +string(9) "FooBarBar" +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +ArrayReferenceProxy::offsetSet(Array, name, FooBarBarBaz) +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +string(12) "FooBarBarBaz" +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetUnset(Array, name) +ArrayReferenceProxy::__construct(Array) +object(ArrayReferenceProxy)#%d (2) { + ["object":"ArrayReferenceProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + array(1) { + [0]=> + &array(0) { + } + } + } + ["element":"ArrayReferenceProxy":private]=> + &array(0) { + } +} +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +NULL +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetSet(Array, name, BlaBla) +ArrayReferenceProxy::__construct(Array) +ArrayReferenceProxy::offsetGet(Array, name) +string(6) "BlaBla" +===DONE=== diff --git a/tests/classes/array_access_011.phpt b/tests/classes/array_access_011.phpt new file mode 100644 index 0000000..aa20a56 --- /dev/null +++ b/tests/classes/array_access_011.phpt @@ -0,0 +1,187 @@ +--TEST-- +ZE2 ArrayAccess and ArrayAccessReferenceProxy with references to main array +--FILE-- +<?php + +// NOTE: This will become part of SPL + +class ArrayAccessReferenceProxy implements ArrayAccess +{ + private $object; + private $oarray; + private $element; + + function __construct(ArrayAccess $object, array &$array, $element) + { + echo __METHOD__ . "($element)\n"; + $this->object = $object; + $this->oarray = &$array; + $this->element = $element; + } + + function offsetExists($index) { + echo __METHOD__ . "($this->element, $index)\n"; + return array_key_exists($index, $this->oarray[$this->element]); + } + + function offsetGet($index) { + echo __METHOD__ . "($this->element, $index)\n"; + return isset($this->oarray[$this->element][$index]) ? $this->oarray[$this->element][$index] : NULL; + } + + function offsetSet($index, $value) { + echo __METHOD__ . "($this->element, $index, $value)\n"; + $this->oarray[$this->element][$index] = $value; + } + + function offsetUnset($index) { + echo __METHOD__ . "($this->element, $index)\n"; + unset($this->oarray[$this->element][$index]); + } +} + +class Peoples implements ArrayAccess +{ + public $person; + + function __construct() + { + $this->person = array(array('name'=>'Foo')); + } + + function offsetExists($index) + { + return array_key_exists($index, $this->person); + } + + function offsetGet($index) + { + if (is_array($this->person[$index])) + { + return new ArrayAccessReferenceProxy($this, $this->person, $index); + } + else + { + return $this->person[$index]; + } + } + + function offsetSet($index, $value) + { + $this->person[$index] = $value; + } + + function offsetUnset($index) + { + unset($this->person[$index]); + } +} + +$people = new Peoples; + +var_dump($people->person[0]['name']); +$people->person[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people->person[0]['name']); +$people->person[0]['name'] .= 'Baz'; +var_dump($people->person[0]['name']); + +echo "===ArrayOverloading===\n"; + +$people = new Peoples; + +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'FooBar'; +var_dump($people[0]['name']); +$people[0]['name'] = $people->person[0]['name'] . 'Bar'; +var_dump($people[0]['name']); +$people[0]['name'] .= 'Baz'; +var_dump($people[0]['name']); +unset($people[0]['name']); +var_dump($people[0]); +var_dump($people[0]['name']); +$people[0]['name'] = 'BlaBla'; +var_dump($people[0]['name']); + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +string(3) "Foo" +string(6) "FooBar" +string(9) "FooBarBaz" +===ArrayOverloading=== +ArrayAccessReferenceProxy::__construct(0) +object(ArrayAccessReferenceProxy)#%d (3) { + ["object":"ArrayAccessReferenceProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + &array(1) { + [0]=> + array(1) { + ["name"]=> + string(3) "Foo" + } + } + } + ["oarray":"ArrayAccessReferenceProxy":private]=> + &array(1) { + [0]=> + array(1) { + ["name"]=> + string(3) "Foo" + } + } + ["element":"ArrayAccessReferenceProxy":private]=> + int(0) +} +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +string(3) "Foo" +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetSet(0, name, FooBar) +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +string(6) "FooBar" +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetSet(0, name, FooBarBar) +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +string(9) "FooBarBar" +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +ArrayAccessReferenceProxy::offsetSet(0, name, FooBarBarBaz) +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +string(12) "FooBarBarBaz" +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetUnset(0, name) +ArrayAccessReferenceProxy::__construct(0) +object(ArrayAccessReferenceProxy)#%d (3) { + ["object":"ArrayAccessReferenceProxy":private]=> + object(Peoples)#%d (1) { + ["person"]=> + &array(1) { + [0]=> + array(0) { + } + } + } + ["oarray":"ArrayAccessReferenceProxy":private]=> + &array(1) { + [0]=> + array(0) { + } + } + ["element":"ArrayAccessReferenceProxy":private]=> + int(0) +} +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +NULL +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetSet(0, name, BlaBla) +ArrayAccessReferenceProxy::__construct(0) +ArrayAccessReferenceProxy::offsetGet(0, name) +string(6) "BlaBla" +===DONE=== diff --git a/tests/classes/array_access_012.phpt b/tests/classes/array_access_012.phpt new file mode 100644 index 0000000..8f85f29 --- /dev/null +++ b/tests/classes/array_access_012.phpt @@ -0,0 +1,36 @@ +--TEST-- +ZE2 ArrayAccess cannot assign by reference +--FILE-- +<?php + +class ArrayAccessImpl implements ArrayAccess { + private $data = array(); + + public function offsetUnset($index) {} + + public function offsetSet($index, $value) { + $this->data[$index] = $value; + } + + public function offsetGet($index) { + return $this->data[$index]; + } + + public function offsetExists($index) { + return isset($this->data[$index]); + } +} + +$data = new ArrayAccessImpl(); +$test = 'some data'; +$data['element'] = NULL; // prevent notice +$data['element'] = &$test; + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- + +Notice: Indirect modification of overloaded element of ArrayAccessImpl has no effect in %sarray_access_012.php on line 24 + +Fatal error: Cannot assign by reference to overloaded object in %sarray_access_012.php on line 24 diff --git a/tests/classes/array_access_013.phpt b/tests/classes/array_access_013.phpt new file mode 100644 index 0000000..206d9d5 --- /dev/null +++ b/tests/classes/array_access_013.phpt @@ -0,0 +1,58 @@ +--TEST-- +ZE2 ArrayAccess and exceptions +--FILE-- +<?php + +class Test implements ArrayAccess +{ + public function offsetExists($offset) { throw new Exception(__METHOD__); return false; } + public function offsetGet($offset) { throw new Exception(__METHOD__); return $offset; } + public function offsetSet($offset, $data ) { throw new Exception(__METHOD__); } + public function offsetUnset($offset) { throw new Exception(__METHOD__); } +} + +$t = new Test; + +try +{ + echo isset($t[0]); +} +catch(Exception $e) +{ + echo "Caught in " . $e->getMessage() . "()\n"; +} + +try +{ + echo $t[0]; +} +catch(Exception $e) +{ + echo "Caught in " . $e->getMessage() . "()\n"; +} + +try +{ + $t[0] = 1; +} +catch(Exception $e) +{ + echo "Caught in " . $e->getMessage() . "()\n"; +} + +try +{ + unset($t[0]); +} +catch(Exception $e) +{ + echo "Caught in " . $e->getMessage() . "()\n"; +} +?> +===DONE=== +--EXPECT-- +Caught in Test::offsetExists() +Caught in Test::offsetGet() +Caught in Test::offsetSet() +Caught in Test::offsetUnset() +===DONE=== diff --git a/tests/classes/arrayobject_001.phpt b/tests/classes/arrayobject_001.phpt new file mode 100644 index 0000000..b75f8c7 --- /dev/null +++ b/tests/classes/arrayobject_001.phpt @@ -0,0 +1,13 @@ +--TEST-- +Ensure that ArrayObject acts like an array +--FILE-- +<?php + +$a = new ArrayObject; +$a['foo'] = 'bar'; +echo reset($a); +echo count($a); +echo current($a); +?> +--EXPECT-- +bar1bar diff --git a/tests/classes/assign_op_property_001.phpt b/tests/classes/assign_op_property_001.phpt new file mode 100644 index 0000000..21e131c --- /dev/null +++ b/tests/classes/assign_op_property_001.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 assign_op property of overloaded object +--FILE-- +<?php + +class Test { + private $real_a = 2; + + function __set($property, $value) { + if ($property == "a") { + $this->real_a = $value; + } + } + + function __get($property) { + if ($property == "a") { + return $this->real_a; + } + } +} + +$obj = new Test; +var_dump($obj->a); +$obj->a += 2; +var_dump($obj->a); +echo "---Done---\n"; +?> +--EXPECT-- +int(2) +int(4) +---Done--- diff --git a/tests/classes/autoload_001.phpt b/tests/classes/autoload_001.phpt new file mode 100644 index 0000000..6f325f4 --- /dev/null +++ b/tests/classes/autoload_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Autoload and class_exists +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + require_once(dirname(__FILE__) . '/' . $class_name . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(class_exists('autoload_root')); + +?> +===DONE=== +--EXPECT-- +__autoload(autoload_root) +bool(true) +===DONE=== diff --git a/tests/classes/autoload_002.phpt b/tests/classes/autoload_002.phpt new file mode 100644 index 0000000..27dea0f --- /dev/null +++ b/tests/classes/autoload_002.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 Autoload and get_class_methods +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + require_once(dirname(__FILE__) . '/' . $class_name . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(get_class_methods('autoload_root')); + +?> +===DONE=== +--EXPECT-- +__autoload(autoload_root) +array(1) { + [0]=> + string(12) "testFunction" +} +===DONE=== diff --git a/tests/classes/autoload_003.phpt b/tests/classes/autoload_003.phpt new file mode 100644 index 0000000..7bdb5da --- /dev/null +++ b/tests/classes/autoload_003.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 Autoload and derived classes +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + require_once(dirname(__FILE__) . '/' . $class_name . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(class_exists('autoload_derived')); + +?> +===DONE=== +--EXPECT-- +__autoload(autoload_root) +__autoload(autoload_derived) +bool(true) +===DONE=== diff --git a/tests/classes/autoload_004.phpt b/tests/classes/autoload_004.phpt new file mode 100644 index 0000000..23aea5d --- /dev/null +++ b/tests/classes/autoload_004.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZE2 Autoload and recursion +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + var_dump(class_exists($class_name)); + require_once(dirname(__FILE__) . '/' . $class_name . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(class_exists('autoload_derived')); + +?> +===DONE=== +--EXPECT-- +bool(false) +bool(false) +__autoload(autoload_root) +__autoload(autoload_derived) +bool(true) +===DONE=== diff --git a/tests/classes/autoload_005.phpt b/tests/classes/autoload_005.phpt new file mode 100644 index 0000000..36a4e18 --- /dev/null +++ b/tests/classes/autoload_005.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 Autoload from destructor +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + var_dump(class_exists($class_name, false)); + require_once(dirname(__FILE__) . '/' . $class_name . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(class_exists('autoload_derived', false)); +var_dump(class_exists('autoload_derived', false)); + +class Test +{ + function __destruct() { + echo __METHOD__ . "\n"; + $o = new autoload_derived; + var_dump($o); + } +} + +$o = new Test; +unset($o); + +?> +===DONE=== +--EXPECTF-- +bool(false) +bool(false) +Test::__destruct +bool(false) +bool(false) +__autoload(autoload_root) +__autoload(autoload_derived) +object(autoload_derived)#%d (0) { +} +===DONE=== diff --git a/tests/classes/autoload_006.phpt b/tests/classes/autoload_006.phpt new file mode 100644 index 0000000..9af6fc9 --- /dev/null +++ b/tests/classes/autoload_006.phpt @@ -0,0 +1,40 @@ +--TEST-- +ZE2 Autoload from destructor +--SKIPIF-- +<?php + if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); + if (class_exists('autoload_root', false)) die('skip Autoload test classes exist already'); +?> +--FILE-- +<?php + +function __autoload($class_name) +{ + require_once(dirname(__FILE__) . '/' . strtolower($class_name) . '.p5c'); + echo __FUNCTION__ . '(' . $class_name . ")\n"; +} + +var_dump(interface_exists('autoload_interface', false)); +var_dump(class_exists('autoload_implements', false)); + +$o = new Autoload_Implements; +var_dump($o); +var_dump($o instanceof autoload_interface); +unset($o); + +var_dump(interface_exists('autoload_interface', false)); +var_dump(class_exists('autoload_implements', false)); + +?> +===DONE=== +--EXPECTF-- +bool(false) +bool(false) +__autoload(autoload_interface) +__autoload(Autoload_Implements) +object(autoload_implements)#%d (0) { +} +bool(true) +bool(true) +bool(true) +===DONE=== diff --git a/tests/classes/autoload_007.phpt b/tests/classes/autoload_007.phpt new file mode 100644 index 0000000..5652c12 --- /dev/null +++ b/tests/classes/autoload_007.phpt @@ -0,0 +1,15 @@ +--TEST-- +Ensure instanceof does not trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + $a = new stdClass; + var_dump($a instanceof UndefC); +?> +--EXPECTF-- +bool(false) diff --git a/tests/classes/autoload_008.phpt b/tests/classes/autoload_008.phpt new file mode 100644 index 0000000..75a9cd0 --- /dev/null +++ b/tests/classes/autoload_008.phpt @@ -0,0 +1,26 @@ +--TEST-- +Ensure catch blocks for unknown exception types do not trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + function f() + { + throw new Exception(); + } + try { + f(); + } + catch (UndefC $u) { + echo "In UndefClass catch block.\n"; + } + catch (Exception $e) { + echo "In Exception catch block. Autoload should not have been triggered.\n"; + } +?> +--EXPECTF-- +In Exception catch block. Autoload should not have been triggered. diff --git a/tests/classes/autoload_009.phpt b/tests/classes/autoload_009.phpt new file mode 100644 index 0000000..46f6055 --- /dev/null +++ b/tests/classes/autoload_009.phpt @@ -0,0 +1,20 @@ +--TEST-- +Ensure type hints for unknown types do not trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + function f(UndefClass $x) + { + } + f(new stdClass); +?> +--EXPECTF-- + +Catchable fatal error: Argument 1 passed to f() must be an instance of UndefClass, instance of stdClass given, called in %s + + diff --git a/tests/classes/autoload_010.phpt b/tests/classes/autoload_010.phpt new file mode 100644 index 0000000..104f688 --- /dev/null +++ b/tests/classes/autoload_010.phpt @@ -0,0 +1,18 @@ +--TEST-- +Ensure implements does trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + class C implements UndefI + { + } +?> +--EXPECTF-- +In autoload: string(6) "UndefI" + +Fatal error: Interface 'UndefI' not found in %s on line %d diff --git a/tests/classes/autoload_011.phpt b/tests/classes/autoload_011.phpt new file mode 100644 index 0000000..86858d5 --- /dev/null +++ b/tests/classes/autoload_011.phpt @@ -0,0 +1,18 @@ +--TEST-- +Ensure extends does trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + class C extends UndefBase + { + } +?> +--EXPECTF-- +In autoload: string(9) "UndefBase" + +Fatal error: Class 'UndefBase' not found in %s on line %d diff --git a/tests/classes/autoload_012.phpt b/tests/classes/autoload_012.phpt new file mode 100644 index 0000000..d6750b7 --- /dev/null +++ b/tests/classes/autoload_012.phpt @@ -0,0 +1,15 @@ +--TEST-- +Ensure callback methods in unknown classes trigger autoload. +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + call_user_func("UndefC::test"); +?> +--EXPECTF-- +In autoload: string(6) "UndefC" + +Warning: call_user_func() expects parameter 1 to be a valid callback, class 'UndefC' not found in %s on line %d diff --git a/tests/classes/autoload_013.phpt b/tests/classes/autoload_013.phpt new file mode 100644 index 0000000..4309cea --- /dev/null +++ b/tests/classes/autoload_013.phpt @@ -0,0 +1,22 @@ +--TEST-- +Ensure the ReflectionClass constructor triggers autoload. +--SKIPIF-- +<?php extension_loaded('reflection') or die('skip'); ?> +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + try { + new ReflectionClass("UndefC"); + } + catch (ReflectionException $e) { + echo $e->getMessage(); + } +?> +--EXPECTF-- +In autoload: string(6) "UndefC" +Class UndefC does not exist diff --git a/tests/classes/autoload_014.phpt b/tests/classes/autoload_014.phpt new file mode 100644 index 0000000..a3f04b7 --- /dev/null +++ b/tests/classes/autoload_014.phpt @@ -0,0 +1,22 @@ +--TEST-- +Ensure the ReflectionMethod constructor triggers autoload. +--SKIPIF-- +<?php extension_loaded('reflection') or die('skip'); ?> +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + try { + new ReflectionMethod("UndefC::test"); + } + catch (ReflectionException $e) { + echo $e->getMessage(); + } +?> +--EXPECTF-- +In autoload: string(6) "UndefC" +Class UndefC does not exist diff --git a/tests/classes/autoload_015.phpt b/tests/classes/autoload_015.phpt new file mode 100644 index 0000000..2b14a0d --- /dev/null +++ b/tests/classes/autoload_015.phpt @@ -0,0 +1,22 @@ +--TEST-- +Ensure the ReflectionProperty constructor triggers autoload. +--SKIPIF-- +<?php extension_loaded('reflection') or die('skip'); ?> +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + try { + new ReflectionProperty('UndefC', 'p'); + } + catch (ReflectionException $e) { + echo $e->getMessage(); + } +?> +--EXPECTF-- +In autoload: string(6) "UndefC" +Class UndefC does not exist diff --git a/tests/classes/autoload_016.phpt b/tests/classes/autoload_016.phpt new file mode 100644 index 0000000..60263ba --- /dev/null +++ b/tests/classes/autoload_016.phpt @@ -0,0 +1,23 @@ +--TEST-- +Ensure ReflectionClass::getProperty() triggers autoload +--SKIPIF-- +<?php extension_loaded('reflection') or die('skip'); ?> +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + $rc = new ReflectionClass("stdClass"); + + try { + $rc->getProperty("UndefC::p"); + } catch (ReflectionException $e) { + echo $e->getMessage(); + } +?> +--EXPECTF-- +In autoload: string(6) "undefc" +Class undefc does not exist diff --git a/tests/classes/autoload_017.phpt b/tests/classes/autoload_017.phpt new file mode 100644 index 0000000..26de9fd --- /dev/null +++ b/tests/classes/autoload_017.phpt @@ -0,0 +1,23 @@ +--TEST-- +Ensure ReflectionClass::implementsInterface triggers autoload. +--SKIPIF-- +<?php extension_loaded('reflection') or die('skip'); ?> +--FILE-- +<?php + function __autoload($name) + { + echo "In autoload: "; + var_dump($name); + } + + $rc = new ReflectionClass("stdClass"); + + try { + $rc->implementsInterface("UndefI"); + } catch (ReflectionException $e) { + echo $e->getMessage(); + } +?> +--EXPECTF-- +In autoload: string(6) "UndefI" +Interface UndefI does not exist
\ No newline at end of file diff --git a/tests/classes/autoload_018.phpt b/tests/classes/autoload_018.phpt new file mode 100644 index 0000000..59e20e2 --- /dev/null +++ b/tests/classes/autoload_018.phpt @@ -0,0 +1,48 @@ +--TEST-- +Ensure __autoload() allows for recursive calls if the class name differs. +--FILE-- +<?php + function __autoload($name) + { + echo "IN: " . __METHOD__ . "($name)\n"; + + static $i = 0; + if ($i++ > 10) { + echo "-> Recursion detected - as expected.\n"; + return; + } + + class_exists('UndefinedClass' . $i); + + echo "OUT: " . __METHOD__ . "($name)\n"; + } + + var_dump(class_exists('UndefinedClass0')); +?> +--EXPECTF-- +IN: __autoload(UndefinedClass0) +IN: __autoload(UndefinedClass1) +IN: __autoload(UndefinedClass2) +IN: __autoload(UndefinedClass3) +IN: __autoload(UndefinedClass4) +IN: __autoload(UndefinedClass5) +IN: __autoload(UndefinedClass6) +IN: __autoload(UndefinedClass7) +IN: __autoload(UndefinedClass8) +IN: __autoload(UndefinedClass9) +IN: __autoload(UndefinedClass10) +IN: __autoload(UndefinedClass11) +-> Recursion detected - as expected. +OUT: __autoload(UndefinedClass10) +OUT: __autoload(UndefinedClass9) +OUT: __autoload(UndefinedClass8) +OUT: __autoload(UndefinedClass7) +OUT: __autoload(UndefinedClass6) +OUT: __autoload(UndefinedClass5) +OUT: __autoload(UndefinedClass4) +OUT: __autoload(UndefinedClass3) +OUT: __autoload(UndefinedClass2) +OUT: __autoload(UndefinedClass1) +OUT: __autoload(UndefinedClass0) +bool(false) + diff --git a/tests/classes/autoload_019.phpt b/tests/classes/autoload_019.phpt new file mode 100644 index 0000000..7836320 --- /dev/null +++ b/tests/classes/autoload_019.phpt @@ -0,0 +1,14 @@ +--TEST-- +Ensure __autoload() recursion is guarded for multiple lookups of same class using difference case. +--FILE-- +<?php + function __autoload($name) + { + echo __FUNCTION__ . " $name\n"; + class_exists("undefinedCLASS"); + } + + class_exists("unDefinedClass"); +?> +--EXPECTF-- +__autoload unDefinedClass diff --git a/tests/classes/autoload_020.phpt b/tests/classes/autoload_020.phpt new file mode 100644 index 0000000..a88e561 --- /dev/null +++ b/tests/classes/autoload_020.phpt @@ -0,0 +1,17 @@ +--TEST-- +Ensure __autoload() is triggered during unserialization. +--FILE-- +<?php + function __autoload($name) + { + echo "in autoload: $name\n"; + } + + var_dump(unserialize('O:1:"C":0:{}')); +?> +--EXPECTF-- +in autoload: C +object(__PHP_Incomplete_Class)#%d (1) { + ["__PHP_Incomplete_Class_Name"]=> + string(1) "C" +} diff --git a/tests/classes/autoload_derived.p5c b/tests/classes/autoload_derived.p5c new file mode 100755 index 0000000..93a4b35 --- /dev/null +++ b/tests/classes/autoload_derived.p5c @@ -0,0 +1,6 @@ +<?php + +class autoload_derived extends autoload_root { +} + +?>
\ No newline at end of file diff --git a/tests/classes/autoload_implements.p5c b/tests/classes/autoload_implements.p5c new file mode 100755 index 0000000..2c3479c --- /dev/null +++ b/tests/classes/autoload_implements.p5c @@ -0,0 +1,10 @@ +<?php + +class autoload_implements implements autoload_interface { + function testFunction() + { + return true; + } +} + +?>
\ No newline at end of file diff --git a/tests/classes/autoload_interface.p5c b/tests/classes/autoload_interface.p5c new file mode 100755 index 0000000..6908155 --- /dev/null +++ b/tests/classes/autoload_interface.p5c @@ -0,0 +1,7 @@ +<?php + +interface autoload_interface { + function testFunction(); +} + +?>
\ No newline at end of file diff --git a/tests/classes/autoload_root.p5c b/tests/classes/autoload_root.p5c new file mode 100755 index 0000000..9559d36 --- /dev/null +++ b/tests/classes/autoload_root.p5c @@ -0,0 +1,10 @@ +<?php + +class autoload_root { + function testFunction() + { + return true; + } +} + +?>
\ No newline at end of file diff --git a/tests/classes/bug23951.phpt b/tests/classes/bug23951.phpt new file mode 100644 index 0000000..2e272b8 --- /dev/null +++ b/tests/classes/bug23951.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #23951 (Defines not working in inherited classes) +--FILE-- +<?php + +define('FOO1', 1); +define('FOO2', 2); + +class A { + + public $a_var = array(FOO1=>'foo1_value', FOO2=>'foo2_value'); + +} + +class B extends A { + + public $b_var = 'foo'; + +} + +$a = new A; +$b = new B; + +print_r($a); +print_r($b->a_var); +print_r($b->b_var); + +?> +--EXPECT-- +A Object +( + [a_var] => Array + ( + [1] => foo1_value + [2] => foo2_value + ) + +) +Array +( + [1] => foo1_value + [2] => foo2_value +) +foo diff --git a/tests/classes/bug24399.phpt b/tests/classes/bug24399.phpt new file mode 100644 index 0000000..fedf8e5 --- /dev/null +++ b/tests/classes/bug24399.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #24399 (is_subclass_of() crashes when parent class doesn't exist) +--FILE-- +<?php +class dooh { + public $blah; +} +$d = new dooh; +var_dump(is_subclass_of($d, 'dooh')); +?> +--EXPECT-- +bool(false) diff --git a/tests/classes/bug24445.phpt b/tests/classes/bug24445.phpt new file mode 100644 index 0000000..af08307 --- /dev/null +++ b/tests/classes/bug24445.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #24445 (get_parent_class() returns the current class when passed an object) +--FILE-- +<?php +class Test { } +var_dump(get_parent_class('Test')); +$t = new Test; +var_dump(get_parent_class($t)); +?> +--EXPECT-- +bool(false) +bool(false) diff --git a/tests/classes/bug26737.phpt b/tests/classes/bug26737.phpt new file mode 100644 index 0000000..e190318 --- /dev/null +++ b/tests/classes/bug26737.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #26737 (Protected and private variables are not saved on serialization when a user defined __sleep is used) +--FILE-- +<?php +class foo +{ + private $private = 'private'; + protected $protected = 'protected'; + public $public = 'public'; + + public function __sleep() + { + return array('private', 'protected', 'public', 'no_such'); + } +} +$foo = new foo(); +$data = serialize($foo); +var_dump(str_replace("\0", '\0', $data)); +?> +--EXPECTF-- +Notice: serialize(): "no_such" returned as member variable from __sleep() but does not exist in %s on line %d +string(130) "O:3:"foo":4:{s:12:"\0foo\0private";s:7:"private";s:12:"\0*\0protected";s:9:"protected";s:6:"public";s:6:"public";s:7:"no_such";N;}" diff --git a/tests/classes/bug27468.phpt b/tests/classes/bug27468.phpt new file mode 100644 index 0000000..58a7b6c --- /dev/null +++ b/tests/classes/bug27468.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #27468 (foreach in __destruct() causes segfault) +--FILE-- +<?php +class foo { + function __destruct() { + foreach ($this->x as $x); + } +} +new foo(); +echo 'OK'; +?> +--EXPECTF-- +Notice: Undefined property: foo::$x in %sbug27468.php on line 4 + +Warning: Invalid argument supplied for foreach() in %sbug27468.php on line 4 +OK diff --git a/tests/classes/bug27504.phpt b/tests/classes/bug27504.phpt new file mode 100644 index 0000000..5f2c5a0 --- /dev/null +++ b/tests/classes/bug27504.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #27504 (call_user_func_array allows calling of private/protected methods) +--FILE-- +<?php + class foo { + function __construct () { + $this->bar('1'); + } + private function bar ( $param ) { + echo 'Called function foo:bar('.$param.')'."\n"; + } + } + + $foo = new foo(); + + call_user_func_array( array( $foo , 'bar' ) , array( '2' ) ); + + $foo->bar('3'); +?> +--EXPECTF-- +Called function foo:bar(1) + +Warning: call_user_func_array() expects parameter 1 to be a valid callback, cannot access private method foo::bar() in %s on line %d + +Fatal error: Call to private method foo::bar() from context '' in %s on line %d diff --git a/tests/classes/bug29446.phpt b/tests/classes/bug29446.phpt new file mode 100644 index 0000000..5e30e8e --- /dev/null +++ b/tests/classes/bug29446.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #29446 (ZE allows multiple declarations of the same class constant) +--FILE-- +<?php + +class testClass { + const TEST_CONST = 'test'; + const TEST_CONST = 'test1'; + + function testClass() { + echo self::TEST_CONST; + } +} + +$test = new testClass; + +?> +--EXPECTF-- +Fatal error: Cannot redefine class constant testClass::TEST_CONST in %s on line 5
\ No newline at end of file diff --git a/tests/classes/bug63462.phpt b/tests/classes/bug63462.phpt new file mode 100644 index 0000000..dc5edbd --- /dev/null +++ b/tests/classes/bug63462.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test script to verify that magic methods should be called only once when accessing an unset property. +--CREDITS-- +Marco Pivetta <ocramius@gmail.com> +--XFAIL-- +Bug 63462 is not yet fixed +--FILE-- +<?php +class Test { + public $publicProperty; + protected $protectedProperty; + private $privateProperty; + + public function __construct() { + unset( + $this->publicProperty, + $this->protectedProperty, + $this->privateProperty + ); + } + + function __get($name) { + echo '__get ' . $name . "\n"; + return $this->$name; + } + + function __set($name, $value) { + echo '__set ' . $name . "\n"; + $this->$name = $value; + } + + function __isset($name) { + echo '__isset ' . $name . "\n"; + return isset($this->$name); + } +} + +$test = new Test(); + +$test->nonExisting; +$test->publicProperty; +$test->protectedProperty; +$test->privateProperty; +isset($test->nonExisting); +isset($test->publicProperty); +isset($test->protectedProperty); +isset($test->privateProperty); +$test->nonExisting = 'value'; +$test->publicProperty = 'value'; +$test->protectedProperty = 'value'; +$test->privateProperty = 'value'; + +?> + +--EXPECTF-- +__get nonExisting +Notice: Undefined index: nonExisting in %__set__get_006.php on line %d +__get publicProperty +Notice: Undefined index: publicProperty in %__set__get_006.php on line %d +__get protectedProperty +Notice: Undefined index: protectedProperty in %__set__get_006.php on line %d +__get privateProperty +Notice: Undefined index: privateProperty in %__set__get_006.php on line %d +__isset nonExisting +__isset publicProperty +__isset protectedProperty +__isset privateProperty +__set nonExisting +__set publicProperty +__set protectedProperty +__set privateProperty diff --git a/tests/classes/class_abstract.phpt b/tests/classes/class_abstract.phpt new file mode 100644 index 0000000..880f849 --- /dev/null +++ b/tests/classes/class_abstract.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZE2 An abstract class cannot be instanciated +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +abstract class base { + function show() { + echo "base\n"; + } +} + +class derived extends base { +} + +$t = new derived(); +$t->show(); + +$t = new base(); +$t->show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +base + +Fatal error: Cannot instantiate abstract class base in %s on line %d diff --git a/tests/classes/class_example.phpt b/tests/classes/class_example.phpt new file mode 100644 index 0000000..621958b --- /dev/null +++ b/tests/classes/class_example.phpt @@ -0,0 +1,85 @@ +--TEST-- +Classes general test +--FILE-- + +<?php + +/* pretty nifty object oriented code! */ + +class user { + public $first_name,$family_name,$address,$phone_num; + function display() + { + echo "User information\n"; + echo "----------------\n\n"; + echo "First name:\t ".$this->first_name."\n"; + echo "Family name:\t ".$this->family_name."\n"; + echo "Address:\t ".$this->address."\n"; + echo "Phone:\t\t ".$this->phone_num."\n"; + echo "\n\n"; + } + function initialize($first_name,$family_name,$address,$phone_num) + { + $this->first_name = $first_name; + $this->family_name = $family_name; + $this->address = $address; + $this->phone_num = $phone_num; + } +}; + + +function test($u) +{ /* one can pass classes as arguments */ + $u->display(); + $t = $u; + $t->address = "New address..."; + return $t; /* and also return them as return values */ +} + +$user1 = new user; +$user2 = new user; + +$user1->initialize("Zeev","Suraski","Ben Gourion 3, Kiryat Bialik, Israel","+972-4-8713139"); +$user2->initialize("Andi","Gutmans","Haifa, Israel","+972-4-8231621"); +$user1->display(); +$user2->display(); + +$tmp = test($user2); +$tmp->display(); + +?> +--EXPECT-- +User information +---------------- + +First name: Zeev +Family name: Suraski +Address: Ben Gourion 3, Kiryat Bialik, Israel +Phone: +972-4-8713139 + + +User information +---------------- + +First name: Andi +Family name: Gutmans +Address: Haifa, Israel +Phone: +972-4-8231621 + + +User information +---------------- + +First name: Andi +Family name: Gutmans +Address: Haifa, Israel +Phone: +972-4-8231621 + + +User information +---------------- + +First name: Andi +Family name: Gutmans +Address: New address... +Phone: +972-4-8231621 diff --git a/tests/classes/class_final.phpt b/tests/classes/class_final.phpt new file mode 100644 index 0000000..5c73cb2 --- /dev/null +++ b/tests/classes/class_final.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 A final class cannot be inherited +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +final class base { + function show() { + echo "base\n"; + } +} + +$t = new base(); + +class derived extends base { +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Class derived may not inherit from final class (base) in %s on line %d diff --git a/tests/classes/class_stdclass.phpt b/tests/classes/class_stdclass.phpt new file mode 100644 index 0000000..5e3422a --- /dev/null +++ b/tests/classes/class_stdclass.phpt @@ -0,0 +1,14 @@ +--TEST-- +Instantiate stdClass +--FILE-- +<?php + +$obj = new stdClass; + +echo get_class($obj)."\n"; + +echo "Done\n"; +?> +--EXPECTF-- +stdClass +Done diff --git a/tests/classes/clone_001.phpt b/tests/classes/clone_001.phpt new file mode 100644 index 0000000..eb06c1f --- /dev/null +++ b/tests/classes/clone_001.phpt @@ -0,0 +1,43 @@ +--TEST-- +ZE2 object cloning, 1 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + public $p1 = 1; + public $p2 = 2; + public $p3; +}; + +$obj = new test; +$obj->p2 = 'A'; +$obj->p3 = 'B'; +$copy = clone $obj; +$copy->p3 = 'C'; +echo "Object\n"; +var_dump($obj); +echo "Clown\n"; +var_dump($copy); +echo "Done\n"; +?> +--EXPECT-- +Object +object(test)#1 (3) { + ["p1"]=> + int(1) + ["p2"]=> + string(1) "A" + ["p3"]=> + string(1) "B" +} +Clown +object(test)#2 (3) { + ["p1"]=> + int(1) + ["p2"]=> + string(1) "A" + ["p3"]=> + string(1) "C" +} +Done diff --git a/tests/classes/clone_002.phpt b/tests/classes/clone_002.phpt new file mode 100644 index 0000000..4430a2c --- /dev/null +++ b/tests/classes/clone_002.phpt @@ -0,0 +1,45 @@ +--TEST-- +ZE2 object cloning, 2 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + public $p1 = 1; + public $p2 = 2; + public $p3; + public function __clone() { + } +}; + +$obj = new test; +$obj->p2 = 'A'; +$obj->p3 = 'B'; +$copy = clone $obj; +$copy->p3 = 'C'; +echo "Object\n"; +var_dump($obj); +echo "Clown\n"; +var_dump($copy); +echo "Done\n"; +?> +--EXPECT-- +Object +object(test)#1 (3) { + ["p1"]=> + int(1) + ["p2"]=> + string(1) "A" + ["p3"]=> + string(1) "B" +} +Clown +object(test)#2 (3) { + ["p1"]=> + int(1) + ["p2"]=> + string(1) "A" + ["p3"]=> + string(1) "C" +} +Done diff --git a/tests/classes/clone_003.phpt b/tests/classes/clone_003.phpt new file mode 100644 index 0000000..9a251c5 --- /dev/null +++ b/tests/classes/clone_003.phpt @@ -0,0 +1,58 @@ +--TEST-- +ZE2 object cloning, 3 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class base { + protected $p1 = 'base:1'; + public $p2 = 'base:2'; + public $p3 = 'base:3'; + public $p4 = 'base:4'; + public $p5 = 'base:5'; + private $p6 = 'base:6'; + public function __clone() { + } +}; + +class test extends base { + public $p1 = 'test:1'; + public $p3 = 'test:3'; + public $p4 = 'test:4'; + public $p5 = 'test:5'; + public function __clone() { + $this->p5 = 'clone:5'; + } +} + +$obj = new test; +$obj->p4 = 'A'; +$copy = clone $obj; +echo "Object\n"; +print_r($obj); +echo "Clown\n"; +print_r($copy); +echo "Done\n"; +?> +--EXPECT-- +Object +test Object +( + [p1] => test:1 + [p3] => test:3 + [p4] => A + [p5] => test:5 + [p2] => base:2 + [p6:base:private] => base:6 +) +Clown +test Object +( + [p1] => test:1 + [p3] => test:3 + [p4] => A + [p5] => clone:5 + [p2] => base:2 + [p6:base:private] => base:6 +) +Done diff --git a/tests/classes/clone_004.phpt b/tests/classes/clone_004.phpt new file mode 100644 index 0000000..2059103 --- /dev/null +++ b/tests/classes/clone_004.phpt @@ -0,0 +1,82 @@ +--TEST-- +ZE2 object cloning, 4 +--FILE-- +<?php +abstract class base { + public $a = 'base'; + + // disallow cloning + private function __clone() {} +} + +class test extends base { + public $b = 'test'; + + // reenable cloning + public function __clone() {} + + public function show() { + var_dump($this); + } +} + +echo "Original\n"; +$o1 = new test; +$o1->a = array(1,2); +$o1->b = array(3,4); +$o1->show(); + +echo "Clone\n"; +$o2 = clone $o1; +$o2->show(); + +echo "Modify\n"; +$o2->a = 5; +$o2->b = 6; +$o2->show(); + +echo "Done\n"; +?> +--EXPECT-- +Original +object(test)#1 (2) { + ["b"]=> + array(2) { + [0]=> + int(3) + [1]=> + int(4) + } + ["a"]=> + array(2) { + [0]=> + int(1) + [1]=> + int(2) + } +} +Clone +object(test)#2 (2) { + ["b"]=> + array(2) { + [0]=> + int(3) + [1]=> + int(4) + } + ["a"]=> + array(2) { + [0]=> + int(1) + [1]=> + int(2) + } +} +Modify +object(test)#2 (2) { + ["b"]=> + int(6) + ["a"]=> + int(5) +} +Done diff --git a/tests/classes/clone_005.phpt b/tests/classes/clone_005.phpt new file mode 100644 index 0000000..bfe4d66 --- /dev/null +++ b/tests/classes/clone_005.phpt @@ -0,0 +1,19 @@ +--TEST-- +ZE2 object cloning, 5 +--FILE-- +<?php +abstract class base { + public $a = 'base'; + + // disallow cloning once forever + final private function __clone() {} +} + +class test extends base { + // reenabling should fail + public function __clone() {} +} + +?> +--EXPECTF-- +Fatal error: Cannot override final method base::__clone() in %sclone_005.php on line %d diff --git a/tests/classes/clone_006.phpt b/tests/classes/clone_006.phpt new file mode 100644 index 0000000..de22fec --- /dev/null +++ b/tests/classes/clone_006.phpt @@ -0,0 +1,41 @@ +--TEST-- +ZE2 object cloning, 6 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--INI-- +error_reporting=2047 +--FILE-- +<?php + +class MyCloneable { + static $id = 0; + + function MyCloneable() { + $this->id = self::$id++; + } + + function __clone() { + $this->address = "New York"; + $this->id = self::$id++; + } +} + +$original = new MyCloneable(); + +$original->name = "Hello"; +$original->address = "Tel-Aviv"; + +echo $original->id . "\n"; + +$clone = clone $original; + +echo $clone->id . "\n"; +echo $clone->name . "\n"; +echo $clone->address . "\n"; + +?> +--EXPECT-- +0 +1 +Hello +New York diff --git a/tests/classes/constants_basic_001.phpt b/tests/classes/constants_basic_001.phpt new file mode 100644 index 0000000..74b0fcd --- /dev/null +++ b/tests/classes/constants_basic_001.phpt @@ -0,0 +1,89 @@ +--TEST-- +Class constant declarations +--FILE-- +<?php + define('DEFINED', 1234); + $def = 456; + define('DEFINED_TO_VAR', $def); + define('DEFINED_TO_UNDEF_VAR', $undef); + + class C + { + const c0 = UNDEFINED; + + const c1 = 1, c2 = 1.5; + const c3 = + 1, c4 = + 1.5; + const c5 = -1, c6 = -1.5; + + const c7 = __LINE__; + const c8 = __FILE__; + const c9 = __CLASS__; + const c10 = __METHOD__; + const c11 = __FUNCTION__; + + const c12 = DEFINED; + const c13 = DEFINED_TO_VAR; + const c14 = DEFINED_TO_UNDEF_VAR; + + const c15 = "hello1"; + const c16 = 'hello2'; + const c17 = C::c16; + const c18 = self::c17; + } + + echo "\nAttempt to access various kinds of class constants:\n"; + var_dump(C::c0); + var_dump(C::c1); + var_dump(C::c2); + var_dump(C::c3); + var_dump(C::c4); + var_dump(C::c5); + var_dump(C::c6); + var_dump(C::c7); + var_dump(C::c8); + var_dump(C::c9); + var_dump(C::c10); + var_dump(C::c11); + var_dump(C::c12); + var_dump(C::c13); + var_dump(C::c14); + var_dump(C::c15); + var_dump(C::c16); + var_dump(C::c17); + var_dump(C::c18); + + echo "\nExpecting fatal error:\n"; + var_dump(C::c19); + + echo "\nYou should not see this."; +?> +--EXPECTF-- + +Notice: Undefined variable: undef in %s on line 5 + +Attempt to access various kinds of class constants: + +Notice: Use of undefined constant UNDEFINED - assumed 'UNDEFINED' in %s on line %d +string(9) "UNDEFINED" +int(1) +float(1.5) +int(1) +float(1.5) +int(-1) +float(-1.5) +int(15) +string(%d) "%s" +string(1) "C" +string(1) "C" +string(0) "" +int(1234) +int(456) +NULL +string(6) "hello1" +string(6) "hello2" +string(6) "hello2" +string(6) "hello2" + +Expecting fatal error: + +Fatal error: Undefined class constant 'c19' in %s on line 53 diff --git a/tests/classes/constants_basic_002.phpt b/tests/classes/constants_basic_002.phpt new file mode 100644 index 0000000..0e53ca9 --- /dev/null +++ b/tests/classes/constants_basic_002.phpt @@ -0,0 +1,32 @@ +--TEST-- +Basic class support - defining and reading a class constant. +--FILE-- +<?php + class aclass + { + const myConst = "hello"; + } + + echo "\nRead class constant.\n"; + var_dump(aclass::myConst); + + echo "\nFail to read class constant from instance.\n"; + $myInstance = new aclass(); + var_dump($myInstance->myConst); + + echo "\nClass constant not visible in object var_dump.\n"; + var_dump($myInstance) +?> +--EXPECTF-- + +Read class constant. +string(5) "hello" + +Fail to read class constant from instance. + +Notice: Undefined property: aclass::$myConst in %s on line 12 +NULL + +Class constant not visible in object var_dump. +object(aclass)#%d (0) { +} diff --git a/tests/classes/constants_basic_003.inc b/tests/classes/constants_basic_003.inc new file mode 100644 index 0000000..be193e6 --- /dev/null +++ b/tests/classes/constants_basic_003.inc @@ -0,0 +1,5 @@ +<?php +class A { + const MY_CONST = "hello from A"; +} +?>
\ No newline at end of file diff --git a/tests/classes/constants_basic_003.phpt b/tests/classes/constants_basic_003.phpt new file mode 100644 index 0000000..052af85 --- /dev/null +++ b/tests/classes/constants_basic_003.phpt @@ -0,0 +1,28 @@ +--TEST-- +Ensure class properties and constants can be defined in terms of constants that are not known at compile time. +--FILE-- +<?php + include 'constants_basic_003.inc'; + class B + { + public static $a = A::MY_CONST; + public static $c = C::MY_CONST; + const ca = A::MY_CONST; + const cc = C::MY_CONST; + } + + class C + { + const MY_CONST = "hello from C"; + } + + var_dump(B::$a); + var_dump(B::$c); + var_dump(B::ca); + var_dump(B::cc); +?> +--EXPECTF-- +string(12) "hello from A" +string(12) "hello from C" +string(12) "hello from A" +string(12) "hello from C" diff --git a/tests/classes/constants_basic_004.phpt b/tests/classes/constants_basic_004.phpt new file mode 100644 index 0000000..cade668 --- /dev/null +++ b/tests/classes/constants_basic_004.phpt @@ -0,0 +1,99 @@ +--TEST-- +Test properties with array default values using class constants as keys and values. +--FILE-- +<?php + class X + { + // Static and instance array using class constants + public static $sa_x = array(B::KEY => B::VALUE); + public $a_x = array(B::KEY => B::VALUE); + } + + class B + { + const KEY = "key"; + const VALUE = "value"; + + // Static and instance array using class constants with self + public static $sa_b = array(self::KEY => self::VALUE); + public $a_b = array(self::KEY => self::VALUE); + } + + class C extends B + { + // Static and instance array using class constants with parent + public static $sa_c_parent = array(parent::KEY => parent::VALUE); + public $a_c_parent = array(parent::KEY => parent::VALUE); + + // Static and instance array using class constants with self (constants should be inherited) + public static $sa_c_self = array(self::KEY => self::VALUE); + public $a_c_self = array(self::KEY => self::VALUE); + + // Should also include inherited properties from B. + } + + echo "\nStatic properties:\n"; + var_dump(X::$sa_x, B::$sa_b, C::$sa_b, C::$sa_c_parent, C::$sa_c_self); + + echo "\nInstance properties:\n"; + $x = new x; + $b = new B; + $c = new C; + var_dump($x, $b, $c); +?> +--EXPECTF-- + +Static properties: +array(1) { + ["key"]=> + string(5) "value" +} +array(1) { + ["key"]=> + string(5) "value" +} +array(1) { + ["key"]=> + string(5) "value" +} +array(1) { + ["key"]=> + string(5) "value" +} +array(1) { + ["key"]=> + string(5) "value" +} + +Instance properties: +object(X)#%d (1) { + ["a_x"]=> + array(1) { + ["key"]=> + string(5) "value" + } +} +object(B)#%d (1) { + ["a_b"]=> + array(1) { + ["key"]=> + string(5) "value" + } +} +object(C)#%d (3) { + ["a_c_parent"]=> + array(1) { + ["key"]=> + string(5) "value" + } + ["a_c_self"]=> + array(1) { + ["key"]=> + string(5) "value" + } + ["a_b"]=> + array(1) { + ["key"]=> + string(5) "value" + } +} diff --git a/tests/classes/constants_basic_005.phpt b/tests/classes/constants_basic_005.phpt new file mode 100644 index 0000000..c840f53 --- /dev/null +++ b/tests/classes/constants_basic_005.phpt @@ -0,0 +1,16 @@ +--TEST-- +Test constants with default values based on other constants. +--FILE-- +<?php + class C + { + const CONST_2 = self::CONST_1; + const CONST_1 = self::BASE_CONST; + const BASE_CONST = 'hello'; + } + var_dump(C::CONST_1, C::CONST_2); +?> +--EXPECTF-- +string(5) "hello" +string(5) "hello" + diff --git a/tests/classes/constants_basic_006.phpt b/tests/classes/constants_basic_006.phpt new file mode 100644 index 0000000..73cf0ef --- /dev/null +++ b/tests/classes/constants_basic_006.phpt @@ -0,0 +1,43 @@ +--TEST-- +Ensure class constants are not evaluated when a class is looked up to resolve inheritance during runtime. +--FILE-- +<?php + class C + { + const X = E::A; + public static $a = array(K => D::V, E::A => K); + } + + eval('class D extends C { const V = \'test\'; }'); + + class E extends D + { + const A = "hello"; + } + + define('K', "nasty"); + + var_dump(C::X, C::$a, D::X, D::$a, E::X, E::$a); +?> +--EXPECTF-- +string(5) "hello" +array(2) { + ["nasty"]=> + string(4) "test" + ["hello"]=> + string(5) "nasty" +} +string(5) "hello" +array(2) { + ["nasty"]=> + string(4) "test" + ["hello"]=> + string(5) "nasty" +} +string(5) "hello" +array(2) { + ["nasty"]=> + string(4) "test" + ["hello"]=> + string(5) "nasty" +} diff --git a/tests/classes/constants_error_001.phpt b/tests/classes/constants_error_001.phpt new file mode 100644 index 0000000..9bb5533 --- /dev/null +++ b/tests/classes/constants_error_001.phpt @@ -0,0 +1,13 @@ +--TEST-- +Error case: duplicate class constant definition +--FILE-- +<?php + class myclass + { + const myConst = "hello"; + const myConst = "hello again"; + } +?> +--EXPECTF-- + +Fatal error: Cannot redefine class constant myclass::myConst in %s on line 5 diff --git a/tests/classes/constants_error_002.phpt b/tests/classes/constants_error_002.phpt new file mode 100644 index 0000000..be27971 --- /dev/null +++ b/tests/classes/constants_error_002.phpt @@ -0,0 +1,12 @@ +--TEST-- +Error case: class constant as an array +--FILE-- +<?php + class myclass + { + const myConst = array(); + } +?> +--EXPECTF-- + +Fatal error: Arrays are not allowed in class constants in %s on line 4 diff --git a/tests/classes/constants_error_003.phpt b/tests/classes/constants_error_003.phpt new file mode 100644 index 0000000..c67768c --- /dev/null +++ b/tests/classes/constants_error_003.phpt @@ -0,0 +1,20 @@ +--TEST-- +Basic class support - attempting to pass a class constant by reference. +--FILE-- +<?php + class aclass + { + const myConst = "hello"; + } + + function f(&$a) + { + $a = "changed"; + } + + f(aclass::myConst); + var_dump(aclass::myConst); +?> +--EXPECTF-- + +Fatal error: Only variables can be passed by reference in %s on line 12 diff --git a/tests/classes/constants_error_004.phpt b/tests/classes/constants_error_004.phpt new file mode 100644 index 0000000..03e6725 --- /dev/null +++ b/tests/classes/constants_error_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +Class constant whose initial value refereces a non-existent class +--FILE-- +<?php + class C + { + const c1 = D::hello; + } + + $a = new C(); +?> +--EXPECTF-- +Fatal error: Class 'D' not found in %s on line %d diff --git a/tests/classes/constants_error_005.phpt b/tests/classes/constants_error_005.phpt new file mode 100644 index 0000000..1283783 --- /dev/null +++ b/tests/classes/constants_error_005.phpt @@ -0,0 +1,12 @@ +--TEST-- +Error case: class constant as an encapsed containing a variable +--FILE-- +<?php + class myclass + { + const myConst = "$myVar"; + } +?> +--EXPECTF-- + +Parse error: %s in %s on line %d diff --git a/tests/classes/constants_error_006.phpt b/tests/classes/constants_error_006.phpt new file mode 100644 index 0000000..f3f14b8 --- /dev/null +++ b/tests/classes/constants_error_006.phpt @@ -0,0 +1,16 @@ +--TEST-- +Basic class support - attempting to modify a class constant by assignment +--FILE-- +<?php + class aclass + { + const myConst = "hello"; + } + + echo "\nTrying to modify a class constant directly - should be parse error.\n"; + aclass::myConst = "no!!"; + var_dump(aclass::myConst); +?> +--EXPECTF-- + +Parse error: %s in %s on line %d diff --git a/tests/classes/constants_error_007.phpt b/tests/classes/constants_error_007.phpt new file mode 100644 index 0000000..4be8d88 --- /dev/null +++ b/tests/classes/constants_error_007.phpt @@ -0,0 +1,15 @@ +--TEST-- +Basic class support - attempting to create a reference to a class constant +--FILE-- +<?php + class aclass + { + const myConst = "hello"; + } + + echo "\nAttempting to create a reference to a class constant - should be parse error.\n"; + $a = &aclass::myConst; +?> +--EXPECTF-- + +Parse error: %s in %s on line %d diff --git a/tests/classes/constants_scope_001.phpt b/tests/classes/constants_scope_001.phpt new file mode 100644 index 0000000..5006628 --- /dev/null +++ b/tests/classes/constants_scope_001.phpt @@ -0,0 +1,38 @@ +--TEST-- +ZE2 class constants and scope +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class ErrorCodes { + const FATAL = "Fatal error\n"; + const WARNING = "Warning\n"; + const INFO = "Informational message\n"; + + static function print_fatal_error_codes() { + echo "FATAL = " . FATAL . "\n"; + echo "self::FATAL = " . self::FATAL; + } +} + +class ErrorCodesDerived extends ErrorCodes { + const FATAL = "Worst error\n"; + static function print_fatal_error_codes() { + echo "self::FATAL = " . self::FATAL; + echo "parent::FATAL = " . parent::FATAL; + } +} + +/* Call the static function and move into the ErrorCodes scope */ +ErrorCodes::print_fatal_error_codes(); +ErrorCodesDerived::print_fatal_error_codes(); + +?> +--EXPECTF-- + +Notice: Use of undefined constant FATAL - assumed 'FATAL' in %sconstants_scope_001.php on line %d +FATAL = FATAL +self::FATAL = Fatal error +self::FATAL = Worst error +parent::FATAL = Fatal error diff --git a/tests/classes/ctor_dtor.phpt b/tests/classes/ctor_dtor.phpt new file mode 100644 index 0000000..ea6813c --- /dev/null +++ b/tests/classes/ctor_dtor.phpt @@ -0,0 +1,40 @@ +--TEST-- +ZE2 The new constructor/destructor is called +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class early { + function early() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + } + function __destruct() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + } +} + +class late { + function __construct() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + } + function __destruct() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + } +} + +$t = new early(); +$t->early(); +unset($t); +$t = new late(); +//unset($t); delay to end of script + +echo "Done\n"; +?> +--EXPECTF-- +early::early +early::early +early::__destruct +late::__construct +Done +late::__destruct diff --git a/tests/classes/ctor_dtor_inheritance.phpt b/tests/classes/ctor_dtor_inheritance.phpt new file mode 100644 index 0000000..8ae2a5d --- /dev/null +++ b/tests/classes/ctor_dtor_inheritance.phpt @@ -0,0 +1,99 @@ +--TEST-- +ZE2 A derived class can use the inherited constructor/destructor +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +// This test checks for: +// - inherited constructors/destructors are not called automatically +// - base classes know about derived properties in constructor/destructor +// - base class constructors/destructors know the instanciated class name + +class base { + public $name; + + function __construct() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + $this->name = 'base'; + print_r($this); + } + + function __destruct() { + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + print_r($this); + } +} + +class derived extends base { + public $other; + + function __construct() { + $this->name = 'init'; + $this->other = 'other'; + print_r($this); + parent::__construct(); + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + $this->name = 'derived'; + print_r($this); + } + + function __destruct() { + parent::__destruct(); + echo __CLASS__ . "::" . __FUNCTION__ . "\n"; + print_r($this); + } +} + +echo "Testing class base\n"; +$t = new base(); +unset($t); +echo "Testing class derived\n"; +$t = new derived(); +unset($t); + +echo "Done\n"; +?> +--EXPECTF-- +Testing class base +base::__construct +base Object +( + [name] => base +) +base::__destruct +base Object +( + [name] => base +) +Testing class derived +derived Object +( + [other] => other + [name] => init +) +base::__construct +derived Object +( + [other] => other + [name] => base +) +derived::__construct +derived Object +( + [other] => other + [name] => derived +) +base::__destruct +derived Object +( + [other] => other + [name] => derived +) +derived::__destruct +derived Object +( + [other] => other + [name] => derived +) +Done diff --git a/tests/classes/ctor_failure.phpt b/tests/classes/ctor_failure.phpt new file mode 100644 index 0000000..b7d3b64 --- /dev/null +++ b/tests/classes/ctor_failure.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 Do not call destructors if constructor fails +--FILE-- +<?php + +class Test +{ + function __construct($msg) { + echo __METHOD__ . "($msg)\n"; + throw new Exception($msg); + } + + function __destruct() { + echo __METHOD__ . "\n"; + } +} + +try +{ + $o = new Test('Hello'); + unset($o); +} +catch (Exception $e) +{ + echo 'Caught ' . get_class($e) . '(' . $e->getMessage() . ")\n"; +} + +?> +===DONE=== +--EXPECT-- +Test::__construct(Hello) +Caught Exception(Hello) +===DONE=== diff --git a/tests/classes/ctor_in_interface_01.phpt b/tests/classes/ctor_in_interface_01.phpt new file mode 100644 index 0000000..e5ad30e --- /dev/null +++ b/tests/classes/ctor_in_interface_01.phpt @@ -0,0 +1,19 @@ +--TEST-- +ZE2 A class constructor must keep the signature of an interface +--FILE-- +<?php +interface constr +{ + function __construct(); +} + +class implem implements constr +{ + function __construct($a) + { + } +} + +?> +--EXPECTF-- +Fatal error: Declaration of implem::__construct() must be compatible with constr::__construct() in %s on line %d diff --git a/tests/classes/ctor_in_interface_02.phpt b/tests/classes/ctor_in_interface_02.phpt new file mode 100644 index 0000000..08e6f36 --- /dev/null +++ b/tests/classes/ctor_in_interface_02.phpt @@ -0,0 +1,34 @@ +--TEST-- +ZE2 A class constructor must keep the signature of all interfaces +--FILE-- +<?php +interface constr1 +{ + function __construct(); +} + +interface constr2 extends constr1 +{ +} + +class implem12 implements constr2 +{ + function __construct() + { + } +} + +interface constr3 +{ + function __construct($a); +} + +class implem13 implements constr1, constr3 +{ + function __construct() + { + } +} +?> +--EXPECTF-- +Fatal error: Declaration of implem13::__construct() must be compatible with constr3::__construct($a) in %s on line %d diff --git a/tests/classes/ctor_in_interface_03.phpt b/tests/classes/ctor_in_interface_03.phpt new file mode 100644 index 0000000..ac73331 --- /dev/null +++ b/tests/classes/ctor_in_interface_03.phpt @@ -0,0 +1,23 @@ +--TEST-- +ZE2 A class constructor must keep the signature of base class interfaces +--FILE-- +<?php +interface constr +{ + function __construct(); +} + +abstract class implem implements constr +{ +} + +class derived extends implem +{ + function __construct($a) + { + } +} + +?> +--EXPECTF-- +Fatal error: Declaration of derived::__construct() must be compatible with constr::__construct() in %s on line %d diff --git a/tests/classes/ctor_in_interface_04.phpt b/tests/classes/ctor_in_interface_04.phpt new file mode 100644 index 0000000..94be655 --- /dev/null +++ b/tests/classes/ctor_in_interface_04.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 A class constructor must keep the signature of base class interfaces +--FILE-- +<?php +interface constr +{ + function __construct(); +} + +class implem implements constr +{ + function __construct() + { + } +} + +class derived extends implem +{ + function __construct($a) + { + } +} + +?> +--EXPECTF-- +Fatal error: Declaration of derived::__construct() must be compatible with constr::__construct() in %s on line %d diff --git a/tests/classes/ctor_name_clash.phpt b/tests/classes/ctor_name_clash.phpt new file mode 100644 index 0000000..1a1d6fa --- /dev/null +++ b/tests/classes/ctor_name_clash.phpt @@ -0,0 +1,22 @@ +--TEST-- +ZE2 The child class can re-use the parent class name for a function member +--FILE-- +<?php +class base { + function base() { + echo __CLASS__."::".__FUNCTION__."\n"; + } +} + +class derived extends base { + function base() { + echo __CLASS__."::".__FUNCTION__."\n"; + } +} + +$obj = new derived(); +$obj->base(); +?> +--EXPECTF-- +base::base +derived::base diff --git a/tests/classes/ctor_visibility.phpt b/tests/classes/ctor_visibility.phpt new file mode 100644 index 0000000..8d3b1c5 --- /dev/null +++ b/tests/classes/ctor_visibility.phpt @@ -0,0 +1,69 @@ +--TEST-- +ZE2 A private constructor cannot be called +--FILE-- +<?php + +class Test +{ + function __construct() + { + echo __METHOD__ . "()\n"; + } +} + +class Derived extends Test +{ + function __construct() + { + echo __METHOD__ . "()\n"; + parent::__construct(); + } + + static function f() + { + new Derived; + } +} + +Derived::f(); + +class TestPriv +{ + private function __construct() + { + echo __METHOD__ . "()\n"; + } + + static function f() + { + new TestPriv; + } +} + +TestPriv::f(); + +class DerivedPriv extends TestPriv +{ + function __construct() + { + echo __METHOD__ . "()\n"; + parent::__construct(); + } + + static function f() + { + new DerivedPriv; + } +} + +DerivedPriv::f(); + +?> +===DONE=== +--EXPECTF-- +Derived::__construct() +Test::__construct() +TestPriv::__construct() +DerivedPriv::__construct() + +Fatal error: Cannot call private TestPriv::__construct() in %sctor_visibility.php on line %d diff --git a/tests/classes/dereferencing_001.phpt b/tests/classes/dereferencing_001.phpt new file mode 100644 index 0000000..dd2aba7 --- /dev/null +++ b/tests/classes/dereferencing_001.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 dereferencing of objects from methods +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Name { + function Name($_name) { + $this->name = $_name; + } + + function display() { + echo $this->name . "\n"; + } +} + +class Person { + private $name; + + function person($_name, $_address) { + $this->name = new Name($_name); + } + + function getName() { + return $this->name; + } +} + +$person = new Person("John", "New York"); +$person->getName()->display(); + +?> +--EXPECT-- +John diff --git a/tests/classes/destructor_and_echo.phpt b/tests/classes/destructor_and_echo.phpt new file mode 100644 index 0000000..0a25359 --- /dev/null +++ b/tests/classes/destructor_and_echo.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Destructors and echo +--FILE-- +<?php + +class Test +{ + function __construct() { + echo __METHOD__ . "\n"; + } + + function __destruct() { + echo __METHOD__ . "\n"; + } +} + +$o = new Test; + +?> +===DONE=== +--EXPECT-- +Test::__construct +===DONE=== +Test::__destruct diff --git a/tests/classes/destructor_and_exceptions.phpt b/tests/classes/destructor_and_exceptions.phpt new file mode 100644 index 0000000..8100c92 --- /dev/null +++ b/tests/classes/destructor_and_exceptions.phpt @@ -0,0 +1,60 @@ +--TEST-- +ZE2 catch exception thrown in destructor +--FILE-- +<?php + +class FailClass +{ + public $fatal; + + function __destruct() + { + echo __METHOD__ . "\n"; + throw new exception("FailClass"); + echo "Done: " . __METHOD__ . "\n"; + } +} + +try +{ + $a = new FailClass; + unset($a); +} +catch(Exception $e) +{ + echo "Caught: " . $e->getMessage() . "\n"; +} + +class FatalException extends Exception +{ + function __construct($what) + { + echo __METHOD__ . "\n"; + $o = new FailClass; + unset($o); + echo "Done: " . __METHOD__ . "\n"; + } +} + +try +{ + throw new FatalException("Damn"); +} +catch(Exception $e) +{ + echo "Caught Exception: " . $e->getMessage() . "\n"; +} +catch(FatalException $e) +{ + echo "Caught FatalException: " . $e->getMessage() . "\n"; +} + +?> +===DONE=== +--EXPECTF-- +FailClass::__destruct +Caught: FailClass +FatalException::__construct +FailClass::__destruct +Caught Exception: FailClass +===DONE=== diff --git a/tests/classes/destructor_and_globals.phpt b/tests/classes/destructor_and_globals.phpt new file mode 100644 index 0000000..9caf0f1 --- /dev/null +++ b/tests/classes/destructor_and_globals.phpt @@ -0,0 +1,56 @@ +--TEST-- +ZE2 accessing globals from destructor in shutdown +--FILE-- +<?php +$test_cnt = 0; +$test_num = 0; + +function Show() { + global $test_cnt; + echo "Count: $test_cnt\n"; +} + +class counter { + protected $id; + + public function __construct() { + global $test_cnt, $test_num; + $test_cnt++; + $this->id = $test_num++; + } + + public function Show() { + echo 'Id: '.$this->id."\n"; + } + + // try protected here + public function __destruct() { + global $test_cnt; + $test_cnt--; + } + + static public function destroy(&$obj) { + $obj = NULL; + } +} +Show(); +$obj1 = new counter; +$obj1->Show(); +Show(); +$obj2 = new counter; +$obj2->Show(); +Show(); +counter::destroy($obj1); +Show(); +// or uncomment this line and it works +//counter::destroy($obj2); +echo "Done\n"; +?> +--EXPECT-- +Count: 0 +Id: 0 +Count: 1 +Id: 1 +Count: 2 +Count: 1 +Done diff --git a/tests/classes/destructor_and_references.phpt b/tests/classes/destructor_and_references.phpt new file mode 100644 index 0000000..6b9b019 --- /dev/null +++ b/tests/classes/destructor_and_references.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 Destructing and references +--FILE-- +<?php + +class test1 {public $x;}; +class test2 {public $x;}; +class test3 {public $x;}; +class test4 {public $x;}; + +$o1 = new test1; +$o2 = new test2; +$o3 = new test3; +$o4 = new test4; + +$o3->x = &$o4; + +$r1 = &$o1; + +class once {} + +$o = new once; +echo "Done\n"; +?> +--EXPECT-- +Done diff --git a/tests/classes/destructor_inheritance.phpt b/tests/classes/destructor_inheritance.phpt new file mode 100644 index 0000000..b9a4665 --- /dev/null +++ b/tests/classes/destructor_inheritance.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 The inherited destructor is called +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class base { + function __construct() { + echo __METHOD__ . "\n"; + } + + function __destruct() { + echo __METHOD__ . "\n"; + } +} + +class derived extends base { +} + +$obj = new derived; + +unset($obj); + +echo 'Done'; +?> +--EXPECT-- +base::__construct +base::__destruct +Done
\ No newline at end of file diff --git a/tests/classes/destructor_visibility_001.phpt b/tests/classes/destructor_visibility_001.phpt new file mode 100644 index 0000000..7674c51 --- /dev/null +++ b/tests/classes/destructor_visibility_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Base { + private function __destruct() { + echo __METHOD__ . "\n"; + } +} + +class Derived extends Base { +} + +$obj = new Derived; + +unset($obj); + +?> +===DONE=== +--EXPECTF-- +Fatal error: Call to private Derived::__destruct() from context '' in %sdestructor_visibility_001.php on line %d diff --git a/tests/classes/destructor_visibility_002.phpt b/tests/classes/destructor_visibility_002.phpt new file mode 100644 index 0000000..2cc8333 --- /dev/null +++ b/tests/classes/destructor_visibility_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Base { + private function __destruct() { + echo __METHOD__ . "\n"; + } +} + +class Derived extends Base { +} + +$obj = new Derived; + +?> +===DONE=== +--EXPECTF-- +===DONE=== + +Warning: Call to private Derived::__destruct() from context '' during shutdown ignored in Unknown on line %d diff --git a/tests/classes/destructor_visibility_003.phpt b/tests/classes/destructor_visibility_003.phpt new file mode 100644 index 0000000..83e3efe --- /dev/null +++ b/tests/classes/destructor_visibility_003.phpt @@ -0,0 +1,28 @@ +--TEST-- +ZE2 Ensuring destructor visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Base { + private function __destruct() { + echo __METHOD__ . "\n"; + } +} + +class Derived extends Base { + public function __destruct() { + echo __METHOD__ . "\n"; + } +} + +$obj = new Derived; + +unset($obj); // Derived::__destruct is being called not Base::__destruct + +?> +===DONE=== +--EXPECTF-- +Derived::__destruct +===DONE=== diff --git a/tests/classes/factory_001.phpt b/tests/classes/factory_001.phpt new file mode 100644 index 0000000..97b69c1 --- /dev/null +++ b/tests/classes/factory_001.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 factory objects +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Circle { + function draw() { + echo "Circle\n"; + } +} + +class Square { + function draw() { + print "Square\n"; + } +} + +function ShapeFactoryMethod($shape) { + switch ($shape) { + case "Circle": + return new Circle(); + case "Square": + return new Square(); + } +} + +ShapeFactoryMethod("Circle")->draw(); +ShapeFactoryMethod("Square")->draw(); + +?> +--EXPECT-- +Circle +Square diff --git a/tests/classes/factory_and_singleton_001.phpt b/tests/classes/factory_and_singleton_001.phpt new file mode 100644 index 0000000..70fa020 --- /dev/null +++ b/tests/classes/factory_and_singleton_001.phpt @@ -0,0 +1,101 @@ +--TEST-- +ZE2 factory and singleton, test 1 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + protected $x; + + static private $test = NULL; + static private $cnt = 0; + + static function factory($x) { + if (test::$test) { + return test::$test; + } else { + test::$test = new test($x); + return test::$test; + } + } + + protected function __construct($x) { + test::$cnt++; + $this->x = $x; + } + + static function destroy() { + test::$test = NULL; + } + + protected function __destruct() { + test::$cnt--; + } + + public function get() { + return $this->x; + } + + static public function getX() { + if (test::$test) { + return test::$test->x; + } else { + return NULL; + } + } + + static public function count() { + return test::$cnt; + } +} + +echo "Access static members\n"; +var_dump(test::getX()); +var_dump(test::count()); + +echo "Create x and y\n"; +$x = test::factory(1); +$y = test::factory(2); +var_dump(test::getX()); +var_dump(test::count()); +var_dump($x->get()); +var_dump($y->get()); + +echo "Destruct x\n"; +$x = NULL; +var_dump(test::getX()); +var_dump(test::count()); +var_dump($y->get()); + +echo "Destruct y\n"; +$y = NULL; +var_dump(test::getX()); +var_dump(test::count()); + +echo "Destruct static\n"; +test::destroy(); +var_dump(test::getX()); +var_dump(test::count()); + +echo "Done\n"; +?> +--EXPECT-- +Access static members +NULL +int(0) +Create x and y +int(1) +int(1) +int(1) +int(1) +Destruct x +int(1) +int(1) +int(1) +Destruct y +int(1) +int(1) +Destruct static +NULL +int(0) +Done diff --git a/tests/classes/factory_and_singleton_002.phpt b/tests/classes/factory_and_singleton_002.phpt new file mode 100644 index 0000000..3308a56 --- /dev/null +++ b/tests/classes/factory_and_singleton_002.phpt @@ -0,0 +1,100 @@ +--TEST-- +ZE2 factory and singleton, test 2 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + protected $x; + + static private $test = NULL; + static private $cnt = 0; + + static function factory($x) { + if (test::$test) { + return test::$test; + } else { + test::$test = new test($x); + return test::$test; + } + } + + protected function __construct($x) { + test::$cnt++; + $this->x = $x; + } + + static function destroy() { + test::$test = NULL; + } + + protected function __destruct() { + test::$cnt--; + } + + public function get() { + return $this->x; + } + + static public function getX() { + if (test::$test) { + return test::$test->x; + } else { + return NULL; + } + } + + static public function count() { + return test::$cnt; + } +} + +echo "Access static members\n"; +var_dump(test::getX()); +var_dump(test::count()); + +echo "Create x and y\n"; +$x = test::factory(1); +$y = test::factory(2); +var_dump(test::getX()); +var_dump(test::count()); +var_dump($x->get()); +var_dump($y->get()); + +echo "Destruct x\n"; +$x = NULL; +var_dump(test::getX()); +var_dump(test::count()); +var_dump($y->get()); + +echo "Destruct y\n"; +$y = NULL; +var_dump(test::getX()); +var_dump(test::count()); + +//echo "Destruct static\n"; +//test::destroy(); +//var_dump(test::getX()); +//var_dump(test::count()); + +echo "Done\n"; +?> +--EXPECT-- +Access static members +NULL +int(0) +Create x and y +int(1) +int(1) +int(1) +int(1) +Destruct x +int(1) +int(1) +int(1) +Destruct y +int(1) +int(1) +Done + +Warning: Call to protected test::__destruct() from context '' during shutdown ignored in Unknown on line 0 diff --git a/tests/classes/factory_and_singleton_003.phpt b/tests/classes/factory_and_singleton_003.phpt new file mode 100644 index 0000000..3d50a81 --- /dev/null +++ b/tests/classes/factory_and_singleton_003.phpt @@ -0,0 +1,18 @@ +--TEST-- +ZE2 factory and singleton, test 3 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + protected function __construct($x) { + } +} + +$obj = new test; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to protected test::__construct() from invalid context in %s on line %d diff --git a/tests/classes/factory_and_singleton_004.phpt b/tests/classes/factory_and_singleton_004.phpt new file mode 100644 index 0000000..14edcb1 --- /dev/null +++ b/tests/classes/factory_and_singleton_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +ZE2 factory and singleton, test 4 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + private function __construct($x) { + } +} + +$obj = new test; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to private test::__construct() from invalid context in %s on line %d diff --git a/tests/classes/factory_and_singleton_005.phpt b/tests/classes/factory_and_singleton_005.phpt new file mode 100644 index 0000000..2cd7e5c --- /dev/null +++ b/tests/classes/factory_and_singleton_005.phpt @@ -0,0 +1,19 @@ +--TEST-- +ZE2 factory and singleton, test 5 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + protected function __destruct() { + } +} + +$obj = new test; +$obj = NULL; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to protected test::__destruct() from context '' in %sfactory_and_singleton_005.php on line %d diff --git a/tests/classes/factory_and_singleton_006.phpt b/tests/classes/factory_and_singleton_006.phpt new file mode 100644 index 0000000..81cf714 --- /dev/null +++ b/tests/classes/factory_and_singleton_006.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 factory and singleton, test 6 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + private function __destruct() { + } +} + +$obj = new test; +$obj = NULL; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to private test::__destruct() from context '' in %sfactory_and_singleton_006.php on line %d + diff --git a/tests/classes/factory_and_singleton_007.phpt b/tests/classes/factory_and_singleton_007.phpt new file mode 100644 index 0000000..4788dbf --- /dev/null +++ b/tests/classes/factory_and_singleton_007.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 factory and singleton, test 7 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + protected function __clone() { + } +} + +$obj = new test; +$clone = clone $obj; +$obj = NULL; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to protected test::__clone() from context '' %sfactory_and_singleton_007.php on line %d diff --git a/tests/classes/factory_and_singleton_008.phpt b/tests/classes/factory_and_singleton_008.phpt new file mode 100644 index 0000000..750b9db --- /dev/null +++ b/tests/classes/factory_and_singleton_008.phpt @@ -0,0 +1,20 @@ +--TEST-- +ZE2 factory and singleton, test 8 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + private function __clone() { + } +} + +$obj = new test; +$clone = clone $obj; +$obj = NULL; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Call to private test::__clone() from context '' %sfactory_and_singleton_008.php on line %d diff --git a/tests/classes/factory_and_singleton_009.phpt b/tests/classes/factory_and_singleton_009.phpt new file mode 100644 index 0000000..acf792c --- /dev/null +++ b/tests/classes/factory_and_singleton_009.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 factory and singleton, test 9 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + protected function __destruct() { + echo __METHOD__ . "\n"; + } +} + +$obj = new test; + +?> +===DONE=== +--EXPECTF-- +===DONE=== + +Warning: Call to protected test::__destruct() from context '' during shutdown ignored in Unknown on line 0 diff --git a/tests/classes/factory_and_singleton_010.phpt b/tests/classes/factory_and_singleton_010.phpt new file mode 100644 index 0000000..0f5fb2d --- /dev/null +++ b/tests/classes/factory_and_singleton_010.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 factory and singleton, test 10 +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class test { + + private function __destruct() { + echo __METHOD__ . "\n"; + } +} + +$obj = new test; + +?> +===DONE=== +--EXPECTF-- +===DONE=== + +Warning: Call to private test::__destruct() from context '' during shutdown ignored in Unknown on line 0 diff --git a/tests/classes/final.phpt b/tests/classes/final.phpt new file mode 100644 index 0000000..b4e37a3 --- /dev/null +++ b/tests/classes/final.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 A method may be redeclared final +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class first { + function show() { + echo "Call to function first::show()\n"; + } +} + +$t = new first(); +$t->show(); + +class second extends first { + final function show() { + echo "Call to function second::show()\n"; + } +} + +$t2 = new second(); +$t2->show(); + +echo "Done\n"; +?> +--EXPECTF-- +Call to function first::show() +Call to function second::show() +Done
\ No newline at end of file diff --git a/tests/classes/final_abstract.phpt b/tests/classes/final_abstract.phpt new file mode 100644 index 0000000..426c852 --- /dev/null +++ b/tests/classes/final_abstract.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZE2 A final method cannot be abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class fail { + final abstract function show(); +} + +echo "Done\n"; // Shouldn't be displayed +?> +--EXPECTF-- + +Fatal error: Cannot use the final modifier on an abstract class member in %s diff --git a/tests/classes/final_ctor1.phpt b/tests/classes/final_ctor1.phpt new file mode 100644 index 0000000..ebfa080 --- /dev/null +++ b/tests/classes/final_ctor1.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 cannot override final __construct +--FILE-- +<?php + +class Base +{ + public final function __construct() + { + } +} + +class Works extends Base +{ +} + +class Extended extends Base +{ + public function Extended() + { + } +} + +ReflectionClass::export('Extended'); + +?> +--EXPECTF-- + +Fatal error: Cannot override final Base::__construct() with Extended::Extended() in %sfinal_ctor1.php on line %d diff --git a/tests/classes/final_ctor2.phpt b/tests/classes/final_ctor2.phpt new file mode 100644 index 0000000..905337b --- /dev/null +++ b/tests/classes/final_ctor2.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 cannot override final old style ctor +--FILE-- +<?php + +class Base +{ + public final function Base() + { + } +} + +class Works extends Base +{ +} + +class Extended extends Base +{ + public function __construct() + { + } +} + +ReflectionClass::export('Extended'); + +?> +--EXPECTF-- + +Fatal error: Cannot override final Base::Base() with Extended::__construct() in %sfinal_ctor2.php on line %d diff --git a/tests/classes/final_ctor3.phpt b/tests/classes/final_ctor3.phpt new file mode 100644 index 0000000..3a61ecf --- /dev/null +++ b/tests/classes/final_ctor3.phpt @@ -0,0 +1,13 @@ +--TEST-- +Ensure implicit final inherited old-style constructor cannot be overridden. +--FILE-- +<?php + class A { + final function A() { } + } + class B extends A { + function A() { } + } +?> +--EXPECTF-- +Fatal error: Cannot override final method A::A() in %s on line %d diff --git a/tests/classes/final_redeclare.phpt b/tests/classes/final_redeclare.phpt new file mode 100644 index 0000000..e8f2e6f --- /dev/null +++ b/tests/classes/final_redeclare.phpt @@ -0,0 +1,25 @@ +--TEST-- +ZE2 A final method may not be overwritten +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + final function show() { + echo "Call to function pass::show()\n"; + } +} + +$t = new pass(); + +class fail extends pass { + function show() { + echo "Call to function fail::show()\n"; + } +} + +echo "Done\n"; // Shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Cannot override final method pass::show() in %s on line %d diff --git a/tests/classes/implicit_instantiation_001.phpt b/tests/classes/implicit_instantiation_001.phpt new file mode 100644 index 0000000..8d2f32d --- /dev/null +++ b/tests/classes/implicit_instantiation_001.phpt @@ -0,0 +1,146 @@ +--TEST-- +Implicit object instantiation when accessing properties of non-object. +--FILE-- +<?php +class C { + // These values get implicitly converted to objects + public $boolFalse = false; + public $emptyString = ''; + public $null = null; + + // These values do not get implicitly converted to objects + public $boolTrue = true; + public $nonEmptyString = 'hello'; + public $intZero = 0; +} + +$c = new C; +foreach($c as $name => $value) { + echo "\n\n---( \$c->$name )---"; + echo "\n --> Attempting implicit conversion to object using increment...\n"; + $c->$name->prop++; + $c->$name = $value; // reset value in case implicit conversion was successful + + echo "\n --> Attempting implicit conversion to object using assignment...\n"; + $c->$name->prop = "Implicit instantiation!"; + $c->$name = $value; // reset value in case implicit conversion was successful + + echo "\n --> Attempting implicit conversion to object using combined assignment...\n"; + $c->$name->prop .= " Implicit instantiation!"; +} + +echo "\n\n\n --> Resulting object:"; +var_dump($c); + +?> +--EXPECTF-- + + +---( $c->boolFalse )--- + --> Attempting implicit conversion to object using increment... + +Warning: Creating default object from empty value in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Creating default object from empty value in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Creating default object from empty value in %s on line 26 + + +---( $c->emptyString )--- + --> Attempting implicit conversion to object using increment... + +Warning: Creating default object from empty value in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Creating default object from empty value in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Creating default object from empty value in %s on line 26 + + +---( $c->null )--- + --> Attempting implicit conversion to object using increment... + +Warning: Creating default object from empty value in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Creating default object from empty value in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Creating default object from empty value in %s on line 26 + + +---( $c->boolTrue )--- + --> Attempting implicit conversion to object using increment... + +Warning: Attempt to %s property of non-object in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Attempt to assign property of non-object in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Attempt to assign property of non-object in %s on line 26 + + +---( $c->nonEmptyString )--- + --> Attempting implicit conversion to object using increment... + +Warning: Attempt to %s property of non-object in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Attempt to assign property of non-object in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Attempt to assign property of non-object in %s on line 26 + + +---( $c->intZero )--- + --> Attempting implicit conversion to object using increment... + +Warning: Attempt to %s property of non-object in %s on line 18 + + --> Attempting implicit conversion to object using assignment... + +Warning: Attempt to assign property of non-object in %s on line 22 + + --> Attempting implicit conversion to object using combined assignment... + +Warning: Attempt to assign property of non-object in %s on line 26 + + + + --> Resulting object:object(C)#%d (6) { + [%u|b%"boolFalse"]=> + object(stdClass)#%d (1) { + [%u|b%"prop"]=> + %unicode|string%(24) " Implicit instantiation!" + } + [%u|b%"emptyString"]=> + object(stdClass)#%d (1) { + [%u|b%"prop"]=> + %unicode|string%(24) " Implicit instantiation!" + } + [%u|b%"null"]=> + object(stdClass)#%d (1) { + [%u|b%"prop"]=> + %unicode|string%(24) " Implicit instantiation!" + } + [%u|b%"boolTrue"]=> + bool(true) + [%u|b%"nonEmptyString"]=> + %unicode|string%(5) "hello" + [%u|b%"intZero"]=> + int(0) +}
\ No newline at end of file diff --git a/tests/classes/incdec_property_001.phpt b/tests/classes/incdec_property_001.phpt new file mode 100644 index 0000000..97a24d3 --- /dev/null +++ b/tests/classes/incdec_property_001.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 post increment/decrement property of overloaded object +--FILE-- +<?php + +class Test { + private $real_a = 2; + + function __set($property, $value) { + if ($property == "a") { + $this->real_a = $value; + } + } + + function __get($property) { + if ($property == "a") { + return $this->real_a; + } + } +} + +$obj = new Test; +var_dump($obj->a); +$obj->a++; +var_dump($obj->a); +echo "---Done---\n"; +?> +--EXPECT-- +int(2) +int(3) +---Done--- diff --git a/tests/classes/incdec_property_002.phpt b/tests/classes/incdec_property_002.phpt new file mode 100644 index 0000000..c1d7dde --- /dev/null +++ b/tests/classes/incdec_property_002.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 post increment/decrement property of overloaded object with assignment +--FILE-- +<?php + +class Test { + private $real_a = 2; + + function __set($property, $value) { + if ($property == "a") { + $this->real_a = $value; + } + } + + function __get($property) { + if ($property == "a") { + return $this->real_a; + } + } +} + +$obj = new Test; +var_dump($obj->a); +$t1 = $obj->a++; +var_dump($obj->a); +echo "---Done---\n"; +?> +--EXPECT-- +int(2) +int(3) +---Done--- diff --git a/tests/classes/incdec_property_003.phpt b/tests/classes/incdec_property_003.phpt new file mode 100644 index 0000000..1a92384 --- /dev/null +++ b/tests/classes/incdec_property_003.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 pre increment/decrement property of overloaded object +--FILE-- +<?php + +class Test { + private $real_a = 2; + + function __set($property, $value) { + if ($property == "a") { + $this->real_a = $value; + } + } + + function __get($property) { + if ($property == "a") { + return $this->real_a; + } + } +} + +$obj = new Test; +var_dump($obj->a); +++$obj->a; +var_dump($obj->a); +echo "---Done---\n"; +?> +--EXPECT-- +int(2) +int(3) +---Done--- diff --git a/tests/classes/incdec_property_004.phpt b/tests/classes/incdec_property_004.phpt new file mode 100644 index 0000000..05e3b44 --- /dev/null +++ b/tests/classes/incdec_property_004.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 pre increment/decrement property of overloaded object with assignment +--FILE-- +<?php + +class Test { + private $real_a = 2; + + function __set($property, $value) { + if ($property == "a") { + $this->real_a = $value; + } + } + + function __get($property) { + if ($property == "a") { + return $this->real_a; + } + } +} + +$obj = new Test; +var_dump($obj->a); +$t1 = ++$obj->a; +var_dump($obj->a); +echo "---Done---\n"; +?> +--EXPECT-- +int(2) +int(3) +---Done--- diff --git a/tests/classes/inheritance.phpt b/tests/classes/inheritance.phpt new file mode 100644 index 0000000..070ad91 --- /dev/null +++ b/tests/classes/inheritance.phpt @@ -0,0 +1,56 @@ +--TEST-- +Classes inheritance test +--FILE-- +<?php + +/* Inheritance test. Pretty nifty if I do say so myself! */ + +class foo { + public $a; + public $b; + function display() { + echo "This is class foo\n"; + echo "a = ".$this->a."\n"; + echo "b = ".$this->b."\n"; + } + function mul() { + return $this->a*$this->b; + } +}; + +class bar extends foo { + public $c; + function display() { /* alternative display function for class bar */ + echo "This is class bar\n"; + echo "a = ".$this->a."\n"; + echo "b = ".$this->b."\n"; + echo "c = ".$this->c."\n"; + } +}; + + +$foo1 = new foo; +$foo1->a = 2; +$foo1->b = 5; +$foo1->display(); +echo $foo1->mul()."\n"; + +echo "-----\n"; + +$bar1 = new bar; +$bar1->a = 4; +$bar1->b = 3; +$bar1->c = 12; +$bar1->display(); +echo $bar1->mul()."\n"; +--EXPECT-- +This is class foo +a = 2 +b = 5 +10 +----- +This is class bar +a = 4 +b = 3 +c = 12 +12 diff --git a/tests/classes/inheritance_002.phpt b/tests/classes/inheritance_002.phpt new file mode 100644 index 0000000..cca528e --- /dev/null +++ b/tests/classes/inheritance_002.phpt @@ -0,0 +1,71 @@ +--TEST-- +ZE2 Constructor precedence +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class Base_php4 { + function Base_php4() { + var_dump('Base constructor'); + } +} + +class Child_php4 extends Base_php4 { + function Child_php4() { + var_dump('Child constructor'); + parent::Base_php4(); + } +} + +class Base_php5 { + function __construct() { + var_dump('Base constructor'); + } + } + +class Child_php5 extends Base_php5 { + function __construct() { + var_dump('Child constructor'); + parent::__construct(); + } + } + +class Child_mx1 extends Base_php4 { + function __construct() { + var_dump('Child constructor'); + parent::Base_php4(); + } +} + +class Child_mx2 extends Base_php5 { + function Child_mx2() { + var_dump('Child constructor'); + parent::__construct(); + } +} + +echo "### PHP 4 style\n"; +$c4= new Child_php4(); + +echo "### PHP 5 style\n"; +$c5= new Child_php5(); + +echo "### Mixed style 1\n"; +$cm= new Child_mx1(); + +echo "### Mixed style 2\n"; +$cm= new Child_mx2(); +?> +--EXPECT-- +### PHP 4 style +string(17) "Child constructor" +string(16) "Base constructor" +### PHP 5 style +string(17) "Child constructor" +string(16) "Base constructor" +### Mixed style 1 +string(17) "Child constructor" +string(16) "Base constructor" +### Mixed style 2 +string(17) "Child constructor" +string(16) "Base constructor" diff --git a/tests/classes/inheritance_003.phpt b/tests/classes/inheritance_003.phpt new file mode 100644 index 0000000..1f4eafa --- /dev/null +++ b/tests/classes/inheritance_003.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 method inheritance without interfaces +--FILE-- +<?php + +class A +{ + function f($x) {} +} + +class B extends A +{ + function f() {} +} + +?> +===DONE=== +--EXPECTF-- + +Strict Standards: Declaration of B::f() should be compatible with A::f($x) in %sinheritance_003.php on line %d +===DONE=== diff --git a/tests/classes/inheritance_004.phpt b/tests/classes/inheritance_004.phpt new file mode 100644 index 0000000..d1f5faf --- /dev/null +++ b/tests/classes/inheritance_004.phpt @@ -0,0 +1,21 @@ +--TEST-- +ZE2 method inheritance without interfaces +--FILE-- +<?php + +class A +{ + function f() {} +} + +class B extends A +{ + function f($x) {} +} + +?> +===DONE=== +--EXPECTF-- + +Strict Standards: Declaration of B::f() should be compatible with A::f() in %sinheritance_004.php on line %d +===DONE=== diff --git a/tests/classes/inheritance_005.phpt b/tests/classes/inheritance_005.phpt new file mode 100644 index 0000000..8990264 --- /dev/null +++ b/tests/classes/inheritance_005.phpt @@ -0,0 +1,57 @@ +--TEST-- +Check for inherited old-style constructor. +--FILE-- +<?php + class A + { + function A() + { + echo "In " . __METHOD__ . "\n"; + } + } + + class B extends A + { + } + + class C extends B + { + } + + + echo "About to construct new B: \n"; + $b = new B; + + echo "Is B::B() callable?\n"; + var_dump(is_callable(array($b, "B"))); + + echo "Is B::A() callable?\n"; + var_dump(is_callable(array($b, "A"))); + + echo "About to construct new C: \n"; + $c = new C; + + echo "Is C::A() callable?\n"; + var_dump(is_callable(array($c, "A"))); + + echo "Is C::B() callable?\n"; + var_dump(is_callable(array($c, "B"))); + + echo "Is C::C() callable?\n"; + var_dump(is_callable(array($c, "C"))); +?> +--EXPECTF-- +About to construct new B: +In A::A +Is B::B() callable? +bool(false) +Is B::A() callable? +bool(true) +About to construct new C: +In A::A +Is C::A() callable? +bool(true) +Is C::B() callable? +bool(false) +Is C::C() callable? +bool(false) diff --git a/tests/classes/inheritance_006.phpt b/tests/classes/inheritance_006.phpt new file mode 100644 index 0000000..d51dafe --- /dev/null +++ b/tests/classes/inheritance_006.phpt @@ -0,0 +1,24 @@ +--TEST-- +Private property inheritance check +--FILE-- +<?php +Class A { + private $c; +} + +Class B extends A { + private $c; +} + +Class C extends B { +} + +var_dump(new C); +?> +--EXPECTF-- +object(C)#%d (2) { + [%u|b%"c":%u|b%"B":private]=> + NULL + [%u|b%"c":%u|b%"A":private]=> + NULL +}
\ No newline at end of file diff --git a/tests/classes/inheritance_007.phpt b/tests/classes/inheritance_007.phpt new file mode 100644 index 0000000..0b2bde0 --- /dev/null +++ b/tests/classes/inheritance_007.phpt @@ -0,0 +1,39 @@ +--TEST-- +Ensure inherited old-style constructor doesn't block other methods +--FILE-- +<?php +class A { + public function B () { echo "In " . __METHOD__ . "\n"; } + public function A () { echo "In " . __METHOD__ . "\n"; } +} +class B extends A { } + +$rc = new ReflectionClass('B'); +var_dump($rc->getMethods()); + + +$b = new B(); +$b->a(); +$b->b(); + +?> +--EXPECTF-- +array(2) { + [0]=> + &object(ReflectionMethod)#%d (2) { + ["name"]=> + string(1) "B" + ["class"]=> + string(1) "A" + } + [1]=> + &object(ReflectionMethod)#%d (2) { + ["name"]=> + string(1) "A" + ["class"]=> + string(1) "A" + } +} +In A::A +In A::A +In A::B diff --git a/tests/classes/interface_and_extends.phpt b/tests/classes/interface_and_extends.phpt new file mode 100644 index 0000000..f9040ae --- /dev/null +++ b/tests/classes/interface_and_extends.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 a class cannot extend an interface +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface Test +{ + function show(); +} + +class Tester extends Test +{ + function show() { + echo __METHOD__ . "\n"; + } +} + +$o = new Tester; +$o->show(); + +?> +===DONE=== +--EXPECTF-- +Fatal error: Class Tester cannot extend from interface Test in %sinterface_and_extends.php on line %d diff --git a/tests/classes/interface_class.phpt b/tests/classes/interface_class.phpt new file mode 100644 index 0000000..22520de --- /dev/null +++ b/tests/classes/interface_class.phpt @@ -0,0 +1,14 @@ +--TEST-- +ZE2 A class can only implement interfaces +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class base { +} + +class derived implements base { +} +?> +--EXPECTF-- +Fatal error: derived cannot implement base - it is not an interface in %s on line %d diff --git a/tests/classes/interface_constant_inheritance_001.phpt b/tests/classes/interface_constant_inheritance_001.phpt new file mode 100644 index 0000000..f982a4a --- /dev/null +++ b/tests/classes/interface_constant_inheritance_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +Ensure an interface may not shadow an inherited constant. +--FILE-- +<?php +interface I1 { + const FOO = 10; +} + +interface I2 extends I1 { + const FOO = 10; +} + +echo "Done\n"; +?> +--EXPECTF-- + +Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I1 in %s on line 6 diff --git a/tests/classes/interface_constant_inheritance_002.phpt b/tests/classes/interface_constant_inheritance_002.phpt new file mode 100644 index 0000000..af4ce69 --- /dev/null +++ b/tests/classes/interface_constant_inheritance_002.phpt @@ -0,0 +1,17 @@ +--TEST-- +Ensure a class may not shadow a constant inherited from an interface. +--FILE-- +<?php +interface I { + const FOO = 10; +} + +class C implements I { + const FOO = 10; +} + +echo "Done\n"; +?> +--EXPECTF-- + +Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I in %s on line 6 diff --git a/tests/classes/interface_constant_inheritance_003.phpt b/tests/classes/interface_constant_inheritance_003.phpt new file mode 100644 index 0000000..6b4139b --- /dev/null +++ b/tests/classes/interface_constant_inheritance_003.phpt @@ -0,0 +1,20 @@ +--TEST-- +Ensure a class may not inherit two constants with the same name from two separate interfaces. +--FILE-- +<?php +interface I1 { + const FOO = 10; +} + +interface I2 { + const FOO = 10; +} + +class C implements I1,I2 { +} + +echo "Done\n"; +?> +--EXPECTF-- + +Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I2 in %s on line 10 diff --git a/tests/classes/interface_constant_inheritance_004.phpt b/tests/classes/interface_constant_inheritance_004.phpt new file mode 100644 index 0000000..f055929 --- /dev/null +++ b/tests/classes/interface_constant_inheritance_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +Ensure a class may implement two interfaces which include the same constant (due to inheritance). +--FILE-- +<?php +interface IA { + const FOO = 10; +} + +interface IB extends IA { +} + +class C implements IA, IB { +} + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/tests/classes/interface_doubled.phpt b/tests/classes/interface_doubled.phpt new file mode 100644 index 0000000..e1dd31f --- /dev/null +++ b/tests/classes/interface_doubled.phpt @@ -0,0 +1,201 @@ +--TEST-- +ZE2 An interface extends base interfaces +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + function f_a(); +} + +interface if_b { + function f_b(); +} + +interface if_c extends if_a, if_b { + function f_c(); +} + +interface if_d extends if_a, if_b { + function f_d(); +} + +interface if_e { + function f_d(); +} + +interface if_f extends /*if_e,*/ if_a, if_b, if_c, if_d /*, if_e*/ { +} + +class base { + function test($class) { + echo "is_a(" . get_class($this) . ", $class) ". (($this instanceof $class) ? "yes\n" : "no\n"); + } +} + +echo "class_a\n"; + +class class_a extends base implements if_a { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_a(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_b\n"; + +class class_b extends base implements if_a, if_b { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_b(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_c\n"; + +class class_c extends base implements if_c { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_c(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_d\n"; + +class class_d extends base implements if_d{ + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_d(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_e\n"; + +class class_e extends base implements if_a, if_b, if_c, if_d { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_e(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_f\n"; + +class class_f extends base implements if_e { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_f(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +echo "class_g\n"; + +class class_g extends base implements if_f { + function f_a() {} + function f_b() {} + function f_c() {} + function f_d() {} + function f_e() {} +} + +$t = new class_g(); +echo $t->test('if_a'); +echo $t->test('if_b'); +echo $t->test('if_c'); +echo $t->test('if_d'); +echo $t->test('if_e'); + +?> +===DONE=== +--EXPECTF-- +class_a +is_a(class_a, if_a) yes +is_a(class_a, if_b) no +is_a(class_a, if_c) no +is_a(class_a, if_d) no +is_a(class_a, if_e) no +class_b +is_a(class_b, if_a) yes +is_a(class_b, if_b) yes +is_a(class_b, if_c) no +is_a(class_b, if_d) no +is_a(class_b, if_e) no +class_c +is_a(class_c, if_a) yes +is_a(class_c, if_b) yes +is_a(class_c, if_c) yes +is_a(class_c, if_d) no +is_a(class_c, if_e) no +class_d +is_a(class_d, if_a) yes +is_a(class_d, if_b) yes +is_a(class_d, if_c) no +is_a(class_d, if_d) yes +is_a(class_d, if_e) no +class_e +is_a(class_e, if_a) yes +is_a(class_e, if_b) yes +is_a(class_e, if_c) yes +is_a(class_e, if_d) yes +is_a(class_e, if_e) no +class_f +is_a(class_f, if_a) no +is_a(class_f, if_b) no +is_a(class_f, if_c) no +is_a(class_f, if_d) no +is_a(class_f, if_e) yes +class_g +is_a(class_g, if_a) yes +is_a(class_g, if_b) yes +is_a(class_g, if_c) yes +is_a(class_g, if_d) yes +is_a(class_g, if_e) no +===DONE=== diff --git a/tests/classes/interface_implemented.phpt b/tests/classes/interface_implemented.phpt new file mode 100644 index 0000000..e33a4da --- /dev/null +++ b/tests/classes/interface_implemented.phpt @@ -0,0 +1,103 @@ +--TEST-- +ZE2 An interface is inherited +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + function f_a(); +} + +interface if_b extends if_a { + function f_b(); +} + +class base { + function _is_a($sub) { + echo 'is_a('.get_class($this).', '.$sub.') = '.(($this instanceof $sub) ? 'yes' : 'no')."\n"; + } + function test() { + echo $this->_is_a('base'); + echo $this->_is_a('derived_a'); + echo $this->_is_a('derived_b'); + echo $this->_is_a('derived_c'); + echo $this->_is_a('derived_d'); + echo $this->_is_a('if_a'); + echo $this->_is_a('if_b'); + echo "\n"; + } +} + +class derived_a extends base implements if_a { + function f_a() {} +} + +class derived_b extends base implements if_a, if_b { + function f_a() {} + function f_b() {} +} + +class derived_c extends derived_a implements if_b { + function f_b() {} +} + +class derived_d extends derived_c { +} + +$t = new base(); +$t->test(); + +$t = new derived_a(); +$t->test(); + +$t = new derived_b(); +$t->test(); + +$t = new derived_c(); +$t->test(); + +$t = new derived_d(); +$t->test(); + +?> +--EXPECTF-- +is_a(base, base) = yes +is_a(base, derived_a) = no +is_a(base, derived_b) = no +is_a(base, derived_c) = no +is_a(base, derived_d) = no +is_a(base, if_a) = no +is_a(base, if_b) = no + +is_a(derived_a, base) = yes +is_a(derived_a, derived_a) = yes +is_a(derived_a, derived_b) = no +is_a(derived_a, derived_c) = no +is_a(derived_a, derived_d) = no +is_a(derived_a, if_a) = yes +is_a(derived_a, if_b) = no + +is_a(derived_b, base) = yes +is_a(derived_b, derived_a) = no +is_a(derived_b, derived_b) = yes +is_a(derived_b, derived_c) = no +is_a(derived_b, derived_d) = no +is_a(derived_b, if_a) = yes +is_a(derived_b, if_b) = yes + +is_a(derived_c, base) = yes +is_a(derived_c, derived_a) = yes +is_a(derived_c, derived_b) = no +is_a(derived_c, derived_c) = yes +is_a(derived_c, derived_d) = no +is_a(derived_c, if_a) = yes +is_a(derived_c, if_b) = yes + +is_a(derived_d, base) = yes +is_a(derived_d, derived_a) = yes +is_a(derived_d, derived_b) = no +is_a(derived_d, derived_c) = yes +is_a(derived_d, derived_d) = yes +is_a(derived_d, if_a) = yes +is_a(derived_d, if_b) = yes diff --git a/tests/classes/interface_instantiate.phpt b/tests/classes/interface_instantiate.phpt new file mode 100644 index 0000000..61c4e6b --- /dev/null +++ b/tests/classes/interface_instantiate.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZE2 An interface cannot be instantiated +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + function f_a(); +} + +$t = new if_a(); + +?> +--EXPECTF-- +Fatal error: Cannot instantiate interface if_a in %s on line %d diff --git a/tests/classes/interface_member.phpt b/tests/classes/interface_member.phpt new file mode 100644 index 0000000..329c072 --- /dev/null +++ b/tests/classes/interface_member.phpt @@ -0,0 +1,13 @@ +--TEST-- +ZE2 An interface cannot have properties +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + public $member; +} +?> +--EXPECTF-- +Fatal error: Interfaces may not include member variables in %s on line %d diff --git a/tests/classes/interface_method.phpt b/tests/classes/interface_method.phpt new file mode 100644 index 0000000..3570b35 --- /dev/null +++ b/tests/classes/interface_method.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 An interface method must be abstract +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + function err() {}; +} + +?> +--EXPECTF-- + +Fatal error: Interface function if_a::err() cannot contain body %s on line %d diff --git a/tests/classes/interface_method_final.phpt b/tests/classes/interface_method_final.phpt new file mode 100644 index 0000000..01e599c --- /dev/null +++ b/tests/classes/interface_method_final.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 An interface method cannot be final +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class if_a { + abstract final function err(); +} + +?> +--EXPECTF-- + +Fatal error: Cannot use the final modifier on an abstract class member in %s on line %d diff --git a/tests/classes/interface_method_private.phpt b/tests/classes/interface_method_private.phpt new file mode 100644 index 0000000..aa46a03 --- /dev/null +++ b/tests/classes/interface_method_private.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZE2 An interface method cannot be private +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + abstract private function err(); +} + +?> +--EXPECTF-- + +Fatal error: Access type for interface method if_a::err() must be omitted in %s on line %d diff --git a/tests/classes/interface_must_be_implemented.phpt b/tests/classes/interface_must_be_implemented.phpt new file mode 100644 index 0000000..a4d7970 --- /dev/null +++ b/tests/classes/interface_must_be_implemented.phpt @@ -0,0 +1,17 @@ +--TEST-- +ZE2 An interface must be implemented +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface if_a { + function f_a(); +} + +class derived_a implements if_a { +} + +?> +--EXPECTF-- +Fatal error: Class derived_a contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (if_a::f_a) in %s on line %d diff --git a/tests/classes/interface_optional_arg.phpt b/tests/classes/interface_optional_arg.phpt new file mode 100644 index 0000000..05f2fc4 --- /dev/null +++ b/tests/classes/interface_optional_arg.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 An interface method allows additional default arguments +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +error_reporting(4095); + +interface test { + public function bar(); +} + +class foo implements test { + + public function bar($foo = NULL) { + echo "foo\n"; + } +} + +$foo = new foo; +$foo->bar(); + +?> +--EXPECT-- +foo + diff --git a/tests/classes/interface_optional_arg_002.phpt b/tests/classes/interface_optional_arg_002.phpt new file mode 100644 index 0000000..92980f6 --- /dev/null +++ b/tests/classes/interface_optional_arg_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +default argument value in interface implementation +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface test { + public function bar(); +} + +class foo implements test { + + public function bar($arg = 2) { + var_dump($arg); + } +} + +$foo = new foo; +$foo->bar(); + +?> +--EXPECT-- +int(2)
\ No newline at end of file diff --git a/tests/classes/interface_optional_arg_003.inc b/tests/classes/interface_optional_arg_003.inc new file mode 100644 index 0000000..a62c656 --- /dev/null +++ b/tests/classes/interface_optional_arg_003.inc @@ -0,0 +1,4 @@ +<?php +interface I { + function f($a = null); +}
\ No newline at end of file diff --git a/tests/classes/interface_optional_arg_003.phpt b/tests/classes/interface_optional_arg_003.phpt new file mode 100644 index 0000000..13e36d5 --- /dev/null +++ b/tests/classes/interface_optional_arg_003.phpt @@ -0,0 +1,17 @@ +--TEST-- +default argument value in and in implementing class with interface in included file +--FILE-- +<?php +include 'interface_optional_arg_003.inc'; + +class C implements I { + function f($a = 2) { + var_dump($a); + } +} + +$c = new C; +$c->f(); +?> +--EXPECTF-- +int(2)
\ No newline at end of file diff --git a/tests/classes/interfaces_001.phpt b/tests/classes/interfaces_001.phpt new file mode 100644 index 0000000..41e1f67 --- /dev/null +++ b/tests/classes/interfaces_001.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 interfaces +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface Throwable { + public function getMessage(); +} + +class Exception_foo implements Throwable { + public $foo = "foo"; + + public function getMessage() { + return $this->foo; + } +} + +$foo = new Exception_foo; +echo $foo->getMessage() . "\n"; + +?> +--EXPECT-- +foo + diff --git a/tests/classes/interfaces_002.phpt b/tests/classes/interfaces_002.phpt new file mode 100644 index 0000000..d26b534 --- /dev/null +++ b/tests/classes/interfaces_002.phpt @@ -0,0 +1,29 @@ +--TEST-- +ZE2 interface with an unimplemented method +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface Throwable { + public function getMessage(); + public function getErrno(); +} + +class Exception_foo implements Throwable { + public $foo = "foo"; + + public function getMessage() { + return $this->foo; + } +} + +// this should die -- Exception class must be abstract... +$foo = new Exception_foo; +echo "Message: " . $foo->getMessage() . "\n"; + +?> +===DONE=== +--EXPECTF-- + +Fatal error: Class Exception_foo contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Throwable::getErrno) in %s on line %d diff --git a/tests/classes/interfaces_003.phpt b/tests/classes/interfaces_003.phpt new file mode 100644 index 0000000..f9ab92b --- /dev/null +++ b/tests/classes/interfaces_003.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 interface and __construct +--FILE-- +<?php + +class MyObject {} + +interface MyInterface +{ + public function __construct(MyObject $o); +} + +class MyTestClass implements MyInterface +{ + public function __construct(MyObject $o) + { + } +} + +$obj = new MyTestClass; + +?> +===DONE=== +--EXPECTF-- + +Catchable fatal error: Argument 1 passed to MyTestClass::__construct() must be an instance of MyObject, none given, called in %sinterfaces_003.php on line %d diff --git a/tests/classes/iterators_001.phpt b/tests/classes/iterators_001.phpt new file mode 100644 index 0000000..02e3610 --- /dev/null +++ b/tests/classes/iterators_001.phpt @@ -0,0 +1,200 @@ +--TEST-- +ZE2 iterators and foreach +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class c_iter implements Iterator { + + private $obj; + private $num = 0; + + function __construct($obj) { + echo __METHOD__ . "\n"; + $this->num = 0; + $this->obj = $obj; + } + function rewind() { + } + function valid() { + $more = $this->num < $this->obj->max; + echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n"; + return $more; + } + function current() { + echo __METHOD__ . "\n"; + return $this->num; + } + function next() { + echo __METHOD__ . "\n"; + $this->num++; + } + function key() { + echo __METHOD__ . "\n"; + switch($this->num) { + case 0: return "1st"; + case 1: return "2nd"; + case 2: return "3rd"; + default: return "???"; + } + } +} + +class c implements IteratorAggregate { + + public $max = 3; + + function getIterator() { + echo __METHOD__ . "\n"; + return new c_iter($this); + } +} + +echo "===Array===\n"; + +$a = array(0,1,2); +foreach($a as $v) { + echo "array:$v\n"; +} + +echo "===Manual===\n"; +$t = new c(); +for ($iter = $t->getIterator(); $iter->valid(); $iter->next()) { + echo $iter->current() . "\n"; +} + +echo "===foreach/std===\n"; +foreach($t as $v) { + echo "object:$v\n"; +} + +echo "===foreach/rec===\n"; +foreach($t as $v) { + foreach($t as $w) { + echo "double:$v:$w\n"; + } +} + +echo "===foreach/key===\n"; +foreach($t as $i => $v) { + echo "object:$i=>$v\n"; +} + +print "Done\n"; +exit(0); +?> +--EXPECT-- +===Array=== +array:0 +array:1 +array:2 +===Manual=== +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +0 +c_iter::next +c_iter::valid = true +c_iter::current +1 +c_iter::next +c_iter::valid = true +c_iter::current +2 +c_iter::next +c_iter::valid = false +===foreach/std=== +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +object:0 +c_iter::next +c_iter::valid = true +c_iter::current +object:1 +c_iter::next +c_iter::valid = true +c_iter::current +object:2 +c_iter::next +c_iter::valid = false +===foreach/rec=== +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +double:0:0 +c_iter::next +c_iter::valid = true +c_iter::current +double:0:1 +c_iter::next +c_iter::valid = true +c_iter::current +double:0:2 +c_iter::next +c_iter::valid = false +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +double:1:0 +c_iter::next +c_iter::valid = true +c_iter::current +double:1:1 +c_iter::next +c_iter::valid = true +c_iter::current +double:1:2 +c_iter::next +c_iter::valid = false +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +double:2:0 +c_iter::next +c_iter::valid = true +c_iter::current +double:2:1 +c_iter::next +c_iter::valid = true +c_iter::current +double:2:2 +c_iter::next +c_iter::valid = false +c_iter::next +c_iter::valid = false +===foreach/key=== +c::getIterator +c_iter::__construct +c_iter::valid = true +c_iter::current +c_iter::key +object:1st=>0 +c_iter::next +c_iter::valid = true +c_iter::current +c_iter::key +object:2nd=>1 +c_iter::next +c_iter::valid = true +c_iter::current +c_iter::key +object:3rd=>2 +c_iter::next +c_iter::valid = false +Done diff --git a/tests/classes/iterators_002.phpt b/tests/classes/iterators_002.phpt new file mode 100644 index 0000000..4a58be0 --- /dev/null +++ b/tests/classes/iterators_002.phpt @@ -0,0 +1,113 @@ +--TEST-- +ZE2 iterators and break +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class c_iter implements Iterator { + + private $obj; + private $num = 0; + + function __construct($obj) { + echo __METHOD__ . "\n"; + $this->obj = $obj; + } + function rewind() { + echo __METHOD__ . "\n"; + $this->num = 0; + } + function valid() { + $more = $this->num < $this->obj->max; + echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n"; + return $more; + } + function current() { + echo __METHOD__ . "\n"; + return $this->num; + } + function next() { + echo __METHOD__ . "\n"; + $this->num++; + } + function key() { + echo __METHOD__ . "\n"; + switch($this->num) { + case 0: return "1st"; + case 1: return "2nd"; + case 2: return "3rd"; + default: return "???"; + } + } + function __destruct() { + echo __METHOD__ . "\n"; + } +} + +class c implements IteratorAggregate { + + public $max = 3; + + function getIterator() { + echo __METHOD__ . "\n"; + return new c_iter($this); + } + function __destruct() { + echo __METHOD__ . "\n"; + } +} + +$t = new c(); + +foreach($t as $k => $v) { + foreach($t as $w) { + echo "double:$v:$w\n"; + break; + } +} + +unset($t); + +print "Done\n"; +?> +--EXPECT-- +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +c_iter::key +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:0:0 +c_iter::__destruct +c_iter::next +c_iter::valid = true +c_iter::current +c_iter::key +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:1:0 +c_iter::__destruct +c_iter::next +c_iter::valid = true +c_iter::current +c_iter::key +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:2:0 +c_iter::__destruct +c_iter::next +c_iter::valid = false +c_iter::__destruct +c::__destruct +Done diff --git a/tests/classes/iterators_003.phpt b/tests/classes/iterators_003.phpt new file mode 100644 index 0000000..42695db --- /dev/null +++ b/tests/classes/iterators_003.phpt @@ -0,0 +1,115 @@ +--TEST-- +ZE2 iterators and break +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class c_iter implements Iterator { + + private $obj; + private $num = 0; + + function __construct($obj) { + echo __METHOD__ . "\n"; + $this->obj = $obj; + } + function rewind() { + echo __METHOD__ . "\n"; + } + function valid() { + $more = $this->num < $this->obj->max; + echo __METHOD__ . ' = ' .($more ? 'true' : 'false') . "\n"; + return $more; + } + function current() { + echo __METHOD__ . "\n"; + return $this->num; + } + function next() { + echo __METHOD__ . "\n"; + $this->num++; + } + function key() { + return $this->num; + } +} + +class c implements IteratorAggregate { + + public $max = 4; + + function getIterator() { + echo __METHOD__ . "\n"; + return new c_iter($this); + } +} + +$t = new c(); + +foreach($t as $v) { + if ($v == 0) { + echo "continue outer\n"; + continue; + } + foreach($t as $w) { + if ($w == 1) { + echo "continue inner\n"; + continue; + } + if ($w == 2) { + echo "break inner\n"; + break; + } + echo "double:$v:$w\n"; + } + if ($v == 2) { + echo "break outer\n"; + break; + } +} + +print "Done\n"; +?> +--EXPECT-- +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +continue outer +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:1:0 +c_iter::next +c_iter::valid = true +c_iter::current +continue inner +c_iter::next +c_iter::valid = true +c_iter::current +break inner +c_iter::next +c_iter::valid = true +c_iter::current +c::getIterator +c_iter::__construct +c_iter::rewind +c_iter::valid = true +c_iter::current +double:2:0 +c_iter::next +c_iter::valid = true +c_iter::current +continue inner +c_iter::next +c_iter::valid = true +c_iter::current +break inner +break outer +Done diff --git a/tests/classes/iterators_004.phpt b/tests/classes/iterators_004.phpt new file mode 100644 index 0000000..3fe0527 --- /dev/null +++ b/tests/classes/iterators_004.phpt @@ -0,0 +1,61 @@ +--TEST-- +ZE2 iterators must be implemented +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +echo "1st try\n"; + +class c1 {} + +$obj = new c1(); + +foreach($obj as $w) { + echo "object:$w\n"; +} + +echo "2nd try\n"; + +class c2 { + + public $max = 3; + public $num = 0; + + function current() { + echo __METHOD__ . "\n"; + return $this->num; + } + function next() { + echo __METHOD__ . "\n"; + $this->num++; + } + function valid() { + echo __METHOD__ . "\n"; + return $this->num < $this->max; + } + function key() { + echo __METHOD__ . "\n"; + switch($this->num) { + case 0: return "1st"; + case 1: return "2nd"; + case 2: return "3rd"; + default: return "???"; + } + } +} + +$obj = new c2(); + +foreach($obj as $v => $w) { + echo "object:$v=>$w\n"; +} + +print "Done\n"; +?> +--EXPECTF-- +1st try +2nd try +object:max=>3 +object:num=>0 +Done diff --git a/tests/classes/iterators_005.phpt b/tests/classes/iterators_005.phpt new file mode 100644 index 0000000..005deb9 --- /dev/null +++ b/tests/classes/iterators_005.phpt @@ -0,0 +1,19 @@ +--TEST-- +ZE2 iterators cannot implement Traversable alone +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class test implements Traversable { +} + +$obj = new test; + +foreach($obj as $v); + +print "Done\n"; +/* the error doesn't show the filename but 'Unknown' */ +?> +--EXPECTF-- +Fatal error: Class test must implement interface Traversable as part of either Iterator or IteratorAggregate in %s on line %d diff --git a/tests/classes/iterators_006.phpt b/tests/classes/iterators_006.phpt new file mode 100644 index 0000000..47fa690 --- /dev/null +++ b/tests/classes/iterators_006.phpt @@ -0,0 +1,87 @@ +--TEST-- +ZE2 iterators and array wrapping +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 is needed'); ?> +--FILE-- +<?php + +class ai implements Iterator { + + private $array; + + function __construct() { + $this->array = array('foo', 'bar', 'baz'); + } + + function rewind() { + reset($this->array); + $this->next(); + } + + function valid() { + return $this->key !== NULL; + } + + function key() { + return $this->key; + } + + function current() { + return $this->current; + } + + function next() { + list($this->key, $this->current) = each($this->array); +// list($key, $current) = each($this->array); +// $this->key = $key; +// $this->current = $current; + } +} + +class a implements IteratorAggregate { + + public function getIterator() { + return new ai(); + } +} + +$array = new a(); + +foreach ($array as $property => $value) { + print "$property: $value\n"; +} + +#$array = $array->getIterator(); +#$array->rewind(); +#$array->valid(); +#var_dump($array->key()); +#var_dump($array->current()); +echo "===2nd===\n"; + +$array = new ai(); + +foreach ($array as $property => $value) { + print "$property: $value\n"; +} + +echo "===3rd===\n"; + +foreach ($array as $property => $value) { + print "$property: $value\n"; +} + +?> +===DONE=== +--EXPECT-- +0: foo +1: bar +2: baz +===2nd=== +0: foo +1: bar +2: baz +===3rd=== +0: foo +1: bar +2: baz +===DONE===
\ No newline at end of file diff --git a/tests/classes/iterators_007.phpt b/tests/classes/iterators_007.phpt new file mode 100644 index 0000000..f2638b3 --- /dev/null +++ b/tests/classes/iterators_007.phpt @@ -0,0 +1,43 @@ +--TEST-- +ZE2 iterators and exceptions +--FILE-- +<?php +class Test implements Iterator +{ + public $arr = array(1, 2, 3); + public $x = 0; + + public function rewind() { if ($this->x == 0) throw new Exception(__METHOD__); reset($this->arr); } + public function current() { if ($this->x == 1) throw new Exception(__METHOD__); return current($this->arr); } + public function key() { if ($this->x == 2) throw new Exception(__METHOD__); return key($this->arr); } + public function next() { if ($this->x == 3) throw new Exception(__METHOD__); next($this->arr); } + public function valid() { if ($this->x == 4) throw new Exception(__METHOD__); return (key($this->arr) !== NULL); } +} + +$t = new Test(); + +while($t->x < 5) +{ + try + { + foreach($t as $k => $v) + { + echo "Current\n"; + } + } + catch(Exception $e) + { + echo "Caught in " . $e->getMessage() . "()\n"; + } + $t->x++; +} +?> +===DONE=== +--EXPECT-- +Caught in Test::rewind() +Caught in Test::current() +Caught in Test::key() +Current +Caught in Test::next() +Caught in Test::valid() +===DONE=== diff --git a/tests/classes/iterators_008.phpt b/tests/classes/iterators_008.phpt new file mode 100644 index 0000000..22e6dc8 --- /dev/null +++ b/tests/classes/iterators_008.phpt @@ -0,0 +1,45 @@ +--TEST-- +Ensure plain userspace superclass does not override special iterator behaviour on child class. +--FILE-- +<?php +Class C {} + +class D extends C implements Iterator { + + private $counter = 2; + + public function valid() { + echo __METHOD__ . "($this->counter)\n"; + return $this->counter; + } + + public function next() { + $this->counter--; + echo __METHOD__ . "($this->counter)\n"; + } + + public function rewind() { + echo __METHOD__ . "($this->counter)\n"; + } + + public function current() { + echo __METHOD__ . "($this->counter)\n"; + } + + public function key() { + echo __METHOD__ . "($this->counter)\n"; + } + +} + +foreach (new D as $x) {} +?> +--EXPECTF-- +D::rewind(2) +D::valid(2) +D::current(2) +D::next(1) +D::valid(1) +D::current(1) +D::next(0) +D::valid(0)
\ No newline at end of file diff --git a/tests/classes/method_call_variation_001.phpt b/tests/classes/method_call_variation_001.phpt new file mode 100644 index 0000000..dd43cfd --- /dev/null +++ b/tests/classes/method_call_variation_001.phpt @@ -0,0 +1,37 @@ +--TEST-- +In $a->$b[Y](), $b[Y] represents a method name on $a. But in $a->X[Y](), $a->X[Y] represents a global function name. +--FILE-- +<?php + class C + { + function foo($a, $b) + { + echo "Called C::foo($a, $b)\n"; + } + } + + $c = new C; + + $functions[0] = 'foo'; + $functions[1][2][3][4] = 'foo'; + + $c->$functions[0](1, 2); + $c->$functions[1][2][3][4](3, 4); + + + function foo($a, $b) + { + echo "Called global foo($a, $b)\n"; + } + + $c->functions[0] = 'foo'; + $c->functions[1][2][3][4] = 'foo'; + + $c->functions[0](5, 6); + $c->functions[1][2][3][4](7, 8); +?> +--EXPECTF-- +Called C::foo(1, 2) +Called C::foo(3, 4) +Called global foo(5, 6) +Called global foo(7, 8) diff --git a/tests/classes/method_override_optional_arg_001.phpt b/tests/classes/method_override_optional_arg_001.phpt new file mode 100644 index 0000000..333c29d --- /dev/null +++ b/tests/classes/method_override_optional_arg_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +Method override allows optional default argument +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class A { + function foo($arg1 = 1) { + } +} + +class B extends A { + function foo($arg1 = 2, $arg2 = 3) { + var_dump($arg1); + var_dump($arg2); + } +} + +class C extends A { + function foo() { + } +} + +$b = new B(); + +$b->foo(1); + +?> +--EXPECTF-- +Strict Standards: Declaration of C::foo() should be compatible with A::foo($arg1 = 1) in %s on line %d +int(1) +int(3) diff --git a/tests/classes/method_override_optional_arg_002.phpt b/tests/classes/method_override_optional_arg_002.phpt new file mode 100644 index 0000000..669a8ca --- /dev/null +++ b/tests/classes/method_override_optional_arg_002.phpt @@ -0,0 +1,22 @@ +--TEST-- +Omitting optional arg in method inherited from abstract class +--FILE-- +<?php + +abstract class A { + function foo($arg = 1) {} +} + +class B extends A { + function foo() { + echo "foo\n"; + } +} + +$b = new B(); +$b->foo(); + +?> +--EXPECTF-- +Strict Standards: Declaration of B::foo() should be compatible with A::foo($arg = 1) in %s on line %d +foo diff --git a/tests/classes/new_001.phpt b/tests/classes/new_001.phpt new file mode 100644 index 0000000..ee7d352 --- /dev/null +++ b/tests/classes/new_001.phpt @@ -0,0 +1,48 @@ +--TEST-- +Confirm difference between assigning new directly and by reference. +--INI-- +error_reporting=E_ALL | E_DEPRECATED +--FILE-- +<?php + echo "Compile-time strict error message should precede this.\n"; + + class Inc + { + private static $counter = 0; + function __construct() + { + $this->id = ++Inc::$counter; + } + } + + $f = new Inc(); + $k =& $f; + echo "\$f initially points to the first object:\n"; + var_dump($f); + + echo "Assigning new object directly to \$k affects \$f:\n"; + $k = new Inc(); + var_dump($f); + + echo "Assigning new object by ref to \$k removes it from \$f's reference set, so \$f is unchanged:\n"; + $k =& new Inc(); + var_dump($f); +?> +--EXPECTF-- +Deprecated: Assigning the return value of new by reference is deprecated in %s on line 23 +Compile-time strict error message should precede this. +$f initially points to the first object: +object(Inc)#%d (1) { + ["id"]=> + int(1) +} +Assigning new object directly to $k affects $f: +object(Inc)#%d (1) { + ["id"]=> + int(2) +} +Assigning new object by ref to $k removes it from $f's reference set, so $f is unchanged: +object(Inc)#%d (1) { + ["id"]=> + int(2) +} diff --git a/tests/classes/object_reference_001.phpt b/tests/classes/object_reference_001.phpt new file mode 100644 index 0000000..74acb5d --- /dev/null +++ b/tests/classes/object_reference_001.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 object references +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Foo { + public $name; + + function Foo() { + $this->name = "I'm Foo!\n"; + } +} + +$foo = new Foo; +echo $foo->name; +$bar = $foo; +$bar->name = "I'm Bar!\n"; + +// In ZE1, we would expect "I'm Foo!" +echo $foo->name; + +?> +--EXPECT-- +I'm Foo! +I'm Bar! diff --git a/tests/classes/private_001.phpt b/tests/classes/private_001.phpt new file mode 100644 index 0000000..310b9c6 --- /dev/null +++ b/tests/classes/private_001.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 A private method can only be called inside the class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private static function show() { + echo "Call show()\n"; + } + + public static function do_show() { + pass::show(); + } +} + +pass::do_show(); +pass::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context '' in %s on line %d diff --git a/tests/classes/private_002.phpt b/tests/classes/private_002.phpt new file mode 100644 index 0000000..258fd3a --- /dev/null +++ b/tests/classes/private_002.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 A private method cannot be called in another class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private static function show() { + echo "Call pass::show()\n"; + } + + public static function do_show() { + pass::show(); + } +} + +pass::do_show(); + +class fail { + public static function show() { + echo "Call fail::show()\n"; + pass::show(); + } +} + +fail::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call pass::show() +Call fail::show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/private_003.phpt b/tests/classes/private_003.phpt new file mode 100644 index 0000000..716efbc --- /dev/null +++ b/tests/classes/private_003.phpt @@ -0,0 +1,36 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +ini_set("error_reporting",2039); +class pass { + private static function show() { + echo "Call show()\n"; + } + + protected static function good() { + pass::show(); + } +} + +class fail extends pass { + static function ok() { + pass::good(); + } + + static function not_ok() { + pass::show(); + } +} + +fail::ok(); +fail::not_ok(); // calling a private function + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/private_003b.phpt b/tests/classes/private_003b.phpt new file mode 100644 index 0000000..780b2e6 --- /dev/null +++ b/tests/classes/private_003b.phpt @@ -0,0 +1,37 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private function show() { + echo "Call show()\n"; + } + + protected function good() { + $this->show(); + } +} + +class fail extends pass { + public function ok() { + $this->good(); + } + + public function not_ok() { + $this->show(); + } +} + +$t = new fail(); +$t->ok(); +$t->not_ok(); // calling a private function + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/private_004.phpt b/tests/classes/private_004.phpt new file mode 100644 index 0000000..027434a --- /dev/null +++ b/tests/classes/private_004.phpt @@ -0,0 +1,32 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private static function show() { + echo "Call show()\n"; + } + + public static function do_show() { + pass::show(); + } +} + +class fail extends pass { + static function do_show() { + fail::show(); + } +} + +pass::do_show(); +fail::do_show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/private_004b.phpt b/tests/classes/private_004b.phpt new file mode 100644 index 0000000..ea3fe61 --- /dev/null +++ b/tests/classes/private_004b.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private function show() { + echo "Call show()\n"; + } + + public function do_show() { + $this->show(); + } +} + +class fail extends pass { + function do_show() { + $this->show(); + } +} + +$t = new pass(); +$t->do_show(); + +$t2 = new fail(); +$t2->do_show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d
\ No newline at end of file diff --git a/tests/classes/private_005.phpt b/tests/classes/private_005.phpt new file mode 100644 index 0000000..49b2bee --- /dev/null +++ b/tests/classes/private_005.phpt @@ -0,0 +1,32 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private static function show() { + echo "Call show()\n"; + } + + public static function do_show() { + pass::show(); + } +} + +class fail extends pass { + static function do_show() { + pass::show(); + } +} + +pass::do_show(); +fail::do_show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/private_005b.phpt b/tests/classes/private_005b.phpt new file mode 100644 index 0000000..ea3fe61 --- /dev/null +++ b/tests/classes/private_005b.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 A private method cannot be called in a derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + private function show() { + echo "Call show()\n"; + } + + public function do_show() { + $this->show(); + } +} + +class fail extends pass { + function do_show() { + $this->show(); + } +} + +$t = new pass(); +$t->do_show(); + +$t2 = new fail(); +$t2->do_show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call show() + +Fatal error: Call to private method pass::show() from context 'fail' in %s on line %d
\ No newline at end of file diff --git a/tests/classes/private_006.phpt b/tests/classes/private_006.phpt new file mode 100644 index 0000000..0bb2b3f --- /dev/null +++ b/tests/classes/private_006.phpt @@ -0,0 +1,41 @@ +--TEST-- +ZE2 A private method can be overwritten in a second derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php +class first { + private static function show() { + echo "Call show()\n"; + } + + public static function do_show() { + first::show(); + } +} + +first::do_show(); + +class second extends first { +} + +second::do_show(); + +class third extends second { +} + +third::do_show(); + +class fail extends third { + static function show() { // cannot be redeclared + echo "Call show()\n"; + } +} + +echo "Done\n"; +?> +--EXPECTF-- +Call show() +Call show() +Call show() +Done diff --git a/tests/classes/private_006b.phpt b/tests/classes/private_006b.phpt new file mode 100644 index 0000000..950f16a --- /dev/null +++ b/tests/classes/private_006b.phpt @@ -0,0 +1,41 @@ +--TEST-- +ZE2 A private method can be overwritten in a second derived class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class first { + private function show() { + echo "Call show()\n"; + } + + public function do_show() { + $this->show(); + } +} + +$t1 = new first(); +$t1->do_show(); + +class second extends first { +} + +//$t2 = new second(); +//$t2->do_show(); + +class third extends second { + private function show() { + echo "Call show()\n"; + } +} + +$t3 = new third(); +$t3->do_show(); + +echo "Done\n"; +?> +--EXPECTF-- +Call show() +Call show() +Done
\ No newline at end of file diff --git a/tests/classes/private_007.phpt b/tests/classes/private_007.phpt new file mode 100644 index 0000000..73a38c4 --- /dev/null +++ b/tests/classes/private_007.phpt @@ -0,0 +1,30 @@ +--TEST-- +ZE2 A derived class does not know about privates of ancestors +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Bar { + public static function pub() { + Bar::priv(); + } + private static function priv() { + echo "Bar::priv()\n"; + } +} +class Foo extends Bar { + public static function priv() { + echo "Foo::priv()\n"; + } +} + +Foo::pub(); +Foo::priv(); + +echo "Done\n"; +?> +--EXPECTF-- +Bar::priv() +Foo::priv() +Done diff --git a/tests/classes/private_007b.phpt b/tests/classes/private_007b.phpt new file mode 100644 index 0000000..02ddc25 --- /dev/null +++ b/tests/classes/private_007b.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 A derived class does not know about privates of ancestors +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Bar { + public function pub() { + $this->priv(); + } + private function priv() { + echo "Bar::priv()\n"; + } +} +class Foo extends Bar { + public function priv() { + echo "Foo::priv()\n"; + } +} + +$obj = new Foo(); +$obj->pub(); +$obj->priv(); + +echo "Done\n"; +?> +--EXPECTF-- +Bar::priv() +Foo::priv() +Done diff --git a/tests/classes/private_members.phpt b/tests/classes/private_members.phpt new file mode 100644 index 0000000..a8ef9ab --- /dev/null +++ b/tests/classes/private_members.phpt @@ -0,0 +1,103 @@ +--TEST-- +ZE2 A private member is +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class base +{ + private $member; + + function __construct() + { + echo __METHOD__ . "(begin)\n"; + $this->member = 'base::member'; + $this->test(); + echo __METHOD__ . "(end)\n"; + } + + function test() + { + echo __METHOD__ . "\n"; + print_r($this); + } +} + +class derived extends base +{ + public $member = 'derived::member (default)'; + + function __construct() + { + echo __METHOD__ . "(begin)\n"; + parent::__construct(); + parent::test(); + $this->test(); + $this->member = 'derived::member'; + echo __METHOD__ . "(end)\n"; + } + + function test() + { + parent::test(); + echo __METHOD__ . "\n"; + print_r($this); + } +} + +$t = new derived; +$t->test(); +unset($t); + +echo "Done\n"; + +?> +--EXPECTF-- +derived::__construct(begin) +base::__construct(begin) +base::test +derived Object +( + [member] => derived::member (default) + [member:base:private] => base::member +) +derived::test +derived Object +( + [member] => derived::member (default) + [member:base:private] => base::member +) +base::__construct(end) +base::test +derived Object +( + [member] => derived::member (default) + [member:base:private] => base::member +) +base::test +derived Object +( + [member] => derived::member (default) + [member:base:private] => base::member +) +derived::test +derived Object +( + [member] => derived::member (default) + [member:base:private] => base::member +) +derived::__construct(end) +base::test +derived Object +( + [member] => derived::member + [member:base:private] => base::member +) +derived::test +derived Object +( + [member] => derived::member + [member:base:private] => base::member +) +Done diff --git a/tests/classes/private_redeclare.phpt b/tests/classes/private_redeclare.phpt new file mode 100644 index 0000000..e3061f1 --- /dev/null +++ b/tests/classes/private_redeclare.phpt @@ -0,0 +1,38 @@ +--TEST-- +ZE2 A derived class does not know anything about inherited private methods +--FILE-- +<?php +class base { + private function show() { + echo "base\n"; + } + function test() { + $this->show(); + } +} + +$t = new base(); +$t->test(); + +class derived extends base { + function show() { + echo "derived\n"; + } + function test() { + echo "test\n"; + $this->show(); + parent::test(); + parent::show(); + } +} + +$t = new derived(); +$t->test(); +?> +--EXPECTF-- +base +test +derived +base + +Fatal error: Call to private method base::show() from context 'derived' in %s on line %d diff --git a/tests/classes/property_override_privateStatic_private.phpt b/tests/classes/property_override_privateStatic_private.phpt new file mode 100644 index 0000000..ddd2e5d --- /dev/null +++ b/tests/classes/property_override_privateStatic_private.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited private static property as private. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p diff --git a/tests/classes/property_override_privateStatic_privateStatic.phpt b/tests/classes/property_override_privateStatic_privateStatic.phpt new file mode 100644 index 0000000..d7d645f --- /dev/null +++ b/tests/classes/property_override_privateStatic_privateStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited private static property as private static. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) diff --git a/tests/classes/property_override_privateStatic_protected.phpt b/tests/classes/property_override_privateStatic_protected.phpt new file mode 100644 index 0000000..d473216 --- /dev/null +++ b/tests/classes/property_override_privateStatic_protected.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited private static property as protected. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p diff --git a/tests/classes/property_override_privateStatic_protectedStatic.phpt b/tests/classes/property_override_privateStatic_protectedStatic.phpt new file mode 100644 index 0000000..169ff9a --- /dev/null +++ b/tests/classes/property_override_privateStatic_protectedStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited private static property as protected static. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) diff --git a/tests/classes/property_override_privateStatic_public.phpt b/tests/classes/property_override_privateStatic_public.phpt new file mode 100644 index 0000000..033eb75 --- /dev/null +++ b/tests/classes/property_override_privateStatic_public.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited private static property as public. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p diff --git a/tests/classes/property_override_privateStatic_publicStatic.phpt b/tests/classes/property_override_privateStatic_publicStatic.phpt new file mode 100644 index 0000000..5f2b6bf --- /dev/null +++ b/tests/classes/property_override_privateStatic_publicStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited private static property as public static. +--FILE-- +<?php + class A + { + private static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) diff --git a/tests/classes/property_override_private_private.phpt b/tests/classes/property_override_private_private.phpt new file mode 100644 index 0000000..2b263ee --- /dev/null +++ b/tests/classes/property_override_private_private.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as private. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +A::p +B::p diff --git a/tests/classes/property_override_private_privateStatic.phpt b/tests/classes/property_override_private_privateStatic.phpt new file mode 100644 index 0000000..606ed21 --- /dev/null +++ b/tests/classes/property_override_private_privateStatic.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as private static. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- +A::p +A::p +B::p (static) diff --git a/tests/classes/property_override_private_protected.phpt b/tests/classes/property_override_private_protected.phpt new file mode 100644 index 0000000..b84ed67 --- /dev/null +++ b/tests/classes/property_override_private_protected.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as protected. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +A::p +B::p diff --git a/tests/classes/property_override_private_protectedStatic.phpt b/tests/classes/property_override_private_protectedStatic.phpt new file mode 100644 index 0000000..1bb303d --- /dev/null +++ b/tests/classes/property_override_private_protectedStatic.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as protected static. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- +A::p +A::p +B::p (static) diff --git a/tests/classes/property_override_private_public.phpt b/tests/classes/property_override_private_public.phpt new file mode 100644 index 0000000..badbe91 --- /dev/null +++ b/tests/classes/property_override_private_public.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as public. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +A::p +B::p diff --git a/tests/classes/property_override_private_publicStatic.phpt b/tests/classes/property_override_private_publicStatic.phpt new file mode 100644 index 0000000..9fc58ec --- /dev/null +++ b/tests/classes/property_override_private_publicStatic.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited private property as public static. +--FILE-- +<?php + class A + { + private $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- +A::p +A::p +B::p (static) diff --git a/tests/classes/property_override_protectedStatic_private.phpt b/tests/classes/property_override_protectedStatic_private.phpt new file mode 100644 index 0000000..18e9c78 --- /dev/null +++ b/tests/classes/property_override_protectedStatic_private.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected static property as private. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_protectedStatic_privateStatic.phpt b/tests/classes/property_override_protectedStatic_privateStatic.phpt new file mode 100644 index 0000000..6886210 --- /dev/null +++ b/tests/classes/property_override_protectedStatic_privateStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited protected static property as private static. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be protected (as in class A) or weaker in %s on line 18 + diff --git a/tests/classes/property_override_protectedStatic_protected.phpt b/tests/classes/property_override_protectedStatic_protected.phpt new file mode 100644 index 0000000..0e5fdd3 --- /dev/null +++ b/tests/classes/property_override_protectedStatic_protected.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected static property as protected. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_protectedStatic_protectedStatic.phpt b/tests/classes/property_override_protectedStatic_protectedStatic.phpt new file mode 100644 index 0000000..16f1100 --- /dev/null +++ b/tests/classes/property_override_protectedStatic_protectedStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited protected static property as protected static. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) diff --git a/tests/classes/property_override_protectedStatic_public.phpt b/tests/classes/property_override_protectedStatic_public.phpt new file mode 100644 index 0000000..6303325 --- /dev/null +++ b/tests/classes/property_override_protectedStatic_public.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected static property as public. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_protectedStatic_publicStatic.phpt b/tests/classes/property_override_protectedStatic_publicStatic.phpt new file mode 100644 index 0000000..e437c5f --- /dev/null +++ b/tests/classes/property_override_protectedStatic_publicStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected static property as public static. +--FILE-- +<?php + class A + { + protected static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) + diff --git a/tests/classes/property_override_protected_private.phpt b/tests/classes/property_override_protected_private.phpt new file mode 100644 index 0000000..22cceda --- /dev/null +++ b/tests/classes/property_override_protected_private.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected property as private (duplicates Zend/tests/errmsg_023.phpt). +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be protected (as in class A) or weaker in %s on line 18 diff --git a/tests/classes/property_override_protected_privateStatic.phpt b/tests/classes/property_override_protected_privateStatic.phpt new file mode 100644 index 0000000..fb7102c --- /dev/null +++ b/tests/classes/property_override_protected_privateStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected property as private static. +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_override_protected_protected.phpt b/tests/classes/property_override_protected_protected.phpt new file mode 100644 index 0000000..c4b0d43 --- /dev/null +++ b/tests/classes/property_override_protected_protected.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited protected property as protected. +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +B::p +B::p diff --git a/tests/classes/property_override_protected_protectedStatic.phpt b/tests/classes/property_override_protected_protectedStatic.phpt new file mode 100644 index 0000000..1ce4130 --- /dev/null +++ b/tests/classes/property_override_protected_protectedStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected property as protected static. +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_override_protected_public.phpt b/tests/classes/property_override_protected_public.phpt new file mode 100644 index 0000000..4702f9a --- /dev/null +++ b/tests/classes/property_override_protected_public.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited protected property as public. +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +B::p +B::p diff --git a/tests/classes/property_override_protected_publicStatic.phpt b/tests/classes/property_override_protected_publicStatic.phpt new file mode 100644 index 0000000..8efdf5f --- /dev/null +++ b/tests/classes/property_override_protected_publicStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited protected property as public static. +--FILE-- +<?php + class A + { + protected $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_override_publicStatic_private.phpt b/tests/classes/property_override_publicStatic_private.phpt new file mode 100644 index 0000000..7abe92c --- /dev/null +++ b/tests/classes/property_override_publicStatic_private.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public static property as private. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_publicStatic_privateStatic.phpt b/tests/classes/property_override_publicStatic_privateStatic.phpt new file mode 100644 index 0000000..d41db6d --- /dev/null +++ b/tests/classes/property_override_publicStatic_privateStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited public static property as private static. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18 + diff --git a/tests/classes/property_override_publicStatic_protected.phpt b/tests/classes/property_override_publicStatic_protected.phpt new file mode 100644 index 0000000..884159f --- /dev/null +++ b/tests/classes/property_override_publicStatic_protected.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public static property as protected. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_publicStatic_protectedStatic.phpt b/tests/classes/property_override_publicStatic_protectedStatic.phpt new file mode 100644 index 0000000..b022ef8 --- /dev/null +++ b/tests/classes/property_override_publicStatic_protectedStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited public static property as protected static. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18 + diff --git a/tests/classes/property_override_publicStatic_public.phpt b/tests/classes/property_override_publicStatic_public.phpt new file mode 100644 index 0000000..d099da0 --- /dev/null +++ b/tests/classes/property_override_publicStatic_public.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public static property as public. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + A::showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare static A::$p as non static B::$p in %s on line 18 + diff --git a/tests/classes/property_override_publicStatic_publicStatic.phpt b/tests/classes/property_override_publicStatic_publicStatic.phpt new file mode 100644 index 0000000..9a86867 --- /dev/null +++ b/tests/classes/property_override_publicStatic_publicStatic.phpt @@ -0,0 +1,32 @@ +--TEST-- +Redeclare inherited public static property as public static. +--FILE-- +<?php + class A + { + public static $p = "A::p (static)"; + static function showA() + { + echo self::$p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + A::showA(); + + B::showA(); + B::showB(); +?> +--EXPECTF-- +A::p (static) +A::p (static) +B::p (static) diff --git a/tests/classes/property_override_public_private.phpt b/tests/classes/property_override_public_private.phpt new file mode 100644 index 0000000..c0f37ad --- /dev/null +++ b/tests/classes/property_override_public_private.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited public property as private. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18 + diff --git a/tests/classes/property_override_public_privateStatic.phpt b/tests/classes/property_override_public_privateStatic.phpt new file mode 100644 index 0000000..36223fd --- /dev/null +++ b/tests/classes/property_override_public_privateStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public property as private static. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + private static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_override_public_protected.phpt b/tests/classes/property_override_public_protected.phpt new file mode 100644 index 0000000..68fdf82 --- /dev/null +++ b/tests/classes/property_override_public_protected.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited public property as protected. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- + +Fatal error: Access level to B::$p must be public (as in class A) in %s on line 18 + diff --git a/tests/classes/property_override_public_protectedStatic.phpt b/tests/classes/property_override_public_protectedStatic.phpt new file mode 100644 index 0000000..77e7ebf --- /dev/null +++ b/tests/classes/property_override_public_protectedStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public property as protected static. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + protected static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_override_public_public.phpt b/tests/classes/property_override_public_public.phpt new file mode 100644 index 0000000..893fe5d --- /dev/null +++ b/tests/classes/property_override_public_public.phpt @@ -0,0 +1,34 @@ +--TEST-- +Redeclare inherited public property as public. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public $p = "B::p"; + function showB() + { + echo $this->p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + $b->showB(); +?> +--EXPECTF-- +A::p +B::p +B::p diff --git a/tests/classes/property_override_public_publicStatic.phpt b/tests/classes/property_override_public_publicStatic.phpt new file mode 100644 index 0000000..725e947 --- /dev/null +++ b/tests/classes/property_override_public_publicStatic.phpt @@ -0,0 +1,33 @@ +--TEST-- +Redeclare inherited public property as public static. +--FILE-- +<?php + class A + { + public $p = "A::p"; + function showA() + { + echo $this->p . "\n"; + } + } + + class B extends A + { + public static $p = "B::p (static)"; + static function showB() + { + echo self::$p . "\n"; + } + } + + + $a = new A; + $a->showA(); + + $b = new B; + $b->showA(); + B::showB(); +?> +--EXPECTF-- + +Fatal error: Cannot redeclare non static A::$p as static B::$p in %s on line 18 diff --git a/tests/classes/property_recreate_private.phpt b/tests/classes/property_recreate_private.phpt new file mode 100644 index 0000000..8bcf485 --- /dev/null +++ b/tests/classes/property_recreate_private.phpt @@ -0,0 +1,81 @@ +--TEST-- +Unsetting and recreating private properties. +--FILE-- +<?php +class C { + private $p = 'test'; + function unsetPrivate() { + unset($this->p); + } + function setPrivate() { + $this->p = 'changed'; + } +} + +class D extends C { + function setP() { + $this->p = 'changed in D'; + } +} + +echo "Unset and recreate a superclass's private property:\n"; +$d = new D; +$d->unsetPrivate(); +$d->setPrivate(); +var_dump($d); + +echo "\nUnset superclass's private property, and recreate it as public in subclass:\n"; +$d = new D; +$d->unsetPrivate(); +$d->setP(); +var_dump($d); + +echo "\nUnset superclass's private property, and recreate it as public at global scope:\n"; +$d = new D; +$d->unsetPrivate(); +$d->p = 'this will create a public property'; +var_dump($d); + + +echo "\n\nUnset and recreate a private property:\n"; +$c = new C; +$c->unsetPrivate(); +$c->setPrivate(); +var_dump($c); + +echo "\nUnset a private property, and attempt to recreate at global scope (expecting failure):\n"; +$c = new C; +$c->unsetPrivate(); +$c->p = 'this will fail'; +var_dump($c); +?> +==Done== +--EXPECTF-- +Unset and recreate a superclass's private property: +object(D)#%d (1) { + [%u|b%"p":%u|b%"C":private]=> + %unicode|string%(7) "changed" +} + +Unset superclass's private property, and recreate it as public in subclass: +object(D)#%d (1) { + [%u|b%"p"]=> + %unicode|string%(12) "changed in D" +} + +Unset superclass's private property, and recreate it as public at global scope: +object(D)#%d (1) { + [%u|b%"p"]=> + %unicode|string%(34) "this will create a public property" +} + + +Unset and recreate a private property: +object(C)#%d (1) { + [%u|b%"p":%u|b%"C":private]=> + %unicode|string%(7) "changed" +} + +Unset a private property, and attempt to recreate at global scope (expecting failure): + +Fatal error: Cannot access private property C::$p in %s on line 46
\ No newline at end of file diff --git a/tests/classes/property_recreate_protected.phpt b/tests/classes/property_recreate_protected.phpt new file mode 100644 index 0000000..4da4de8 --- /dev/null +++ b/tests/classes/property_recreate_protected.phpt @@ -0,0 +1,53 @@ +--TEST-- +Unsetting and recreating protected properties. +--FILE-- +<?php +class C { + protected $p = 'test'; + function unsetProtected() { + unset($this->p); + } + function setProtected() { + $this->p = 'changed'; + } +} + +class D extends C { + function setP() { + $this->p = 'changed in D'; + } +} + +$d = new D; +echo "Unset and recreate a protected property from property's declaring class scope:\n"; +$d->unsetProtected(); +$d->setProtected(); +var_dump($d); + +echo "\nUnset and recreate a protected property from subclass:\n"; +$d = new D; +$d->unsetProtected(); +$d->setP(); +var_dump($d); + +echo "\nUnset a protected property, and attempt to recreate it outside of scope (expected failure):\n"; +$d->unsetProtected(); +$d->p = 'this will fail'; +var_dump($d); +?> +--EXPECTF-- +Unset and recreate a protected property from property's declaring class scope: +object(D)#%d (1) { + [%u|b%"p":protected]=> + %unicode|string%(7) "changed" +} + +Unset and recreate a protected property from subclass: +object(D)#%d (1) { + [%u|b%"p":protected]=> + %unicode|string%(12) "changed in D" +} + +Unset a protected property, and attempt to recreate it outside of scope (expected failure): + +Fatal error: Cannot access protected property %s::$p in %s on line 32
\ No newline at end of file diff --git a/tests/classes/protected_001.phpt b/tests/classes/protected_001.phpt new file mode 100644 index 0000000..19872c6 --- /dev/null +++ b/tests/classes/protected_001.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 A protected method can only be called inside the class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + protected static function fail() { + echo "Call fail()\n"; + } + + public static function good() { + pass::fail(); + } +} + +pass::good(); +pass::fail();// must fail because we are calling from outside of class pass + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call fail() + +Fatal error: Call to protected method pass::fail() from context '' in %s on line %d diff --git a/tests/classes/protected_001b.phpt b/tests/classes/protected_001b.phpt new file mode 100644 index 0000000..4d24a92 --- /dev/null +++ b/tests/classes/protected_001b.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 A protected method can only be called inside the class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + protected function fail() { + echo "Call fail()\n"; + } + + public function good() { + $this->fail(); + } +} + +$t = new pass(); +$t->good(); +$t->fail();// must fail because we are calling from outside of class pass + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call fail() + +Fatal error: Call to protected method pass::fail() from context '' in %s on line %d diff --git a/tests/classes/protected_002.phpt b/tests/classes/protected_002.phpt new file mode 100644 index 0000000..f26ef9c --- /dev/null +++ b/tests/classes/protected_002.phpt @@ -0,0 +1,35 @@ +--TEST-- +ZE2 A protected method cannot be called in another class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + protected static function show() { + echo "Call pass::show()\n"; + } + + public static function do_show() { + pass::show(); + } +} + +pass::do_show(); + +class fail { + public static function show() { + echo "Call fail::show()\n"; + pass::show(); + } +} + +fail::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Call pass::show() +Call fail::show() + +Fatal error: Call to protected method pass::show() from context 'fail' in %s on line %d diff --git a/tests/classes/serialize_001.phpt b/tests/classes/serialize_001.phpt new file mode 100644 index 0000000..142fc50 --- /dev/null +++ b/tests/classes/serialize_001.phpt @@ -0,0 +1,79 @@ +--TEST-- +ZE2 Serializable +--FILE-- +<?php + +class Test implements Serializable +{ + public $data; + + function __construct($data) + { + echo __METHOD__ . "($data)\n"; + $this->data = $data; + } + + function serialize() + { + echo __METHOD__ . "({$this->data})\n"; + return $this->data; + } + + function unserialize($serialized) + { + echo __METHOD__ . "($serialized)\n"; + $this->data = $serialized; + var_dump($this); + } +} + +$tests = array('String', NULL, 42, false); + +foreach($tests as $data) +{ + try + { + echo "==========\n"; + var_dump($data); + $ser = serialize(new Test($data)); + var_dump(unserialize($ser)); + } + catch(Exception $e) + { + echo 'Exception: ' . $e->getMessage() . "\n"; + } +} + +?> +===DONE=== +<?php exit(0); ?> +--EXPECTF-- +========== +%unicode|string%(6) "String" +Test::__construct(String) +Test::serialize(String) +Test::unserialize(String) +object(Test)#%d (1) { + [%u|b%"data"]=> + %unicode|string%(6) "String" +} +object(Test)#%d (1) { + [%u|b%"data"]=> + %unicode|string%(6) "String" +} +========== +NULL +Test::__construct() +Test::serialize() +NULL +========== +int(42) +Test::__construct(42) +Test::serialize(42) +Exception: Test::serialize() must return a string or NULL +========== +bool(false) +Test::__construct() +Test::serialize() +Exception: Test::serialize() must return a string or NULL +===DONE=== diff --git a/tests/classes/singleton_001.phpt b/tests/classes/singleton_001.phpt new file mode 100644 index 0000000..ee729b9 --- /dev/null +++ b/tests/classes/singleton_001.phpt @@ -0,0 +1,37 @@ +--TEST-- +ZE2 singleton +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Counter { + private $counter = 0; + + function increment_and_print() { + echo ++$this->counter; + echo "\n"; + } +} + + +class SingletonCounter { + private static $m_instance = NULL; + + static function Instance() { + if (self::$m_instance == NULL) { + self::$m_instance = new Counter(); + } + return self::$m_instance; + } +} + +SingletonCounter::Instance()->increment_and_print(); +SingletonCounter::Instance()->increment_and_print(); +SingletonCounter::Instance()->increment_and_print(); + +?> +--EXPECT-- +1 +2 +3 diff --git a/tests/classes/static_mix_1.phpt b/tests/classes/static_mix_1.phpt new file mode 100644 index 0000000..ecc9c01 --- /dev/null +++ b/tests/classes/static_mix_1.phpt @@ -0,0 +1,26 @@ +--TEST-- +ZE2 You cannot overload a static method with a non static method +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + static function show() { + echo "Call to function pass::show()\n"; + } +} + +class fail extends pass { + function show() { + echo "Call to function fail::show()\n"; + } +} + +pass::show(); +fail::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Cannot make static method pass::show() non static in class fail in %s on line %d
\ No newline at end of file diff --git a/tests/classes/static_mix_2.phpt b/tests/classes/static_mix_2.phpt new file mode 100644 index 0000000..bbdaedf --- /dev/null +++ b/tests/classes/static_mix_2.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 You cannot overload a non static method with a static method +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class pass { + function show() { + echo "Call to function pass::show()\n"; + } +} + +class fail extends pass { + static function show() { + echo "Call to function fail::show()\n"; + } +} + +$t = new pass(); +$t->show(); +fail::show(); + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Cannot make non static method pass::show() static in class fail in %s on line %d
\ No newline at end of file diff --git a/tests/classes/static_properties_001.phpt b/tests/classes/static_properties_001.phpt new file mode 100644 index 0000000..1c34f68 --- /dev/null +++ b/tests/classes/static_properties_001.phpt @@ -0,0 +1,27 @@ +--TEST-- +ZE2 Initializing static properties to arrays +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class test { + static public $ar = array(); +} + +var_dump(test::$ar); + +test::$ar[] = 1; + +var_dump(test::$ar); + +echo "Done\n"; +?> +--EXPECTF-- +array(0) { +} +array(1) { + [0]=> + int(1) +} +Done diff --git a/tests/classes/static_properties_003.phpt b/tests/classes/static_properties_003.phpt new file mode 100644 index 0000000..2441e41 --- /dev/null +++ b/tests/classes/static_properties_003.phpt @@ -0,0 +1,49 @@ +--TEST-- +Attempting to access static properties using instance property syntax +--FILE-- +<?php +class C { + public static $x = 'C::$x'; + protected static $y = 'C::$y'; +} + +$c = new C; + +echo "\n--> Access visible static prop like instance prop:\n"; +var_dump(isset($c->x)); +unset($c->x); +echo $c->x; +$c->x = 1; +$ref = 'ref'; +$c->x =& $ref; +var_dump($c->x, C::$x); + +echo "\n--> Access non-visible static prop like instance prop:\n"; +var_dump(isset($c->y)); +//unset($c->y); // Fatal error, tested in static_properties_003_error1.phpt +//echo $c->y; // Fatal error, tested in static_properties_003_error2.phpt +//$c->y = 1; // Fatal error, tested in static_properties_003_error3.phpt +//$c->y =& $ref; // Fatal error, tested in static_properties_003_error4.phpt +?> +==Done== +--EXPECTF-- +--> Access visible static prop like instance prop: +bool(false) + +Strict Standards: Accessing static property C::$x as non static in %s on line 11 + +Strict Standards: Accessing static property C::$x as non static in %s on line 12 + +Notice: Undefined property: C::$x in %s on line 12 + +Strict Standards: Accessing static property C::$x as non static in %s on line 13 + +Strict Standards: Accessing static property C::$x as non static in %s on line 15 + +Strict Standards: Accessing static property C::$x as non static in %s on line 16 +%unicode|string%(3) "ref" +%unicode|string%(5) "C::$x" + +--> Access non-visible static prop like instance prop: +bool(false) +==Done==
\ No newline at end of file diff --git a/tests/classes/static_properties_003_error1.phpt b/tests/classes/static_properties_003_error1.phpt new file mode 100644 index 0000000..7a5e3d9 --- /dev/null +++ b/tests/classes/static_properties_003_error1.phpt @@ -0,0 +1,18 @@ +--TEST-- +Attempting to access static properties using instance property syntax +--FILE-- +<?php +class C { + protected static $y = 'C::$y'; +} +$c = new C; + +echo "\n--> Access non-visible static prop like instance prop:\n"; +unset($c->y); +?> +==Done== +--EXPECTF-- + +--> Access non-visible static prop like instance prop: + +Fatal error: Cannot access protected property C::$y in %s on line 8 diff --git a/tests/classes/static_properties_003_error2.phpt b/tests/classes/static_properties_003_error2.phpt new file mode 100644 index 0000000..589cc69 --- /dev/null +++ b/tests/classes/static_properties_003_error2.phpt @@ -0,0 +1,18 @@ +--TEST-- +Attempting to access static properties using instance property syntax +--FILE-- +<?php +class C { + protected static $y = 'C::$y'; +} +$c = new C; + +echo "\n--> Access non-visible static prop like instance prop:\n"; +echo $c->y; +?> +==Done== +--EXPECTF-- + +--> Access non-visible static prop like instance prop: + +Fatal error: Cannot access protected property C::$y in %s on line 8 diff --git a/tests/classes/static_properties_003_error3.phpt b/tests/classes/static_properties_003_error3.phpt new file mode 100644 index 0000000..3e01e0e --- /dev/null +++ b/tests/classes/static_properties_003_error3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Attempting to access static properties using instance property syntax +--FILE-- +<?php +class C { + protected static $y = 'C::$y'; +} +$c = new C; + +echo "\n--> Access non-visible static prop like instance prop:\n"; +$c->y = 1; +?> +==Done== +--EXPECTF-- + +--> Access non-visible static prop like instance prop: + +Fatal error: Cannot access protected property C::$y in %s on line 8 diff --git a/tests/classes/static_properties_003_error4.phpt b/tests/classes/static_properties_003_error4.phpt new file mode 100644 index 0000000..fd69a9f --- /dev/null +++ b/tests/classes/static_properties_003_error4.phpt @@ -0,0 +1,18 @@ +--TEST-- +Attempting to access static properties using instance property syntax +--FILE-- +<?php +class C { + protected static $y = 'C::$y'; +} +$c = new C; + +echo "\n--> Access non-visible static prop like instance prop:\n"; +$c->y =& $ref; +?> +==Done== +--EXPECTF-- + +--> Access non-visible static prop like instance prop: + +Fatal error: Cannot access protected property C::$y in %s on line 8 diff --git a/tests/classes/static_properties_004.phpt b/tests/classes/static_properties_004.phpt new file mode 100644 index 0000000..ce1d19d --- /dev/null +++ b/tests/classes/static_properties_004.phpt @@ -0,0 +1,37 @@ +--TEST-- +Inherited static properties can be separated from their reference set. +--FILE-- +<?php +class C { public static $p = 'original'; } +class D extends C { } +class E extends D { } + +echo "\nInherited static properties refer to the same value accross classes:\n"; +var_dump(C::$p, D::$p, E::$p); + +echo "\nChanging one changes all the others:\n"; +D::$p = 'changed.all'; +var_dump(C::$p, D::$p, E::$p); + +echo "\nBut because this is implemented using PHP references, the reference set can easily be split:\n"; +$ref = 'changed.one'; +D::$p =& $ref; +var_dump(C::$p, D::$p, E::$p); +?> +==Done== +--EXPECTF-- +Inherited static properties refer to the same value accross classes: +%unicode|string%(8) "original" +%unicode|string%(8) "original" +%unicode|string%(8) "original" + +Changing one changes all the others: +%unicode|string%(11) "changed.all" +%unicode|string%(11) "changed.all" +%unicode|string%(11) "changed.all" + +But because this is implemented using PHP references, the reference set can easily be split: +%unicode|string%(11) "changed.all" +%unicode|string%(11) "changed.one" +%unicode|string%(11) "changed.all" +==Done==
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_assign.phpt b/tests/classes/static_properties_undeclared_assign.phpt new file mode 100644 index 0000000..99340e9 --- /dev/null +++ b/tests/classes/static_properties_undeclared_assign.phpt @@ -0,0 +1,9 @@ +--TEST-- +Assigning to a non-existent static property +--FILE-- +<?php +Class C {} +C::$p = 1; +?> +--EXPECTF-- +Fatal error: Access to undeclared static property: C::$p in %s on line 3
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_assignInc.phpt b/tests/classes/static_properties_undeclared_assignInc.phpt new file mode 100644 index 0000000..258f2f8 --- /dev/null +++ b/tests/classes/static_properties_undeclared_assignInc.phpt @@ -0,0 +1,9 @@ +--TEST-- +Assigning & incrementing a non-existent static property +--FILE-- +<?php +Class C {} +C::$p += 1; +?> +--EXPECTF-- +Fatal error: Access to undeclared static property: C::$p in %s on line 3
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_assignRef.phpt b/tests/classes/static_properties_undeclared_assignRef.phpt new file mode 100644 index 0000000..75cf270 --- /dev/null +++ b/tests/classes/static_properties_undeclared_assignRef.phpt @@ -0,0 +1,10 @@ +--TEST-- +Assigning a non-existent static property by reference +--FILE-- +<?php +Class C {} +$a = 'foo'; +C::$p =& $a; +?> +--EXPECTF-- +Fatal error: Access to undeclared static property: C::$p in %s on line 4
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_inc.phpt b/tests/classes/static_properties_undeclared_inc.phpt new file mode 100644 index 0000000..ff8b8c3 --- /dev/null +++ b/tests/classes/static_properties_undeclared_inc.phpt @@ -0,0 +1,9 @@ +--TEST-- +Incrementing a non-existent static property +--FILE-- +<?php +Class C {} +C::$p++; +?> +--EXPECTF-- +Fatal error: Access to undeclared static property: C::$p in %s on line 3
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_isset.phpt b/tests/classes/static_properties_undeclared_isset.phpt new file mode 100644 index 0000000..58aac40 --- /dev/null +++ b/tests/classes/static_properties_undeclared_isset.phpt @@ -0,0 +1,9 @@ +--TEST-- +Issetting a non-existent static property +--FILE-- +<?php +Class C {} +var_dump(isset(C::$p)); +?> +--EXPECTF-- +bool(false)
\ No newline at end of file diff --git a/tests/classes/static_properties_undeclared_read.phpt b/tests/classes/static_properties_undeclared_read.phpt new file mode 100644 index 0000000..715b41e --- /dev/null +++ b/tests/classes/static_properties_undeclared_read.phpt @@ -0,0 +1,9 @@ +--TEST-- +Reading a non-existent static property +--FILE-- +<?php +Class C {} +echo C::$p; +?> +--EXPECTF-- +Fatal error: Access to undeclared static property: C::$p in %s on line 3
\ No newline at end of file diff --git a/tests/classes/static_this.phpt b/tests/classes/static_this.phpt new file mode 100644 index 0000000..91b0287 --- /dev/null +++ b/tests/classes/static_this.phpt @@ -0,0 +1,39 @@ +--TEST-- +ZE2 $this can be an argument to a static function +--FILE-- +<?php + +class TestClass +{ + function __construct() + { + self::Test1(); + $this->Test1(); + } + + static function Test1() + { + var_dump($this); + } + + static function Test2($this) + { + var_dump($this); + } +} + +$obj = new TestClass; +TestClass::Test2(new stdClass); + +?> +===DONE=== +--EXPECTF-- + +Notice: Undefined variable: this in %sstatic_this.php on line %d +NULL + +Notice: Undefined variable: this in %sstatic_this.php on line %d +NULL +object(stdClass)#%d (0) { +} +===DONE=== diff --git a/tests/classes/this.phpt b/tests/classes/this.phpt new file mode 100644 index 0000000..1d9c623 --- /dev/null +++ b/tests/classes/this.phpt @@ -0,0 +1,54 @@ +--TEST-- +ZE2 $this cannot be exchanged +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +/* please don't shorten this test. It shows what would happen if + * the fatal error would have been a warning. + */ +class Foo +{ + function replace($other) + { + echo __METHOD__ . "\n"; + $this = $other; + print $this->prop; + print $other->prop; + } + + function indirect($other) + { + echo __METHOD__ . "\n"; + $this = $other; + $result = $this = $other; + print $result->prop; + print $this->prop; + } + + function retrieve(&$other) + { + echo __METHOD__ . "\n"; + $other = $this; + } +} + +$object = new Foo; +$object->prop = "Hello\n"; + +$other = new Foo; +$other->prop = "World\n"; + +$object->replace($other); +$object->indirect($other); + +print $object->prop; // still shows 'Hello' + +$object->retrieve($other); +print $other->prop; // shows 'Hello' + +?> +===DONE=== +--EXPECTF-- +Fatal error: Cannot re-assign $this in %sthis.php on line %d diff --git a/tests/classes/tostring_001.phpt b/tests/classes/tostring_001.phpt new file mode 100644 index 0000000..53144ca --- /dev/null +++ b/tests/classes/tostring_001.phpt @@ -0,0 +1,130 @@ +--TEST-- +ZE2 __toString() +--FILE-- +<?php + +function my_error_handler($errno, $errstr, $errfile, $errline) { + var_dump($errstr); +} + +set_error_handler('my_error_handler'); + +class test1 +{ +} + +class test2 +{ + function __toString() + { + echo __METHOD__ . "()\n"; + return "Converted\n"; + } +} + +class test3 +{ + function __toString() + { + echo __METHOD__ . "()\n"; + return 42; + } +} +echo "====test1====\n"; +$o = new test1; +print_r($o); +var_dump((string)$o); +var_dump($o); + +echo "====test2====\n"; +$o = new test2; +print_r($o); +print $o; +var_dump($o); +echo "====test3====\n"; +echo $o; + +echo "====test4====\n"; +echo "string:".$o; + +echo "====test5====\n"; +echo 1 . $o; +echo 1 , $o; + +echo "====test6====\n"; +echo $o . $o; +echo $o , $o; + +echo "====test7====\n"; +$ar = array(); +$ar[$o->__toString()] = "ERROR"; +echo $ar[$o]; + +echo "====test8====\n"; +var_dump(trim($o)); +var_dump(trim((string)$o)); + +echo "====test9====\n"; +echo sprintf("%s", $o); + +echo "====test10====\n"; +$o = new test3; +var_dump($o); +echo $o; + +?> +====DONE==== +--EXPECTF-- +====test1==== +test1 Object +( +) +string(54) "Object of class test1 could not be converted to string" +string(0) "" +object(test1)#%d (0) { +} +====test2==== +test2 Object +( +) +test2::__toString() +Converted +object(test2)#%d (0) { +} +====test3==== +test2::__toString() +Converted +====test4==== +test2::__toString() +string:Converted +====test5==== +test2::__toString() +1Converted +1test2::__toString() +Converted +====test6==== +test2::__toString() +test2::__toString() +Converted +Converted +test2::__toString() +Converted +test2::__toString() +Converted +====test7==== +test2::__toString() +string(19) "Illegal offset type" +====test8==== +test2::__toString() +string(9) "Converted" +test2::__toString() +string(9) "Converted" +====test9==== +test2::__toString() +Converted +====test10==== +object(test3)#%d (0) { +} +test3::__toString() +string(53) "Method test3::__toString() must return a string value" +====DONE==== diff --git a/tests/classes/tostring_002.phpt b/tests/classes/tostring_002.phpt new file mode 100644 index 0000000..8a4a7af --- /dev/null +++ b/tests/classes/tostring_002.phpt @@ -0,0 +1,31 @@ +--TEST-- +ZE2 __toString() in __destruct +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Test +{ + function __toString() + { + return "Hello\n"; + } + + function __destruct() + { + echo $this; + } +} + +$o = new Test; +$o = NULL; + +$o = new Test; + +?> +====DONE==== +--EXPECTF-- +Hello +====DONE==== +Hello diff --git a/tests/classes/tostring_003.phpt b/tests/classes/tostring_003.phpt new file mode 100644 index 0000000..8815bd9 --- /dev/null +++ b/tests/classes/tostring_003.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 __toString() in __destruct/exception +--FILE-- +<?php + +class Test +{ + function __toString() + { + throw new Exception("Damn!"); + return "Hello\n"; + } + + function __destruct() + { + echo $this; + } +} + +try +{ + $o = new Test; + $o = NULL; +} +catch(Exception $e) +{ + var_dump($e->getMessage()); +} + +?> +====DONE==== +--EXPECTF-- +Fatal error: Method Test::__toString() must not throw an exception in %stostring_003.php on line %d diff --git a/tests/classes/tostring_004.phpt b/tests/classes/tostring_004.phpt new file mode 100644 index 0000000..de0283e --- /dev/null +++ b/tests/classes/tostring_004.phpt @@ -0,0 +1,56 @@ +--TEST-- +Object to string conversion: error cases and behaviour variations. +--FILE-- +<?php +function test_error_handler($err_no, $err_msg, $filename, $linenum, $vars) { + echo "Error: $err_no - $err_msg\n"; +} +set_error_handler('test_error_handler'); +error_reporting(8191); + + +echo "Object with no __toString():\n"; +$obj = new stdClass; +echo "Try 1:\n"; +printf($obj); +printf("\n"); + +echo "\nTry 2:\n"; +printf($obj . "\n"); + + +echo "\n\nObject with bad __toString():\n"; +class badToString { + function __toString() { + return 0; + } +} +$obj = new badToString; +echo "Try 1:\n"; +printf($obj); +printf("\n"); + +echo "\nTry 2:\n"; +printf($obj . "\n"); + +?> +--EXPECTF-- +Object with no __toString(): +Try 1: +Error: 4096 - Object of class stdClass could not be converted to string +Error: 8 - Object of class stdClass to string conversion +Object + +Try 2: +Error: 4096 - Object of class stdClass could not be converted to string + + + +Object with bad __toString(): +Try 1: +Error: 4096 - Method badToString::__toString() must return a string value + + +Try 2: +Error: 4096 - Method badToString::__toString() must return a string value + diff --git a/tests/classes/type_hinting_001.phpt b/tests/classes/type_hinting_001.phpt new file mode 100644 index 0000000..f55dd53 --- /dev/null +++ b/tests/classes/type_hinting_001.phpt @@ -0,0 +1,38 @@ +--TEST-- +ZE2 class type hinting +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +interface Foo { + function a(Foo $foo); +} + +interface Bar { + function b(Bar $bar); +} + +class FooBar implements Foo, Bar { + function a(Foo $foo) { + // ... + } + + function b(Bar $bar) { + // ... + } +} + +class Blort { +} + +$a = new FooBar; +$b = new Blort; + +$a->a($b); +$a->b($b); + +?> +--EXPECTF-- + +Catchable fatal error: Argument 1 passed to FooBar::a() must implement interface Foo, instance of Blort given, called in %s on line 27 and defined in %s on line 12 diff --git a/tests/classes/type_hinting_002.phpt b/tests/classes/type_hinting_002.phpt new file mode 100644 index 0000000..7c685bf --- /dev/null +++ b/tests/classes/type_hinting_002.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZE2 class type hinting non existing class +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class Foo { + function a(NonExisting $foo) {} +} + +$o = new Foo; +$o->a($o); +?> +--EXPECTF-- +Catchable fatal error: Argument 1 passed to Foo::a() must be an instance of NonExisting, instance of Foo given, called in %s on line %d and defined in %s on line %d diff --git a/tests/classes/type_hinting_003.phpt b/tests/classes/type_hinting_003.phpt new file mode 100644 index 0000000..a966210 --- /dev/null +++ b/tests/classes/type_hinting_003.phpt @@ -0,0 +1,60 @@ +--TEST-- +ZE2 class type hinting with arrays +--FILE-- +<?php + +class Test +{ + static function f1(array $ar) + { + echo __METHOD__ . "()\n"; + var_dump($ar); + } + + static function f2(array $ar = NULL) + { + echo __METHOD__ . "()\n"; + var_dump($ar); + } + + static function f3(array $ar = array()) + { + echo __METHOD__ . "()\n"; + var_dump($ar); + } + + static function f4(array $ar = array(25)) + { + echo __METHOD__ . "()\n"; + var_dump($ar); + } +} + +Test::f1(array(42)); +Test::f2(NULL); +Test::f2(); +Test::f3(); +Test::f4(); +Test::f1(1); + +?> +--EXPECTF-- +Test::f1() +array(1) { + [0]=> + int(42) +} +Test::f2() +NULL +Test::f2() +NULL +Test::f3() +array(0) { +} +Test::f4() +array(1) { + [0]=> + int(25) +} + +Catchable fatal error: Argument 1 passed to Test::f1() must be of the type array, integer given, called in %s on line %d and defined in %s on line %d diff --git a/tests/classes/type_hinting_004.phpt b/tests/classes/type_hinting_004.phpt new file mode 100644 index 0000000..9068909 --- /dev/null +++ b/tests/classes/type_hinting_004.phpt @@ -0,0 +1,109 @@ +--TEST-- +Ensure type hints are enforced for functions invoked as callbacks. +--FILE-- +<?php + set_error_handler('myErrorHandler', E_RECOVERABLE_ERROR); + function myErrorHandler($errno, $errstr, $errfile, $errline) { + echo "$errno: $errstr - $errfile($errline)\n"; + return true; + } + + echo "---> Type hints with callback function:\n"; + class A { } + function f1(A $a) { + echo "in f1;\n"; + } + function f2(A $a = null) { + echo "in f2;\n"; + } + call_user_func('f1', 1); + call_user_func('f1', new A); + call_user_func('f2', 1); + call_user_func('f2'); + call_user_func('f2', new A); + call_user_func('f2', null); + + + echo "\n\n---> Type hints with callback static method:\n"; + class C { + static function f1(A $a) { + if (isset($this)) { + echo "in C::f1 (instance);\n"; + } else { + echo "in C::f1 (static);\n"; + } + } + static function f2(A $a = null) { + if (isset($this)) { + echo "in C::f2 (instance);\n"; + } else { + echo "in C::f2 (static);\n"; + } + } + } + call_user_func(array('C', 'f1'), 1); + call_user_func(array('C', 'f1'), new A); + call_user_func(array('C', 'f2'), 1); + call_user_func(array('C', 'f2')); + call_user_func(array('C', 'f2'), new A); + call_user_func(array('C', 'f2'), null); + + + echo "\n\n---> Type hints with callback instance method:\n"; + class D { + function f1(A $a) { + if (isset($this)) { + echo "in C::f1 (instance);\n"; + } else { + echo "in C::f1 (static);\n"; + } + } + function f2(A $a = null) { + if (isset($this)) { + echo "in C::f2 (instance);\n"; + } else { + echo "in C::f2 (static);\n"; + } + } + } + $d = new D; + call_user_func(array($d, 'f1'), 1); + call_user_func(array($d, 'f1'), new A); + call_user_func(array($d, 'f2'), 1); + call_user_func(array($d, 'f2')); + call_user_func(array($d, 'f2'), new A); + call_user_func(array($d, 'f2'), null); + +?> +--EXPECTF-- +---> Type hints with callback function: +4096: Argument 1 passed to f1() must be an instance of A, integer given%s(10) +in f1; +in f1; +4096: Argument 1 passed to f2() must be an instance of A, integer given%s(13) +in f2; +in f2; +in f2; +in f2; + + +---> Type hints with callback static method: +4096: Argument 1 passed to C::f1() must be an instance of A, integer given%s(26) +in C::f1 (static); +in C::f1 (static); +4096: Argument 1 passed to C::f2() must be an instance of A, integer given%s(33) +in C::f2 (static); +in C::f2 (static); +in C::f2 (static); +in C::f2 (static); + + +---> Type hints with callback instance method: +4096: Argument 1 passed to D::f1() must be an instance of A, integer given%s(51) +in C::f1 (instance); +in C::f1 (instance); +4096: Argument 1 passed to D::f2() must be an instance of A, integer given%s(58) +in C::f2 (instance); +in C::f2 (instance); +in C::f2 (instance); +in C::f2 (instance); diff --git a/tests/classes/type_hinting_005a.phpt b/tests/classes/type_hinting_005a.phpt new file mode 100644 index 0000000..5e4c43b --- /dev/null +++ b/tests/classes/type_hinting_005a.phpt @@ -0,0 +1,18 @@ +--TEST-- +Check type hint compatibility in overrides with array hints. +--FILE-- +<?php +Class C { function f(array $a) {} } + +echo "Compatible hint.\n"; +Class D1 extends C { function f(array $a) {} } + +echo "Class hint, should be array.\n"; +Class D2 extends C { function f(SomeClass $a) {} } +?> +==DONE== +--EXPECTF-- +Strict Standards: Declaration of D2::f() should be compatible with C::f(array $a) in %s on line 8 +Compatible hint. +Class hint, should be array. +==DONE== diff --git a/tests/classes/type_hinting_005b.phpt b/tests/classes/type_hinting_005b.phpt new file mode 100644 index 0000000..f13ab95 --- /dev/null +++ b/tests/classes/type_hinting_005b.phpt @@ -0,0 +1,14 @@ +--TEST-- +Check type hint compatibility in overrides with array hints. +--FILE-- +<?php +Class C { function f(array $a) {} } + +echo "No hint, should be array.\n"; +Class D extends C { function f($a) {} } +?> +==DONE== +--EXPECTF-- +Strict Standards: Declaration of D::f() should be compatible with C::f(array $a) in %s on line 5 +No hint, should be array. +==DONE== diff --git a/tests/classes/type_hinting_005c.phpt b/tests/classes/type_hinting_005c.phpt new file mode 100644 index 0000000..30a114e --- /dev/null +++ b/tests/classes/type_hinting_005c.phpt @@ -0,0 +1,14 @@ +--TEST-- +Check type hint compatibility in overrides with array hints. +--FILE-- +<?php +Class C { function f(SomeClass $a) {} } + +echo "Array hint, should be class.\n"; +Class D extends C { function f(array $a) {} } +?> +==DONE== +--EXPECTF-- +Strict Standards: Declaration of D::f() should be compatible with C::f(SomeClass $a) in %s on line 5 +Array hint, should be class. +==DONE== diff --git a/tests/classes/type_hinting_005d.phpt b/tests/classes/type_hinting_005d.phpt new file mode 100644 index 0000000..830054d --- /dev/null +++ b/tests/classes/type_hinting_005d.phpt @@ -0,0 +1,14 @@ +--TEST-- +Check type hint compatibility in overrides with array hints. +--FILE-- +<?php +Class C { function f($a) {} } + +echo "Array hint, should be nothing.\n"; +Class D extends C { function f(array $a) {} } +?> +==DONE== +--EXPECTF-- +Strict Standards: Declaration of D::f() should be compatible with C::f($a) in %s on line 5 +Array hint, should be nothing. +==DONE== diff --git a/tests/classes/unset_properties.phpt b/tests/classes/unset_properties.phpt new file mode 100644 index 0000000..264e720 --- /dev/null +++ b/tests/classes/unset_properties.phpt @@ -0,0 +1,154 @@ +--TEST-- +Un-setting instance properties causes magic methods to be called when trying to access them from outside the magic +methods themselves. +--FILE-- +<?php + +class Test +{ + public $publicProperty = 'publicProperty set'; + + protected $protectedProperty = 'protectedProperty set'; + + private $privateProperty = 'privateProperty set'; + + public function __get($name) + { + return '__get "' . $name . '"'; + } + + public function __set($name, $value) + { + $this->$name = $value; + echo '__set "' . $name . '" to "' . $value . '"'; + } + + public function __isset($name) + { + echo '__isset "' . $name . '"'; + return isset($this->$name); + } + + public function getPublicProperty() + { + return $this->publicProperty; + } + + public function setPublicProperty($publicProperty) + { + $this->publicProperty = $publicProperty; + } + + public function unsetProtectedProperty() + { + unset($this->protectedProperty); + } + + public function getProtectedProperty() + { + return $this->protectedProperty; + } + + public function setProtectedProperty($protectedProperty) + { + $this->protectedProperty = $protectedProperty; + } + + public function unsetPrivateProperty() + { + unset($this->privateProperty); + } + + public function getPrivateProperty() + { + return $this->privateProperty; + } + + public function setPrivateProperty($privateProperty) + { + $this->privateProperty = $privateProperty; + } +} + +// verifying public property +$o = new Test; +echo $o->publicProperty; +echo "\n"; +var_export(isset($o->publicProperty)); +echo "\n"; +unset($o->publicProperty); +isset($o->publicProperty); +echo "\n"; +echo $o->publicProperty; +echo "\n"; +echo $o->getPublicProperty(); +echo "\n"; +echo $o->setPublicProperty('new publicProperty value via setter'); +echo "\n"; +echo $o->publicProperty; +echo "\n"; +unset($o->publicProperty); +$o->publicProperty = 'new publicProperty value via public access'; +echo "\n"; +var_export(isset($o->publicProperty)); +echo "\n"; +echo $o->publicProperty; +echo "\n\n"; + +// verifying protected property +echo $o->getProtectedProperty(); +echo "\n"; +$o->unsetProtectedProperty(); +var_export(isset($o->protectedProperty)); +echo "\n"; +echo $o->getProtectedProperty(); +echo "\n"; +echo $o->setProtectedProperty('new protectedProperty value via setter'); +echo "\n"; +var_export(isset($o->protectedProperty)); +echo "\n"; +echo $o->getProtectedProperty(); +echo "\n\n"; + +// verifying private property +echo $o->getPrivateProperty(); +echo "\n"; +$o->unsetPrivateProperty(); +var_export(isset($o->privateProperty)); +echo "\n"; +echo $o->getPrivateProperty(); +echo "\n"; +echo $o->setPrivateProperty('new privateProperty value via setter'); +echo "\n"; +var_export(isset($o->privateProperty)); +echo "\n"; +echo $o->getPrivateProperty(); +echo "\n\n"; + +?> + +--EXPECTF-- +publicProperty set +true +__isset "publicProperty" +__get "publicProperty" +__get "publicProperty" +__set "publicProperty" to "new publicProperty value via setter" +new publicProperty value via setter +__set "publicProperty" to "new publicProperty value via public access" +true +new publicProperty value via public access + +protectedProperty set +__isset "protectedProperty"false +__get "protectedProperty" +__set "protectedProperty" to "new protectedProperty value via setter" +__isset "protectedProperty"true +new protectedProperty value via setter + +privateProperty set +__isset "privateProperty"false +__get "privateProperty" +__set "privateProperty" to "new privateProperty value via setter" +__isset "privateProperty"true +new privateProperty value via setter diff --git a/tests/classes/visibility_000a.phpt b/tests/classes/visibility_000a.phpt new file mode 100644 index 0000000..2524494 --- /dev/null +++ b/tests/classes/visibility_000a.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + protected function f0() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f0() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_000b.phpt b/tests/classes/visibility_000b.phpt new file mode 100644 index 0000000..9305467 --- /dev/null +++ b/tests/classes/visibility_000b.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + private function f0() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f0() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_000c.phpt b/tests/classes/visibility_000c.phpt new file mode 100644 index 0000000..064106e --- /dev/null +++ b/tests/classes/visibility_000c.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + function f0() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_001a.phpt b/tests/classes/visibility_001a.phpt new file mode 100644 index 0000000..ebd1cc3 --- /dev/null +++ b/tests/classes/visibility_001a.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + protected function f1() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f1() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_001b.phpt b/tests/classes/visibility_001b.phpt new file mode 100644 index 0000000..e61078e --- /dev/null +++ b/tests/classes/visibility_001b.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + private function f1() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f1() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_001c.phpt b/tests/classes/visibility_001c.phpt new file mode 100644 index 0000000..bb1075a --- /dev/null +++ b/tests/classes/visibility_001c.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + function f1() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_002a.phpt b/tests/classes/visibility_002a.phpt new file mode 100644 index 0000000..6c88d20 --- /dev/null +++ b/tests/classes/visibility_002a.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + protected function f2() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f2() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_002b.phpt b/tests/classes/visibility_002b.phpt new file mode 100644 index 0000000..71f47c3 --- /dev/null +++ b/tests/classes/visibility_002b.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + private function f2() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f2() must be public (as in class same) in %s on line %d diff --git a/tests/classes/visibility_002c.phpt b/tests/classes/visibility_002c.phpt new file mode 100644 index 0000000..5edae1d --- /dev/null +++ b/tests/classes/visibility_002c.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + function f2() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_003a.phpt b/tests/classes/visibility_003a.phpt new file mode 100644 index 0000000..1693386 --- /dev/null +++ b/tests/classes/visibility_003a.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + public function f3() {} +} + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_003b.phpt b/tests/classes/visibility_003b.phpt new file mode 100644 index 0000000..fcfdbe3 --- /dev/null +++ b/tests/classes/visibility_003b.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + private function f3() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Fatal error: Access level to fail::f3() must be protected (as in class same) or weaker in %s on line %d diff --git a/tests/classes/visibility_003c.phpt b/tests/classes/visibility_003c.phpt new file mode 100644 index 0000000..d94a9c1 --- /dev/null +++ b/tests/classes/visibility_003c.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + function f3() {} +} + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_004a.phpt b/tests/classes/visibility_004a.phpt new file mode 100644 index 0000000..6f16a09 --- /dev/null +++ b/tests/classes/visibility_004a.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + public function f4() {} +} + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_004b.phpt b/tests/classes/visibility_004b.phpt new file mode 100644 index 0000000..74a8318 --- /dev/null +++ b/tests/classes/visibility_004b.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + protected function f4() {} +} + +echo "Done\n"; // shouldn't be displayed +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_004c.phpt b/tests/classes/visibility_004c.phpt new file mode 100644 index 0000000..92a7703 --- /dev/null +++ b/tests/classes/visibility_004c.phpt @@ -0,0 +1,33 @@ +--TEST-- +ZE2 A redeclared method must have the same or higher visibility +--SKIPIF-- +<?php if (version_compare(zend_version(), '2.0.0-dev', '<')) die('skip ZendEngine 2 needed'); ?> +--FILE-- +<?php + +class father { + function f0() {} + function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class same extends father { + + // overload fn with same visibility + function f0() {} + public function f1() {} + public function f2() {} + protected function f3() {} + private function f4() {} +} + +class fail extends same { + function f4() {} +} + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/tests/classes/visibility_005.phpt b/tests/classes/visibility_005.phpt new file mode 100644 index 0000000..859a5f7 --- /dev/null +++ b/tests/classes/visibility_005.phpt @@ -0,0 +1,59 @@ +--TEST-- +ZE2 foreach and property visibility +--FILE-- +<?php + +class base +{ + public $a=1; + protected $b=2; + private $c=3; + + function f() + { + foreach($this as $k=>$v) { + echo "$k=>$v\n"; + } + } +} + +class derived extends base +{ +} + +$o = new base; +$o->d = 4; +echo "===base::function===\n"; +$o->f(); +echo "===base,foreach===\n"; +foreach($o as $k=>$v) { + echo "$k=>$v\n"; +} + +$o = new derived; +$o->d = 4; +echo "===derived::function===\n"; +$o->f(); +echo "===derived,foreach===\n"; +foreach($o as $k=>$v) { + echo "$k=>$v\n"; +} + +?> +--EXPECT-- +===base::function=== +a=>1 +b=>2 +c=>3 +d=>4 +===base,foreach=== +a=>1 +d=>4 +===derived::function=== +a=>1 +b=>2 +c=>3 +d=>4 +===derived,foreach=== +a=>1 +d=>4 |