Repository: phpbench/phpbench (php)

Issue:
Environment variables through phpbench.json
```json
{
    "bootstrap": "vendor/autoload.php",
    "path": "src/Benchmark",
    "env": [
        {
            "name": "APP_ENV",
            "value": "test",
            "force": true
        },
        {
            "name": "SOME_VAR",
            "value": "foo bar"
        }
    ]
}
```

Are there any plans to implement something like this? This would help a lot when writing benchmarks when working with a database in a test environment...

What do you think about this?

Pull request description:
Add support for passing env vars to PHP
Fixes #628 

Patch:
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 7dbbe96c..fd3b12a4 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -240,6 +240,17 @@ Default: ``NULL``
 
 Types: ``["string","null"]``
 
+.. _configuration_runner_php_env:
+
+runner.php_env
+~~~~~~~~~~~~~~
+
+Key-value set of environment variables to pass to the PHP process
+
+Default: ``NULL``
+
+Types: ``["array","null"]``
+
 .. _configuration_runner_progress:
 
 runner.progress
diff --git a/lib/Extension/RunnerExtension.php b/lib/Extension/RunnerExtension.php
index c104c34a..420f8fdd 100644
--- a/lib/Extension/RunnerExtension.php
+++ b/lib/Extension/RunnerExtension.php
@@ -82,6 +82,7 @@ class RunnerExtension implements ExtensionInterface
     public const PARAM_PHP_CONFIG = 'runner.php_config';
     public const PARAM_PHP_DISABLE_INI = 'runner.php_disable_ini';
     public const PARAM_PHP_WRAPPER = 'runner.php_wrapper';
+    public const PARAM_PHP_ENV = 'runner.php_env';
     public const PARAM_PROGRESS = 'runner.progress';
     public const PARAM_PROGRESS_SUMMARY_BASELINE_FORMAT = 'runner.progress_summary_baseline_format';
     public const PARAM_PROGRESS_SUMMARY_FORMAT = 'runner.progress_summary_variant_format';
@@ -131,6 +132,7 @@ class RunnerExtension implements ExtensionInterface
             self::PARAM_PHP_CONFIG => [],
             self::PARAM_PHP_DISABLE_INI => false,
             self::PARAM_PHP_WRAPPER => null,
+            self::PARAM_PHP_ENV => null,
             self::PARAM_PROGRESS => 'verbose',
             self::PARAM_PROGRESS_SUMMARY_FORMAT => VariantSummaryFormatter::DEFAULT_FORMAT,
             self::PARAM_PROGRESS_SUMMARY_BASELINE_FORMAT => VariantSummaryFormatter::BASELINE_FORMAT,
@@ -163,6 +165,7 @@ class RunnerExtension implements ExtensionInterface
         $resolver->setAllowedTypes(self::PARAM_PHP_CONFIG, ['array']);
         $resolver->setAllowedTypes(self::PARAM_PHP_DISABLE_INI, ['bool']);
         $resolver->setAllowedTypes(self::PARAM_PHP_WRAPPER, ['string', 'null']);
+        $resolver->setAllowedTypes(self::PARAM_PHP_ENV, ['array', 'null']);
         $resolver->setAllowedTypes(self::PARAM_PROGRESS, ['string']);
         $resolver->setAllowedTypes(self::PARAM_PROGRESS_SUMMARY_BASELINE_FORMAT, ['string']);
         $resolver->setAllowedTypes(self::PARAM_PROGRESS_SUMMARY_FORMAT, ['string']);
@@ -195,6 +198,7 @@ class RunnerExtension implements ExtensionInterface
             self::PARAM_PHP_CONFIG => 'Map of PHP ini settings to use when executing out-of-band benchmarks',
             self::PARAM_PHP_DISABLE_INI => 'Disable reading the default PHP configuration',
             self::PARAM_PHP_WRAPPER => 'Wrap the PHP binary with this command (e.g. ``blackfire run``)',
+            self::PARAM_PHP_ENV => 'Key-value set of environment variables to pass to the PHP process',
             self::PARAM_PROGRESS => 'Default progress logger to use',
             self::PARAM_PROGRESS_SUMMARY_FORMAT => 'Expression used to render the summary text default progress loggers',
             self::PARAM_PROGRESS_SUMMARY_BASELINE_FORMAT => 'When the a comparison benchmark is referenced, alternative expression used to render the summary text default progress loggers',
@@ -370,7 +374,10 @@ class RunnerExtension implements ExtensionInterface
         });
 
         $container->register(ProcessFactory::class, function (Container $container) {
-            return new ProcessFactory($container->get(LoggerInterface::class));
+            return new ProcessFactory(
+                $container->get(LoggerInterface::class),
+                $container->getParameter(self::PARAM_PHP_ENV)
+            );
         });
 
         $container->register(Launcher::class, function (Container $container) {
diff --git a/lib/Remote/ProcessFactory.php b/lib/Remote/ProcessFactory.php
index a4e32efd..3566b4c0 100644
--- a/lib/Remote/ProcessFactory.php
+++ b/lib/Remote/ProcessFactory.php
@@ -13,16 +13,28 @@ final class ProcessFactory implements ProcessFactoryInterface
      */
     private $logger;
 
-    public function __construct(?LoggerInterface $logger = null)
+    /**
+     * @var array|null
+     */
+    private $env;
+
+    public function __construct(?LoggerInterface $logger = null, ?array $env = null)
     {
         $this->logger = $logger ?: new NullLogger();
+        $this->env = $env;
     }
 
     public function create(string $commandLine, ?float $timeout = null): Process
     {
         $this->logger->debug(sprintf('Spawning process: %s', $commandLine));
 
-        return Process::fromShellCommandline($commandLine)
+        $process = Process::fromShellCommandline($commandLine)
             ->setTimeout($timeout);
+
+        if (null !== $this->env) {
+            $process->setEnv($this->env);
+        }
+
+        return $process;
     }
 }
diff --git a/phpbench.schema.json b/phpbench.schema.json
index c9ccd8aa..ff4edd18 100644
--- a/phpbench.schema.json
+++ b/phpbench.schema.json
@@ -138,6 +138,13 @@
                 "null"
             ]
         },
+        "runner.php_env": {
+            "description": "Key-value set of environment variables to pass to the PHP process",
+            "type": [
+                "object",
+                "null"
+            ]
+        },
         "runner.progress": {
             "description": "Default progress logger to use",
             "type": [


Test patch:
diff --git a/tests/Unit/Remote/ProcessFactoryTest.php b/tests/Unit/Remote/ProcessFactoryTest.php
new file mode 100644
index 00000000..a078b846
--- /dev/null
+++ b/tests/Unit/Remote/ProcessFactoryTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace PhpBench\Tests\Unit\Remote;
+
+use PhpBench\Remote\ProcessFactory;
+use PHPUnit\Framework\TestCase;
+use Psr\Log\NullLogger;
+
+class ProcessFactoryTest extends TestCase
+{
+    public function testCreatesProcessWithEnv(): void
+    {
+        $process = (new ProcessFactory(new NullLogger(), [
+            'FOO' => 'hello',
+        ]))->create('echo $FOO');
+        $process->mustRun();
+        self::assertStringContainsString('hello', $process->getOutput());
+    }
+
+    public function testCreatesProcessInheritsEnv(): void
+    {
+        $_ENV['FOO'] = 'bar';
+        $process = (new ProcessFactory(new NullLogger(), ['BAZ' => 'boo']))->create('echo $FOO$BAZ');
+        $process->mustRun();
+        self::assertStringContainsString('barboo', $process->getOutput());
+    }
+}