Skip to content

Commit 762b0c4

Browse files
authored
ext/readline: write test for readline CLI (#22994)
This commit offers basic behavior tests for ext/readline/readline_cli.c
1 parent 9950a59 commit 762b0c4

6 files changed

Lines changed: 194 additions & 0 deletions
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Interactive shell: auto_prepend_file is executed before input
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('proc_open')) die('skip proc_open() not available');
8+
?>
9+
--FILE--
10+
<?php
11+
$prepend = tempnam(sys_get_temp_dir(), 'readline_cli_prepend');
12+
file_put_contents($prepend, <<<'PHP'
13+
<?php
14+
echo "prepended\n";
15+
define('READLINE_CLI_PREPENDED', 'ok');
16+
readline_completion_function(static fn() => []);
17+
PHP);
18+
19+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
20+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
21+
$descriptorspec = [['pipe', 'r'], STDOUT, STDERR];
22+
$proc = proc_open("$php $ini -d auto_prepend_file=" . escapeshellarg($prepend) . " -a", $descriptorspec, $pipes);
23+
fwrite($pipes[0], "echo READLINE_CLI_PREPENDED . \"\n\";\n");
24+
fwrite($pipes[0], "exit\n");
25+
fclose($pipes[0]);
26+
proc_close($proc);
27+
unlink($prepend);
28+
?>
29+
--EXPECTF--
30+
%AInteractive shell%Aprepended%Aok%A
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Interactive shell: default completion function
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (READLINE_LIB !== "readline") die('skip readline only');
8+
if (!function_exists('shell_exec')) die('skip shell_exec() not available');
9+
?>
10+
--FILE--
11+
<?php
12+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
13+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
14+
15+
putenv('TERM=VT100');
16+
17+
$code = <<<'PHP'
18+
$readline_cli_completion_variable = strtolower("VARIABLE_OK\n");
19+
echo $readline_cli_completion_var ;
20+
#prec 3
21+
echo "precision_result=" . ini_get("precision") . "\n";
22+
function readline_cli_completion_function() { echo strtolower("FUNCTION_OK\n"); }
23+
readline_cli_completion_fun );
24+
define('READLINE_CLI_COMPLETION_CONSTANT', strtolower("CONSTANT_OK\n"));
25+
echo READLINE_CLI_COMPLETION_CON ;
26+
class ReadlineCliCompletionClass {
27+
public static function completionMethod() { echo strtolower("METHOD_OK\n"); }
28+
}
29+
echo "class_ok:" . ReadlineCliCompletionCla ::class . "\n";
30+
ReadlineCliCompletionClass::completionM );
31+
exit
32+
PHP;
33+
34+
echo shell_exec("echo " . escapeshellarg($code) . " | $php $ini -a");
35+
?>
36+
--EXPECTF--
37+
%AInteractive shell%Avariable_ok%Aprecision_result=3%Afunction_ok%Aconstant_ok%Aclass_ok:ReadlineCliCompletionClass%Amethod_ok%A
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Interactive shell: input buffer grows for long lines
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('proc_open')) die('skip proc_open() not available');
8+
?>
9+
--FILE--
10+
<?php
11+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
12+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
13+
$descriptorspec = [['pipe', 'r'], STDOUT, STDERR];
14+
$proc = proc_open("$php $ini -a", $descriptorspec, $pipes);
15+
$long = str_repeat('x', 5000);
16+
fwrite($pipes[0], 'echo strlen("' . $long . '") . "\n";' . "\n");
17+
fwrite($pipes[0], "exit\n");
18+
fclose($pipes[0]);
19+
proc_close($proc);
20+
?>
21+
--EXPECTF--
22+
%AInteractive shell%A5000%A
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Interactive shell: multiline input states
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('proc_open')) die('skip proc_open() not available');
8+
?>
9+
--FILE--
10+
<?php
11+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
12+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
13+
$descriptorspec = [['pipe', 'r'], STDOUT, STDERR];
14+
$proc = proc_open("$php $ini -a", $descriptorspec, $pipes);
15+
16+
fwrite($pipes[0], "\n");
17+
fwrite($pipes[0], "echo strtoupper('single \\' semi ; brace }\nend');\n");
18+
fwrite($pipes[0], "echo strtoupper(\"double \\\" semi ; brace }\nend\");\n");
19+
fwrite($pipes[0], "echo strtoupper(\n\"paren\"\n);\n");
20+
fwrite($pipes[0], "echo \"arithmetic=\", 6 /\n2 + 100;\n");
21+
fwrite($pipes[0], "if (true) {\necho strtoupper(\"block_body\n\");\n}\n");
22+
fwrite($pipes[0], "echo strtoupper(\n\"hash_comment\\n\"\n# ) ;\n);\n");
23+
fwrite($pipes[0], "echo strtoupper(\n\"slash_comment\\n\"\n// ) ;\n);\n");
24+
fwrite($pipes[0], "echo strtoupper(\n\"block_comment\\n\" /*\n) ;\n*/\n);\n");
25+
fwrite($pipes[0], "#[AllowDynamicProperties]\nclass ReadlineCliCoverageClass {}\n");
26+
fwrite($pipes[0], "echo strtoupper((new ReflectionClass(ReadlineCliCoverageClass::class))->getAttributes()[0]->getName()), \"\\n\";\n");
27+
fwrite($pipes[0], "if (true) ?>outside } );\n<?php\necho strtoupper(\"outside_ok\\n\");\n");
28+
fwrite($pipes[0], "quit\n");
29+
fclose($pipes[0]);
30+
proc_close($proc);
31+
?>
32+
--EXPECTF--
33+
%AInteractive shell%ASINGLE%ADOUBLE%APAREN%Aarithmetic=103%ABLOCK_BODY%AHASH_COMMENT%ASLASH_COMMENT%ABLOCK_COMMENT%AALLOWDYNAMICPROPERTIES%AOUTSIDE_OK%A
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
Interactive shell: output through cli.pager
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (!function_exists('proc_open')) die('skip proc_open() not available');
8+
if (READLINE_LIB !== "readline") die('skip readline only');
9+
if (PHP_OS_FAMILY === 'Windows') die('skip tr pager is not portable on Windows');
10+
?>
11+
--FILE--
12+
<?php
13+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
14+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
15+
$descriptorspec = [['pipe', 'r'], STDOUT, STDERR];
16+
$proc = proc_open("$php $ini -d cli.pager='tr a-z A-Z' -a", $descriptorspec, $pipes);
17+
fwrite($pipes[0], "echo \"pager output\n\";\n");
18+
fwrite($pipes[0], "quit\n");
19+
fclose($pipes[0]);
20+
proc_close($proc);
21+
?>
22+
--EXPECT--
23+
Interactive shell
24+
25+
php > echo "pager output
26+
php " ";
27+
pager output
28+
PAGER OUTPUT
29+
php > quit
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
--TEST--
2+
Interactive shell: custom prompt escape sequences
3+
--EXTENSIONS--
4+
readline
5+
--SKIPIF--
6+
<?php
7+
if (READLINE_LIB !== "readline") die('skip readline only');
8+
if (!function_exists('proc_open')) die('skip proc_open() not available');
9+
?>
10+
--FILE--
11+
<?php
12+
$php = getenv('TEST_PHP_EXECUTABLE_ESCAPED');
13+
$ini = getenv('TEST_PHP_EXTRA_ARGS');
14+
$prompt = 'pre\\\\-\n-\t-\e-\v-\b-\>-\`-\q-' . "\xC3\xA9\xC3\xA9" . '-`echo \'dyn\';`-`-x ';
15+
$descriptorspec = [['pipe', 'r'], STDOUT, STDERR];
16+
$proc = proc_open("$php $ini -d " . escapeshellarg("cli.prompt=\"$prompt\"") . " -a", $descriptorspec, $pipes);
17+
fwrite($pipes[0], "if (true) {\n");
18+
fwrite($pipes[0], "echo strtoupper(\"prompt_body\\n\");\n");
19+
fwrite($pipes[0], "}\n");
20+
fwrite($pipes[0], "quit\n");
21+
fclose($pipes[0]);
22+
proc_close($proc);
23+
?>
24+
--EXPECTF--
25+
Interactive shell
26+
27+
28+
Warning: prompt contains unsupported unicode characters in Unknown on line 0
29+
dynpre\-
30+
- -%c-%d.%d.%s-php->-`-\q-????-dyn--x if (true) {
31+
32+
Warning: prompt contains unsupported unicode characters in Unknown on line 0
33+
dynpre\-
34+
- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x echo strtoupper("prompt_body\n");
35+
36+
Warning: prompt contains unsupported unicode characters in Unknown on line 0
37+
dynpre\-
38+
- -%c-%d.%d.%s-php-{-`-\q-????-dyn--x }
39+
40+
Warning: prompt contains unsupported unicode characters in Unknown on line 0
41+
dynPROMPT_BODY
42+
pre\-
43+
- -%c-%d.%d.%s-php->-`-\q-????-dyn--x quit

0 commit comments

Comments
 (0)