$ignored_by_ext = 0;
sort($exts_to_test);
$test_dirs = array();
-$optionals = array('tests', 'ext', 'Zend', 'ZendEngine2', 'sapi/cli', 'sapi/cgi');
+$optionals = array('tests', 'ext', 'Zend', 'ZendEngine2', 'sapi/cli', 'sapi/cgi', 'sapi/fpm');
foreach($optionals as $dir) {
if (@filetype($dir) == 'dir') {
--- /dev/null
+--TEST--
+FPM: version string
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$php = get_fpm_path();
+
+var_dump(`$php -n -v`);
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(%d) "PHP %s (fpm%s (built: %s
+Copyright (c) 1997-20%s The PHP Group
+Zend Engine v%s, Copyright (c) 1998-20%s Zend Technologies
+"
+Done
--- /dev/null
+--TEST--
+FPM: Startup and connect
+--SKIPIF--
+<?php include "skipif.inc"; ?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[unconfined]
+listen = 127.0.0.1:9000
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+EOT;
+
+$fpm = run_fpm($cfg, $tail);
+if (is_resource($fpm)) {
+ var_dump(fgets($tail));
+ var_dump(fgets($tail));
+ $i = 0;
+ while (($i++ < 30) && !($fp = @fsockopen('127.0.0.1', 9000))) {
+ usleep(10000);
+ }
+ if ($fp) {
+ echo "Done\n";
+ fclose($fp);
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+}
+
+?>
+--EXPECTF--
+string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: fpm is running, pid %d
+"
+string(%d) "[%d-%s-%d %d:%d:%d] NOTICE: ready to handle connections
+"
+Done
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
--- /dev/null
+--TEST--
+FPM: Apparmor Test
+--DESCRIPTION--
+This test tries to launches a pool which tries to change to non existing
+apparmor hat a. Test succeeds if apparmor is not running or hat is non
+existant.
+--SKIPIF--
+<?php
+include "skipif.inc";
+include "skipapparmor.inc";
+
+?>
+--FILE--
+<?php
+
+include "include.inc";
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[a]
+listen = 127.0.0.1:9001
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+apparmor_hat = a
+EOT;
+
+/* libapparmor has a bug which can cause SIGSEGV till Version 2.8.0-0ubuntu28
+ See https://bugs.launchpad.net/apparmor/+bug/1196880
+ Possible outcomes:
+
+ - SIGSEGV|failed to query apparmor confinement
+ apparmor not running
+ - failed to change to new confinement
+ something in apparmor went wrong
+ - exited with code 70
+ Change to successful; Hat not existant (Process gets killed by apparmor)
+ */
+var_dump(run_fpm_till('/(SIGSEGV|failed to query apparmor confinement|failed to change to new confinement|exited with code 70)/', $cfg));
+
+?>
+--EXPECTF--
+string(%d) "%s
+"
+--CLEAN--
+<?php
+ $logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+ @unlink($logfile);
+?>
--- /dev/null
+<?php
+
+function get_fpm_path() /* {{{ */
+{
+ $php_path = getenv("TEST_PHP_EXECUTABLE");
+
+ for ($i = 0; $i < 2; $i++) {
+ $slash_pos = strrpos($php_path, "/");
+ if ($slash_pos) {
+ $php_path = substr($php_path, 0, $slash_pos);
+ } else {
+ return false;
+ }
+ }
+
+ if ($php_path && is_dir($php_path) && file_exists($php_path."/fpm/php-fpm") && is_executable($php_path."/fpm/php-fpm")) {
+ /* gotcha */
+ return $php_path."/fpm/php-fpm";
+ }
+ return false;
+}
+/* }}} */
+
+function run_fpm($config, &$out = false, $extra_args = '') /* {{{ */
+{
+ $cfg = dirname(__FILE__).'/test-fpm-config.tmp';
+ file_put_contents($cfg, $config);
+ $desc = [];
+ if ($out !== false) {
+ $desc = [1 => array('pipe', 'w')];
+ }
+ /* Since it's not possible to spawn a process under linux without using a
+ * shell in php (why?!?) we need a little shell trickery, so that we can
+ * actually kill php-fpm */
+ $fpm = proc_open('killit () { kill $child; }; trap killit TERM; '.get_fpm_path().' -F -O -y '.$cfg.' '.$extra_args.' 2>&1 & child=$!; wait', $desc, $pipes);
+ register_shutdown_function(
+ function($fpm) use($cfg) {
+ @unlink($cfg);
+ if (is_resource($fpm)) {
+ @proc_terminate($fpm);
+ while (proc_get_status($fpm)['running']) {
+ usleep(10000);
+ }
+ }
+ },
+ $fpm
+ );
+ if ($out !== false) {
+ $out = $pipes[1];
+ }
+ return $fpm;
+}
+/* }}} */
+
+function run_fpm_till($needle, $config, $max = 10) /* {{{ */
+{
+ $i = 0;
+ $fpm = run_fpm($config, $tail);
+ if (is_resource($fpm)) {
+ while($i < $max) {
+ $i++;
+ $line = fgets($tail);
+ if(preg_match($needle, $line) === 1) {
+ break;
+ }
+ }
+ if ($i >= $max) {
+ $line = false;
+ }
+ proc_terminate($fpm);
+ stream_get_contents($tail);
+ fclose($tail);
+ proc_close($fpm);
+ }
+ return $line;
+}
+/* }}} */
+
+?>
--- /dev/null
+<?php
+
+$logfile = dirname(__FILE__).'/php-fpm.log.tmp';
+$cfg = <<<EOT
+[global]
+error_log = $logfile
+[a]
+listen = 127.0.0.1:9001
+pm = dynamic
+pm.max_children = 5
+pm.start_servers = 2
+pm.min_spare_servers = 1
+pm.max_spare_servers = 3
+apparmor_hat = a
+EOT;
+
+$fpm = run_fpm($cfg, $out, '-t');
+$ok = false;
+if (is_resource($fpm)) {
+ if (strpos(stream_get_contents($out), "test is successful") !== FALSE) {
+ $ok = true;
+ }
+ fclose($out);
+ proc_close($fpm);
+}
+if (!$ok) {
+ die("skip No apparmor support built in");
+}
+
+?>
--- /dev/null
+<?php
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ die ("skip not for Windows");
+}
+
+include dirname(__FILE__)."/include.inc";
+
+if (!get_fpm_path()) {
+ die("skip FPM not found");
+}
+
+?>