diff options
author | Ilija Tovilo <ilija.tovilo@me.com> | 2020-04-09 22:36:37 +0200 |
---|---|---|
committer | Ilija Tovilo <ilija.tovilo@me.com> | 2020-07-09 23:52:17 +0200 |
commit | 9fa1d1330138ac424f990ff03e62721120aaaec3 (patch) | |
tree | ca3550c82b86ccf844745fbe80c77134ed5cbef4 /Zend/tests/match | |
parent | c60d0dc2f41f1d4817414e37a39ae87c5677e31a (diff) | |
download | php-git-9fa1d1330138ac424f990ff03e62721120aaaec3.tar.gz |
Implement match expression
RFC: https://wiki.php.net/rfc/match_expression_v2
Closes GH-5371.
Diffstat (limited to 'Zend/tests/match')
-rw-r--r-- | Zend/tests/match/001.phpt | 36 | ||||
-rw-r--r-- | Zend/tests/match/002.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/match/003.phpt | 24 | ||||
-rw-r--r-- | Zend/tests/match/004.phpt | 31 | ||||
-rw-r--r-- | Zend/tests/match/005.phpt | 12 | ||||
-rw-r--r-- | Zend/tests/match/006.phpt | 13 | ||||
-rw-r--r-- | Zend/tests/match/007.phpt | 26 | ||||
-rw-r--r-- | Zend/tests/match/008.phpt | 25 | ||||
-rw-r--r-- | Zend/tests/match/009.phpt | 22 | ||||
-rw-r--r-- | Zend/tests/match/011.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/match/012.phpt | 36 | ||||
-rw-r--r-- | Zend/tests/match/017.phpt | 92 | ||||
-rw-r--r-- | Zend/tests/match/023.phpt | 20 | ||||
-rw-r--r-- | Zend/tests/match/024.phpt | 19 | ||||
-rw-r--r-- | Zend/tests/match/027.phpt | 36 | ||||
-rw-r--r-- | Zend/tests/match/028.phpt | 36 | ||||
-rw-r--r-- | Zend/tests/match/029.phpt | 22 | ||||
-rw-r--r-- | Zend/tests/match/030.phpt | 22 | ||||
-rw-r--r-- | Zend/tests/match/037.phpt | 68 | ||||
-rw-r--r-- | Zend/tests/match/038.phpt | 15 | ||||
-rw-r--r-- | Zend/tests/match/039.phpt | 61 | ||||
-rw-r--r-- | Zend/tests/match/040.phpt | 44 | ||||
-rw-r--r-- | Zend/tests/match/041.phpt | 33 | ||||
-rw-r--r-- | Zend/tests/match/042.phpt | 22 |
24 files changed, 753 insertions, 0 deletions
diff --git a/Zend/tests/match/001.phpt b/Zend/tests/match/001.phpt new file mode 100644 index 0000000000..9d338c1b42 --- /dev/null +++ b/Zend/tests/match/001.phpt @@ -0,0 +1,36 @@ +--TEST-- +Basic match expression functionality test +--FILE-- +<?php + +function wordify($x) { + return match ($x) { + 0 => 'Zero', + 1 => 'One', + 2 => 'Two', + 3 => 'Three', + 4 => 'Four', + 5 => 'Five', + 6 => 'Six', + 7 => 'Seven', + 8 => 'Eight', + 9 => 'Nine', + }; +} + +for ($i = 0; $i <= 9; $i++) { + print wordify($i) . "\n"; +} + +?> +--EXPECT-- +Zero +One +Two +Three +Four +Five +Six +Seven +Eight +Nine diff --git a/Zend/tests/match/002.phpt b/Zend/tests/match/002.phpt new file mode 100644 index 0000000000..ad087c5926 --- /dev/null +++ b/Zend/tests/match/002.phpt @@ -0,0 +1,19 @@ +--TEST-- +Match expression omit trailing comma +--FILE-- +<?php + +function print_bool($bool) { + echo match ($bool) { + true => "true\n", + false => "false\n" + }; +} + +print_bool(true); +print_bool(false); + +?> +--EXPECT-- +true +false diff --git a/Zend/tests/match/003.phpt b/Zend/tests/match/003.phpt new file mode 100644 index 0000000000..550d2277d6 --- /dev/null +++ b/Zend/tests/match/003.phpt @@ -0,0 +1,24 @@ +--TEST-- +Match expression default case +--FILE-- +<?php + +function get_value($i) { + return match ($i) { + 1 => 1, + 2 => 2, + default => 'default', + }; +} + +echo get_value(0) . "\n"; +echo get_value(1) . "\n"; +echo get_value(2) . "\n"; +echo get_value(3) . "\n"; + +?> +--EXPECT-- +default +1 +2 +default diff --git a/Zend/tests/match/004.phpt b/Zend/tests/match/004.phpt new file mode 100644 index 0000000000..2f8717f74e --- /dev/null +++ b/Zend/tests/match/004.phpt @@ -0,0 +1,31 @@ +--TEST-- +Match expression with true as expression +--FILE-- +<?php + +function get_range($i) { + return match (true) { + $i >= 50 => '50+', + $i >= 40 => '40-50', + $i >= 30 => '30-40', + $i >= 20 => '20-30', + $i >= 10 => '10-20', + default => '0-10', + }; +} + +echo get_range(22) . "\n"; +echo get_range(0) . "\n"; +echo get_range(59) . "\n"; +echo get_range(13) . "\n"; +echo get_range(39) . "\n"; +echo get_range(40) . "\n"; + +?> +--EXPECT-- +20-30 +0-10 +50+ +10-20 +30-40 +40-50 diff --git a/Zend/tests/match/005.phpt b/Zend/tests/match/005.phpt new file mode 100644 index 0000000000..cc72739f43 --- /dev/null +++ b/Zend/tests/match/005.phpt @@ -0,0 +1,12 @@ +--TEST-- +Match expression discarding result +--FILE-- +<?php + +match (1) { + 1 => print "Executed\n", +}; + +?> +--EXPECT-- +Executed diff --git a/Zend/tests/match/006.phpt b/Zend/tests/match/006.phpt new file mode 100644 index 0000000000..fec28f82da --- /dev/null +++ b/Zend/tests/match/006.phpt @@ -0,0 +1,13 @@ +--TEST-- +Match expression with no cases +--FILE-- +<?php + +$x = match (true) {}; + +?> +--EXPECTF-- +Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type bool in %s +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/match/007.phpt b/Zend/tests/match/007.phpt new file mode 100644 index 0000000000..7b442a66a0 --- /dev/null +++ b/Zend/tests/match/007.phpt @@ -0,0 +1,26 @@ +--TEST-- +Match expression exception on unhandled case +--FILE-- +<?php + +function get_value($i) { + return match ($i) { + 1 => 1, + 2 => 2, + }; +} + +echo get_value(1) . "\n"; +echo get_value(2) . "\n"; +echo get_value(3) . "\n"; + +?> +--EXPECTF-- +1 +2 + +Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type int in %s +Stack trace: +#0 %s: get_value(3) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/match/008.phpt b/Zend/tests/match/008.phpt new file mode 100644 index 0000000000..db91d80b87 --- /dev/null +++ b/Zend/tests/match/008.phpt @@ -0,0 +1,25 @@ +--TEST-- +Match expression multiple conditions per case +--FILE-- +<?php + +function is_working_day($day) { + return match ($day) { + 1, 7 => false, + 2, 3, 4, 5, 6 => true, + }; +} + +for ($i = 1; $i <= 7; $i++) { + var_dump(is_working_day($i)); +} + +?> +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) diff --git a/Zend/tests/match/009.phpt b/Zend/tests/match/009.phpt new file mode 100644 index 0000000000..32153e7453 --- /dev/null +++ b/Zend/tests/match/009.phpt @@ -0,0 +1,22 @@ +--TEST-- +Pretty printing for match expression +--FILE-- +<?php + +assert((function () { + match ('foo') { + 'foo', 'bar' => false, + 'baz' => 'a', + default => 'b', + }; +})()); + +?> +--EXPECTF-- +Warning: assert(): assert(function () { + match ('foo') { + 'foo', 'bar' => false, + 'baz' => 'a', + default => 'b', + }; +}()) failed in %s on line %d diff --git a/Zend/tests/match/011.phpt b/Zend/tests/match/011.phpt new file mode 100644 index 0000000000..1c3c139ef7 --- /dev/null +++ b/Zend/tests/match/011.phpt @@ -0,0 +1,19 @@ +--TEST-- +Implicit break in match expression +--FILE-- +<?php + +function dump_and_return($string) { + var_dump($string); + return $string; +} + +var_dump(match ('foo') { + 'foo' => dump_and_return('foo'), + 'bar' => dump_and_return('bar'), +}); + +?> +--EXPECT-- +string(3) "foo" +string(3) "foo" diff --git a/Zend/tests/match/012.phpt b/Zend/tests/match/012.phpt new file mode 100644 index 0000000000..c75fc73de8 --- /dev/null +++ b/Zend/tests/match/012.phpt @@ -0,0 +1,36 @@ +--TEST-- +Strict comparison in match expression +--FILE-- +<?php + +function wrong() { + throw new Exception(); +} + +var_dump(match (0) { + null => wrong(), + false => wrong(), + 0.0 => wrong(), + [] => wrong(), + '' => wrong(), + 0 => 'int', +}); + +function get_value() { + return 0; +} + +var_dump(match (get_value()) { + null => wrong(), + false => wrong(), + 0.0 => wrong(), + [] => wrong(), + '' => wrong(), + 0 => 'int', + default => 'default', +}); + +?> +--EXPECT-- +string(3) "int" +string(3) "int" diff --git a/Zend/tests/match/017.phpt b/Zend/tests/match/017.phpt new file mode 100644 index 0000000000..622f7bb165 --- /dev/null +++ b/Zend/tests/match/017.phpt @@ -0,0 +1,92 @@ +--TEST-- +Test strict comparison with match expression jump table +--FILE-- +<?php + +function wrong() { + throw new Exception(); +} + +function test_int($char) { + return match ($char) { + 0 => wrong(), + 1 => wrong(), + 2 => wrong(), + 3 => wrong(), + 4 => wrong(), + 5 => wrong(), + 6 => wrong(), + 7 => wrong(), + 8 => wrong(), + 9 => wrong(), + default => 'Not matched', + }; +} + +foreach (range(0, 9) as $int) { + var_dump((string) $int); + var_dump(test_int((string) $int)); +} + +function test_string($int) { + return match ($int) { + '0' => wrong(), + '1' => wrong(), + '2' => wrong(), + '3' => wrong(), + '4' => wrong(), + '5' => wrong(), + '6' => wrong(), + '7' => wrong(), + '8' => wrong(), + '9' => wrong(), + default => 'Not matched', + }; +} + +foreach (range(0, 9) as $int) { + var_dump($int); + var_dump(test_string($int)); +} + +--EXPECT-- +string(1) "0" +string(11) "Not matched" +string(1) "1" +string(11) "Not matched" +string(1) "2" +string(11) "Not matched" +string(1) "3" +string(11) "Not matched" +string(1) "4" +string(11) "Not matched" +string(1) "5" +string(11) "Not matched" +string(1) "6" +string(11) "Not matched" +string(1) "7" +string(11) "Not matched" +string(1) "8" +string(11) "Not matched" +string(1) "9" +string(11) "Not matched" +int(0) +string(11) "Not matched" +int(1) +string(11) "Not matched" +int(2) +string(11) "Not matched" +int(3) +string(11) "Not matched" +int(4) +string(11) "Not matched" +int(5) +string(11) "Not matched" +int(6) +string(11) "Not matched" +int(7) +string(11) "Not matched" +int(8) +string(11) "Not matched" +int(9) +string(11) "Not matched" diff --git a/Zend/tests/match/023.phpt b/Zend/tests/match/023.phpt new file mode 100644 index 0000000000..f82ece2873 --- /dev/null +++ b/Zend/tests/match/023.phpt @@ -0,0 +1,20 @@ +--TEST-- +Test match strict comparison with true expression +--FILE-- +<?php + +function wrong() { + throw new Exception(); +} + +echo match (true) { + 'truthy' => wrong(), + ['truthy'] => wrong(), + new stdClass() => wrong(), + 1 => wrong(), + 1.0 => wrong(), + true => "true\n", +}; + +--EXPECT-- +true diff --git a/Zend/tests/match/024.phpt b/Zend/tests/match/024.phpt new file mode 100644 index 0000000000..020bb3764b --- /dev/null +++ b/Zend/tests/match/024.phpt @@ -0,0 +1,19 @@ +--TEST-- +Test match strict comparison with false expression +--FILE-- +<?php + +function wrong() { + throw new Exception(); +} + +echo match (false) { + '' => wrong(), + [] => wrong(), + 0 => wrong(), + 0.0 => wrong(), + false => "false\n", +}; + +--EXPECT-- +false diff --git a/Zend/tests/match/027.phpt b/Zend/tests/match/027.phpt new file mode 100644 index 0000000000..788f5d6039 --- /dev/null +++ b/Zend/tests/match/027.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test result of match cannot be modified by reference +--FILE-- +<?php + +// opcache can't be certain Test::usesRef is actually this method +if (!class_exists('Test')) { + class Test { + public static function usesRef(&$x) { + $x = 'modified'; + } + public static function usesValue($x) { + echo "usesValue $x\n"; + } + } +} + +function main() { + $i = 0; + Test::usesValue(match(true) { true => $i }); + echo "i is $i\n"; + $j = 1; + Test::usesRef(match(true) { true => $j }); + echo "j is $j\n"; +} +main(); + +--EXPECTF-- +usesValue 0 +i is 0 + +Fatal error: Uncaught Error: Cannot pass parameter 1 by reference in %s027.php:20 +Stack trace: +#0 %s027.php(23): main() +#1 {main} + thrown in %s027.php on line 20 diff --git a/Zend/tests/match/028.phpt b/Zend/tests/match/028.phpt new file mode 100644 index 0000000000..8cad03c099 --- /dev/null +++ b/Zend/tests/match/028.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test result of match cannot be modified by reference +--FILE-- +<?php + +// opcache can't be certain Test::usesRef is actually this method +if (!class_exists('Test')) { + class Test { + public static function usesRef(&$x) { + $x = 'modified'; + } + public static function usesValue($x) { + echo "usesValue $x\n"; + } + } +} + +function main(int $i): int { + Test::usesValue(match(true) { true => $i }); + Test::usesValue(match($i) { 42 => $i }); + var_dump($i); + Test::usesRef(match(true) { true => $i }); + var_dump($i); +} + +try { + main(42); +} catch (Error $e) { + printf("Caught %s\n", $e->getMessage()); +} + +--EXPECT-- +usesValue 42 +usesValue 42 +int(42) +Caught Cannot pass parameter 1 by reference diff --git a/Zend/tests/match/029.phpt b/Zend/tests/match/029.phpt new file mode 100644 index 0000000000..7ebcdedc70 --- /dev/null +++ b/Zend/tests/match/029.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test long match with undefined variable +--FILE-- +<?php + +set_error_handler(function ($errno, $message) { + throw new Exception("Custom error handler: $message"); +}); + +echo match ($undefVar) { + default => "This should not get printed with or without opcache\n", + 1, 2, 3, 4, 5 => "Also should not be printed\n", +}; + +echo "unreachable\n"; + +--EXPECTF-- +Fatal error: Uncaught Exception: Custom error handler: Undefined variable $undefVar in %s029.php:4 +Stack trace: +#0 %s029.php(7): {closure}(%d, 'Undefined varia...', '%s', %d) +#1 {main} + thrown in %s029.php on line 4 diff --git a/Zend/tests/match/030.phpt b/Zend/tests/match/030.phpt new file mode 100644 index 0000000000..1271d72e42 --- /dev/null +++ b/Zend/tests/match/030.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test string match with undefined variable +--FILE-- +<?php + +set_error_handler(function ($errno, $message) { + throw new Exception("Custom error handler: $message"); +}); + +echo match ($undefVar) { + default => "This should not get printed with or without opcache\n", + '1', '2', '3', '4', '5' => "Also should not be printed\n", +}; + +echo "unreachable\n"; + +--EXPECTF-- +Fatal error: Uncaught Exception: Custom error handler: Undefined variable $undefVar in %s030.php:4 +Stack trace: +#0 %s030.php(7): {closure}(%d, 'Undefined varia...', '%s', %d) +#1 {main} + thrown in %s030.php on line 4 diff --git a/Zend/tests/match/037.phpt b/Zend/tests/match/037.phpt new file mode 100644 index 0000000000..e114696f5f --- /dev/null +++ b/Zend/tests/match/037.phpt @@ -0,0 +1,68 @@ +--TEST-- +Test match jumptable with only one arm +--FILE-- +<?php + +try { + var_dump(match(true) { + 1, 2, 3, 4, 5 => 'foo', + }); +} catch (Error $e) { + var_dump((string) $e); +} + +try { + var_dump(match(6) { + 1, 2, 3, 4, 5 => 'foo', + }); +} catch (Error $e) { + var_dump((string) $e); +} + +try { + var_dump(match('3') { + 1, 2, 3, 4, 5 => 'foo', + }); +} catch (Error $e) { + var_dump((string) $e); +} + +var_dump(match(3) { + 1, 2, 3, 4, 5 => 'foo', +}); + +var_dump(match(true) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', +}); + +var_dump(match(6) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', +}); + +var_dump(match('3') { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', +}); + +var_dump(match(3) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', +}); + +--EXPECTF-- +string(%d) "UnhandledMatchError: Unhandled match value of type bool in %s037.php:5 +Stack trace: +#0 {main}" +string(%d) "UnhandledMatchError: Unhandled match value of type int in %s037.php:13 +Stack trace: +#0 {main}" +string(%d) "UnhandledMatchError: Unhandled match value of type string in %s037.php:21 +Stack trace: +#0 {main}" +string(3) "foo" +string(3) "bar" +string(3) "bar" +string(3) "bar" +string(3) "foo" diff --git a/Zend/tests/match/038.phpt b/Zend/tests/match/038.phpt new file mode 100644 index 0000000000..cc158038a9 --- /dev/null +++ b/Zend/tests/match/038.phpt @@ -0,0 +1,15 @@ +--TEST-- +Test multiple default arms in match in different arms +--FILE-- +<?php + +match (1) { + default => 'foo', + 1 => 'bar', + 2 => 'baz', + default => 'qux', +}; + +?> +--EXPECTF-- +Fatal error: Match expressions may only contain one default arm in %s on line 7 diff --git a/Zend/tests/match/039.phpt b/Zend/tests/match/039.phpt new file mode 100644 index 0000000000..d37aed5986 --- /dev/null +++ b/Zend/tests/match/039.phpt @@ -0,0 +1,61 @@ +--TEST-- +Test match with duplicate conditions +--FILE-- +<?php + +$value = 1; + +echo match ($value) { + 1 => 1, + 2 => 2, + 3 => 3, + 4 => 4, + 5 => 5, + 1 => 6, +}; +echo "\n"; + +echo match ($value) { + 2, 1 => '2, 1', + 1 => 1, + 3 => 3, + 4 => 4, + 5 => 5, +}; +echo "\n"; + +echo match ($value) { + 1, 1 => '1, 1', + 2, 2 => '2, 2', + 3, 3 => '3, 3', + 4, 4 => '4, 4', + 5, 5 => '5, 5', +}; +echo "\n"; + +echo match ($value) { + 1 => 1, + 1 => 2, +}; +echo "\n"; + +echo match ($value) { + 2, 1 => '2, 1', + 1 => 1, +}; +echo "\n"; + +echo match ($value) { + 1, 1 => '1, 1', + 1 => 1, +}; +echo "\n"; + +?> +--EXPECT-- +1 +2, 1 +1, 1 +1 +2, 1 +1, 1 diff --git a/Zend/tests/match/040.phpt b/Zend/tests/match/040.phpt new file mode 100644 index 0000000000..223c3727ec --- /dev/null +++ b/Zend/tests/match/040.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test match with mixed int/string jumptable +--FILE-- +<?php + +function test($value) { + echo match ($value) { + 1 => '1 int', + '1' => '1 string', + 2 => '2 int', + '2' => '2 string', + 3 => '3 int', + '3' => '3 string', + 4 => '4 int', + '4' => '4 string', + 5 => '5 int', + '5' => '5 string', + }; + echo "\n"; +} + +test(1); +test('1'); +test(2); +test('2'); +test(3); +test('3'); +test(4); +test('4'); +test(5); +test('5'); + +?> +--EXPECT-- +1 int +1 string +2 int +2 string +3 int +3 string +4 int +4 string +5 int +5 string diff --git a/Zend/tests/match/041.phpt b/Zend/tests/match/041.phpt new file mode 100644 index 0000000000..1e22f1d688 --- /dev/null +++ b/Zend/tests/match/041.phpt @@ -0,0 +1,33 @@ +--TEST-- +Match expression with trailing comma in condition list +--FILE-- +<?php + +function print_bool($bool) { + echo match ($bool) { + false, + 0, + => "false\n", + true, + 1, + => "true\n", + default, + => "not bool\n", + }; +} + +print_bool(false); +print_bool(0); +print_bool(true); +print_bool(1); +print_bool(2); +print_bool('foo'); + +?> +--EXPECT-- +false +false +true +true +not bool +not bool diff --git a/Zend/tests/match/042.phpt b/Zend/tests/match/042.phpt new file mode 100644 index 0000000000..6ea30dd376 --- /dev/null +++ b/Zend/tests/match/042.phpt @@ -0,0 +1,22 @@ +--TEST-- +Match expression with undefined variable as expression +--FILE-- +<?php + +var_dump(match ($undefinedVariable) { + null => 'null', + default => 'default', +}); + +var_dump(match ($undefinedVariable) { + 1, 2, 3, 4, 5 => 'foo', + default => 'bar', +}); + +?> +--EXPECTF-- +Warning: Undefined variable $undefinedVariable in %s.php on line 3 +string(4) "null" + +Warning: Undefined variable $undefinedVariable in %s.php on line 8 +string(3) "bar" |