Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Unique token for child processes through environment variables

  • Loading branch information...
commit eb65da1fb13fa81457d80b58069448ad23761135 1 parent 648cd59
Dimitris Baltas authored January 30, 2013
25  src/ParaTest/Runners/PHPUnit/ExecutableTest.php
@@ -8,6 +8,7 @@
8 8
     protected $process;
9 9
     protected $status;
10 10
     protected $stderr;
  11
+    protected $token;
11 12
 
12 13
     protected static $descriptors = array(
13 14
         0 => array('pipe', 'r'),
@@ -69,7 +70,7 @@ public function isDoneRunning()
69 70
     }
70 71
 
71 72
     /**
72  
-     * Called after a polling context to retrieve 
  73
+     * Called after a polling context to retrieve
73 74
      * the exit code of the phpunit process
74 75
      */
75 76
     public function getExitCode()
@@ -77,10 +78,11 @@ public function getExitCode()
77 78
         return $this->status['exitcode'];
78 79
     }
79 80
 
80  
-    public function run($binary, $options = array())
  81
+    public function run($binary, $options = array(), $environmentVariables = array())
81 82
     {
82 83
         $options = array_merge($this->prepareOptions($options), array('log-junit' => $this->getTempFile()));
83  
-        $command = $this->getCommandString($binary, $options);
  84
+        $this->handleEnvironmentVariables($environmentVariables);
  85
+        $command = $this->getCommandString($binary, $options, $environmentVariables);
84 86
         $this->process = proc_open($command, self::$descriptors, $this->pipes);
85 87
         return $this;
86 88
     }
@@ -101,12 +103,25 @@ protected function prepareOptions($options)
101 103
         return $options;
102 104
     }
103 105
 
104  
-    protected function getCommandString($binary, $options = array())
  106
+    protected function getCommandString($binary, $options = array(), $environmentVariables = array())
105 107
     {
106 108
         $command = $binary;
  109
+        $environmentVariablePrefix = '';
  110
+
107 111
         foreach($options as $key => $value) $command .= " --$key %s";
108  
-        $args = array_merge(array("$command %s"), array_values($options), array($this->getPath()));
  112
+        foreach($environmentVariables as $key => $value) $environmentVariablePrefix .= "$key=%s ";
  113
+        $args = array_merge(array("$environmentVariablePrefix$command %s"), array_values($environmentVariables), array_values($options), array($this->getPath()));
109 114
         $command = call_user_func_array('sprintf', $args);
110 115
         return $command;
111 116
     }
  117
+
  118
+    public function getToken()
  119
+    {
  120
+        return $this->token;
  121
+    }
  122
+
  123
+    protected function handleEnvironmentVariables($environmentVariables)
  124
+    {
  125
+        if (isset($environmentVariables['TEST_TOKEN'])) $this->token = $environmentVariables['TEST_TOKEN'];
  126
+    }
112 127
 }
44  src/ParaTest/Runners/PHPUnit/Runner.php
@@ -13,12 +13,14 @@ class Runner
13 13
     protected $interpreter;
14 14
     protected $printer;
15 15
     protected $exitcode = -1;
16  
-    
  16
+    protected $tokens = array();
  17
+
17 18
     public function __construct($opts = array())
18 19
     {
19 20
         $this->options = new Options($opts);
20 21
         $this->interpreter = new LogInterpreter();
21 22
         $this->printer = new ResultPrinter($this->interpreter);
  23
+        $this->initTokens();
22 24
     }
23 25
 
24 26
     public function run()
@@ -28,7 +30,10 @@ public function run()
28 30
         $this->printer->start($this->options);
29 31
         while(count($this->running) || count($this->pending)) {
30 32
             foreach($this->running as $key => $test)
31  
-                if(!$this->testIsStillRunning($test)) unset($this->running[$key]);
  33
+                if(!$this->testIsStillRunning($test)) {
  34
+                    unset($this->running[$key]);
  35
+                    $this->releaseToken($key);
  36
+                }
32 37
             $this->fillRunQueue();
33 38
         }
34 39
         $this->complete();
@@ -78,8 +83,13 @@ private function log()
78 83
     private function fillRunQueue()
79 84
     {
80 85
         $opts = $this->options;
81  
-        while(sizeof($this->pending) && sizeof($this->running) < $opts->processes)
82  
-            $this->running[] = array_shift($this->pending)->run($opts->phpunit, $opts->filtered);
  86
+        while(sizeof($this->pending) && sizeof($this->running) < $opts->processes) {
  87
+            $token = $this->getNextAvailableToken();
  88
+            if ($token !== false) {
  89
+                $this->acquireToken($token);
  90
+                $this->running[$token] = array_shift($this->pending)->run($opts->phpunit, $opts->filtered, array('TEST_TOKEN' => $token));
  91
+            }
  92
+        }
83 93
     }
84 94
 
85 95
     private function testIsStillRunning($test)
@@ -99,4 +109,30 @@ private function setExitCode(ExecutableTest $test)
99 109
         if($exit > $this->exitcode)
100 110
             $this->exitcode = $exit;
101 111
     }
  112
+
  113
+    protected function initTokens()
  114
+    {
  115
+        $this->tokens = array();
  116
+        for ($i=0; $i< $this->options->processes; $i++) {
  117
+            $this->tokens[$i] = true;
  118
+        }
  119
+    }
  120
+
  121
+    protected function getNextAvailableToken()
  122
+    {
  123
+        for ($i=0; $i< count($this->tokens); $i++) {
  124
+            if ($this->tokens[$i]) return $i;
  125
+        }
  126
+        return false;
  127
+    }
  128
+
  129
+    protected function releaseToken($tokenIdentifier)
  130
+    {
  131
+        $this->tokens[$tokenIdentifier] = true;
  132
+    }
  133
+
  134
+    protected function acquireToken($tokenIdentifier)
  135
+    {
  136
+        $this->tokens[$tokenIdentifier] = false;
  137
+    }
102 138
 }
58  test/ParaTest/Runners/PHPUnit/ExecutableTestTest.php
... ...
@@ -0,0 +1,58 @@
  1
+<?php namespace ParaTest\Runners\PHPUnit;
  2
+
  3
+class ExecutableTestChild extends ExecutableTest
  4
+{
  5
+
  6
+}
  7
+
  8
+class ExecutableTestTest extends \TestBase
  9
+{
  10
+    /**
  11
+     *
  12
+     * @var ExecutableTestChild
  13
+     */
  14
+    protected $executableTestChild;
  15
+
  16
+    public function setUp()
  17
+    {
  18
+        $this->executableTestChild = new ExecutableTestChild('pathToFile');
  19
+        parent::setUp();
  20
+    }
  21
+
  22
+    public function testConstructor()
  23
+    {
  24
+          $this->assertEquals('pathToFile', $this->getObjectValue($this->executableTestChild, 'path'));
  25
+    }
  26
+
  27
+    public function testGetCommandStringIncludesOptions()
  28
+    {
  29
+        $options = array('bootstrap' => 'test/bootstrap.php');
  30
+        $binary = '/usr/bin/phpunit';
  31
+
  32
+        $command = $this->call($this->executableTestChild, 'getCommandString', $binary, $options);
  33
+        $this->assertEquals('/usr/bin/phpunit --bootstrap test/bootstrap.php pathToFile', $command);
  34
+    }
  35
+
  36
+    public function testGetCommandStringIncludesEnvironmentVariables()
  37
+    {
  38
+        $options = array('bootstrap' => 'test/bootstrap.php');
  39
+        $binary = '/usr/bin/phpunit';
  40
+        $environmentVariables = array('TEST_TOKEN' => 3, 'APPLICATION_ENVIRONMENT_VAR' => 'abc');
  41
+        $command = $this->call($this->executableTestChild, 'getCommandString', $binary, $options, $environmentVariables);
  42
+
  43
+        $this->assertEquals('TEST_TOKEN=3 APPLICATION_ENVIRONMENT_VAR=abc /usr/bin/phpunit --bootstrap test/bootstrap.php pathToFile', $command);
  44
+    }
  45
+
  46
+    public function testHandleEnvironmentVariablesAssignsToken()
  47
+    {
  48
+        $environmentVariables = array('TEST_TOKEN' => 3, 'APPLICATION_ENVIRONMENT_VAR' => 'abc');
  49
+        $this->call($this->executableTestChild, 'handleEnvironmentVariables', $environmentVariables);
  50
+        $this->assertEquals(3, $this->getObjectValue($this->executableTestChild, 'token'));
  51
+    }
  52
+
  53
+    public function testGetTokenReturnsValidToken()
  54
+    {
  55
+        $this->setObjectValue($this->executableTestChild, 'token', 3);
  56
+        $this->assertEquals(3, $this->executableTestChild->getToken());
  57
+    }
  58
+}
43  test/ParaTest/Runners/PHPUnit/RunnerTest.php
@@ -34,4 +34,47 @@ public function testGetExitCode()
34 34
     {
35 35
         $this->assertEquals(-1, $this->runner->getExitCode());
36 36
     }
  37
+
  38
+    public function testConstructorAssignsTokens()
  39
+    {
  40
+        $opts = array('processes' => 4, 'path' => FIXTURES . DS . 'tests', 'bootstrap' => 'hello', 'functional' => true);
  41
+        $runner = new Runner($opts);
  42
+        $tokens = $this->getObjectValue($runner, 'tokens');
  43
+        $this->assertEquals(4, count($tokens));
  44
+    }
  45
+
  46
+    public function testGetsNextAvailableTokenReturnsTokenIdentifier()
  47
+    {
  48
+        $tokens = array(0 => false, 1 => false, 2 => true, 3 => false);
  49
+        $opts = array('processes' => 4, 'path' => FIXTURES . DS . 'tests', 'bootstrap' => 'hello', 'functional' => true);
  50
+        $runner = new Runner($opts);
  51
+        $this->setObjectValue($runner, 'tokens', $tokens);
  52
+
  53
+        $token = $this->call($runner, 'getNextAvailableToken');
  54
+        $this->assertEquals(2, $token);
  55
+    }
  56
+
  57
+    public function testGetNextAvailableTokenReturnsFalseWhenNoTokensAreAvailable()
  58
+    {
  59
+        $tokens = array(0 => false, 1 => false, 2 => false, 3 => false);
  60
+        $opts = array('processes' => 4, 'path' => FIXTURES . DS . 'tests', 'bootstrap' => 'hello', 'functional' => true);
  61
+        $runner = new Runner($opts);
  62
+        $this->setObjectValue($runner, 'tokens', $tokens);
  63
+
  64
+        $token = $this->call($runner, 'getNextAvailableToken');
  65
+        $this->assertTrue($token === false);
  66
+    }
  67
+
  68
+    public function testReleaseTokenMakesTokenAvailable()
  69
+    {
  70
+        $tokens = array(0 => false, 1 => false, 2 => false, 3 => false);
  71
+        $opts = array('processes' => 4, 'path' => FIXTURES . DS . 'tests', 'bootstrap' => 'hello', 'functional' => true);
  72
+        $runner = new Runner($opts);
  73
+        $this->setObjectValue($runner, 'tokens', $tokens);
  74
+
  75
+        $this->assertFalse($tokens[1]);
  76
+        $this->call($runner, 'releaseToken', 1);
  77
+        $tokens = $this->getObjectValue($runner, 'tokens');
  78
+        $this->assertTrue($tokens[1]);
  79
+    }
37 80
 }
10  test/ParaTest/Runners/PHPUnit/TestMethodTest.php
... ...
@@ -0,0 +1,10 @@
  1
+<?php namespace ParaTest\Runners\PHPUnit;
  2
+
  3
+class TestMethodTest extends \TestBase
  4
+{
  5
+    public function testConstructor()
  6
+    {
  7
+        $testMethod = new TestMethod('pathToFile', 'methodName');
  8
+        $this->assertEquals('pathToFile', $this->getObjectValue($testMethod, 'path'));
  9
+    }
  10
+}

0 notes on commit eb65da1

Please sign in to comment.
Something went wrong with that request. Please try again.