예제 #1
0
 /**
  * @dataProvider nonBlockingProvider
  *
  * @param $timeout
  * @param bool $wait
  * @param bool $finish
  * @param string $output
  * @param string $expectedOutput
  */
 public function testNonBlocking($timeout, $wait, $finish, $output, $expectedOutput)
 {
     $this->pid->shouldReceive("getPid")->withArgs([true])->andThrow("Silktide\\Teamster\\Exception\\PidException");
     $this->pid->shouldReceive("cleanPid")->once()->andReturn(true);
     // seems we need to use a real file and can't mock the filesystem
     $outFile = __DIR__ . "/output/output";
     $spec = $this->setupOutFile($outFile);
     // setup command
     $command = "php -r \"\\\$s = microtime(true); do {usleep({$timeout} / 4);} while (microtime(true) - \\\$s < {$timeout} / 1000000); echo '{$output}';\"";
     // do the test
     $runner = new ProcessRunner($this->pidFactory, $spec, "dud", 1, 5, 5);
     $runner->execute($command, false);
     $this->assertTrue($runner->isRunning($this->pid));
     if ($wait) {
         usleep($timeout * 2);
     }
     if ($finish) {
         $runner->finish($this->pid);
     }
     $this->assertFalse($runner->isRunning($this->pid));
     $this->assertEquals($expectedOutput, file_get_contents($outFile));
 }
예제 #2
0
 public function testStart()
 {
     $this->input->shouldReceive("getArgument")->andReturn("start");
     $pid = getmypid();
     $this->pid->shouldReceive("getPid")->andReturn($pid);
     $poolCommand = "pool:command";
     // test when pool is already running
     $command = new PoolControlCommand($this->runnerFactory, $this->pidFactory, "pool.pid", $poolCommand);
     try {
         $command->execute($this->input, $this->output);
         $this->fail("Should not be able to start a pool when one is already running");
     } catch (ProcessException $e) {
     }
     // test when pool is stopped
     $noPidFile = "no.pid";
     $noPid = \Mockery::mock("Silktide\\Teamster\\Pool\\Pid\\PidInterface")->shouldIgnoreMissing(true);
     $noPid->shouldReceive("getPid")->atLeast()->times(1)->andThrow("Silktide\\Teamster\\Exception\\PidException");
     $noPidFactory = \Mockery::mock("Silktide\\Teamster\\Pool\\Pid\\PidFactoryInterface");
     $noPidFactory->shouldReceive("create")->withArgs([$noPidFile])->once()->andReturn($noPid);
     $this->runner->shouldReceive("execute")->withArgs([$poolCommand, false])->once();
     $command = new PoolControlCommand($this->runnerFactory, $noPidFactory, $noPidFile, $poolCommand);
     $command->execute($this->input, $this->output);
 }
예제 #3
0
 /**
  * {@inheritDoc}
  * @throws RunnerException
  */
 public function finish(PidInterface $pid = null)
 {
     if (!is_resource($this->process)) {
         // no process to close, make sure the PID file is removed
         if (!empty($pid)) {
             $pid->cleanPid();
         }
         return;
     }
     // check if the process is still running
     $status = proc_get_status($this->process);
     if ($status["running"]) {
         // terminate the process kindly
         proc_terminate($this->process, SIGTERM);
         $startTime = microtime(true);
         $terminating = false;
         do {
             if (!$terminating && microtime(true) - $startTime > self::TERMINATE_TIMEOUT) {
                 // terminate the process with extreme prejudice
                 proc_terminate($this->process, SIGKILL);
                 $terminating = true;
             }
             // ... and wait for confirmation
             usleep(self::PROCESS_CHECK_INTERVAL);
             $status = proc_get_status($this->process);
         } while ($status["running"]);
     }
     // close the pipes
     $this->closePipes();
     if (proc_close($this->process) === false) {
         throw new RunnerException("Could not close process");
     }
     $this->process = null;
     if (!empty($pid) && !$pid->cleanPid()) {
         // error deleting the PID file, DO NOT CONTINUE
         throw new RunnerException("Could not release the PID file");
     }
 }