summaryrefslogtreecommitdiff
path: root/Zend/tests/match
diff options
context:
space:
mode:
authorIlija Tovilo <ilija.tovilo@me.com>2020-04-09 22:36:37 +0200
committerIlija Tovilo <ilija.tovilo@me.com>2020-07-09 23:52:17 +0200
commit9fa1d1330138ac424f990ff03e62721120aaaec3 (patch)
treeca3550c82b86ccf844745fbe80c77134ed5cbef4 /Zend/tests/match
parentc60d0dc2f41f1d4817414e37a39ae87c5677e31a (diff)
downloadphp-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.phpt36
-rw-r--r--Zend/tests/match/002.phpt19
-rw-r--r--Zend/tests/match/003.phpt24
-rw-r--r--Zend/tests/match/004.phpt31
-rw-r--r--Zend/tests/match/005.phpt12
-rw-r--r--Zend/tests/match/006.phpt13
-rw-r--r--Zend/tests/match/007.phpt26
-rw-r--r--Zend/tests/match/008.phpt25
-rw-r--r--Zend/tests/match/009.phpt22
-rw-r--r--Zend/tests/match/011.phpt19
-rw-r--r--Zend/tests/match/012.phpt36
-rw-r--r--Zend/tests/match/017.phpt92
-rw-r--r--Zend/tests/match/023.phpt20
-rw-r--r--Zend/tests/match/024.phpt19
-rw-r--r--Zend/tests/match/027.phpt36
-rw-r--r--Zend/tests/match/028.phpt36
-rw-r--r--Zend/tests/match/029.phpt22
-rw-r--r--Zend/tests/match/030.phpt22
-rw-r--r--Zend/tests/match/037.phpt68
-rw-r--r--Zend/tests/match/038.phpt15
-rw-r--r--Zend/tests/match/039.phpt61
-rw-r--r--Zend/tests/match/040.phpt44
-rw-r--r--Zend/tests/match/041.phpt33
-rw-r--r--Zend/tests/match/042.phpt22
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"