diff options
Diffstat (limited to 'Zend/tests')
139 files changed, 3312 insertions, 31 deletions
diff --git a/Zend/tests/bug18556.phpt b/Zend/tests/bug18556.phpt new file mode 100644 index 0000000000..036abb2ada --- /dev/null +++ b/Zend/tests/bug18556.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug #18556 (Setting locale to 'tr_TR' lowercases class names) +--FILE-- +<?php +$g_lang = 'tr_TR'; +putenv("LANG=$g_lang"); +setlocale(LC_ALL, $g_lang); + +class InfoBlob { + var $foo; + function InfoBlob() { + $this->foo = "Foo"; + } +} + +echo "Instantiating an infoBlob with a lowercase i\n"; +$foobar = new infoBlob(); +echo $foobar->foo; +echo "\nInstantiating an InfoBlob with an uppercase I\n"; +$foobar = new InfoBlob(); +echo $foobar->foo; +echo "\n"; +setlocale(LC_ALL, "tr_TR.utf8"); +foreach(get_declared_classes() as $class) +{ + if(!class_exists($class)) + echo "$class No Longer Exists!\n"; + +} +echo "Done.\n"; +?> +--EXPECT-- +Instantiating an infoBlob with a lowercase i +Foo +Instantiating an InfoBlob with an uppercase I +Foo +Done. diff --git a/Zend/tests/bug39018.phpt b/Zend/tests/bug39018.phpt index 32566ba864..a00e1fb819 100644 --- a/Zend/tests/bug39018.phpt +++ b/Zend/tests/bug39018.phpt @@ -64,6 +64,8 @@ print "\nDone\n"; --EXPECTF-- Notice: String offset cast occurred in %s on line %d +Notice: Uninitialized string offset: %s in %s on line 6 + Notice: Uninitialized string offset: 0 in %s on line %d Notice: Uninitialized string offset: 0 in %s on line %d diff --git a/Zend/tests/bug41421.phpt b/Zend/tests/bug41421.phpt index f10db10980..f39fb15dda 100644 --- a/Zend/tests/bug41421.phpt +++ b/Zend/tests/bug41421.phpt @@ -24,6 +24,6 @@ Warning: feof(): wrapper::stream_eof is not implemented! Assuming EOF in %s on l Fatal error: Uncaught exception 'Exception' in %s:%d Stack trace: #0 [internal function]: wrapper->stream_eof() -#1 %s(%d): feof(Resource id #6) +#1 %s(%d): feof(Resource id #%d) #2 {main} thrown in %s on line %d diff --git a/Zend/tests/bug43450.phpt b/Zend/tests/bug43450.phpt index 926e146f4e..a94eba312e 100644 --- a/Zend/tests/bug43450.phpt +++ b/Zend/tests/bug43450.phpt @@ -2,6 +2,8 @@ Bug #43450 (Memory leak on some functions with implicit object __toString() call) --SKIPIF-- <?php if (!function_exists('memory_get_usage')) die('memory_get_usage() not installed'); ?> +--INI-- +opcache.enable_cli=0 --FILE-- <?php error_reporting(E_ALL|E_STRICT); diff --git a/Zend/tests/bug51394.phpt b/Zend/tests/bug51394.phpt index 406de13a9b..b0dddffaf8 100644 --- a/Zend/tests/bug51394.phpt +++ b/Zend/tests/bug51394.phpt @@ -13,10 +13,8 @@ function eh() set_error_handler("eh"); $a = $empty($b); --EXPECTF-- -Warning: Uncaught exception 'Exception' with message 'error!' in %sbug51394.php:4 +Fatal error: Uncaught exception 'Exception' with message 'error!' in %sbug51394.php:%d Stack trace: -#0 %sbug51394.php(9): eh(8, 'Undefined varia...', '%s', 9, Array) +#0 %sbug51394.php(%d): eh(8, 'Undefined varia%s', '%s', %d, Array) #1 {main} - thrown in %sbug51394.php on line 4 - -Fatal error: Function name must be a string in %sbug51394.php on line 9
\ No newline at end of file + thrown in %sbug51394.php on line %d diff --git a/Zend/tests/bug52041.phpt b/Zend/tests/bug52041.phpt index c4b9f97ee5..7e1f3423a6 100644 --- a/Zend/tests/bug52041.phpt +++ b/Zend/tests/bug52041.phpt @@ -35,18 +35,30 @@ Notice: Undefined variable: x in %sbug52041.php on line 3 Warning: Creating default object from empty value in %sbug52041.php on line 8 +Notice: Undefined property: stdClass::$a in %sbug52041.php on line 8 + Notice: Undefined variable: x in %sbug52041.php on line 3 +Notice: Undefined property: stdClass::$a in %sbug52041.php on line 9 + Warning: Creating default object from empty value in %sbug52041.php on line 9 +Notice: Undefined property: stdClass::$b in %sbug52041.php on line 9 + Notice: Undefined variable: x in %sbug52041.php on line 3 Warning: Creating default object from empty value in %sbug52041.php on line 10 +Notice: Undefined property: stdClass::$a in %sbug52041.php on line 10 + Notice: Undefined variable: x in %sbug52041.php on line 3 +Notice: Undefined property: stdClass::$a in %sbug52041.php on line 11 + Warning: Creating default object from empty value in %sbug52041.php on line 11 +Notice: Undefined property: stdClass::$b in %sbug52041.php on line 11 + Notice: Undefined variable: x in %sbug52041.php on line 3 Notice: Undefined variable: x in %sbug52041.php on line 3 diff --git a/Zend/tests/bug55156.phpt b/Zend/tests/bug55156.phpt index 6c0ff768d1..7d75ce3e94 100644 --- a/Zend/tests/bug55156.phpt +++ b/Zend/tests/bug55156.phpt @@ -1,5 +1,8 @@ --TEST-- Bug #55156 (ReflectionClass::getDocComment() returns comment even though the class has none) +--INI-- +opcache.save_comments=1 +opcache.load_comments=1 --FILE-- <?php diff --git a/Zend/tests/bug60536_001.phpt b/Zend/tests/bug60536_001.phpt index 916646727d..a94e21ecee 100644 --- a/Zend/tests/bug60536_001.phpt +++ b/Zend/tests/bug60536_001.phpt @@ -3,18 +3,18 @@ Bug #60536 (Traits Segfault) --FILE-- <?php trait T { private $x = 0; } -class X { +class X { use T; } class Y extends X { use T; function x() { - return ++$this->x; + return ++$this->x; } } class Z extends Y { function z() { - return ++$this->x; + return ++$this->x; } } $a = new Z(); @@ -22,4 +22,6 @@ $a->x(); echo "DONE"; ?> --EXPECTF-- + +Notice: Undefined property: Z::$x in %s on line 14 DONE diff --git a/Zend/tests/bug60738.phpt b/Zend/tests/bug60738.phpt new file mode 100644 index 0000000000..e4080715ec --- /dev/null +++ b/Zend/tests/bug60738.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #60738 Allow 'set_error_handler' to handle NULL +--FILE-- +<?php + +var_dump(set_error_handler( + function() { echo 'Intercepted error!', "\n"; } +)); + +trigger_error('Error!'); + +var_dump(set_error_handler(null)); + +trigger_error('Error!'); +?> +--EXPECTF-- +NULL +Intercepted error! +object(Closure)#1 (0) { +} + +Notice: Error! in %s on line %d diff --git a/Zend/tests/bug60738_variation.phpt b/Zend/tests/bug60738_variation.phpt new file mode 100644 index 0000000000..d7cf00ecdb --- /dev/null +++ b/Zend/tests/bug60738_variation.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #60738 Allow 'set_error_handler' to handle NULL +--FILE-- +<?php + +var_dump(set_exception_handler( + function() { echo 'Intercepted exception!', "\n"; } +)); + +var_dump(set_exception_handler(null)); + +throw new Exception('Exception!'); +?> +--EXPECTF-- +NULL +object(Closure)#1 (0) { +} + +Fatal error: Uncaught exception 'Exception' with message 'Exception!' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d + diff --git a/Zend/tests/bug60833.phpt b/Zend/tests/bug60833.phpt new file mode 100644 index 0000000000..deb6c0f691 --- /dev/null +++ b/Zend/tests/bug60833.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #60833 (self, parent, static behave inconsistently case-sensitive) +--FILE-- +<?php +class A { + static $x = "A"; + function testit() { + $this->v1 = new sELF; + $this->v2 = new SELF; + } +} + +class B extends A { + static $x = "B"; + function testit() { + PARENT::testit(); + $this->v3 = new sELF; + $this->v4 = new PARENT; + $this->v4 = STATIC::$x; + } +} +$t = new B(); +$t->testit(); +var_dump($t); +?> +--EXPECTF-- +object(B)#%d (4) { + ["v1"]=> + object(A)#%d (0) { + } + ["v2"]=> + object(A)#%d (0) { + } + ["v3"]=> + object(B)#%d (0) { + } + ["v4"]=> + string(1) "B" +} + diff --git a/Zend/tests/bug61025.phpt b/Zend/tests/bug61025.phpt new file mode 100644 index 0000000000..0709c28fbc --- /dev/null +++ b/Zend/tests/bug61025.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #61025 (__invoke() visibility not honored) +--FILE-- +<?php + +Interface InvokeAble { + static function __invoke(); +} + +class Bar { + private function __invoke() { + return __CLASS__; + } +} + +$b = new Bar; +echo $b(); + +echo $b->__invoke(); + +?> +--EXPECTF-- +Warning: The magic method __invoke() must have public visibility and cannot be static in %sbug61025.php on line %d + +Warning: The magic method __invoke() must have public visibility and cannot be static in %sbug61025.php on line %d +Bar +Fatal error: Call to private method Bar::__invoke() from context '' in %sbug61025.php on line %d diff --git a/Zend/tests/bug61681.phpt b/Zend/tests/bug61681.phpt new file mode 100644 index 0000000000..acc0275398 --- /dev/null +++ b/Zend/tests/bug61681.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #61681: Malformed grammar +--FILE-- +<?php +$la = "ooxx"; + +echo "${substr('laruence', 0, 2)}"; + +?> +--EXPECT-- +ooxx diff --git a/Zend/tests/bug61767.phpt b/Zend/tests/bug61767.phpt index 5270872e5d..9bd9c907bd 100644 --- a/Zend/tests/bug61767.phpt +++ b/Zend/tests/bug61767.phpt @@ -17,18 +17,16 @@ $undefined->foo(); --EXPECTF-- Error handler called (Undefined variable: undefined) -Warning: Uncaught exception 'ErrorException' with message 'Undefined variable: undefined' in %sbug61767.php:13 +Fatal error: Uncaught exception 'ErrorException' with message 'Undefined variable: undefined' in %sbug61767.php:%d Stack trace: -#0 %sbug61767.php(13): {closure}(8, 'Undefined varia...', '%s', 13, Array) +#0 %sbug61767.php(%d): {closure}(%s, 'Undefined varia...', '%s', %d, Array) #1 {main} - thrown in %sbug61767.php on line 13 - -Fatal error: Call to a member function foo() on a non-object in %sbug61767.php on line 13 + thrown in %sbug61767.php on line %d Shutting down Array ( [type] => 1 - [message] => Call to a member function foo() on a non-object + [message] => %a [file] => %sbug61767.php - [line] => 13 + [line] => %d ) diff --git a/Zend/tests/bug62005.phpt b/Zend/tests/bug62005.phpt index c99b28726f..83158d5cc2 100644 --- a/Zend/tests/bug62005.phpt +++ b/Zend/tests/bug62005.phpt @@ -9,6 +9,8 @@ function add_points($player, $points) { add_points(NULL, 2); --EXPECTF-- Warning: Creating default object from empty value in %sbug62005.php on line %d + +Notice: Undefined property: stdClass::$energy in %sbug62005.php on line 3 stdClass Object ( [energy] => 2 diff --git a/Zend/tests/bug62991.phpt b/Zend/tests/bug62991.phpt new file mode 100644 index 0000000000..cb4ff93359 --- /dev/null +++ b/Zend/tests/bug62991.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #62991 (Segfault with generator and closure) +--FILE-- +<?php + +function test( array $array ) +{ + $closure = function() use ( $array ) { + print_r( $array ); + yield "hi"; + }; + return $closure(); +} + +function test2( array $array ) +{ + $closure = function() use ( $array ) { + print_r( $array ); + yield "hi"; + }; + return $closure; // if you return the $closure and call it outside this function it works. +} + +$generator = test(array( 1, 2, 3 ) ); +foreach($generator as $something) { +} + +$generator = test2(array( 1, 2, 3 ) ); +foreach($generator() as $something) { +} + + +$generator = test2(array( 1, 2, 3 ) ); + +echo "okey\n"; +?> +--EXPECT-- +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +okey diff --git a/Zend/tests/bug63741.phpt b/Zend/tests/bug63741.phpt new file mode 100644 index 0000000000..fc04c9e79c --- /dev/null +++ b/Zend/tests/bug63741.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #63741 (Crash when autoloading from spl) +--FILE-- +<?php +file_put_contents(dirname(__FILE__)."/bug63741.tmp.php", +<<<'EOT' +<?php +if (isset($autoloading)) +{ + class ClassToLoad + { + static function func () + { + print "OK!\n"; + } + } + return; +} +else +{ + class autoloader + { + static function autoload($classname) + { + print "autoloading...\n"; + $autoloading = true; + include __FILE__; + } + } + + spl_autoload_register(["autoloader", "autoload"]); + + function start() + { + ClassToLoad::func(); + } + + start(); +} +?> +EOT +); + +include dirname(__FILE__)."/bug63741.tmp.php"; +?> +--CLEAN-- +<?php unlink(dirname(__FILE__)."/bug63741.tmp.php"); ?> +--EXPECT-- +autoloading... +OK! diff --git a/Zend/tests/bug64135.phpt b/Zend/tests/bug64135.phpt new file mode 100644 index 0000000000..1c7b1500a2 --- /dev/null +++ b/Zend/tests/bug64135.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #64135 (Exceptions from set_error_handler are not always propagated) +--FILE-- +<?php + +function exception_error_handler() { + throw new Exception(); +} + +set_error_handler("exception_error_handler"); +try { + $undefined->undefined(); +} catch(Exception $e) { + echo "Exception is thrown"; +} +--EXPECT-- +Exception is thrown diff --git a/Zend/tests/bug64555.phpt b/Zend/tests/bug64555.phpt new file mode 100644 index 0000000000..d5226af7a9 --- /dev/null +++ b/Zend/tests/bug64555.phpt @@ -0,0 +1,42 @@ +--TEST-- +Bug #64555: Array key within interned string gets wrong hash value +--FILE-- +<?php + +class Foo { + protected $unsetme = 1; + protected $keepme = 2; + + public function test() { + $a = get_object_vars($this); + + foreach ($a as $k => $v) { + if ($k == 'unsetme') { + echo "Unsetting: $k\n"; + unset($a[$k]); + } else if ($k == 'keepme') { + echo "Changing: $k\n"; + $a[$k] = 42; + $a['keepme'] = 43; + } + } + + var_dump($a, array_keys($a)); + } +} + +$f = new Foo; +$f->test(); + +?> +--EXPECT-- +Unsetting: unsetme +Changing: keepme +array(1) { + ["keepme"]=> + int(43) +} +array(1) { + [0]=> + string(6) "keepme" +} diff --git a/Zend/tests/bug64677.phpt b/Zend/tests/bug64677.phpt new file mode 100644 index 0000000000..44a7c5fc6f --- /dev/null +++ b/Zend/tests/bug64677.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #64677 (execution operator `` stealing surrounding arguments) +--FILE-- +<?PHP +class cat { + public function show_output($prepend, $output = '') { + } +} +$cat = new cat(); +$cat->show_output('Files: ', trim(`cd .`)); // this gives invalid args to shell_exec +$cat->show_output('Files: ', `cd .`); // this causes a segmentation fault +$cat->show_output(`cd .`); // this causes a segmentation fault + +function show_outputa($prepend, $output) { + echo "Okey"; +} +show_outputa('Files: ', `cd .`); // this works as expected + +?> +--EXPECT-- +Okey diff --git a/Zend/tests/bug64979.phpt b/Zend/tests/bug64979.phpt new file mode 100644 index 0000000000..5bc8e5a6ab --- /dev/null +++ b/Zend/tests/bug64979.phpt @@ -0,0 +1,30 @@ +--TEST--
+Bug #64979 (Wrong behavior of static variables in closure generators)
+--FILE--
+<?php
+
+function new_closure_gen() {
+ return function() {
+ static $foo = 0;
+ yield ++$foo;
+ };
+}
+
+$closure1 = new_closure_gen();
+$closure2 = new_closure_gen();
+
+$gen1 = $closure1();
+$gen2 = $closure1();
+$gen3 = $closure2();
+
+foreach (array($gen1, $gen2, $gen3) as $gen) {
+ foreach ($gen as $val) {
+ var_dump($val);
+ }
+}
+
+?>
+--EXPECT--
+int(1)
+int(2)
+int(1)
diff --git a/Zend/tests/bug65051.phpt b/Zend/tests/bug65051.phpt new file mode 100644 index 0000000000..42febf5b92 --- /dev/null +++ b/Zend/tests/bug65051.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #65051: count() off by one inside unset() +--FILE-- +<?php + +class Foo { + public $array; + + public function __destruct() { + var_dump(count($this->array[0])); + var_dump($this->array[0]); + } +} + +$array = [[new Foo]]; +$array[0][0]->array =& $array; +unset($array[0][0]); + +?> +--EXPECT-- +int(0) +array(0) { +} diff --git a/Zend/tests/bug65784.phpt b/Zend/tests/bug65784.phpt new file mode 100644 index 0000000000..adc34113a5 --- /dev/null +++ b/Zend/tests/bug65784.phpt @@ -0,0 +1,62 @@ +--TEST-- +Fixed Bug #65784 (Segfault with finally) +--XFAIL-- +This bug is not fixed in 5.5 due to ABI BC +--FILE-- +<?php +function foo1() { + try { + throw new Exception("not catch"); + return true; + } finally { + try { + throw new Exception("catched"); + } catch (Exception $e) { + } + } +} +try { + $foo = foo1(); + var_dump($foo); +} catch (Exception $e) { + do { + var_dump($e->getMessage()); + } while ($e = $e->getPrevious()); +} + +function foo2() { + try { + try { + throw new Exception("catched"); + return true; + } finally { + try { + throw new Exception("catched"); + } catch (Exception $e) { + } + } + } catch (Exception $e) { + } +} + +$foo = foo2(); +var_dump($foo); + +function foo3() { + try { + throw new Exception("not catched"); + return true; + } finally { + try { + throw new NotExists(); + } catch (Exception $e) { + } + } +} + +$bar = foo3(); +--EXPECTF-- +string(9) "not catch" +NULL + +Fatal error: Class 'NotExists' not found in %sbug65784.php on line %d diff --git a/Zend/tests/catch_finally_001.phpt b/Zend/tests/catch_finally_001.phpt new file mode 100644 index 0000000000..0c3f597a0a --- /dev/null +++ b/Zend/tests/catch_finally_001.phpt @@ -0,0 +1,32 @@ +--TEST-- +Try catch finally (basic test) +--FILE-- +<?php +function foo ($throw = FALSE) { + try { + echo "try\n"; + if ($throw) { + throw new Exception("ex"); + } + } catch (Exception $e) { + echo "catch\n"; + } finally { + echo "finally\n"; + } + + echo "end\n"; +} + +foo(); +echo "\n"; +foo(true); +?> +--EXPECTF-- +try +finally +end + +try +catch +finally +end diff --git a/Zend/tests/catch_finally_002.phpt b/Zend/tests/catch_finally_002.phpt new file mode 100644 index 0000000000..c54477ff8c --- /dev/null +++ b/Zend/tests/catch_finally_002.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try catch finally (basic test with return) +--FILE-- +<?php +function foo () { + try { + echo "try\n"; + return 1; + } catch (Exception $e) { + } finally { + echo "finally\n"; + } + return 2; +} + +var_dump(foo()); +?> +--EXPECTF-- +try +finally +int(1) diff --git a/Zend/tests/catch_finally_003.phpt b/Zend/tests/catch_finally_003.phpt new file mode 100644 index 0000000000..24e468d335 --- /dev/null +++ b/Zend/tests/catch_finally_003.phpt @@ -0,0 +1,40 @@ +--TEST-- +Try catch finally (with multi-returns) +--FILE-- +<?php +function dummy($msg) { + var_dump($msg); +} + +function foo ($a) { + try { + dummy("try"); + return $a; + } catch (Exception $e) { + throw $e; + } finally { + dummy("finally"); + return "finally"; + } + return "end"; +} + +function &bar($a) { + try { + echo "try\n"; + throw new Exception("ex"); + } catch (Exception $e) { + } finally { + return $a; + } + return ($c = "end"); +} +var_dump(foo("para")); +var_dump(bar("para")); +?> +--EXPECTF-- +string(3) "try" +string(7) "finally" +string(7) "finally" +try +string(4) "para" diff --git a/Zend/tests/catch_finally_004.phpt b/Zend/tests/catch_finally_004.phpt new file mode 100644 index 0000000000..a2c22beab1 --- /dev/null +++ b/Zend/tests/catch_finally_004.phpt @@ -0,0 +1,41 @@ +--TEST-- +Try catch finally (nesting try-catch-finally) +--FILE-- +<?php + +function throw_exception($msg) { + throw new Exception($msg); +} + +function foo (&$ex) { + try { + echo "1"; + try { + echo "2"; + throw_exception("try"); + } catch (Exception $e) { + echo "3"; + throw_exception("catch"); + } finally { + echo "4"; + throw_exception("finally"); + } + } catch (Exception $e) { + $ex = $e; + echo "3"; + } finally { + echo "2"; + } + return 1; +} + +var_dump(foo($ex)); + +do { + var_dump($ex->getMessage()); +} while ($ex = $ex->getPrevious()); +?> +--EXPECT-- +123432int(1) +string(7) "finally" +string(5) "catch" diff --git a/Zend/tests/catch_finally_005.phpt b/Zend/tests/catch_finally_005.phpt new file mode 100644 index 0000000000..c2fd55df27 --- /dev/null +++ b/Zend/tests/catch_finally_005.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try catch finally (with multi-returns and exception) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } catch (PdoException $e) { + die("error"); + } catch (Exception $e) { + return 2; + } finally { + return 3; + } + return 1; +} + +var_dump(foo("para")); +?> +--EXPECTF-- +int(3) diff --git a/Zend/tests/catch_finally_006.phpt b/Zend/tests/catch_finally_006.phpt new file mode 100644 index 0000000000..216219b6a5 --- /dev/null +++ b/Zend/tests/catch_finally_006.phpt @@ -0,0 +1,28 @@ +--TEST-- +Try catch finally (re-throw exception in catch block) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } catch (Exception $e) { + var_dump($a); + throw $e; + } finally { + var_dump("finally"); + return "return"; + } + return 1; +} + +try { + var_dump(foo("para")); +} catch (Exception $e) { + "caught exception" . PHP_EOL; + var_dump($e->getMessage()); +} +?> +--EXPECT-- +string(4) "para" +string(7) "finally" +string(6) "return" diff --git a/Zend/tests/class_name_as_scalar.phpt b/Zend/tests/class_name_as_scalar.phpt new file mode 100644 index 0000000000..38e55b16d5 --- /dev/null +++ b/Zend/tests/class_name_as_scalar.phpt @@ -0,0 +1,77 @@ +--TEST-- +class name as scalar from ::class keyword +--FILE-- +<?php + +namespace Foo\Bar { + class One { + // compile time constants + const A = self::class; + const B = Two::class; + } + class Two extends One { + public static function run() { + var_dump(self::class); // self compile time lookup + var_dump(static::class); // runtime lookup + var_dump(parent::class); // runtime lookup + var_dump(Baz::class); // default compile time lookup + } + } + class Three extends Two { + // compile time static lookups + public static function checkCompileTime( + $one = self::class, + $two = Baz::class, + $three = One::A, + $four = self::B + ) { + var_dump($one, $two, $three, $four); + } + } + echo "In NS\n"; + var_dump(Moo::CLASS); // resolve in namespace +} + +namespace { + use Bee\Bop as Moo, + Foo\Bar\One; + echo "Top\n"; + var_dump(One::class); // resolve from use + var_dump(Boo::class); // resolve in global namespace + var_dump(Moo::CLASS); // resolve from use as + var_dump(\Moo::Class); // resolve fully qualified + $class = One::class; // assign class as scalar to var + $x = new $class; // create new class from original scalar assignment + var_dump($x); + Foo\Bar\Two::run(); // resolve runtime lookups + echo "Parent\n"; + Foo\Bar\Three::run(); // resolve runtime lookups with inheritance + echo "Compile Check\n"; + Foo\Bar\Three::checkCompileTime(); +} + +?> +--EXPECTF-- +In NS +string(11) "Foo\Bar\Moo" +Top +string(11) "Foo\Bar\One" +string(3) "Boo" +string(7) "Bee\Bop" +string(3) "Moo" +object(Foo\Bar\One)#1 (0) { +} +string(11) "Foo\Bar\Two" +string(11) "Foo\Bar\Two" +string(11) "Foo\Bar\One" +string(11) "Foo\Bar\Baz" +Parent +string(11) "Foo\Bar\Two" +string(13) "Foo\Bar\Three" +string(11) "Foo\Bar\One" +string(11) "Foo\Bar\Baz" +Compile Check +string(13) "Foo\Bar\Three" +string(11) "Foo\Bar\Baz" +string(11) "Foo\Bar\One" +string(11) "Foo\Bar\Two" diff --git a/Zend/tests/class_name_as_scalar_error_001.phpt b/Zend/tests/class_name_as_scalar_error_001.phpt new file mode 100644 index 0000000000..1c7aa7ea84 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_001.phpt @@ -0,0 +1,13 @@ +--TEST-- +class name as scalar from ::class keyword error using static in class constant +--FILE-- +<?php + +namespace Foo\Bar { + class One { + const Baz = static::class; + } +} +?> +--EXPECTF-- +Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d diff --git a/Zend/tests/class_name_as_scalar_error_002.phpt b/Zend/tests/class_name_as_scalar_error_002.phpt new file mode 100644 index 0000000000..59b7a2edc9 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_002.phpt @@ -0,0 +1,13 @@ +--TEST-- +class name as scalar from ::class keyword error using parent in class constant +--FILE-- +<?php + +namespace Foo\Bar { + class One { + const Baz = parent::class; + } +} +?> +--EXPECTF-- +Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d diff --git a/Zend/tests/class_name_as_scalar_error_003.phpt b/Zend/tests/class_name_as_scalar_error_003.phpt new file mode 100644 index 0000000000..9299041693 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_003.phpt @@ -0,0 +1,13 @@ +--TEST-- +class name as scalar from ::class keyword error using static in method signature +--FILE-- +<?php + +namespace Foo\Bar { + class One { + public function baz($x = static::class) {} + } +} +?> +--EXPECTF-- +Fatal error: static::class cannot be used for compile-time class name resolution in %s on line %d diff --git a/Zend/tests/class_name_as_scalar_error_004.phpt b/Zend/tests/class_name_as_scalar_error_004.phpt new file mode 100644 index 0000000000..c00037fca3 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +class name as scalar from ::class keyword error using parent in method signature +--FILE-- +<?php + +namespace Foo\Bar { + class One { + public function baz($x = parent::class) {} + } +} +?> +--EXPECTF-- +Fatal error: parent::class cannot be used for compile-time class name resolution in %s on line %d diff --git a/Zend/tests/class_name_as_scalar_error_005.phpt b/Zend/tests/class_name_as_scalar_error_005.phpt new file mode 100644 index 0000000000..39de69ffb3 --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_005.phpt @@ -0,0 +1,10 @@ +--TEST-- +class name as scalar from ::class keyword error using static non class context +--FILE-- +<?php + +$x = static::class; + +?> +--EXPECTF-- +Fatal error: Cannot access static::class when no class scope is active in %s on line %d
\ No newline at end of file diff --git a/Zend/tests/class_name_as_scalar_error_006.phpt b/Zend/tests/class_name_as_scalar_error_006.phpt new file mode 100644 index 0000000000..a4cc9a528b --- /dev/null +++ b/Zend/tests/class_name_as_scalar_error_006.phpt @@ -0,0 +1,10 @@ +--TEST-- +class name as scalar from ::class keyword error using parent in non class context +--FILE-- +<?php + +$x = parent::class; + +?> +--EXPECTF-- +Fatal error: Cannot access parent::class when no class scope is active in %s on line %d diff --git a/Zend/tests/closure_047.phpt b/Zend/tests/closure_047.phpt new file mode 100644 index 0000000000..2377bef6b7 --- /dev/null +++ b/Zend/tests/closure_047.phpt @@ -0,0 +1,26 @@ +--TEST-- +Closure 047: Use in preg_replace_callback() using variables by reference +--FILE-- +<?php + +function replace_variables($text, $params) { + + preg_replace_callback( '/(\?)/', function($matches) use (&$params, &$text) { + + $text = preg_replace( '/(\?)/', array_shift( $params ), $text, 1 ); + + }, $text ); + + return $text; +} + +echo replace_variables('a=?', array('0')) . "\n"; +echo replace_variables('a=?, b=?', array('0', '1')) . "\n"; +echo replace_variables('a=?, b=?, c=?', array('0', '1', '2')) . "\n"; +echo "Done\n"; +?> +--EXPECT-- +a=0 +a=0, b=1 +a=0, b=1, c=2 +Done diff --git a/Zend/tests/closure_048.phpt b/Zend/tests/closure_048.phpt new file mode 100644 index 0000000000..40f2e2fbac --- /dev/null +++ b/Zend/tests/closure_048.phpt @@ -0,0 +1,26 @@ +--TEST-- +Closure 048: Use in preg_replace_callback() using variables by reference +--FILE-- +<?php + +function replace_variables($text, $params) { + + $c = function($matches) use (&$params, &$text) { + $text = preg_replace( '/(\?)/', array_shift( $params ), $text, 1 ); + }; + + preg_replace_callback( '/(\?)/', $c, $text ); + + return $text; +} + +echo replace_variables('a=?', array('0')) . "\n"; +echo replace_variables('a=?, b=?', array('0', '1')) . "\n"; +echo replace_variables('a=?, b=?, c=?', array('0', '1', '2')) . "\n"; +echo "Done\n"; +?> +--EXPECT-- +a=0 +a=0, b=1 +a=0, b=1, c=2 +Done diff --git a/Zend/tests/const_dereference_001.phpt b/Zend/tests/const_dereference_001.phpt new file mode 100644 index 0000000000..5fe6e4d433 --- /dev/null +++ b/Zend/tests/const_dereference_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Const array deference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump(array(1, 2, 3, 4,) [3]); +var_dump(array(1, 2, 3, 4,) ['foo']); +var_dump(array(array(1,2,3), array(4, 5, 6))[1][2]); + +foreach (array(array(1, 2, 3))[0] as $var) { + echo $var; +} +?> +--EXPECTF-- +int(4) + +Notice: Undefined index: foo in %sconst_dereference_001.php on line %d +NULL +int(6) +123 diff --git a/Zend/tests/const_dereference_002.phpt b/Zend/tests/const_dereference_002.phpt new file mode 100644 index 0000000000..ff89519755 --- /dev/null +++ b/Zend/tests/const_dereference_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +Const string dereference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump("foobar"[3]); +var_dump("foobar"[2][0]); +var_dump("foobar"["foo"]["bar"]); + +--EXPECTF-- +string(1) "b" +string(1) "o" + +Warning: Illegal string offset 'foo' in %sconst_dereference_002.php on line %d + +Warning: Illegal string offset 'bar' in %sconst_dereference_002.php on line %d +string(1) "f" diff --git a/Zend/tests/const_dereference_003.phpt b/Zend/tests/const_dereference_003.phpt new file mode 100644 index 0000000000..810ad14b8e --- /dev/null +++ b/Zend/tests/const_dereference_003.phpt @@ -0,0 +1,21 @@ +--TEST-- +Const array deference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump([1, 2, 3, 4,][3]); +var_dump([1, 2, 3, 4]['foo']); +var_dump([array(1,2,3), [4, 5, 6]][1][2]); + +foreach (array([1, 2, 3])[0] as $var) { + echo $var; +} +?> +--EXPECTF-- +int(4) + +Notice: Undefined index: foo in %sconst_dereference_003.php on line %d +NULL +int(6) +123 diff --git a/Zend/tests/dval_to_lval_32.phpt b/Zend/tests/dval_to_lval_32.phpt new file mode 100644 index 0000000000..f2acc39f51 --- /dev/null +++ b/Zend/tests/dval_to_lval_32.phpt @@ -0,0 +1,32 @@ +--TEST-- +zend_dval_to_lval preserves low bits (32 bit long) +--SKIPIF-- +<?php +if (PHP_INT_SIZE != 4) + die("skip for machines with 32-bit longs"); +?> +--FILE-- +<?php + /* test doubles around -4e21 */ + $values = [ + -4000000000000001048576., + -4000000000000000524288., + -4000000000000000000000., + -3999999999999999475712., + -3999999999999998951424., + ]; + /* see if we're rounding negative numbers right */ + $values[] = -2147483649.8; + + foreach ($values as $v) { + var_dump((int)$v); + } + +?> +--EXPECT-- +int(-2056257536) +int(-2055733248) +int(-2055208960) +int(-2054684672) +int(-2054160384) +int(2147483647) diff --git a/Zend/tests/dval_to_lval_64.phpt b/Zend/tests/dval_to_lval_64.phpt new file mode 100644 index 0000000000..da7f56d81c --- /dev/null +++ b/Zend/tests/dval_to_lval_64.phpt @@ -0,0 +1,29 @@ +--TEST-- +zend_dval_to_lval preserves low bits (64 bit long) +--SKIPIF-- +<?php +if (PHP_INT_SIZE != 8) + die("skip for machines with 64-bit longs"); +?> +--FILE-- +<?php + /* test doubles around -4e21 */ + $values = [ + -4000000000000001048576., + -4000000000000000524288., + -4000000000000000000000., + -3999999999999999475712., + -3999999999999998951424., + ]; + + foreach ($values as $v) { + var_dump((int)$v); + } + +?> +--EXPECT-- +int(2943463994971652096) +int(2943463994972176384) +int(2943463994972700672) +int(2943463994973224960) +int(2943463994973749248) diff --git a/Zend/tests/empty_with_expr.phpt b/Zend/tests/empty_with_expr.phpt new file mode 100644 index 0000000000..582eb3d2d0 --- /dev/null +++ b/Zend/tests/empty_with_expr.phpt @@ -0,0 +1,32 @@ +--TEST-- +empty() with arbitrary expressions +--FILE-- +<?php + +function getEmptyArray() { return []; } +function getNonEmptyArray() { return [1, 2, 3]; } + +var_dump(empty([])); +var_dump(empty([1, 2, 3])); + +var_dump(empty(getEmptyArray())); +var_dump(empty(getNonEmptyArray())); + +var_dump(empty([] + [])); +var_dump(empty([1, 2, 3] + [])); + +var_dump(empty("string")); +var_dump(empty("")); +var_dump(empty(true)); +var_dump(empty(false)); +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) diff --git a/Zend/tests/errmsg_043.phpt b/Zend/tests/errmsg_043.phpt deleted file mode 100644 index 3de8bc2062..0000000000 --- a/Zend/tests/errmsg_043.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -errmsg: cannot create references to temp array ---FILE-- -<?php - -foreach (array(1,2,3) as $k=>&$v) { -} - -echo "Done\n"; -?> ---EXPECTF-- -Fatal error: Cannot create references to elements of a temporary array expression in %s on line %d diff --git a/Zend/tests/exception_before_fatal.phpt b/Zend/tests/exception_before_fatal.phpt new file mode 100644 index 0000000000..608d65094b --- /dev/null +++ b/Zend/tests/exception_before_fatal.phpt @@ -0,0 +1,64 @@ +--TEST-- +Exceptions before fatal error +--FILE-- +<?php +function exception_error_handler($code, $msg) { + throw new Exception($msg); +} + +set_error_handler("exception_error_handler"); + +try { + $foo->a(); +} catch(Exception $e) { + var_dump($e->getMessage()); +} + +try { + new $foo(); +} catch(Exception $e) { + var_dump($e->getMessage()); +} + +try { + throw $foo; +} catch(Exception $e) { + var_dump($e->getMessage()); +} + +try { + $foo(); +} catch(Exception $e) { + var_dump($e->getMessage()); +} + +try { + $foo::b(); +} catch(Exception $e) { + var_dump($e->getMessage()); +} + + +try { + $b = clone $foo; +} catch(Exception $e) { + var_dump($e->getMessage()); +} + +class b { +} + +try { + b::$foo(); +} catch(Exception $e) { + var_dump($e->getMessage()); +} +?> +--EXPECT-- +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" +string(23) "Undefined variable: foo" diff --git a/Zend/tests/foreach_list_001.phpt b/Zend/tests/foreach_list_001.phpt new file mode 100644 index 0000000000..a318f1aad9 --- /dev/null +++ b/Zend/tests/foreach_list_001.phpt @@ -0,0 +1,43 @@ +--TEST-- +foreach with list syntax +--FILE-- +<?php + +foreach(array(array(1,2), array(3,4)) as list($a, $b)) { + var_dump($a . $b); +} + +$array = array( + array('a', 'b'), + array('c', 'd'), +); + +foreach ($array as list($a, $b)) { + var_dump($a . $b); +} + + +$multi = array( + array(array(1,2), array(3,4)), + array(array(5,6), array(7,8)), +); + +foreach ($multi as list(list($a, $b), list($c, $d))) { + var_dump($a . $b . $c . $d); +} + +foreach ($multi as $key => list(list($a, $b), list($c, $d))) { + var_dump($key . $a . $b . $c . $d); +} + + +?> +--EXPECT-- +string(2) "12" +string(2) "34" +string(2) "ab" +string(2) "cd" +string(4) "1234" +string(4) "5678" +string(5) "01234" +string(5) "15678" diff --git a/Zend/tests/foreach_list_002.phpt b/Zend/tests/foreach_list_002.phpt new file mode 100644 index 0000000000..251870ba09 --- /dev/null +++ b/Zend/tests/foreach_list_002.phpt @@ -0,0 +1,26 @@ +--TEST-- +foreach with freak lists +--FILE-- +<?php + +foreach (array(array(1,2), array(3,4)) as list($a, )) { + var_dump($a); +} + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as list(list(), $a)) { + var_dump($a); +} + +?> +--EXPECTF-- +int(1) +int(3) +string(1) "b" + +Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d +string(0) "" + +Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d +string(0) "" diff --git a/Zend/tests/foreach_list_003.phpt b/Zend/tests/foreach_list_003.phpt new file mode 100644 index 0000000000..8674ecd754 --- /dev/null +++ b/Zend/tests/foreach_list_003.phpt @@ -0,0 +1,13 @@ +--TEST-- +foreach with list key +--FILE-- +<?php + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as list($key) => list(list(), $a)) { +} + +?> +--EXPECTF-- +Fatal error: Cannot use list as key element in %sforeach_list_003.php on line %d diff --git a/Zend/tests/foreach_list_004.phpt b/Zend/tests/foreach_list_004.phpt new file mode 100644 index 0000000000..fd48e8a1f3 --- /dev/null +++ b/Zend/tests/foreach_list_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +foreach with empty list +--FILE-- +<?php + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as $key => list()) { +} + +?> +--EXPECTF-- +Fatal error: Cannot use empty list in %sforeach_list_004.php on line %d diff --git a/Zend/tests/foreach_temp_array_expr_with_refs.phpt b/Zend/tests/foreach_temp_array_expr_with_refs.phpt new file mode 100644 index 0000000000..8978b7b011 --- /dev/null +++ b/Zend/tests/foreach_temp_array_expr_with_refs.phpt @@ -0,0 +1,18 @@ +--TEST-- +Temporary array expressions can be iterated by reference +--FILE-- +<?php + +$a = 'a'; +$b = 'b'; + +foreach ([&$a, &$b] as &$value) { + $value .= '-foo'; +} + +var_dump($a, $b); + +?> +--EXPECT-- +string(5) "a-foo" +string(5) "b-foo" diff --git a/Zend/tests/generators/auto_incrementing_keys.phpt b/Zend/tests/generators/auto_incrementing_keys.phpt new file mode 100644 index 0000000000..acfb2f2ce0 --- /dev/null +++ b/Zend/tests/generators/auto_incrementing_keys.phpt @@ -0,0 +1,22 @@ +--TEST-- +Generator keys are auto-incrementing by default +--FILE-- +<?php + +function gen() { + yield 'foo'; + yield 'bar'; + yield 5 => 'rab'; + yield 'oof'; +} + +foreach (gen() as $k => $v) { + echo $k, ' => ', $v, "\n"; +} + +?> +--EXPECT-- +0 => foo +1 => bar +5 => rab +6 => oof diff --git a/Zend/tests/generators/backtrace.phpt b/Zend/tests/generators/backtrace.phpt new file mode 100644 index 0000000000..5fed1d467e --- /dev/null +++ b/Zend/tests/generators/backtrace.phpt @@ -0,0 +1,27 @@ +--TEST-- +Printing the stack trace in a generator +--FILE-- +<?php + +function f1() { + debug_print_backtrace(); +} + +function f2($arg1, $arg2) { + f1(); + yield; // force generator +} + +function f3($gen) { + $gen->rewind(); // trigger run +} + +$gen = f2('foo', 'bar'); +f3($gen); + +?> +--EXPECTF-- +#0 f1() called at [%s:%d] +#1 f2(foo, bar) +#2 Generator->rewind() called at [%s:%d] +#3 f3(Generator Object ()) called at [%s:%d] diff --git a/Zend/tests/generators/bug63066.phpt b/Zend/tests/generators/bug63066.phpt new file mode 100644 index 0000000000..8c4c8b4a84 --- /dev/null +++ b/Zend/tests/generators/bug63066.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #63066 (Calling an undefined method in a generator results in a seg fault) +--FILE-- +<?php +function gen($o) +{ + yield 'foo'; + $o->fatalError(); +} + +foreach(gen(new stdClass()) as $value) + echo $value, "\n"; +--EXPECTF-- +foo + +Fatal error: Call to undefined method stdClass::fatalError() in %sbug63066.php on line 5 diff --git a/Zend/tests/generators/bug65035.phpt b/Zend/tests/generators/bug65035.phpt new file mode 100644 index 0000000000..18276cc23a --- /dev/null +++ b/Zend/tests/generators/bug65035.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #65035: yield / exit segfault +--FILE-- +<?php + +function gen() { + fn(); + yield; +} + +function fn() { + exit('Done'); +} + +$gen = gen(); +$gen->current(); + +?> +--EXPECT-- +Done diff --git a/Zend/tests/generators/bug65161.phpt b/Zend/tests/generators/bug65161.phpt new file mode 100644 index 0000000000..215c1880e3 --- /dev/null +++ b/Zend/tests/generators/bug65161.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #65161: Generator + autoload + syntax error = segfault +--FILE-- +<?php + +function autoload() { + foo(); +} +spl_autoload_register('autoload'); + +function testGenerator() { + new SyntaxError('param'); + yield; +} + +foreach (testGenerator() as $i); + +?> +--EXPECTF-- +Fatal error: Call to undefined function foo() in %s on line %d diff --git a/Zend/tests/generators/bug66041.phpt b/Zend/tests/generators/bug66041.phpt new file mode 100644 index 0000000000..d944224134 --- /dev/null +++ b/Zend/tests/generators/bug66041.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #66041: list() fails to unpack yielded ArrayAccess object +--FILE-- +<?php +function dumpElement() { + list($value) = yield; + var_dump($value); +}; + +$fixedArray = new SplFixedArray(1); +$fixedArray[0] = 'the element'; + +$generator = dumpElement(); +$generator->send($fixedArray); +?> +--EXPECT-- +string(11) "the element" diff --git a/Zend/tests/generators/clone.phpt b/Zend/tests/generators/clone.phpt new file mode 100644 index 0000000000..22f4428121 --- /dev/null +++ b/Zend/tests/generators/clone.phpt @@ -0,0 +1,15 @@ +--TEST-- +Generators cannot be cloned +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +clone $gen; + +?> +--EXPECTF-- +Fatal error: Trying to clone an uncloneable object of class Generator in %s on line %d diff --git a/Zend/tests/generators/dynamic_call.phpt b/Zend/tests/generators/dynamic_call.phpt new file mode 100644 index 0000000000..d564540952 --- /dev/null +++ b/Zend/tests/generators/dynamic_call.phpt @@ -0,0 +1,19 @@ +--TEST-- +It's possible to invoke a generator dynamically +--FILE-- +<?php + +function gen($foo, $bar) { + yield $foo; + yield $bar; +} + +$gen = call_user_func('gen', 'bar', 'foo'); +foreach ($gen as $value) { + var_dump($value); +} + +?> +--EXPECT-- +string(3) "bar" +string(3) "foo" diff --git a/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt new file mode 100644 index 0000000000..ad618d20ba --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt @@ -0,0 +1,13 @@ +--TEST-- +Generators cannot return values (even before yield) +--FILE-- +<?php + +function gen() { + return $foo; + yield; +} + +?> +--EXPECTF-- +Fatal error: Generators cannot return values using "return" in %s on line 4 diff --git a/Zend/tests/generators/errors/generator_cannot_return_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_error.phpt new file mode 100644 index 0000000000..51149062a7 --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_error.phpt @@ -0,0 +1,13 @@ +--TEST-- +Generators cannot return values +--FILE-- +<?php + +function gen() { + yield; + return $abc; +} + +?> +--EXPECTF-- +Fatal error: Generators cannot return values using "return" in %s on line 5 diff --git a/Zend/tests/generators/errors/generator_extend_error.phpt b/Zend/tests/generators/errors/generator_extend_error.phpt new file mode 100644 index 0000000000..550f16ae03 --- /dev/null +++ b/Zend/tests/generators/errors/generator_extend_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +The Generator class cannot be extended +--FILE-- +<?php + +class ExtendedGenerator extends Generator { } + +?> +--EXPECTF-- +Fatal error: Class ExtendedGenerator may not inherit from final class (Generator) in %s on line %d diff --git a/Zend/tests/generators/errors/generator_instantiate_error.phpt b/Zend/tests/generators/errors/generator_instantiate_error.phpt new file mode 100644 index 0000000000..f8941c087a --- /dev/null +++ b/Zend/tests/generators/errors/generator_instantiate_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +It's not possible to directly instantiate the Generator class +--FILE-- +<?php + +new Generator; + +?> +--EXPECTF-- +Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %s on line %d diff --git a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt new file mode 100644 index 0000000000..de5b22f6ba --- /dev/null +++ b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt @@ -0,0 +1,18 @@ +--TEST-- +Non-ref generators cannot be iterated by-ref +--FILE-- +<?php + +function gen() { yield; } + +$gen = gen(); +foreach ($gen as &$value) { } + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/errors/resume_running_generator_error.phpt b/Zend/tests/generators/errors/resume_running_generator_error.phpt new file mode 100644 index 0000000000..567d72f3f9 --- /dev/null +++ b/Zend/tests/generators/errors/resume_running_generator_error.phpt @@ -0,0 +1,17 @@ +--TEST-- +It is not possible to resume an already running generator +--FILE-- +<?php + +function gen() { + $gen = yield; + $gen->next(); +} + +$gen = gen(); +$gen->send($gen); +$gen->next(); + +?> +--EXPECTF-- +Fatal error: Cannot resume an already running generator in %s on line %d diff --git a/Zend/tests/generators/errors/serialize_unserialize_error.phpt b/Zend/tests/generators/errors/serialize_unserialize_error.phpt new file mode 100644 index 0000000000..aa2d4693f7 --- /dev/null +++ b/Zend/tests/generators/errors/serialize_unserialize_error.phpt @@ -0,0 +1,44 @@ +--TEST-- +Generators can't be serialized or unserialized +--FILE-- +<?php + +function gen() { yield; } + +$gen = gen(); + +try { + serialize($gen); +} catch (Exception $e) { + echo $e, "\n\n"; +} + +try { + var_dump(unserialize('O:9:"Generator":0:{}')); +} catch (Exception $e) { + echo $e, "\n\n"; +} + +try { + var_dump(unserialize('C:9:"Generator":0:{}')); +} catch (Exception $e) { + echo $e; +} + +?> +--EXPECTF-- +exception 'Exception' with message 'Serialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): serialize(Object(Generator)) +#1 {main} + +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 [internal function]: Generator->__wakeup() +#1 %s(%d): unserialize('O:9:"Generator"...') +#2 {main} + +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): unserialize('C:9:"Generator"...') +#1 {main} diff --git a/Zend/tests/generators/errors/yield_const_by_ref_error.phpt b/Zend/tests/generators/errors/yield_const_by_ref_error.phpt new file mode 100644 index 0000000000..e79f83e24a --- /dev/null +++ b/Zend/tests/generators/errors/yield_const_by_ref_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +A notice is thrown when yielding a constant value by reference +--FILE-- +<?php + +function &gen() { + yield "foo"; +} + +$gen = gen(); +var_dump($gen->current()); + +?> +--EXPECTF-- +Notice: Only variable references should be yielded by reference in %s on line %d +string(3) "foo" diff --git a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt new file mode 100644 index 0000000000..aada676a68 --- /dev/null +++ b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt @@ -0,0 +1,29 @@ +--TEST-- +yield cannot be used in a finally block when the generator is force-closed +--FILE-- +<?php + +function gen() { + try { + echo "before yield\n"; + yield; + echo "after yield\n"; + } finally { + echo "before yield in finally\n"; + yield; + echo "after yield in finally\n"; + } + + echo "after finally\n"; +} + +$gen = gen(); +$gen->rewind(); +unset($gen); + +?> +--EXPECTF-- +before yield +before yield in finally + +Fatal error: Cannot yield from finally in a force-closed generator in %s on line %d diff --git a/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt b/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt new file mode 100644 index 0000000000..4b8563331c --- /dev/null +++ b/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt @@ -0,0 +1,20 @@ +--TEST-- +Yielding the result of a non-ref function call throw a notice +--FILE-- +<?php + +function foo() { + return "bar"; +} + +function &gen() { + yield foo(); +} + +$gen = gen(); +var_dump($gen->current()); + +?> +--EXPECTF-- +Notice: Only variable references should be yielded by reference in %s on line %d +string(3) "bar" diff --git a/Zend/tests/generators/errors/yield_outside_function_error.phpt b/Zend/tests/generators/errors/yield_outside_function_error.phpt new file mode 100644 index 0000000000..f999c1c03b --- /dev/null +++ b/Zend/tests/generators/errors/yield_outside_function_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Yield cannot be used outside of functions +--FILE-- +<?php + +yield "Test"; + +?> +--EXPECTF-- +Fatal error: The "yield" expression can only be used inside a function in %s on line %d diff --git a/Zend/tests/generators/fibonacci.phpt b/Zend/tests/generators/fibonacci.phpt new file mode 100644 index 0000000000..35b31352ff --- /dev/null +++ b/Zend/tests/generators/fibonacci.phpt @@ -0,0 +1,36 @@ +--TEST-- +Creating an infinite fibonacci list using a generator +--FILE-- +<?php + +function fib() { + list($a, $b) = [1, 1]; + while (true) { + yield $b; + list($a, $b) = [$b, $a + $b]; + } +} + +foreach (fib() as $n) { + if ($n > 1000) break; + + var_dump($n); +} + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(5) +int(8) +int(13) +int(21) +int(34) +int(55) +int(89) +int(144) +int(233) +int(377) +int(610) +int(987) diff --git a/Zend/tests/generators/finally/finally_ran_on_close.phpt b/Zend/tests/generators/finally/finally_ran_on_close.phpt new file mode 100644 index 0000000000..04a0561c87 --- /dev/null +++ b/Zend/tests/generators/finally/finally_ran_on_close.phpt @@ -0,0 +1,30 @@ +--TEST-- +finally is run even if a generator is closed mid-execution +--FILE-- +<?php + +function gen() { + try { + try { + echo "before yield\n"; + yield; + echo "after yield\n"; + } finally { + echo "finally run\n"; + } + echo "code after finally\n"; + } finally { + echo "second finally run\n"; + } + echo "code after second finally\n"; +} + +$gen = gen(); +$gen->rewind(); +unset($gen); + +?> +--EXPECT-- +before yield +finally run +second finally run diff --git a/Zend/tests/generators/finally/return_return.phpt b/Zend/tests/generators/finally/return_return.phpt new file mode 100644 index 0000000000..02e2739de7 --- /dev/null +++ b/Zend/tests/generators/finally/return_return.phpt @@ -0,0 +1,33 @@ +--TEST-- +try { return } finally { return } in generator +--FILE-- +<?php + +function gen() { + try { + try { + echo "before return\n"; + return; + echo "after return\n"; + } finally { + echo "before return in inner finally\n"; + return; + echo "after return in inner finally\n"; + } + } finally { + echo "outer finally run\n"; + } + + echo "code after finally\n"; + + yield; // force generator +} + +$gen = gen(); +$gen->rewind(); // force run + +?> +--EXPECTF-- +before return +before return in inner finally +outer finally run diff --git a/Zend/tests/generators/finally/return_yield.phpt b/Zend/tests/generators/finally/return_yield.phpt new file mode 100644 index 0000000000..c4f3485987 --- /dev/null +++ b/Zend/tests/generators/finally/return_yield.phpt @@ -0,0 +1,18 @@ +--TEST-- +try { return } finally { yield } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + return; + } finally { + yield $i; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECT-- +1 diff --git a/Zend/tests/generators/finally/run_on_dtor.phpt b/Zend/tests/generators/finally/run_on_dtor.phpt new file mode 100644 index 0000000000..35f8f4e0de --- /dev/null +++ b/Zend/tests/generators/finally/run_on_dtor.phpt @@ -0,0 +1,22 @@ +--TEST-- +finally is run on object dtor, not free +--FILE-- +<?php + +function gen() { + try { + yield; + } finally { + var_dump($_GET); + } +} + +$gen = gen(); +$gen->rewind(); + +set_error_handler(function() use($gen) {}); + +?> +--EXPECT-- +array(0) { +} diff --git a/Zend/tests/generators/finally/throw_yield.phpt b/Zend/tests/generators/finally/throw_yield.phpt new file mode 100644 index 0000000000..2013c3ee14 --- /dev/null +++ b/Zend/tests/generators/finally/throw_yield.phpt @@ -0,0 +1,24 @@ +--TEST-- +try { throw } finally { yield } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + throw new Exception; + } finally { + yield $i; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECTF-- +1 + +Fatal error: Uncaught exception 'Exception' in %s:%d +Stack trace: +#0 %s(%d): foo(1, 5) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/finally/yield_return.phpt b/Zend/tests/generators/finally/yield_return.phpt new file mode 100644 index 0000000000..e3e1bec357 --- /dev/null +++ b/Zend/tests/generators/finally/yield_return.phpt @@ -0,0 +1,18 @@ +--TEST-- +try { yield } finally { return } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + yield $i; + } finally { + return; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECT-- +1 diff --git a/Zend/tests/generators/finally/yield_throw.phpt b/Zend/tests/generators/finally/yield_throw.phpt new file mode 100644 index 0000000000..0ead4501af --- /dev/null +++ b/Zend/tests/generators/finally/yield_throw.phpt @@ -0,0 +1,24 @@ +--TEST-- +try { yield } finally { throw } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + yield $i; + } finally { + throw new Exception; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECTF-- +1 + +Fatal error: Uncaught exception 'Exception' in %s:%d +Stack trace: +#0 %s(%d): foo(1, 5) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/finally/yield_yield.phpt b/Zend/tests/generators/finally/yield_yield.phpt new file mode 100644 index 0000000000..76610ef1a4 --- /dev/null +++ b/Zend/tests/generators/finally/yield_yield.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try { yield } finally { yield } +--FILE-- +<?php + +function foo() { + try { + echo "1"; + yield "2"; + echo "3"; + } finally { + echo "4"; + yield "5"; + echo "6"; + } + echo "7"; +} +foreach (foo() as $x) { + echo $x; +} +--EXPECT-- +1234567 diff --git a/Zend/tests/generators/func_get_args.phpt b/Zend/tests/generators/func_get_args.phpt new file mode 100644 index 0000000000..f8d3fa7c14 --- /dev/null +++ b/Zend/tests/generators/func_get_args.phpt @@ -0,0 +1,21 @@ +--TEST-- +func_get_args() can be used inside generator functions +--FILE-- +<?php + +function gen() { + var_dump(func_get_args()); + yield; // trigger generator +} + +$gen = gen("foo", "bar"); +$gen->rewind(); + +?> +--EXPECT-- +array(2) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" +} diff --git a/Zend/tests/generators/generator_closure.phpt b/Zend/tests/generators/generator_closure.phpt new file mode 100644 index 0000000000..bf80066015 --- /dev/null +++ b/Zend/tests/generators/generator_closure.phpt @@ -0,0 +1,20 @@ +--TEST-- +Closures can be generators +--FILE-- +<?php + +$genFactory = function() { + yield 1; + yield 2; + yield 3; +}; + +foreach ($genFactory() as $value) { + var_dump($value); +} + +?> +--EXPECT-- +int(1) +int(2) +int(3) diff --git a/Zend/tests/generators/generator_closure_with_this.phpt b/Zend/tests/generators/generator_closure_with_this.phpt new file mode 100644 index 0000000000..d5a4861e80 --- /dev/null +++ b/Zend/tests/generators/generator_closure_with_this.phpt @@ -0,0 +1,20 @@ +--TEST-- +Non-static closures can be generators +--FILE-- +<?php + +class Test { + public function getGenFactory() { + return function() { + yield $this; + }; + } +} + +$genFactory = (new Test)->getGenFactory(); +var_dump($genFactory()->current()); + +?> +--EXPECT-- +object(Test)#1 (0) { +} diff --git a/Zend/tests/generators/generator_in_multipleiterator.phpt b/Zend/tests/generators/generator_in_multipleiterator.phpt new file mode 100644 index 0000000000..611dbc9652 --- /dev/null +++ b/Zend/tests/generators/generator_in_multipleiterator.phpt @@ -0,0 +1,37 @@ +--TEST-- +Generators work properly in MultipleIterator +--FILE-- +<?php + +function gen1() { + yield 'a'; + yield 'aa'; +} + +function gen2() { + yield 'b'; + yield 'bb'; +} + +$it = new MultipleIterator; +$it->attachIterator(gen1()); +$it->attachIterator(gen2()); + +foreach ($it as $values) { + var_dump($values); +} + +?> +--EXPECT-- +array(2) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" +} +array(2) { + [0]=> + string(2) "aa" + [1]=> + string(2) "bb" +} diff --git a/Zend/tests/generators/generator_method.phpt b/Zend/tests/generators/generator_method.phpt new file mode 100644 index 0000000000..b8196c171e --- /dev/null +++ b/Zend/tests/generators/generator_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +Methods can be generators +--FILE-- +<?php + +class Test implements IteratorAggregate { + protected $data; + + public function __construct(array $data) { + $this->data = $data; + } + + public function getIterator() { + foreach ($this->data as $value) { + yield $value; + } + } +} + +$test = new Test(['foo', 'bar', 'baz']); +foreach ($test as $value) { + var_dump($value); +} + +?> +--EXPECT-- +string(3) "foo" +string(3) "bar" +string(3) "baz" diff --git a/Zend/tests/generators/generator_method_by_ref.phpt b/Zend/tests/generators/generator_method_by_ref.phpt new file mode 100644 index 0000000000..cfe52fe67f --- /dev/null +++ b/Zend/tests/generators/generator_method_by_ref.phpt @@ -0,0 +1,44 @@ +--TEST-- +Generator methods can yield by reference +--FILE-- +<?php + +class Test implements IteratorAggregate { + protected $data; + + public function __construct(array $data) { + $this->data = $data; + } + + public function getData() { + return $this->data; + } + + public function &getIterator() { + foreach ($this->data as $key => &$value) { + yield $key => $value; + } + } +} + +$test = new Test([1, 2, 3, 4, 5]); +foreach ($test as &$value) { + $value *= -1; +} + +var_dump($test->getData()); + +?> +--EXPECT-- +array(5) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + int(-3) + [3]=> + int(-4) + [4]=> + &int(-5) +} diff --git a/Zend/tests/generators/generator_returns_generator.phpt b/Zend/tests/generators/generator_returns_generator.phpt new file mode 100644 index 0000000000..ad332a3be9 --- /dev/null +++ b/Zend/tests/generators/generator_returns_generator.phpt @@ -0,0 +1,18 @@ +--TEST-- +A generator function returns a Generator object +--FILE-- +<?php + +function gen() { + // execution is suspended here, so the following never gets run: + echo "Foo"; + // trigger a generator + yield; +} + +$generator = gen(); +var_dump($generator instanceof Generator); + +?> +--EXPECT-- +bool(true) diff --git a/Zend/tests/generators/generator_rewind.phpt b/Zend/tests/generators/generator_rewind.phpt new file mode 100644 index 0000000000..c4b5bbbdf4 --- /dev/null +++ b/Zend/tests/generators/generator_rewind.phpt @@ -0,0 +1,62 @@ +--TEST-- +A generator can only be rewinded before or at the first yield +--FILE-- +<?php + +function gen() { + echo "before yield\n"; + yield; + echo "after yield\n"; + yield; +} + +$gen = gen(); +$gen->rewind(); +$gen->rewind(); +$gen->next(); + +try { + $gen->rewind(); +} catch (Exception $e) { + echo "\n", $e, "\n\n"; +} + +function &gen2() { + $foo = 'bar'; + yield $foo; + yield $foo; +} + +$gen = gen2(); +foreach ($gen as $v) { } +try { + foreach ($gen as $v) { } +} catch (Exception $e) { + echo $e, "\n\n"; +} + +function gen3() { + echo "in generator\n"; + + if (false) yield; +} + +$gen = gen3(); +$gen->rewind(); + +?> +--EXPECTF-- +before yield +after yield + +exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d +Stack trace: +#0 %s(%d): Generator->rewind() +#1 {main} + +exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + +in generator diff --git a/Zend/tests/generators/generator_send.phpt b/Zend/tests/generators/generator_send.phpt new file mode 100644 index 0000000000..074d815389 --- /dev/null +++ b/Zend/tests/generators/generator_send.phpt @@ -0,0 +1,22 @@ +--TEST-- +Values can be sent back to the generator +--FILE-- +<?php + +function gen() { + var_dump(yield "yield foo"); + var_dump(yield "yield bar"); +} + +$gen = gen(); +var_dump($gen->current()); +$gen->send("send bar"); +var_dump($gen->current()); +$gen->send("send foo"); + +?> +--EXPECT-- +string(9) "yield foo" +string(8) "send bar" +string(9) "yield bar" +string(8) "send foo" diff --git a/Zend/tests/generators/generator_static_method.phpt b/Zend/tests/generators/generator_static_method.phpt new file mode 100644 index 0000000000..cd9b450a76 --- /dev/null +++ b/Zend/tests/generators/generator_static_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +A static method can be a generator +--FILE-- +<?php + +class Test { + public static function gen() { + var_dump(get_class()); + var_dump(get_called_class()); + yield 1; + yield 2; + yield 3; + } +} + +class ExtendedTest extends Test { +} + +foreach (ExtendedTest::gen() as $i) { + var_dump($i); +} + +?> +--EXPECT-- +string(4) "Test" +string(12) "ExtendedTest" +int(1) +int(2) +int(3) diff --git a/Zend/tests/generators/generator_throwing_during_function_call.phpt b/Zend/tests/generators/generator_throwing_during_function_call.phpt new file mode 100644 index 0000000000..bd0d2448b7 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_during_function_call.phpt @@ -0,0 +1,32 @@ +--TEST-- +Stack is cleaned up properly when an exception is thrown during a function call +--FILE-- +<?php + +function throwException() { + throw new Exception('test'); +} + +function gen() { + yield 'foo'; + strlen("foo", "bar", throwException()); + yield 'bar'; +} + +$gen = gen(); + +var_dump($gen->current()); + +try { + $gen->next(); +} catch (Exception $e) { + echo 'Caught exception with message "', $e->getMessage(), '"', "\n"; +} + +var_dump($gen->current()); + +?> +--EXPECT-- +string(3) "foo" +Caught exception with message "test" +NULL diff --git a/Zend/tests/generators/generator_throwing_exception.phpt b/Zend/tests/generators/generator_throwing_exception.phpt new file mode 100644 index 0000000000..f537c3fc77 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_exception.phpt @@ -0,0 +1,28 @@ +--TEST-- +Generators can throw exceptions +--FILE-- +<?php + +function gen() { + yield 'foo'; + throw new Exception('test'); + yield 'bar'; +} + +$gen = gen(); + +var_dump($gen->current()); + +try { + $gen->next(); +} catch (Exception $e) { + echo 'Caught exception with message "', $e->getMessage(), '"', "\n"; +} + +var_dump($gen->current()); + +?> +--EXPECT-- +string(3) "foo" +Caught exception with message "test" +NULL diff --git a/Zend/tests/generators/generator_throwing_in_foreach.phpt b/Zend/tests/generators/generator_throwing_in_foreach.phpt new file mode 100644 index 0000000000..dbf20c2ca1 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_in_foreach.phpt @@ -0,0 +1,20 @@ +--TEST-- +Exceptions throwing by generators during foreach iteration are properly handled +--FILE-- +<?php + +function gen() { + throw new Exception("foo"); + yield; // force generator +} + +foreach (gen() as $value) { } + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'foo' in %s:%d +Stack trace: +#0 %s(%d): gen() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/generator_with_keys.phpt b/Zend/tests/generators/generator_with_keys.phpt new file mode 100644 index 0000000000..efb377679e --- /dev/null +++ b/Zend/tests/generators/generator_with_keys.phpt @@ -0,0 +1,26 @@ +--TEST-- +Generators can also yield keys +--FILE-- +<?php + +function reverse(array $array) { + end($array); + while (null !== $key = key($array)) { + yield $key => current($array); + prev($array); + } +} + +$array = [ + 'foo' => 'bar', + 'bar' => 'foo', +]; + +foreach (reverse($array) as $key => $value) { + echo $key, ' => ', $value, "\n"; +} + +?> +--EXPECT-- +bar => foo +foo => bar diff --git a/Zend/tests/generators/generator_with_nonscalar_keys.phpt b/Zend/tests/generators/generator_with_nonscalar_keys.phpt new file mode 100644 index 0000000000..5ae55a1be0 --- /dev/null +++ b/Zend/tests/generators/generator_with_nonscalar_keys.phpt @@ -0,0 +1,52 @@ +--TEST-- +Generators can return non-scalar keys +--FILE-- +<?php + +function gen() { + yield [1, 2, 3] => [4, 5, 6]; + yield (object) ['a' => 'b'] => (object) ['b' => 'a']; + yield 3.14 => 2.73; + yield false => true; + yield true => false; + yield null => null; +} + +foreach (gen() as $k => $v) { + var_dump($k, $v); +} + +?> +--EXPECT-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(3) { + [0]=> + int(4) + [1]=> + int(5) + [2]=> + int(6) +} +object(stdClass)#3 (1) { + ["a"]=> + string(1) "b" +} +object(stdClass)#4 (1) { + ["b"]=> + string(1) "a" +} +float(3.14) +float(2.73) +bool(false) +bool(true) +bool(true) +bool(false) +NULL +NULL diff --git a/Zend/tests/generators/ignored_send_leak.phpt b/Zend/tests/generators/ignored_send_leak.phpt new file mode 100644 index 0000000000..352ba406ba --- /dev/null +++ b/Zend/tests/generators/ignored_send_leak.phpt @@ -0,0 +1,17 @@ +--TEST-- +Ignoring a sent value shouldn't leak memory +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->send(NULL); + +echo "DONE"; + +?> +--EXPECT-- +DONE diff --git a/Zend/tests/generators/nested_calls_with_die.phpt b/Zend/tests/generators/nested_calls_with_die.phpt new file mode 100644 index 0000000000..f43d89ba21 --- /dev/null +++ b/Zend/tests/generators/nested_calls_with_die.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test nested calls with die() in a generator +--FILE-- +<?php + +function gen() { + die('Test'); + yield; // force generator +} + +function function_with_3_args() { + $gen = gen(); + $gen->rewind(); +} + +function function_with_4_args() { + function_with_3_args(4, 5, 6); +} + +function outerGen() { + function_with_4_args(0, 1, 2, 3); + yield; // force generator +} + +$outerGen = outerGen(); +$outerGen->rewind(); + +?> +--EXPECT-- +Test diff --git a/Zend/tests/generators/nested_method_calls.phpt b/Zend/tests/generators/nested_method_calls.phpt new file mode 100644 index 0000000000..0d640b31c6 --- /dev/null +++ b/Zend/tests/generators/nested_method_calls.phpt @@ -0,0 +1,36 @@ +--TEST-- +Yield can be used in nested method calls +--FILE-- +<?php + +class A { + function foo() { + echo "Called A::foo\n"; + } +} + +class B { + function foo() { + echo "Called B::foo\n"; + } +} + +function gen($obj) { + $obj->foo($obj->foo(yield)); +} + +$g1 = gen(new A); +$g1->current(); + +$g2 = gen(new B); +$g2->current(); + +$g1->next(); +$g2->next(); + +?> +--EXPECT-- +Called A::foo +Called A::foo +Called B::foo +Called B::foo diff --git a/Zend/tests/generators/no_foreach_var_leaks.phpt b/Zend/tests/generators/no_foreach_var_leaks.phpt new file mode 100644 index 0000000000..62743895eb --- /dev/null +++ b/Zend/tests/generators/no_foreach_var_leaks.phpt @@ -0,0 +1,19 @@ +--TEST-- +foreach() (and other) variables aren't leaked on premature close +--FILE-- +<?php + +function gen(array $array) { + foreach ($array as $value) { + yield $value; + } +} + +$gen = gen(['Foo', 'Bar']); +var_dump($gen->current()); + +// generator is closed here, without running SWITCH_FREE + +?> +--EXPECT-- +string(3) "Foo" diff --git a/Zend/tests/generators/send_after_close.phpt b/Zend/tests/generators/send_after_close.phpt new file mode 100644 index 0000000000..806baf8cee --- /dev/null +++ b/Zend/tests/generators/send_after_close.phpt @@ -0,0 +1,14 @@ +--TEST-- +Calls to send() after close should do nothing +--FILE-- +<?php + +function gen() { var_dump(yield); } + +$gen = gen(); +$gen->send('foo'); +$gen->send('bar'); + +?> +--EXPECT-- +string(3) "foo" diff --git a/Zend/tests/generators/send_returns_current.phpt b/Zend/tests/generators/send_returns_current.phpt new file mode 100644 index 0000000000..27ba74bc1b --- /dev/null +++ b/Zend/tests/generators/send_returns_current.phpt @@ -0,0 +1,20 @@ +--TEST-- +$generator->send() returns the yielded value +--FILE-- +<?php + +function reverseEchoGenerator() { + $data = yield; + while (true) { + $data = (yield strrev($data)); + } +} + +$gen = reverseEchoGenerator(); +var_dump($gen->send('foo')); +var_dump($gen->send('bar')); + +?> +--EXPECT-- +string(3) "oof" +string(3) "rab" diff --git a/Zend/tests/generators/throw_already_closed.phpt b/Zend/tests/generators/throw_already_closed.phpt new file mode 100644 index 0000000000..e918e540ab --- /dev/null +++ b/Zend/tests/generators/throw_already_closed.phpt @@ -0,0 +1,23 @@ +--TEST-- +Generator::throw() on an already closed generator +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->next(); +$gen->next(); +var_dump($gen->valid()); +$gen->throw(new Exception('test')); + +?> +--EXPECTF-- +bool(false) + +Fatal error: Uncaught exception 'Exception' with message 'test' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/throw_caught.phpt b/Zend/tests/generators/throw_caught.phpt new file mode 100644 index 0000000000..c5e9d81ebc --- /dev/null +++ b/Zend/tests/generators/throw_caught.phpt @@ -0,0 +1,27 @@ +--TEST-- +Generator::throw() where the exception is caught in the generator +--FILE-- +<?php + +function gen() { + echo "before yield\n"; + try { + yield; + } catch (RuntimeException $e) { + echo $e, "\n\n"; + } + + yield 'result'; +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('Test'))); + +?> +--EXPECTF-- +before yield +exception 'RuntimeException' with message 'Test' in %s:%d +Stack trace: +#0 {main} + +string(6) "result" diff --git a/Zend/tests/generators/throw_not_an_exception.phpt b/Zend/tests/generators/throw_not_an_exception.phpt new file mode 100644 index 0000000000..d93903e215 --- /dev/null +++ b/Zend/tests/generators/throw_not_an_exception.phpt @@ -0,0 +1,15 @@ +--TEST-- +Generator::throw() with something that's not an exception +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->throw(new stdClass); + +?> +--EXPECTF-- +Fatal error: Exceptions must be valid objects derived from the Exception base class in %s on line %d diff --git a/Zend/tests/generators/throw_rethrow.phpt b/Zend/tests/generators/throw_rethrow.phpt new file mode 100644 index 0000000000..65044ee3f3 --- /dev/null +++ b/Zend/tests/generators/throw_rethrow.phpt @@ -0,0 +1,34 @@ +--TEST-- +Generator::throw() where the generator throws a different exception +--FILE-- +<?php + +function gen() { + echo "before yield\n"; + try { + yield; + } catch (RuntimeException $e) { + echo 'Caught: ', $e, "\n\n"; + + throw new LogicException('new throw'); + } +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('throw'))); + +?> +--EXPECTF-- +before yield +Caught: exception 'RuntimeException' with message 'throw' in %s:%d +Stack trace: +#0 {main} + + +Fatal error: Uncaught exception 'LogicException' with message 'new throw' in %s:%d +Stack trace: +#0 [internal function]: gen() +#1 %s(%d): Generator->throw(Object(RuntimeException)) +#2 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/throw_uncaught.phpt b/Zend/tests/generators/throw_uncaught.phpt new file mode 100644 index 0000000000..f06cff1b8e --- /dev/null +++ b/Zend/tests/generators/throw_uncaught.phpt @@ -0,0 +1,19 @@ +--TEST-- +Generator::throw() where the exception is not caught in the generator +--FILE-- +<?php + +function gen() { + yield 'thisThrows'; + yield 'notReached'; +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('test'))); + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'RuntimeException' with message 'test' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/unused_return_value.phpt b/Zend/tests/generators/unused_return_value.phpt new file mode 100644 index 0000000000..ddce64542c --- /dev/null +++ b/Zend/tests/generators/unused_return_value.phpt @@ -0,0 +1,13 @@ +--TEST-- +There shouldn't be any leaks when the genertor's return value isn't used +--FILE-- +<?php + +function gen($foo) { yield; } + +gen('foo'); // return value not used + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/generators/xrange.phpt b/Zend/tests/generators/xrange.phpt new file mode 100644 index 0000000000..4d8b60fa90 --- /dev/null +++ b/Zend/tests/generators/xrange.phpt @@ -0,0 +1,23 @@ +--TEST-- +Simple generator xrange() test +--FILE-- +<?php + +function xrange($start, $end, $step = 1) { + for ($i = $start; $i <= $end; $i += $step) { + yield $i; + } +} + +foreach (xrange(10, 20, 2) as $i) { + var_dump($i); +} + +?> +--EXPECT-- +int(10) +int(12) +int(14) +int(16) +int(18) +int(20) diff --git a/Zend/tests/generators/yield_array_key.phpt b/Zend/tests/generators/yield_array_key.phpt new file mode 100644 index 0000000000..5afba00de8 --- /dev/null +++ b/Zend/tests/generators/yield_array_key.phpt @@ -0,0 +1,18 @@ +--TEST-- +Array keys can be yielded from generators +--FILE-- +<?php + +function gen() { + yield [] => 1; +} + +$gen = gen(); +var_dump($gen->key()); +var_dump($gen->current()); + +?> +--EXPECT-- +array(0) { +} +int(1) diff --git a/Zend/tests/generators/yield_array_offset_by_ref.phpt b/Zend/tests/generators/yield_array_offset_by_ref.phpt new file mode 100644 index 0000000000..544108e64d --- /dev/null +++ b/Zend/tests/generators/yield_array_offset_by_ref.phpt @@ -0,0 +1,26 @@ +--TEST-- +Array offsets can be yielded by reference +--FILE-- +<?php + +function &gen(array &$array) { + yield $array[0]; +} + +$array = [1, 2, 3]; +$gen = gen($array); +foreach ($gen as &$val) { + $val *= -1; +} +var_dump($array); + +?> +--EXPECT-- +array(3) { + [0]=> + &int(-1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/Zend/tests/generators/yield_by_reference.phpt b/Zend/tests/generators/yield_by_reference.phpt new file mode 100644 index 0000000000..dba0791c0d --- /dev/null +++ b/Zend/tests/generators/yield_by_reference.phpt @@ -0,0 +1,42 @@ +--TEST-- +Generators can yield by-reference +--FILE-- +<?php + +function &iter(array &$array) { + foreach ($array as $key => &$value) { + yield $key => $value; + } +} + +$array = [1, 2, 3]; +$iter = iter($array); +foreach ($iter as &$value) { + $value *= -1; +} +var_dump($array); + +$array = [1, 2, 3]; +foreach (iter($array) as &$value) { + $value *= -1; +} +var_dump($array); + +?> +--EXPECT-- +array(3) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + &int(-3) +} +array(3) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + &int(-3) +} diff --git a/Zend/tests/generators/yield_closure.phpt b/Zend/tests/generators/yield_closure.phpt new file mode 100644 index 0000000000..e380b29946 --- /dev/null +++ b/Zend/tests/generators/yield_closure.phpt @@ -0,0 +1,17 @@ +--TEST-- +Generator shouldn't crash if last yielded value is a closure +--FILE-- +<?php + +function gen() { + yield function() {}; +} + +$gen = gen(); +$gen->next(); + +echo "Done!"; + +?> +--EXPECT-- +Done! diff --git a/Zend/tests/generators/yield_during_function_call.phpt b/Zend/tests/generators/yield_during_function_call.phpt new file mode 100644 index 0000000000..21071f9fb4 --- /dev/null +++ b/Zend/tests/generators/yield_during_function_call.phpt @@ -0,0 +1,15 @@ +--TEST-- +"yield" can occur during a function call +--FILE-- +<?php + +function gen() { + var_dump(str_repeat("x", yield)); +} + +$gen = gen(); +$gen->send(10); + +?> +--EXPECT-- +string(10) "xxxxxxxxxx" diff --git a/Zend/tests/generators/yield_during_method_call.phpt b/Zend/tests/generators/yield_during_method_call.phpt new file mode 100644 index 0000000000..3a9914d58b --- /dev/null +++ b/Zend/tests/generators/yield_during_method_call.phpt @@ -0,0 +1,27 @@ +--TEST-- +Yield can be used during a method call +--FILE-- +<?php + +class A { + public function b($c) { + echo $c, "\n"; + } +} + +function gen() { + $a = new A; + $a->b(yield); +} + +$gen = gen(); +$gen->send('foo'); + +// test resource cleanup +$gen = gen(); +$gen->rewind(); +unset($gen); + +?> +--EXPECT-- +foo diff --git a/Zend/tests/generators/yield_in_finally.phpt b/Zend/tests/generators/yield_in_finally.phpt new file mode 100644 index 0000000000..805484ad1d --- /dev/null +++ b/Zend/tests/generators/yield_in_finally.phpt @@ -0,0 +1,29 @@ +--TEST-- +yield can be used in finally (apart from forced closes) +--FILE-- +<?php + +function gen() { + try { + echo "before return\n"; + return; + echo "after return\n"; + } finally { + echo "before yield\n"; + yield "yielded value"; + echo "after yield\n"; + } + + echo "after finally\n"; +} + +$gen = gen(); +var_dump($gen->current()); +$gen->next(); + +?> +--EXPECTF-- +before return +before yield +string(%d) "yielded value" +after yield diff --git a/Zend/tests/generators/yield_in_parenthesis.phpt b/Zend/tests/generators/yield_in_parenthesis.phpt new file mode 100644 index 0000000000..4a603f4cc1 --- /dev/null +++ b/Zend/tests/generators/yield_in_parenthesis.phpt @@ -0,0 +1,23 @@ +--TEST-- +No additional parenthesis are required around yield if they are already present +--FILE-- +<?php + +function gen() { + if (yield $foo); elseif (yield $foo); + if (yield $foo): elseif (yield $foo): endif; + while (yield $foo); + do {} while (yield $foo); + switch (yield $foo) {} + (yield $foo); + die(yield $foo); + func(yield $foo); + $foo->func(yield $foo); + new Foo(yield $foo); +} + +echo "Done"; + +?> +--EXPECT-- +Done diff --git a/Zend/tests/generators/yield_ref_function_call_by_reference.phpt b/Zend/tests/generators/yield_ref_function_call_by_reference.phpt new file mode 100644 index 0000000000..e371affd92 --- /dev/null +++ b/Zend/tests/generators/yield_ref_function_call_by_reference.phpt @@ -0,0 +1,24 @@ +--TEST-- +The result of a by-ref function call can be yielded just fine +--FILE-- +<?php + +function &nop(&$var) { + return $var; +} + +function &gen(&$var) { + yield nop($var); +} + +$var = "foo"; +$gen = gen($var); +foreach ($gen as &$varRef) { + $varRef = "bar"; +} + +var_dump($var); + +?> +--EXPECT-- +string(3) "bar" diff --git a/Zend/tests/generators/yield_without_value.phpt b/Zend/tests/generators/yield_without_value.phpt new file mode 100644 index 0000000000..52292b737c --- /dev/null +++ b/Zend/tests/generators/yield_without_value.phpt @@ -0,0 +1,27 @@ +--TEST-- +yield can be used without a value +--FILE-- +<?php + +function recv() { + while (true) { + var_dump(yield); + } +} + +$receiver = recv(); +var_dump($receiver->current()); +$receiver->send(1); +var_dump($receiver->current()); +$receiver->send(2); +var_dump($receiver->current()); +$receiver->send(3); + +?> +--EXPECT-- +NULL +int(1) +NULL +int(2) +NULL +int(3) diff --git a/Zend/tests/isset_expr_error.phpt b/Zend/tests/isset_expr_error.phpt new file mode 100644 index 0000000000..27fc6cd8d3 --- /dev/null +++ b/Zend/tests/isset_expr_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(1 + 1); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead) in %s on line %d diff --git a/Zend/tests/isset_func_error.phpt b/Zend/tests/isset_func_error.phpt new file mode 100644 index 0000000000..7d1036def8 --- /dev/null +++ b/Zend/tests/isset_func_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(abc()); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of a function call (you can use "null !== func()" instead) in %s on line %d diff --git a/Zend/tests/ns_026.phpt b/Zend/tests/ns_026.phpt index af2bf2ca55..45f88750eb 100644 --- a/Zend/tests/ns_026.phpt +++ b/Zend/tests/ns_026.phpt @@ -1,5 +1,7 @@ --TEST-- 026: Name ambiguity (class name & namespace name) +--INI-- +opcache.optimization_level=0 --FILE-- <?php namespace Foo; diff --git a/Zend/tests/offset_assign.phpt b/Zend/tests/offset_assign.phpt index 6a00591095..721516f53c 100644 --- a/Zend/tests/offset_assign.phpt +++ b/Zend/tests/offset_assign.phpt @@ -3,11 +3,11 @@ Crash on $x['x']['y'] += 1 when $x is string --FILE-- <?php $x = "a"; -$x['x']['y'] += 1; +$x['x']['y'] += 1; echo "Done\n"; ?> ---EXPECTF-- +--EXPECTF-- Warning: Illegal string offset 'x' in %soffset_assign.php on line %d Fatal error: Cannot use string offset as an array in %soffset_assign.php on line %d diff --git a/Zend/tests/offset_string.phpt b/Zend/tests/offset_string.phpt index f7cb81bb20..c546b37183 100644 --- a/Zend/tests/offset_string.phpt +++ b/Zend/tests/offset_string.phpt @@ -27,7 +27,7 @@ var_dump($str[$arr]); echo "Done\n"; ?> ---EXPECTF-- +--EXPECTF-- string(1) "i" Notice: String offset cast occurred in %s on line %d diff --git a/Zend/tests/try_catch_finally_001.phpt b/Zend/tests/try_catch_finally_001.phpt new file mode 100644 index 0000000000..3d478f461a --- /dev/null +++ b/Zend/tests/try_catch_finally_001.phpt @@ -0,0 +1,36 @@ +--TEST-- +Try catch finally +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + throw new Exception("try"); + } catch (AE $e) { + echo "0"; + die("error"); + } finally { + echo "1"; + } + } finally { + echo "2"; + } + } catch (BE $e) { + die("error"); + } catch (Exception $e) { + echo "3"; + } finally { + echo "4"; + } + return 1; +} + +var_dump(foo()); +?> +--EXPECTF-- +1234int(1) diff --git a/Zend/tests/try_catch_finally_002.phpt b/Zend/tests/try_catch_finally_002.phpt new file mode 100644 index 0000000000..79efcb3de8 --- /dev/null +++ b/Zend/tests/try_catch_finally_002.phpt @@ -0,0 +1,42 @@ +--TEST-- +Try catch finally catch(multi catch blocks) +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + try { + echo "1"; + throw new Exception("try"); + } catch (AE $e) { + die("error"); + } finally { + echo "2"; + } + } finally { + echo "3"; + } + } catch (BE $e) { + die("error"); + } finally { + echo "4"; + } + } catch (Exception $e) { + echo "5"; + } catch (AE $e) { + die("error"); + } finally { + echo "6"; + } + return 7; +} + +var_dump(foo()); +?> +--EXPECTF-- +123456int(7) diff --git a/Zend/tests/try_catch_finally_003.phpt b/Zend/tests/try_catch_finally_003.phpt new file mode 100644 index 0000000000..7ec8ec82db --- /dev/null +++ b/Zend/tests/try_catch_finally_003.phpt @@ -0,0 +1,36 @@ +--TEST-- +Try catch finally (multi catch blocks with return) +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + throw new Exception("try"); + } catch (AE $e) { + die("error"); + } finally { + echo "1"; + } + } finally { + echo "2"; + } + } catch (BE $e) { + die("error"); + } catch (Exception $e) { + echo "3"; + } finally { + echo "4"; + return 4; + } + return 5; +} + +var_dump(foo()); +?> +--EXPECTF-- +1234int(4) diff --git a/Zend/tests/try_catch_finally_004.phpt b/Zend/tests/try_catch_finally_004.phpt new file mode 100644 index 0000000000..eb8d0966a1 --- /dev/null +++ b/Zend/tests/try_catch_finally_004.phpt @@ -0,0 +1,30 @@ +--TEST-- +Try catch finally (re-throw exception in catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function dummy($msg) { + var_dump($msg); +} +try { + try { + var_dump("try"); + return; + } catch (Exception $e) { + dummy("catch"); + throw $e; + } finally { + dummy("finally"); + } +} catch (Exception $e) { + dummy("catch2"); +} finally { + dummy("finally2"); +} +var_dump("end"); +?> +--EXPECTF-- +string(3) "try" +string(7) "finally" +string(8) "finally2" diff --git a/Zend/tests/try_catch_finally_005.phpt b/Zend/tests/try_catch_finally_005.phpt new file mode 100644 index 0000000000..dafeb6bbe0 --- /dev/null +++ b/Zend/tests/try_catch_finally_005.phpt @@ -0,0 +1,52 @@ +--TEST-- +Try catch finally (break / cont in try block) +--CREDITS-- +adoy +--FILE-- +<?php +for ($i = 0; $i < 100 ; $i ++) { + try { + break; + } finally { + var_dump("break"); + } +} + + +for ($i = 0; $i < 2; $i ++) { + try { + continue; + } finally { + var_dump("continue1"); + } +} + +for ($i = 0; $i < 3; $i ++) { + try { + try { + continue; + } finally { + var_dump("continue2"); + if ($i == 1) { + throw new Exception("continue exception"); + } + } + } catch (Exception $e) { + var_dump("cactched"); + } finally { + var_dump("finally"); + } +} + +?> +--EXPECTF-- +string(5) "break" +string(9) "continue1" +string(9) "continue1" +string(9) "continue2" +string(7) "finally" +string(9) "continue2" +string(8) "cactched" +string(7) "finally" +string(9) "continue2" +string(7) "finally" diff --git a/Zend/tests/try_catch_finally_006.phpt b/Zend/tests/try_catch_finally_006.phpt new file mode 100644 index 0000000000..dab6af6a58 --- /dev/null +++ b/Zend/tests/try_catch_finally_006.phpt @@ -0,0 +1,39 @@ +--TEST-- +Try catch finally (goto in try/catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function foo($ex = NULL) { + try { + try { + goto label; + } finally { + var_dump("finally1"); + if ($ex) throw $ex; + } + } catch (Exception $e) { + var_dump("catched"); + if ($ex) return "return1"; + } finally { + var_dump("finally2"); + } + +label: + var_dump("label"); + return "return2"; +} + +var_dump(foo()); +var_dump(foo(new Exception())); + +?> +--EXPECTF-- +string(8) "finally1" +string(8) "finally2" +string(5) "label" +string(7) "return2" +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(7) "return1" diff --git a/Zend/tests/try_catch_finally_007.phpt b/Zend/tests/try_catch_finally_007.phpt new file mode 100644 index 0000000000..ad33c68131 --- /dev/null +++ b/Zend/tests/try_catch_finally_007.phpt @@ -0,0 +1,46 @@ +--TEST-- +Try catch finally (goto in try/catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function foo($ret = FALSE) { + try { + try { + do { + goto label; + } while(0); + foreach (array() as $val) { + continue; + } + } finally { + var_dump("finally1"); + throw new Exception("exception"); + } + } catch (Exception $e) { + goto local; +local: + var_dump("catched"); + if ($ret) return "return"; + } finally { + var_dump("finally2"); + } + +label: + var_dump("label"); +} + +var_dump(foo()); +var_dump(foo(true)); + +?> +--EXPECTF-- +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(5) "label" +NULL +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(6) "return" diff --git a/Zend/tests/try_finally_001.phpt b/Zend/tests/try_finally_001.phpt new file mode 100644 index 0000000000..0f740872c2 --- /dev/null +++ b/Zend/tests/try_finally_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try finally (basic test) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } finally { + var_dump($a); + } +} + +foo("finally"); +?> +--EXPECTF-- +string(7) "finally" + +Fatal error: Uncaught exception 'Exception' with message 'ex' %s +Stack trace: +#0 %stry_finally_001.php(%d): foo('finally') +#1 {main} + thrown in %stry_finally_001.php on line %d diff --git a/Zend/tests/try_finally_002.phpt b/Zend/tests/try_finally_002.phpt new file mode 100644 index 0000000000..99a34f62fb --- /dev/null +++ b/Zend/tests/try_finally_002.phpt @@ -0,0 +1,23 @@ +--TEST-- +Try finally (re-throw exception in finally block) +--FILE-- +<?php +function foo () { + try { + throw new Exception("try"); + } finally { + throw new Exception("finally"); + } +} + +try { + foo(); +} catch (Exception $e) { + do { + var_dump($e->getMessage()); + } while ($e = $e->getPrevious()); +} +?> +--EXPECT-- +string(7) "finally" +string(3) "try" diff --git a/Zend/tests/try_finally_003.phpt b/Zend/tests/try_finally_003.phpt new file mode 100644 index 0000000000..c1294911bd --- /dev/null +++ b/Zend/tests/try_finally_003.phpt @@ -0,0 +1,27 @@ +--TEST-- +Try finally (call sequence test) +--FILE-- +<?php +function foo () { + try { + echo "1"; + try { + echo "2"; + throw new Exception("ex"); + } finally { + echo "3"; + } + } finally { + echo "4"; + } +} + +foo(); +?> +--EXPECTF-- +1234 +Fatal error: Uncaught exception 'Exception' with message 'ex' %s +Stack trace: +#0 %stry_finally_003.php(%d): foo() +#1 {main} + thrown in %stry_finally_003.php on line %d diff --git a/Zend/tests/try_finally_004.phpt b/Zend/tests/try_finally_004.phpt new file mode 100644 index 0000000000..08930a40c5 --- /dev/null +++ b/Zend/tests/try_finally_004.phpt @@ -0,0 +1,14 @@ +--TEST-- +Try finally (without catch/finally block) +--FILE-- +<?php +function foo () { + try { + echo "3"; + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: Cannot use try without catch or finally in %stry_finally_004.php on line %d diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt new file mode 100644 index 0000000000..8664d6b1bf --- /dev/null +++ b/Zend/tests/try_finally_005.phpt @@ -0,0 +1,17 @@ +--TEST-- +Try finally (with long goto) +--FILE-- +<?php +function foo () { + try { + } finally { + goto label; + } +label: + return 1; +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_005.php on line %d diff --git a/Zend/tests/try_finally_006.phpt b/Zend/tests/try_finally_006.phpt new file mode 100644 index 0000000000..f53e6b5bc1 --- /dev/null +++ b/Zend/tests/try_finally_006.phpt @@ -0,0 +1,26 @@ +--TEST-- +Try finally (with near goto) +--FILE-- +<?php +function foo () { + $jmp = 1; + try { + } finally { +previous: + if ($jmp) { + goto label; + echo "dummy"; +label: + echo "label\n"; + $jmp = 0; + goto previous; + } + echo "okey"; + } +} + +foo(); +?> +--EXPECTF-- +label +okey diff --git a/Zend/tests/try_finally_007.phpt b/Zend/tests/try_finally_007.phpt new file mode 100644 index 0000000000..634937495c --- /dev/null +++ b/Zend/tests/try_finally_007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try finally (with goto previous label) +--FILE-- +<?php +function foo () { + try { +label: + echo "label"; + try { + } finally { + goto label; + echo "dummy"; + } + } catch (Exception $e) { + } finally { + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_007.php on line %d diff --git a/Zend/tests/try_finally_008.phpt b/Zend/tests/try_finally_008.phpt new file mode 100644 index 0000000000..cee37aedab --- /dev/null +++ b/Zend/tests/try_finally_008.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try finally (with break in do...while) +--FILE-- +<?php +function foo () { + do { + try { + try { + } finally { + break; + } + } catch (Exception $e) { + } finally { + } + } while (0); +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_008.php on line %d diff --git a/Zend/tests/try_finally_009.phpt b/Zend/tests/try_finally_009.phpt new file mode 100644 index 0000000000..b29930a75e --- /dev/null +++ b/Zend/tests/try_finally_009.phpt @@ -0,0 +1,23 @@ +--TEST-- +Try finally (with for continue) +--FILE-- +<?php +function foo () { + for($i = 0; $i < 5; $i++) { + do { + try { + try { + } finally { + } + } catch (Exception $e) { + } finally { + continue; + } + } while (0); + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_009.php on line %d diff --git a/Zend/tests/try_finally_010.phpt b/Zend/tests/try_finally_010.phpt new file mode 100644 index 0000000000..bbac8dd1e5 --- /dev/null +++ b/Zend/tests/try_finally_010.phpt @@ -0,0 +1,30 @@ +--TEST-- +Try finally (function call in the finaly block after exception) +--FILE-- +<?php +function foo() { + echo "4"; +} +function bar() { + try { + echo "2"; + throw new Exception(); + echo "x"; + } catch (MyEx $ex) { + echo "x"; + } finally { + echo "3"; + foo(); + echo "5"; + } +} +try { + echo "1"; + bar(); + echo "x"; +} catch (Exception $ex) { + echo "6"; +} +echo "\n"; +--EXPECT-- +123456 |