1<?php 2define("PHP_CLI_SERVER_HOSTNAME", "localhost"); 3define("PHP_CLI_SERVER_PORT", 8964); 4define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT); 5 6function php_cli_server_start( 7 ?string $code = 'echo "Hello world";', 8 ?string $router = 'index.php', 9 array $cmd_args = [] 10) { 11 $php_executable = getenv('TEST_PHP_EXECUTABLE'); 12 $doc_root = __DIR__; 13 $error = null; 14 15 if ($code) { 16 file_put_contents($doc_root . '/' . ($router ?: 'index.php'), '<?php ' . $code . ' ?>'); 17 } 18 19 $cmd = [$php_executable, '-t', $doc_root, '-n', ...$cmd_args, '-S', PHP_CLI_SERVER_ADDRESS]; 20 if (!is_null($router)) { 21 $cmd[] = $router; 22 } 23 24 $descriptorspec = array( 25 0 => STDIN, 26 1 => STDOUT, 27 2 => array("null"), 28 ); 29 $handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root, null, array("suppress_errors" => true)); 30 31 // note: here we check the process is running 32 for ($i=0; $i < 120; $i++) { 33 $status = proc_get_status($handle); 34 35 if (!$status || !$status['running']) { 36 if ($status && 37 ($status['running'] == false && $status['exitcode'] != 0)) { 38 $error = 39 "Server could not be started\n"; 40 break; 41 } 42 43 usleep(50000); // 50ms per try 44 continue; 45 } 46 47 if ($status['signaled']) { 48 $error = 49 "Server was terminated with {$status['termsig']}\n"; 50 break; 51 } 52 53 if ($status['stopped']) { 54 $error = 55 "Server was stopped with {$status['stopsig']}\n"; 56 break; 57 } 58 59 // note: here we check the server is listening, even when the server prints 60 // listening on %s:%d 61 // it may not be ready to accept connections 62 $start = time(); 63 64 for ($try = 0; $try < 120; $try++) { 65 $error = @fsockopen( 66 PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT) ? 67 null : 68 sprintf( 69 "Server is not accepting connections after %d seconds\n", 70 time() - $start); 71 72 if (!$error) { 73 break 2; 74 } 75 76 usleep(50000); 77 } 78 79 break; 80 } 81 82php_cli_server_start_error: 83 if ($error) { 84 echo $error; 85 proc_terminate($handle); 86 exit(1); 87 } 88 89 register_shutdown_function( 90 function($handle) use($router) { 91 proc_terminate($handle); 92 @unlink(__DIR__ . "/{$router}"); 93 }, 94 $handle 95 ); 96 97 return $handle; 98} 99 100function php_cli_server_connect() { 101 $timeout = 1.0; 102 $fp = fsockopen(PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT, $errno, $errstr, $timeout); 103 if (!$fp) { 104 die("connect failed"); 105 } 106 return $fp; 107} 108 109?> 110